Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iText - avoid last row not to cut tables on page split to next page

I am working on itext 5 using java. I have pages with mutiple tables with dynamic rows. In some instances, the table last row is splitted into next page with the folowing header. I am using setHeaderRows() and setSkipFirstHeader() to manage continuation of next page. The last row has enough space to fit on earlier page. I would like to fit that last row in same page instead of next page.

For example, on page 1, the last row is splitted into first row of next page. Instead I would like to fit that row in page 1 so save one extra page with all blanks.

I tried using setExtendLastRow(), but its not working. Does anyone know how to fix this problem. I am attaching a working sample code.

public class ProposalItextSplitLastRow {
 public static void main(String[] args) {
    try {
        Document document = new Document();
        document.setPageSize(PageSize.LETTER);
        document.setMargins(16, 14, 14, 14);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:/SplitLastRow.pdf"));
        document.open();
        document.setPageSize(PageSize.LETTER);
        document.setMargins(16, 14, 42, 38);

        for (int m = 1; m < 20; m++) {

            int row = 0;
            PdfPTable table = new PdfPTable(1);
            table.setSpacingAfter(0);
            table.setSpacingBefore(0);
            table.setWidthPercentage(100);

            table.setHeaderRows(1);
            table.setSkipFirstHeader(true);
            add(table, "Header Row continued " + m, BaseColor.LIGHT_GRAY, row++);
            add(table, "Header Row normal " + m, BaseColor.LIGHT_GRAY, row++);

            add(table, "Text Row 1 ", BaseColor.WHITE, row++);
            add(table, "Text Row 2 ", BaseColor.WHITE, row++);
            add(table, "Text Row 3 ", BaseColor.WHITE, row++);

            addPadding(table);

            document.add(table);
        }

        document.close();
    } catch (Exception de) {
        de.printStackTrace();
    }
}

private static void add(PdfPTable table, String text, BaseColor color, int row) {
    PdfPCell pdfCellHeader = new PdfPCell();
    pdfCellHeader.setBackgroundColor(color);
    pdfCellHeader.addElement(new Paragraph(new Phrase(text)));
    table.addCell(pdfCellHeader);
}

private static void addPadding(PdfPTable table) {
    PdfPCell cell = new PdfPCell();
    cell.setFixedHeight(2f);
    cell.setBorder(Rectangle.NO_BORDER);
    cell.setColspan(table.getNumberOfColumns());
    table.addCell(cell);
}
}
like image 854
Chandra Shekar Avatar asked May 18 '13 01:05

Chandra Shekar


2 Answers

I had to execute the example to understand your question. You confused me by talking about a header that isn't a header (the rows with "Header Row normal" aren't header rows!) and your reference to setExtendLastRow() didn't help either (mentioning that method doesn't make sense to me; it's very confusing).

This being said, the solution to your problem is a no-brainer. I've rewritten the main class:

public static void main(String[] args) {
    try {
        Document document = new Document();
        document.setPageSize(PageSize.LETTER);
        document.setMargins(16, 14, 14, 14);
        PdfWriter writer = PdfWriter.getInstance(document,
                new FileOutputStream("SplitLastRow.pdf"));
        document.open();
        document.setPageSize(PageSize.LETTER);
        document.setMargins(16, 14, 42, 38);

        for (int m = 1; m < 20; m++) {

            int row = 0;
            PdfPTable table = new PdfPTable(1);
            table.setSpacingAfter(0);
            table.setSpacingBefore(0);
            table.setTotalWidth(document.right() - document.left());
            table.setLockedWidth(true);

            table.setHeaderRows(1);
            table.setSkipFirstHeader(true);
            add(table, "Header Row continued " + m, BaseColor.LIGHT_GRAY, row++);
            add(table, "Header Row normal " + m, BaseColor.LIGHT_GRAY, row++);

            add(table, "Text Row 1 ", BaseColor.WHITE, row++);
            add(table, "Text Row 2 ", BaseColor.WHITE, row++);
            add(table, "Text Row 3 ", BaseColor.WHITE, row++);

            addPadding(table);
            if (writer.getVerticalPosition(true) - table.getRowHeight(0) - table.getRowHeight(1) < document.bottom()) {
                document.newPage();
            }
            document.add(table);
        }

        document.close();
    } catch (Exception de) {
        de.printStackTrace();
    }
}

Make sure you define a total width instead of a width percentage, and lock the width. As documented (and as common sense tells you), a PdfPTable object doesn't know its actual width if you define a width percentage. It goes without saying that you can't calculate the height of a table that doesn't know it's actual width.

Then use getVerticalPosition() method to get the current position of the cursor, and check if the first two rows fit on the page. If they don't go to a new page before adding the table. If you want to check if the complete table fits, use the getTotalHeight() method instead of the getRowHeight() method.

like image 55
Bruno Lowagie Avatar answered Nov 17 '22 02:11

Bruno Lowagie


you can table.setKeepRowsTogather(true);

table.setHeaderRows(1) as well alongwith it

setKeepRowsTogather() checks if it can keep all the rows in page but splits the rows in case the table spans multiple pages. In that case setHeaderRows(1) will put the header rows again in the next page.

like image 28
Subhadeep Ray Avatar answered Nov 17 '22 02:11

Subhadeep Ray