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

使用Apache POI XWPF生成的Word转PDF后丢失页码问题求助

解决Apache POI生成Word转PDF后页码丢失的问题

嘿,这个坑我之前踩过!你遇到的问题本质是:Apache POI生成的Word里的动态页码(不管是用PgNum标签还是PAGE域),在你用的PdfConverter转换时没有被解析——这类工具大多只渲染Word里的静态文本,不会执行Word的域计算,所以转PDF后页码就丢了。

下面给你两个实用的解决方案:

方法1:改用支持域解析的PDF转换工具

最靠谱的免费方案是用docx4j来处理Word转PDF,它能正确识别并解析Word中的动态页码域。

示例代码如下:

import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class WordToPdfWithPageNumbers {
    public static void main(String[] args) throws Exception {
        // 加载你用POI生成的Word文档
        WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File("your-generated-document.docx"));
        
        // 配置PDF转换参数
        FOSettings foSettings = Docx4J.createFOSettings();
        foSettings.setWmlPackage(wordMLPackage);
        
        // 输出PDF
        try (OutputStream out = new FileOutputStream(new File("output-with-pages.pdf"))) {
            Docx4J.toFO(foSettings, out, Docx4J.FLAG_EXPORT_PREFER_XSL);
        }
    }
}

这个方案能完美保留Word里的页码,因为docx4j会完整处理Word的域逻辑。

方法2:手动插入静态页码(适合简单场景)

如果不想引入新的依赖,可以先计算文档总页数,然后给页脚插入静态的页码文本。这个方法适合内容固定、生成后不需要修改的文档:

步骤大概是这样:

  1. 先写完所有Word内容,计算总页数(可以通过估算段落数或者用POI的文档属性获取)
  2. 遍历页脚,替换动态标记为静态页码文本

示例代码片段:

// 先完成所有内容写入后,计算总页数(这里用段落数估算,你可以根据实际排版调整)
int totalPages = (document.getParagraphs().size() / 18) + 1; // 假设每页18个段落

// 获取默认页脚
XWPFFooter footer = headerFooterPolicy.getFooter(XWPFHeaderFooterPolicy.DEFAULT);
for (XWPFParagraph para : footer.getParagraphs()) {
    for (XWPFRun run : para.getRuns()) {
        // 替换原有的"Page "文本,插入完整的页码信息
        if (run.getText(0) != null && run.getText(0).equals("Page ")) {
            // 单页文档直接写1,多页场景需循环处理每一页的页脚
            run.setText("Page 1 of " + totalPages, 0);
        }
    }
}

注意:这个方法的页码是静态的,后续修改Word内容后页码不会自动更新,但如果只是生成后直接转PDF,完全够用。

另外,你原来的代码里同时用了两种插入页码的方式(域和PgNum标签),建议只保留一种标准方式,比如用PAGE域的正确写法:

// 正确插入PAGE域的代码
XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);
XWPFParagraph paragraph = footer.createParagraph();
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run = paragraph.createRun();
run.setFontSize(8);
run.setItalic(true);
run.setColor(header_color);
run.setText("Page ");

// 添加PAGE域
CTP ctp = paragraph.getCTP();
CTFldSimple fldSimple = ctp.addNewFldSimple();
fldSimple.setInstr("PAGE \\* MERGEFORMAT");
// 添加占位符文本,Word会自动替换成实际页码
CTR ctr = ctp.addNewR();
CTText ctText = ctr.addNewT();
ctText.setStringValue("1");

这样生成的Word在本地打开会正确显示页码,但还是那句话,转换工具得支持域解析才能在PDF里显示。

如果坚持用你原来的PdfConverter,可以去查它的官方文档,看是否有开启域解析的配置选项——有些工具默认不开启这个功能,需要手动设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 06:59:12