使用iText生成含大PdfPTable及总页码页脚的PDF问题求助
我来帮你理清楚这个逻辑!其实带总页码的页脚核心在于总页数得等整个文档都生成完才知道,所以没法一开始就直接写死,得用「先占位、后补值」的思路来实现。结合你的代码,我给你一套完整的可运行方案:
第一步:实现页脚事件处理器
我们需要继承PdfPageEventHelper,重写几个关键方法来处理页脚的绘制和总页数的填充:
class PageFooter extends PdfPageEventHelper { private PdfTemplate totalPageTemplate; private BaseFont baseFont; @Override public void onOpenDocument(PdfWriter writer, Document document) { try { // 初始化字体,这里用中文宋体避免乱码,英文场景可以换成BaseFont.HELVETICA baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); // 创建一个空白模板,用来后续填充总页数 totalPageTemplate = writer.getDirectContent().createTemplate(50, 15); } catch (Exception e) { throw new RuntimeException("初始化页脚资源失败", e); } } @Override public void onEndPage(PdfWriter writer, Document document) { PdfContentByte contentByte = writer.getDirectContent(); contentByte.saveState(); // 拼接当前页文本:"第X页,共" String currentPageText = "第" + writer.getPageNumber() + "页,共"; float textWidth = baseFont.getWidthPoint(currentPageText, 12); // 页脚位置:页面左边缘,底部下方15个单位(可以自己调整) float x = document.left(); float y = document.bottom() - 15; // 绘制当前页号部分 contentByte.beginText(); contentByte.setFontAndSize(baseFont, 12); contentByte.setTextMatrix(x, y); contentByte.showText(currentPageText); contentByte.endText(); // 把总页数模板放在当前页文本的右侧,占位置 contentByte.addTemplate(totalPageTemplate, x + textWidth, y); contentByte.restoreState(); } @Override public void onCloseDocument(PdfWriter writer, Document document) { // 文档全部生成完毕,现在可以拿到总页数了,把它写入之前的模板 try { totalPageTemplate.beginText(); totalPageTemplate.setFontAndSize(baseFont, 12); totalPageTemplate.setTextMatrix(0, 0); // writer.getPageNumber()就是最终的总页数 totalPageTemplate.showText(String.valueOf(writer.getPageNumber())); totalPageTemplate.endText(); } catch (Exception e) { throw new RuntimeException("填充总页数失败", e); } } }
第二步:主代码整合你的表格逻辑
把页脚事件注册到PdfWriter上,然后正常添加你的大表格即可(iText会自动处理表格分页,每页都会触发页脚事件):
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Document document = new Document(PageSize.A4); PdfWriter writer = PdfWriter.getInstance(document, baos); // 注册我们写的页脚事件 PageFooter pageFooter = new PageFooter(); writer.setPageEvent(pageFooter); document.open(); // 初始化你的10列大表格 PdfPTable table = new PdfPTable(10); // 这里替换成你填充表格的实际代码,比如循环添加大量行 for (int row = 0; row < 100; row++) { for (int col = 0; col < 10; col++) { table.addCell("单元格 " + (row + 1) + "-" + (col + 1)); } } // 把表格添加到文档,iText会自动处理分页 document.add(table); // 关闭文档和writer,这一步会触发onCloseDocument方法填充总页数 document.close(); writer.close(); // 后续你可以把baos中的内容输出为PDF文件,比如: // FileOutputStream fos = new FileOutputStream("带页脚的表格.pdf"); // baos.writeTo(fos); // fos.close();
关键逻辑说明
- PdfTemplate的作用:相当于一个“动态占位符”,因为总页数只有在文档完全生成后才能确定,所以先在每页页脚放这个模板,等文档写完再把总页数填进去。
- PageEvent的三个方法:
onOpenDocument:初始化字体和模板,确保整个文档生命周期内可用。onEndPage:每一页结束时触发,绘制当前页号并放置总页数模板。onCloseDocument:文档关闭前触发,此时已经知道总页数,把它写入模板。
- 大表格自动分页:
PdfPTable会自动拆分跨页的内容,不需要你手动处理,每页都会自动触发页脚事件,所以所有页面都会有正确的页脚。
内容的提问来源于stack exchange,提问作者El_Merendero
相关产品推荐
相关产品推荐

