当 Word 模板文档的内容是复杂表单时,处理方式会比普通文字更复杂一些,但依旧可以借助 Apache POI 库来完成。以下是详细的处理思路和示例代码:
处理思路
示例代码
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class ComplexFormDocGenerator {
public static void main(String[] args) {
String[] templatePaths = {"complex_template.docx"};
String outputPath = "complex_output.docx";
Map<String, String> values = new HashMap<>();
values.put("${name}", "李四");
values.put("${department}", "技术部");
try {
generateDocument(templatePaths, outputPath, values);
System.out.println("文档生成成功,路径为: " + outputPath);
} catch (IOException e) {
System.err.println("生成文档时出现错误: " + e.getMessage());
e.printStackTrace();
}
}
public static void generateDocument(String[] templatePaths, String outputPath, Map<String, String> values) throws IOException {
XWPFDocument finalDocument = new XWPFDocument();
for (String templatePath : templatePaths) {
try (FileInputStream templateStream = new FileInputStream(templatePath);
XWPFDocument templateDocument = new XWPFDocument(templateStream)) {
replacePlaceholders(templateDocument, values);
appendDocument(finalDocument, templateDocument);
}
}
try (FileOutputStream outputStream = new FileOutputStream(outputPath)) {
finalDocument.write(outputStream);
}
}
private static void replacePlaceholders(XWPFDocument document, Map<String, String> values) {
// 处理段落中的占位符
for (XWPFParagraph paragraph : document.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
// 处理表格中的占位符
for (XWPFTable table : document.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
}
}
}
// 处理文本框中的占位符(POI 对文本框处理有限,可结合其他库)
// 这里仅简单示例,实际可能需要更复杂逻辑
// 可以使用 docx4j 等库来更好地处理文本框
for (IBodyElement element : document.getBodyElements()) {
if (element instanceof XWPFSDT) {
XWPFSDT sdt = (XWPFSDT) element;
for (XWPFParagraph paragraph : sdt.getContent().getParagraphs()) {
for (XWPFRun run : paragraph.getRuns()) {
String text = run.getText(0);
if (text != null) {
for (Map.Entry<String, String> entry : values.entrySet()) {
text = text.replace(entry.getKey(), entry.getValue());
}
run.setText(text, 0);
}
}
}
}
}
}
private static void appendDocument(XWPFDocument mainDocument, XWPFDocument appendDocument) throws IOException {
CTBody mainBody = mainDocument.getDocument().getBody();
CTBody appendBody = appendDocument.getDocument().getBody();
for (Object object : appendBody.getContent()) {
mainBody.addNewP().set(object);
}
}
}
代码解释
- 处理段落:和普通文字处理一样,遍历文档中的段落和运行对象,把占位符替换成实际的值。
- 处理表格:遍历文档中的所有表格,再遍历表格的行和单元格,对单元格内的段落和运行对象进行占位符替换。
- 处理文本框:使用
XWPFSDT
来识别文本框,遍历文本框内的段落和运行对象,进行占位符替换。不过 Apache POI 对文本框的处理能力有限,实际应用中可能需要结合docx4j
等其他库。
注意事项
- 要保证
complex_template.docx
文件存在于项目的根目录下,或者根据实际情况修改文件路径。 - 运行代码前,要确保项目中已经正确引入了 Apache POI 的依赖。
- 对于复杂的表单元素,如下拉框、复选框等,可能需要更复杂的处理逻辑,你可以结合
docx4j
等库来实现。