You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring Boot中如何向Word文档段落动态填充数据并保留原模板格式

Spring Boot中如何向Word文档段落动态填充数据并保留原模板格式

你说的这个情况我太有共鸣了!之前帮同事调过类似的需求,要么填完数据后字体、行距全乱套,要么格式保住了但数据死活插不对位置,尤其是带自定义样式、图片的复杂模板,简直让人头大。下面给你分享几个亲测有效的解决思路,都是实打实踩坑踩出来的:

一、选对工具库是关键

Java生态里处理Word文档,常用的就是Apache POI和Docx4j,这俩我都用过,给你说说各自的用法和优势:

1. Apache POI:轻量灵活,适合简单模板

POI是很多人最先接触的库,但要注意不能用简单的字符串替换整个段落——那样会直接把段落的格式(缩进、行距、字体)全部清空。正确的姿势是操作到「Run」级别,也就是Word里自带格式的最小文本块:

  • 先在模板里给要替换的内容设占位符,比如${userName}${orderNo},而且要保证占位符单独在一个Run里(别和其他文本混在一起,不然替换时会带乱格式)
  • 加载模板后,遍历每个段落,再遍历段落里的每个Run,判断Run的文本里是否包含占位符,直接替换Run里的文本,这样Run的格式(字体大小、颜色、加粗)会完全保留

给你贴个我之前写的简化版代码:

// 加载本地模板文档,也可以从资源文件里读
XWPFDocument doc = new XWPFDocument(new FileInputStream("template.docx"));

// 遍历文档中所有段落
for (XWPFParagraph para : doc.getParagraphs()) {
    // 遍历段落中的每个带格式的文本块(Run)
    for (XWPFRun run : para.getRuns()) {
        String runText = run.getText(0);
        if (runText != null) {
            // 替换占位符,第二个参数0表示覆盖原文本,保留Run格式
            if (runText.contains("${userName}")) {
                run.setText(runText.replace("${userName}", "张三"), 0);
            }
            if (runText.contains("${orderNo}")) {
                run.setText(runText.replace("${orderNo}", "ORD20240520001"), 0);
            }
        }
    }
}

// 输出到文件,Spring Boot里可以直接写到response的输出流里供下载
doc.write(new FileOutputStream("filled_template.docx"));
doc.close();

2. Docx4j:更专业的OpenXML操作,复杂模板首选

如果你的模板里有表格、内容控件、图片这类复杂元素,Docx4j比POI更靠谱,它是完全基于Word的OpenXML标准来操作的,替换数据时几乎不会破坏原格式:

  • 模板里同样用${变量名}当占位符,先打开模板,用VariablePrepare.prepare(docx)预处理文档
  • 然后把要替换的键值对放进一个Map里,直接调用MainDocumentPart.variableReplace(map)就能完成替换,全程会保留原有的所有格式,包括表格的边框、单元格样式、图片位置

举个简单的代码例子:

// 加载模板
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new File("template.docx"));
MainDocumentPart mainPart = wordMLPackage.getMainDocumentPart();

// 预处理模板,确保变量能被正确识别
VariablePrepare.prepare(wordMLPackage);

// 准备要替换的变量
Map<String, String> variables = new HashMap<>();
variables.put("userName", "张三");
variables.put("orderNo", "ORD20240520001");

// 执行替换,保留原格式
mainPart.variableReplace(variables);

// 输出文档
wordMLPackage.save(new File("filled_template.docx"));

二、避坑小Tips

  • 模板里的占位符一定要单独占一个Run:你可以打开Word的「开始」选项卡,点击「显示/隐藏编辑标记」,就能看到每个Run的边界,确保${userName}是一个独立的标记块
  • 不要用字符串替换整个文档的XML内容:这种操作看似简单,但很容易破坏Word的内部XML结构,导致文档打不开或者格式全乱
  • 如果是Spring Boot项目,要注意把模板放在resources目录下,读取时用ResourceLoader来加载,避免路径问题

内容来源于stack exchange

火山引擎 最新活动