1

I am trying to create a pdf file in Java using PDFBox. The file is to contain a large table with 2 columns. To render tables insidde the pdf, I am using another library: boxable.

The file is successfully created and the table is also rendered. But problem arise when one of the row contain large data. In that case, the table splits and does not display data properly:

enter image description hereenter image description hereenter image description hereenter image description here

The large row is moved automatically to a new page while the first page remains empty. In the second page, the row ends abruptly at New task entered for testing without displaying entire data in the cell. This is a recurring issue and is not specific to this case.

Row<PDPage> headerRow;
Row<PDPage> row;
Cell<PDPage> cell;
int i;

headerRow = table.createRow(15f);

cell = headerRow.createCell(30, "Goal Category");
cell.setFont(PDType1Font.HELVETICA);
cell.setFontSize(11);
cell = headerRow.createCell(70, "My Goal");
cell.setFont(PDType1Font.HELVETICA);
cell.setFontSize(11);
table.addHeaderRow(headerRow);

for(i=0;i<goals.size();i++)
{
    ArrayList<String> goal=goals.get(i);
    row = table.createRow(12);
    cell = row.createCell(30, goal.get(0));
    cell.setFont(PDType1Font.HELVETICA);
    cell.setFontSize(11);
    System.out.println("My Goal="+goal.get(1));
    cell = row.createCell(70, goal.get(1));
    cell.setFont(PDType1Font.HELVETICA);
    cell.setFontSize(11);

}
table.draw();

I am looking for a solution or an alternate way to render tables in pdf.

HBK
  • 735
  • 1
  • 11
  • 29
  • Just from reading, this seems a bug needing some investigation on the side of boxable. First try to have a table cell of at most the lines that would fit on a page; by introducing "carry over" cells of a row. As long as a row has any cell carry overs, add a new row. – Joop Eggen Nov 20 '17 at 07:49
  • @JoopEggen How do we fix max lines for a cell?? There can be many cells with variable lines and in that case the max lines would also vary – HBK Nov 20 '17 at 07:51
  • I sketchy added some patch code below.. – Joop Eggen Nov 20 '17 at 12:01
  • If it is a bug in boxable, then you should open an issue here: https://github.com/dhorions/boxable/issues – Tilman Hausherr Nov 20 '17 at 12:25
  • @TilmanHausherr I thought of that but found issues pending since early 2016 and hence changed my mind – HBK Nov 20 '17 at 12:27

2 Answers2

1

you can use this snippet to split your large text into chunks which fit in each page (tested):

private static final int MAX_LINES = 95;
...
String[] lignes = ch.split("\r?\n");
StringBuilder sb = new StringBuilder();
int nblignes = 0;

for (String ligne : lignes) {
    nblignes++;
    sb.append(ligne).append("\n");

    if (nblignes % MAX_LINES == 0) {
        row = table.createRow(10);
        cell = row.createCell(100, sb.toString());
        sb = new StringBuilder();
    }
}

if (sb.length() > 0) {
    row = table.createRow(10);
    cell = row.createCell(100, sb.toString());
}
khaliloo
  • 11
  • 1
0

It seems the libraries cannot handle page breaks satisfactory. The commercial work horse itext is worth mentioning in this case.

Preparing the table yourself for page breaks, doing a preemptive split of a row in several rows might be a pragmatic solution.

Below rows will be restricted to at most the lines per page, relying on that then the page breaks work correctly.

public int lineno;
public int linesPerPage = 50; // Not counting header lines.

public void splitRow(List<String> multilineRow) {

Split single row cell values in multiple lines (word wrap ignored here):

    List<List<String>> sublines = new ArrayList<>(multilineRow.size());
    int sublineCount = 0;
    for (String cellValue : multilineRow) {
        List<String> column = Arrays.asList(cellValue.split("\r?\n"));
        sublines.add(column);
        sublineCount = Math.max(sublineCount, column.size());
    }

Then we have sublines per column, and bundle several sublines into one row:

    for (int sublineI = 0; sublineI < sublineCount; ) {
        int linesPerRow = Math.min(sublineCount, linesPerPage - lineno);
        if (linesPerRow <= 0) {
            break;
        }
        int sublineI2 = sublineI + linesPerRow;

        List<String> cellValues = new ArrayList<>(multilineRow.size());
        for (int j = 0; j < multilineRow.size(); ++j) {
            List<String> column = sublines.get(j);
            String value = "";
            if (sublineI < column.size()) {
                List<String> vs = column.subList(sublineI,
                                      Math.min(sublineI2, column.size()));
                value = vs.stream().collect(Collectors.joining("\n"));
            }
            cellValues.add(value);
        }
        createRow();
        ++lineno;
        .... fill with cellValues.get(0) and get(1)
        sublineI = sublineI2;
        if (lineno >= linesPerPage) {
            lineno = 0
        }
        //if (sublineI < sublineCount) {
        //    Page break / createHeader;
        //}
    }
}

This is not a very solid solution. But it might provide a patch until the library bug is removed.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138