You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在iText 7中获取当前页码?(替代iText 5中PdfWriter的getCurrentPageNumber()方法)

在iText 7中获取当前页码并处理分页逻辑(替代iText 5的getCurrentPageNumber())

我刚帮朋友解决过类似的iText 5到7的迁移问题,针对你需要获取当前页码并处理分页逻辑的需求,这里有两种实用的解决方案,适配你全程复用同一个Document实例的场景:


方法1:通过添加内容前后对比页码判断分页

这种方法简单直接,适合需要事后判断是否发生分页的场景(比如内容添加后才知道是否分页,然后追加标题)。

核心思路是:利用PdfDocument.getNumberOfPages()获取已完成的页面数,在添加可能分页的内容前后分别记录页码,对比后判断是否发生了分页。

代码示例

// 修改你的buildBody方法
public void buildBody(PdfData pdfData, Document document) {
    PdfDocument pdfDocument = document.getPdfDocument();
    
    // 记录添加内容前的页码
    int pageBefore = pdfDocument.getNumberOfPages();
    
    // 添加可能触发分页的内容
    Paragraph longContent = new Paragraph(pdfData.getLongBillContent())
            .setFontSize(12)
            .setMarginBottom(10);
    document.add(longContent);
    
    // 对比页码,判断是否分页
    int pageAfter = pdfDocument.getNumberOfPages();
    if (pageAfter > pageBefore) {
        // 分页触发,添加额外标题
        Paragraph sectionHeader = new Paragraph("后续账单明细")
                .setBold()
                .setFontSize(14)
                .setMarginTop(15);
        document.add(sectionHeader);
    }
    
    // 继续添加其他内容...
}

注意事项

  • 当内容刚好填满当前页时,iText 7会自动创建新页面,因此pageAfter会比pageBefore大1,这个判断逻辑是可靠的。
  • 不需要额外维护状态,代码侵入性低。

方法2:利用页面事件跟踪当前页码(提前预判分页)

如果你需要提前判断内容是否会超出当前页面(比如在添加内容前就决定是否要插入分页和标题),可以结合你已经在使用的页面事件处理器,维护一个全局的页码跟踪器。

步骤1:创建页码跟踪器类

// 简单的状态跟踪类,确保全程复用同一实例
public class PageNumberTracker {
    private int currentPage = 0;

    public int getCurrentPage() {
        return currentPage;
    }

    public void updateCurrentPage(int newPageNum) {
        this.currentPage = newPageNum;
    }
}

步骤2:修改页面事件处理器更新页码

在START_PAGE事件触发时,iText已经完成了新页面的创建,此时可以获取到当前正确的页码:

public class StartPageHandler<T> implements IEventHandler {
    private final PdfData pdfData;
    private final Document document;
    private final PageNumberTracker pageTracker;

    // 修改构造函数,传入页码跟踪器
    public StartPageHandler(PdfData pdfData, Document document, PageNumberTracker pageTracker) {
        this.pdfData = pdfData;
        this.document = document;
        this.pageTracker = pageTracker;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfDocument pdfDoc = docEvent.getDocument();
        
        // 更新当前页码(START_PAGE触发时,新页面已经创建,getNumberOfPages()就是当前页号)
        pageTracker.updateCurrentPage(pdfDoc.getNumberOfPages());
        
        // 你的原有页眉逻辑
        Rectangle rectangle = new Rectangle(51, 750, 500, 60);
        document.setRenderer(new ColumnDocumentRenderer(document, new Rectangle[]{rectangle}));
        document.add(new LineSeparator());
        document.add(new Paragraph(pdfData.getBillHeaderInfo()));
    }
}

步骤3:在buildBody中预判分页

通过当前页面的剩余空间和内容高度对比,判断是否会分页:

public void buildBody(PdfData pdfData, Document document, PageNumberTracker pageTracker) {
    int currentPage = pageTracker.getCurrentPage();
    if (currentPage == 0) {
        // 处理初始状态(还没触发START_PAGE的情况)
        currentPage = 1;
    }

    // 获取当前页面的剩余空间
    PdfPage page = document.getPdfDocument().getPage(currentPage);
    Rectangle pageSize = page.getPageSizeWithRotation();
    float usedBottom = document.getRenderer().getCurrentArea().getBBox().getBottom();
    float remainingHeight = pageSize.getHeight() - document.getBottomMargin() - usedBottom;

    // 计算待添加内容的高度
    Paragraph longContent = new Paragraph(pdfData.getLongBillContent());
    float contentHeight = longContent.createRendererSubTree()
            .setParent(document.getRenderer())
            .calculateMaxHeight();

    // 判断内容是否会超出当前页
    if (contentHeight > remainingHeight) {
        // 先插入分页,再添加标题
        document.add(new AreaBreak());
        Paragraph sectionHeader = new Paragraph("新账单段标题")
                .setBold()
                .setFontSize(14)
                .setMarginTop(10);
        document.add(sectionHeader);
    }

    // 添加内容
    document.add(longContent);
}

注意事项

  • 这个方法可以提前预判分页,适合需要在内容前插入标题的场景。
  • 要确保PageNumberTracker在整个PDF生成过程中是同一个实例,避免状态混乱。

初始化时的整合示例

public void generateMonthlyBill(String filename, PdfData pdfData) throws IOException {
    PdfWriter writer = new PdfWriter(new FileOutputStream(filename));
    PdfDocument pdfDocument = new PdfDocument(writer);
    Document document = new Document(pdfDocument, PageSize.A4);
    document.setMargins(235, 35, 0, 38);

    // 创建页码跟踪器
    PageNumberTracker pageTracker = new PageNumberTracker();

    // 注册事件处理器,传入跟踪器
    pdfDocument.addEventHandler(PdfDocumentEvent.START_PAGE, new StartPageHandler<>(pdfData, document, pageTracker));
    pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new EndPageHandler<>(pdfData, document, pageTracker));

    // 调用buildBody
    buildBody(pdfData, document, pageTracker);

    document.close();
}

内容的提问来源于stack exchange,提问作者skorpyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:59:08