依赖准备
确保 Maven 依赖包含以下库:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
核心实现步骤
模板准备
创建 Word 模板文档(.docx),使用 ${placeholder} 格式标记需要替换的占位符。例如:
尊敬的${name}:
您的订单编号为${orderId}。
代码实现
import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WordTemplateProcessor {
public static void processTemplate(String inputPath, String outputPath,
Map<String, String> replacements) throws IOException {
try (XWPFDocument doc = new XWPFDocument(new FileInputStream(inputPath))) {
// 替换段落占位符
for (XWPFParagraph p : doc.getParagraphs()) {
replacePlaceholders(p, replacements);
}
// 处理表格中的占位符
for (XWPFTable tbl : doc.getTables()) {
for (XWPFTableRow row : tbl.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph p : cell.getParagraphs()) {
replacePlaceholders(p, replacements);
}
}
}
}
// 动态添加段落(基于最后一段样式)
if (!doc.getParagraphs().isEmpty()) {
XWPFParagraph lastParagraph = doc.getParagraphs().get(doc.getParagraphs().size()-1);
XWPFParagraph newPara = doc.createParagraph();
newPara.createRun().setText("动态生成的新内容");
newPara.setStyle(lastParagraph.getStyle());
}
try (FileOutputStream out = new FileOutputStream(outputPath)) {
doc.write(out);
}
}
}
private static void replacePlaceholders(XWPFParagraph p, Map<String, String> replacements) {
String text = p.getText();
if (text != null && text.contains("${")) {
for (Map.Entry<String, String> entry : replacements.entrySet()) {
text = text.replace("${" + entry.getKey() + "}", entry.getValue());
}
p.removeRun(0);
p.createRun().setText(text);
}
}
}
动态段落生成扩展
克隆段落样式
当需要根据模板段落动态生成新内容时,可通过以下方式保持格式一致:
XWPFParagraph templatePara = doc.getParagraphs().get(0);
XWPFParagraph newPara = doc.createParagraph();
// 复制段落样式
newPara.setStyle(templatePara.getStyle());
newPara.setAlignment(templatePara.getAlignment());
newPara.setSpacingBetween(templatePara.getSpacingBetween());
// 复制文本样式
XWPFRun templateRun = templatePara.getRuns().get(0);
XWPFRun newRun = newPara.createRun();
newRun.setFontFamily(templateRun.getFontFamily());
newRun.setFontSize(templateRun.getFontSize());
newRun.setBold(templateRun.isBold());
处理复杂替换场景
多行内容替换
对于需要换行的替换内容,使用 \n 并设置 run 的换行属性:
String multiLineText = "第一行\n第二行";
XWPFRun run = paragraph.createRun();
run.setText(multiLineText);
run.addBreak(BreakType.TEXT_WRAPPING);
条件性段落生成
根据业务逻辑决定是否添加段落:
if (needAdditionalContent) {
XWPFParagraph newPara = doc.createParagraph();
newPara.createRun().setText("条件性生成的内容");
// 复制之前段落的样式...
}
注意事项
- POI 操作 Word 文档时会保留原有样式,但直接替换文本可能影响格式复杂度
- 对于表格中的占位符,需要递归处理每个单元格
- 动态生成的段落应考虑文档的分节符(Section)和页面布局影响
- 大量文本替换时建议使用 StringBuilder 优化性能
完整示例可扩展为支持循环生成表格行、条件性插入图片等复杂场景,原理类似通过定位模板标记位置后进行动态内容操作。
1197

被折叠的 条评论
为什么被折叠?



