简体   繁体   English

iText - 如何找到最后一行分为下一页

[英]iText - how to find last row is split into next page

I have group of tables with dynamic rows. 我有一组动态行表。 There are some scenarios where a table is splitted between pages. 在某些情况下,表格在页面之间分割。 In some scenarios, only the last row is split into next page. 在某些情况下,只有最后一行被拆分为下一页。 Suppose if a table has 10 rows, the rows 1 thru 9 are displayed in page 1 and row 10 is displayed in page 2. 假设一个表有10行,第1行到第9行显示在第1页,第10行显示在第2页。

I am looking for a solution to have a page break (document.newpage()) to happen to move the entire table to next page in this scenario. 我正在寻找一个解决方案,让分页符(document.newpage())在这种情况下将整个表移动到下一页。 I tried below code and it was working for some scenarios but not for all. 我尝试了下面的代码,它适用于某些场景,但不适用于所有场景。 I would like to find out when a table last row is going to split so I can add page break to move the complete table to next page to avoid last row orphan. 我想知道什么时候表的最后一行要拆分,所以我可以添加分页符来将整个表移动到下一页以避免最后一行孤儿。

public class SplitItextLastRow {

final static private String BODY_FONT = FontFactory.getFont("Arial").getFamilyname();

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:/SplitItext.pdf"));
        document.open();
        document.setPageSize(PageSize.LETTER);
        document.setMargins(16, 14, 14, 14);

        int[] maxCountRows = new int[] { 3, 9, 2, 3, 7, 9, 2, 4, 5, 4, 9, 7, 6, 5, 4, 6, 8, 3 };

        for (int k = 1; k <= maxCountRows.length; k++) {

            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);
            addHeader(table, "Header Row continued " + k, BaseColor.LIGHT_GRAY);
            addHeader(table, "Header Row normal " + k, BaseColor.LIGHT_GRAY);

            for (int i = 1; i < maxCountRows[k - 1]; i++) {
                StringBuilder sb = new StringBuilder();
                for (int p = 0; p < maxCountRows[k - 1] * 6; p++) {
                    sb.append("Text Row ");
                }
                add(table, sb.toString() + i, BaseColor.WHITE);
            }

            float verticalPosition = writer.getVerticalPosition(true);
            System.out.println("------Table " + k);
            if ((verticalPosition - table.getTotalHeight()) <= document.bottom()) {
                System.out.println("........................................Last Row splitted");
            }

            document.add(table);
        }

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

}

private static void addHeader(PdfPTable table, String text, BaseColor color) {
    PdfPCell pdfCellHeader = new PdfPCell();
    pdfCellHeader.setBackgroundColor(color);
    pdfCellHeader.addElement(new Paragraph(new Phrase(text, FontFactory.getFont(BODY_FONT, 8f, BaseColor.BLUE))));
    table.addCell(pdfCellHeader);
}

private static void add(PdfPTable table, String text, BaseColor color) {
    PdfPCell pdfCellHeader = new PdfPCell();
    pdfCellHeader.setBackgroundColor(color);
    pdfCellHeader.addElement(new Paragraph(new Phrase(text, FontFactory.getFont(BODY_FONT, 5f, BaseColor.GREEN))));
    table.addCell(pdfCellHeader);
}

} }

Yeah, it works as following: 是的,它的工作原理如下:

At the beginning of your loop for (int k = 1; ... you have to add: 在你的循环开始时for (int k = 1; ...你必须添加:

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

and at it's end, you replace the document.add(table); 最后,你替换document.add(table); with: 有:

outerTable.addCell(new PdfPCell(table));
document.add(outerTable);

And this is it... :-) 这就是...... :-)
You should then remove your debug outputs and you can remove the "continued" header thing and its corresponding table.setSkipFirstHeader(true); 然后你应该删除你的调试输出,你可以删除“继续”标题和它对应的table.setSkipFirstHeader(true); . It's enough that you have table.setHeaderRows(1); 你有table.setHeaderRows(1);足够了table.setHeaderRows(1); .

