我一直在寻找答案,但无法找到一个好的教程。我正在使用Java itext生成pdf。我有一张桌子,可以打印超过50行,大约2页。在继续打印列表之前,我需要将上一页的最后5行打印到下一页。
Example:
row 31
row 32
row 33
row 34
row 35
row 36
--end of page 1--
row 32
row 33
row 34
row 35
row 36
row 37
关于如何做到这一点的任何想法?
Currently it prints like this:
row 35
row 36
--end of page 1--
row 37
row 38
代码:(专注于启动循环,不要介意那些标题)
PdfPTable table = new PdfPTable(4);
table.setWidthPercentage(97);
table.setWidths(new float[] {10, 45, 25, 25});
PdfPCell c1 = new PdfPCell(new Phrase("Logo", FontFactory.getFont(FontFactory.TIMES_ROMAN, 14)));
c1.setPadding(5);
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setVerticalAlignment(Element.ALIGN_CENTER);
c1.setBorder(0);
c1.setColspan(4);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("09/01/2013 - 09/15/2013", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setPadding(5);
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setVerticalAlignment(Element.ALIGN_CENTER);
c1.setBorder(0);
c1.setColspan(4);
c1.setPaddingBottom(20);
table.addCell(c1);
//start header
c1 = new PdfPCell(new Phrase(" ", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setPaddingBottom(5);
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setBackgroundColor(WebColors.getRGBColor("#99CCFF"));
c1.setBorder(1);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("Name", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setPaddingBottom(5);
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setBackgroundColor(WebColors.getRGBColor("#99CCFF"));
c1.setBorder(1);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("Number", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setPaddingBottom(5);
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setBackgroundColor(WebColors.getRGBColor("#99CCFF"));
c1.setBorder(1);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("Amount", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setPaddingBottom(5);
c1.setHorizontalAlignment(Element.ALIGN_RIGHT);
c1.setBackgroundColor(WebColors.getRGBColor("#99CCFF"));
c1.setBorder(1);
table.addCell(c1);
//end header
//start for loop
for(int a=0; a<50; a++)
{
int border=0;
if(a%5==0)
{border=1;}
c1 = new PdfPCell(new Phrase((a+1)+"", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setBorder(border);
c1.setPaddingBottom(5);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("Last Name, First Name", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setHorizontalAlignment(Element.ALIGN_LEFT);
c1.setBorder(border);
c1.setPaddingBottom(5);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("1", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setHorizontalAlignment(Element.ALIGN_CENTER);
c1.setBorder(border);
c1.setPaddingBottom(5);
table.addCell(c1);
c1 = new PdfPCell(new Phrase("1", FontFactory.getFont(FontFactory.TIMES_ROMAN, 12)));
c1.setHorizontalAlignment(Element.ALIGN_RIGHT);
c1.setBorder(border);
c1.setPaddingBottom(5);
table.addCell(c1);
}
//end for loop
subCatPart.add(table);
答案 0 :(得分:1)
使用document.add()
无法实现此目的;相反,您需要使用writeSelectedRows()
方法编写特定行。例如,参见RepeatLastRows方法。
在这个例子中,我有一个包含99行的表。如果我使用document.add()
将此表添加到文档中,则需要3页,第三页只显示3行。您希望此页面显示5行,重复上一页的2行。
这是如何做到的,假设我们有一个边距为36pt的A4页面。这意味着可用表面测量523乘770 pt:
// we create a table that spans the width of the page and that has 99 rows
PdfPTable table = new PdfPTable(1);
table.setTotalWidth(523);
for (int i = 1; i < 100; i++)
table.addCell("row " + i);
请注意,我设置了总宽度。如果在未指定宽度的情况下使用writeSelectedRows()
,则会出现异常。
我们初始化一些参数:
PdfContentByte canvas = writer.getDirectContent();
int currentRowStart = 0;
int currentRow = 0;
int totalRows = table.getRows().size();
只要currentRow
低于totalRows
,我们就会创建一个循环:
while (true) {
// available height of the page
float available_height = 770;
// how many rows fit the height?
while (available_height > 0 && currentRow < totalRows) {
available_height -= table.getRowHeight(currentRow++);
}
// we stop as soon as all the rows are counted
if (currentRow == totalRows)
break;
// we draw part the rows that fit the page and start a new page
table.writeSelectedRows(currentRowStart, --currentRow, 36, 806, canvas);
document.newPage();
currentRowStart = currentRow;
}
在这个循环中,我们已经填充了两个页面:一个显示第1行到第48行,另一个显示第49到96行。当我们退出循环时,currentRow为99且currentRowStart为96(这是第97行的行索引。这意味着仅显示行97,98和99。我们想要显示5行,因此我们相应地更改currentRow
的值。
if (currentRow - currentRowStart < 5)
currentRowStart = currentRow - 5;
table.writeSelectedRows(currentRowStart, currentRow, 36, 806, canvas);
请查看生成的PDF,您会看到第三页以第95行开头(第2页已经显示的一行)。
更新:我误解了这个问题,我认为只有在最后一页上有一些孤立的行时才需要重复这些行。实际要求是每次分割表时总是重复5行。
我稍微更新了我的原始示例。见RepeatLastRows2。您更改了currentRowStart
的值,以便开始返回5行,但您忘记更新currentRow
值。因此,您不会从可用高度中减去足够的空间。
如果只有5行(或更少)适合单个页面,请确保不要反复重复相同的5行(或ArrayIndexOutOfBoundsExceptions
)。
答案 1 :(得分:0)
您可以使用最近引入的PdfPTableEventAfterSplit
,这是在需要拆分表时触发的。它在呈现当前页面之后但在下一页面启动之前触发。您可以使用它来复制下一页要重复的行。
class RepeatSplitEvent extends PdfPTableEventForwarder {
@Override
public void afterSplitTable(PdfPTable table, PdfPRow startRow, int startIdx) {
for (int i = startIdx - 5; i < startIdx; i++) {
table.getRows().add(0, table.getRow(i));
}
}
}
和
// ...
PdfPTable table = new PdfPTable(4);
table.setTableEvent(new RepeatSplitEvent());
// ...