Integrar tablas PDF con fuentes de datos en Java

El ejemplo Java crea tablas PDF a partir de datos CSV sin depender de bibliotecas externas de marcos de datos.

Crear una tabla a partir de filas CSV

Utilice este ejemplo cuando las columnas CSV seleccionadas deban transformarse en una tabla PDF con estilo.

  1. Cree un Table y configure sus bordes.
  2. Detecte los índices de columna requeridos de la fila de encabezado CSV.
  3. Agregue la fila de encabezado y la cantidad solicitada de filas de datos, luego devuelve la tabla.
public static Table createTableFromCsv(List<String[]> rows, int maxRows) {
    Table table = new Table();
    table.setBorder(new BorderInfo(BorderSide.All, 1, Color.getLightGray()));
    table.setDefaultCellBorder(new BorderInfo(BorderSide.Bottom, 1, Color.getLightGray()));

    String[] header = rows.get(0);
    int[] selectedColumns = findColumns(header, "city", "country", "population", "iso3");

    Row headerRow = table.getRows().add();
    headerRow.setRowBroken(false);
    for (int columnIndex : selectedColumns) {
        Cell cell = headerRow.getCells().add(header[columnIndex]);
        cell.setBackgroundColor(Color.getLightGray());
    }

    int limit = Math.min(maxRows, rows.size() - 1);
    for (int rowIndex = 1; rowIndex <= limit; rowIndex++) {
        Row row = table.getRows().add();
        String[] rowData = rows.get(rowIndex);
        for (int columnIndex : selectedColumns) {
            row.getCells().add(columnIndex < rowData.length ? rowData[columnIndex] : "");
        }
    }

    return table;
}

Crear un PDF a partir de datos CSV

Utilice este ejemplo cuando la entrada CSV debe renderizarse como un documento de tabla PDF.

  1. Lea las filas CSV del archivo de entrada.
  2. Vea una vista previa de un subconjunto de las filas analizadas en la consola.
  3. Cree un PDF Document, agregue la tabla generada y guarde el archivo de salida.
public static void createPdfFromCsv(Path inputFile, Path outputFile, int maxRows) throws Exception {
    List<String[]> rows = readCsv(inputFile);
    for (int i = 0; i < Math.min(20, rows.size()); i++) {
        System.out.println(String.join(" | ", rows.get(i)));
    }

    try (Document document = new Document()) {
        Page page = document.getPages().add();
        page.getParagraphs().add(createTableFromCsv(rows, maxRows));
        document.save(outputFile.toString());
    }
}

Buscar índices de columnas CSV por nombre

Utilice este asistente cuando sea necesario localizar columnas con nombres específicos en la fila de encabezado del CSV.

  1. Itere a través de los nombres de columna solicitados.
  2. Busque en la fila de encabezado los índices coincidentes.
  3. Devuelva las posiciones de columna recopiladas.
private static int[] findColumns(String[] header, String... names) {
    int[] indexes = new int[names.length];
    for (int i = 0; i < names.length; i++) {
        indexes[i] = 0;
        for (int j = 0; j < header.length; j++) {
            if (names[i].equals(header[j])) {
                indexes[i] = j;
                break;
            }
        }
    }
    return indexes;
}

Leer filas CSV de un archivo

Utilice este asistente cuando la fuente CSV debe cargarse en memoria antes de la generación de la tabla.

  1. Lea todas las líneas del archivo de entrada.
  2. Divida cada línea con el asistente del analizador CSV.
  3. Devuelva los valores de fila recopilados.
private static List<String[]> readCsv(Path inputFile) throws Exception {
    List<String[]> rows = new ArrayList<>();
    for (String line : Files.readAllLines(inputFile)) {
        rows.add(splitCsvLine(line));
    }
    return rows;
}

Dividir una línea CSV en valores

Use este asistente cuando una fila CSV pueda contener valores entre comillas y caracteres de comilla escapados.

  1. Itere a través de los caracteres en la línea.
  2. Rastree si el analizador está actualmente dentro de texto entre comillas.
  3. Construya la lista de valores final y devuélvala como una matriz.
private static String[] splitCsvLine(String line) {
    List<String> values = new ArrayList<>();
    StringBuilder current = new StringBuilder();
    boolean inQuotes = false;
    for (int i = 0; i < line.length(); i++) {
        char ch = line.charAt(i);
        if (ch == '"') {
            if (inQuotes && i + 1 < line.length() && line.charAt(i + 1) == '"') {
                current.append('"');
                i++;
            } else {
                inQuotes = !inQuotes;
            }
        } else if (ch == ',' && !inQuotes) {
            values.add(current.toString());
            current.setLength(0);
        } else {
            current.append(ch);
        }
    }
    values.add(current.toString());
    return values.toArray(String[]::new);
}