To be a bit lazier, since your original table has only one column as well, you can create your outerTable with PdfPTable outerTable = new PdfPTable(table); 是有点懒惰,因为你原来的表只有一列,以及,你可以创建你outerTablePdfPTable outerTable = new PdfPTable(table); after you initialized your table with its width and spacings. 用你的宽度和间距初始化你的table后。 But you have to create it before you add your content to your table . 但是,在将内容添加到table之前,必须先创建它。

I tried Johannes' solution, but it did not work, I don't know why. 我试过约翰内斯的解决方案,但它不起作用,我不知道为什么。 Anyways, I found an own solution. 无论如何,我找到了自己的解决方案。 I tested it with some random scenarios and it worked. 我用一些随机场景对它进行了测试,结果很有效。 The solution I found is to put the code below before adding the table to the document with document.add(table) . 我找到的解决方案是在使用document.add(table)将表添加到文档之前放下面的代码。

int headerRowsCount = table.getHeaderRows();
float headerRowsHeight = 0f;
for (int j = 0; j < headerRowsCount; j++) {
    headerRowsHeight += table.getRowHeight(j);
}
float totalTableHeight = table.getTotalHeight() - headerRowsHeight;
float lastRowHeight = table.getRowHeight(table.getRows().size() - 1);
float tableHeightExceptLastRow = totalTableHeight - lastRowHeight + document.bottom();
float tableGap = verticalPosition - tableHeightExceptLastRow;
boolean lastRowSplit = (tableGap > -35 && (tableGap < lastRowHeight) && tableHeightExceptLastRow > 0);
if (lastRowSplit) {
    document.newPage();
}

Here's the complete working example as explained here ... I used iText 2.1.7. 下面是完整的工作示例说明这里 ...我用的iText 2.1.7。

import java.awt.Color;
import java.io.FileOutputStream;

import com.lowagie.text.Document;
import com.lowagie.text.FontFactory;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfWriter;

public class SplitItextLastRow
{
    final static private String BODY_FONT = FontFactory.getFont("Arial").getFamilyname();

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

            int[] maxCountRows = new int[]
            {
                    3, 9, 2, 3, 7, 9, 2, 4, 5, 4, 9, 7, 6, 5, 4, 6, 8, 3
            };

            for (int k = 1; k <= maxCountRows.length; k++)
            {
                PdfPTable table = new PdfPTable(1);
                table.setSpacingAfter(0);
                table.setSpacingBefore(0);
                table.setTotalWidth(document.right() - document.left());
                table.setLockedWidth(true);

                PdfPTable outerTable = new PdfPTable(table);

                table.setHeaderRows(1);
                table.setSkipFirstHeader(true);
                addHeader(table, "Header Row continued " + k, Color.LIGHT_GRAY);
                addHeader(table, "Header Row normal " + k, Color.LIGHT_GRAY);

                for (int i = 1; i < maxCountRows[k - 1]; i++)
                {
                    StringBuilder sb = new StringBuilder();
                    for (int p = 0; p < (maxCountRows[k - 1] * 6); p++)
                    {
                        sb.append("Text Row ");
                    }
                    add(table, sb.toString() + i, Color.WHITE);
                }

                float verticalPosition = writer.getVerticalPosition(true);
                System.out.println("------Table " + k);
                if ((verticalPosition - table.getTotalHeight()) <= document.bottom())
                {
                    System.out.println("........................................Last Row splitted");
                }

                outerTable.addCell(new PdfPCell(table));
                document.add(outerTable);
            }

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

    private static void addHeader(final PdfPTable table, final String text, final Color color)
    {
        PdfPCell pdfCellHeader = new PdfPCell();
        pdfCellHeader.setBackgroundColor(color);
        pdfCellHeader.addElement(new Paragraph(new Phrase(text, FontFactory.getFont(BODY_FONT, 8f,
                Color.BLUE))));
        table.addCell(pdfCellHeader);
    }

    private static void add(final PdfPTable table, final String text, final Color color)
    {
        PdfPCell pdfCellHeader = new PdfPCell();
        pdfCellHeader.setBackgroundColor(color);
        pdfCellHeader.addElement(new Paragraph(new Phrase(text, FontFactory.getFont(BODY_FONT, 5f,
                Color.GREEN))));
        table.addCell(pdfCellHeader);
    }
}

And the output it produces is here . 它产生的输出就在这里 Isn't that what you expected to achieve? 这不是你期望实现的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM