用WPS或者office编辑好word的样式,然后另存为word xml文档,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Docx。
1、把需要注入的信息换成变量名称,比如公司名称用${data1}表示,全部替换后的格式如下图所示
1、引用到freemaker的jar包,以及这里还引用了冰蓝云的一个jar包(导入这个jar包是为了后续解决用WPS创建的文档部分手机不能兼容,出现很多格式的问题,使用office手机可以很好的兼容),在pom.xml配置文件中,添加依赖
<!-- freemarker jar -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<!-- spire.doc jar -->
<dependency>
<groupId> e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>3.9.0</version>
</dependency>
2、创建生成动态文档帮助类
package com.mallplus.order.utils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.Data;
import java.io.*;
import java.util.Map;
/**
* @author
* @date
* @apiNote 生成动态文档帮助类
*/
@Data
public class WordUtil {
private Configuration configuration = null;
/*
* 模板文件存放的目录
*/
private String baseDir;
/*
* 模板文件名称
*/
private String templateFile;
/*
* word生成的输出目录
*/
private String outputDir;
public WordUtil(){
configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
}
/*
* 转换成word
*/
public String createWord(Map<String,Object> dataMap){
configuration.setClassForTemplateLoading(this.getClass(), "");//模板文件所在路径
Template t = null;
try {
//得到模板文件
configuration.setDirectoryForTemplateLoading(new File(baseDir));
t = configuration.getTemplate(templateFile);
} catch (IOException e) {
e.printStackTrace();
}
// GwUtil.getFileNo(""); 调用生成随机数的方法
File outFile = new File(outputDir+ GwUtil.getFileNo("") + ".docx"); //导出文件
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
t.process(dataMap, out); //将填充数据填入模板文件并输出到目标文件
return outFile.getPath();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "文档生成失败";
}
}
3、将ftl模板文件复制到项目的指定路径下,模拟数据进行测试
public static void main(String[] args) {
// 调用word文档帮助类
WordUtil wordUtil = new WordUtil();
// 模板文件存放的目录
wordUtil.setBaseDir("E:/ww");
// 模板文件名称
wordUtil.setTemplateFile("采购计划表模板.ftl");
// word生成的输出目录
wordUtil.setOutputDir("E:/image/");
// 初始化数据map
Map<String,Object> dataMap = new HashMap<>();
// 录入采购基本数据
dataMap.put("data1", "XX公司");
dataMap.put("data2", "XX项目");
dataMap.put("data3", "2022.01.01");
dataMap.put("data4", "采购部");
dataMap.put("data5", "张三");
dataMap.put("data6", "189XXXXXXX");
dataMap.put("data7", "李四");
dataMap.put("data8", "张主任");
dataMap.put("data9", "王总");
dataMap.put("data10", "王某");
dataMap.put("data11", "王某");
dataMap.put("data12", "张三");
// 录入表格数据(3条数据循环三次)
for (int i = 1; i <= 3; i++) {
dataMap.put("dataName"+i, "笔记本电脑"+i);
dataMap.put("dataBand"+i, "金山牌"+i);
dataMap.put("model"+i, "JHHJ6"+i);
dataMap.put("price"+i, 5000+i);
dataMap.put("quantity"+i, 3+i);
dataMap.put("total"+i, 15000+i);
}
//处理定价方式复选框
dataMap.put("select", "☑境内采购" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "□境外采购");
String oldPath = wordUtil.createWord(dataMap);
if (oldPath.equals("操作失败")){
System.out.println("操作失败");
}
//输出生成后的文件路径
System.out.println(oldPath);
}
如果是使用WPS创建的文档需要最后一步加上如下代码进行处理(防止文档在部分手机上不能兼容或者格式问题):
//转化后本质是doc(x)的word文档。
Document document = new Document(oldPath);
File file = new File(oldPath);
// 判断有没有父路径,就是判断文件整个路径是否存在
if (!file.getParentFile().exists()) {
// 不存在就全部创建
file.getParentFile().mkdirs();
}
//将本质是xml的文件转化为真正的doc(x)
document.saveToFile(oldPath, FileFormat.Docx);
spire.doc 免费版的对word的内容量有限制(要求 Word 文档不超过 500 个段落,https://www.e-iceblue.cn/Introduce/Free-Spire-Doc-JAVA.html)
采购计划表word模板文档地址:https://download.csdn.net/download/weixin_49104405/85187627?spm=1001.2014.3001.5501