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

Apache POI与XDOCREPORT替换占位符后转PDF报空指针异常

解决docx占位符替换后转PDF抛出NullPointerException的问题

我之前也碰到过一模一样的坑,原始docx能正常转PDF,但替换占位符后就直接炸了,排查下来主要是两个操作导致xdocreport解析文档时触发了空指针:

问题根源分析

  1. 多余的doc.createStyles()调用
    你代码里的doc.createStyles()会直接重置文档的样式集合,把原始docx里的内置样式全部清空重建。而xdocreport在转换PDF时严重依赖文档的原始样式信息,样式被清空后,转换过程中找不到对应的样式对象就会抛出NullPointerException。

  2. 未处理空文本的边界情况
    当r.getText(0)返回null时(比如某些空的文本run),StringSubstitutor.replace(text)会返回null,接着r.setText(replacedText, 0)会把这个run的文本设为null,这种异常的文本节点会让xdocreport的解析逻辑直接崩溃。

修复后的完整代码示例

// 读取待处理的docx文件
FileInputStream fis = new FileInputStream(COPIED);
XWPFDocument doc = new XWPFDocument(fis);
// 移除这行危险代码:doc.createStyles();

// 替换段落中的占位符
for (XWPFParagraph p : doc.getParagraphs()) {
    List<XWPFRun> runs = p.getRuns();
    if (runs != null) {
        for (XWPFRun r : runs) {
            String text = r.getText(0);
            // 跳过空文本的run,避免设置null值
            if (text == null) {
                continue;
            }
            StringSubstitutor substitutor = new StringSubstitutor(fieldsForReport);
            String replacedText = substitutor.replace(text);
            r.setText(replacedText, 0);
        }
    }
}

// 替换表格中的占位符
for (XWPFTable tbl : doc.getTables()) {
    for (XWPFTableRow row : tbl.getRows()) {
        for (XWPFTableCell cell : row.getTableCells()) {
            for (XWPFParagraph p : cell.getParagraphs()) {
                for (XWPFRun r : p.getRuns()) {
                    String text = r.getText(0);
                    if (text == null) {
                        continue;
                    }
                    StringSubstitutor substitutor = new StringSubstitutor(fieldsForReport);
                    String replacedText = substitutor.replace(text);
                    r.setText(replacedText, 0);
                }
            }
        }
    }
}

// 保存修改后的文档,注意关闭输出流避免文件损坏
FileOutputStream fos = new FileOutputStream(COPIED);
doc.write(fos);
fos.close();
doc.close();

// 执行PDF转换
FileInputStream pdfFis = new FileInputStream(COPIED);
XWPFDocument document = new XWPFDocument(pdfFis);
PdfOptions options = PdfOptions.create();
PdfConverter converter = (PdfConverter) PdfConverter.getInstance();
converter.convert(document, new FileOutputStream(DEST), options);
document.close();
pdfFis.close();

额外验证建议

  1. 替换保存后的docx文件,先手动用Word打开,确认文档没有损坏、样式正常显示
  2. 如果还是有问题,可以检查fieldsForReport中的占位符是否包含特殊字符(比如换行、制表符),某些特殊格式可能会干扰xdocreport的解析逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:56:55