使用XWPFTemplate生成Word并使用docx4j转Pdf
一、所需依赖
<!-- 引入 poi-tl,推荐 1.12.x 版本 -->
<!-- 无法引入时在在终端执行以下命令,强制下载 poi-tl 的元数据到本地仓库:
mvn dependency:get -Dartifact=com.deepoove:poi-tl:1.12.1-->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.12.1</version>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-JAXB-ReferenceImpl</artifactId>
<version>8.3.15</version>
</dependency>
<!-- mvn dependency:get -Dartifact=org.docx4j:docx4j-core:8.3.15-->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>8.3.15</version>
</dependency>
如果jdk版本过高,大于8以上,可以尝试再添加以下依赖:
<!-- 1. JAXB API (javax 版本) -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 2. JAXB Runtime (实现,推荐使用 Glassfish) -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.9</version>
</dependency>
<!-- 3. (可选) 激活 API -->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
二、配置模板
需要填充的数据使用{{data}}来标记,动态数量表格行可用内置的循环标签如{{?dataList}}和{{/dataList}},具体模板如下:


三、实现代码
@Override
public void createWord(UserDto userDto) {
try {
//读取文件模板
XWPFTemplate template = XWPFTemplate.compile("E:\\file\\template\\word生成模板.docx");
//填充数据
template.render(dataMap());
String timeStr = LocalDateTimeUtil.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
//输出文件
template.writeToFile("E:\\file\\generateDocxFile\\word生成文件" + timeStr + ".docx");
template.close();
//转pdf,使用docx4j ,只能处理docx文件
// 1. 加载Word文档
WordprocessingMLPackage wordMLPackage =
WordprocessingMLPackage.load(new File("E:\\file\\generateDocxFile\\word生成文件" + timeStr + ".docx"));
//配置字体映射
Mapper mapper = new IdentityPlusMapper();
PhysicalFonts.discoverPhysicalFonts();
//没有映射的字体将会变成"##"
String[][] fontMap = {
{"宋体", "SimSun"},
{"黑体", "SimHei"},
{"微软雅黑", "Microsoft YaHei"},
{"楷体", "KaiTi"},
{"隶书", "LiSu"},
{"幼圆", "YouYuan"},
{"华文细黑", "STXihei"},
{"华文楷体", "STKaiti"},
{"华文宋体", "STSong"},
{"华文仿宋", "STFangsong"},
{"华文中宋", "STZhongsong"},
{"华文彩云", "STCaiyun"},
{"华文琥珀", "STHupo"},
{"华文新魏", "STXinwei"},
{"华文隶书", "STLiti"},
{"华文行楷", "STXingkai"},
{"方正舒体", "FZShuTi"},
{"方正姚体", "FZYaoti"},
{"仿宋_GB2312", "FangSong_GB2312"},
{"楷体_GB2312", "KaiTi_GB2312"},
{"宋体_GB2312", "SimSun_GB2312"},
{"新宋体", "NSimSun"},
{"仿宋", "FangSong"},
};
for (String[] font : fontMap) {
PhysicalFont physicalFont = PhysicalFonts.get(font[1]);
if (physicalFont != null) {
mapper.put(font[0], physicalFont);
}
}
wordMLPackage.setFontMapper(mapper);
// 2. 执行转换,将PDF输出到文件流
try (FileOutputStream fos = new FileOutputStream("E:\\file\\generatePDFFile\\word生成文件" + timeStr + ".pdf")) {
Docx4J.toPDF(wordMLPackage, fos);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private Map dataMap() {
Map map = new HashMap<>();
map.put("userName", "张三");
map.put("age", 20);
map.put("sex", "男");
map.put("address", "北京市海淀区");
map.put("phone", "12345678901");
map.put("email", "zhangsan@example.com");
//表格数据
List<Map<String, Object>> list = new ArrayList<>();
Map<String, Object> map1 = new HashMap<>();
map1.put("workTime", "2024-01-01——2025-01-01");
map1.put("companyName", "字节跳动");
map1.put("post", "Java开发工程师");
Map<String, Object> map2 = new HashMap<>();
map2.put("workTime", "2025-01-01——2026-01-01");
map2.put("companyName", "腾讯");
map2.put("post", "项目经理");
list.add(map1);
list.add(map2);
map.put("workList", list);
return map;
}

浙公网安备 33010602011771号