最近遇到了生成报表操作的需求,使用easyExcel导出表格,并不能很好的满足项目需求,所以最终选择了freemarker的方式来导出word报表,网上各种各样的笔记层出不穷,所以此文用来记录自己实际应用的过程。
使用freemarker模板导出word文档大致可分为三步
- 制作word模板
- 编写生成word文档的工具类
- 准备数据,调用模板生成word文档
1.制作模板
1.1打开office-word,创建新的word文档,并编写自己需要的样式,例如:
1.2编写好样式之后,另存为xml格式
1.3用相关工具(我用的是notepad++)打开文档并格式化,修改你要填入实际数据的地方
例如:该模板是一个报表表格,有很多行,所以需要在表格前加<#List 实际数据名称 as 数据名称>标签,然后替换相关字段,此处终端一号替换为${dataList。terminalName};是因为我的数据名称为terminalName;
注:图片则需要将那一大串base64编码(在binData标签中间)修改为相关字段:例如下图
也要注意图片的ID,不修改的话会所有图片都长一样!!!!!!!
1.4 完成字段替代后,保存,将文件后缀名修改为.ftl
1.5 将文件放在项目中:例如下图
2.编写工具类
2.1导入依赖
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
2.2编写工具类
/**
* @author Lsc
*/
@Component
public class WordUtils {
/**
* 生成word
* @param dataMap
* @throws Exception
*/
public void saveWord(Map<String,Object> dataMap) throws Exception {
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("UTF-8");
//模板文件所在路径,此处我将刚才生成的模板放在了resources/templates下
configuration.setClassForTemplateLoading(this.getClass(), "/templates");
Template template = configuration.getTemplate("report.ftl", "utf-8");
//导出文件
File outFile = new File(commonProperties.getWordPath() + dataMap.get("fileName") +".doc");
Writer out = null;
try {
FileOutputStream fileOutputStream = new FileOutputStream(outFile);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
out = new BufferedWriter(outputStreamWriter);
template.process(dataMap, out);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
out.close();
}
}
/**
* 将图片转为base64编码
*/
public String getImgStr(String imgFile){
//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
InputStream in = null;
byte[] data = null;
//读取图片字节数组
try
{
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return new String(Base64.encodeBase64(data));
}
}
3.准备数据,调用工具类
此处为一个测试类,实际生产中放在具体的业务中就可以了,记得字段要和模板统一!
@SpringBootTest(classes = UapApplication.class)
public class FreemarkerTest {
@Autowired
private WordUtils wordUtils;
@Test
public void test1() throws Exception {
Map<String,Object> maps = new HashMap<>();
maps.put("fileName","报表测试111");
Map<String,String> map = new HashMap<>();
map.put("terminalName","终端1号");
map.put("terminalSn","36695sss");
map.put("time","2021-11-11");
map.put("result","正常");
// 图片要转为base64编码才可以正常展示
map.put("originalImg",wordUtils.getImgStr("C:\\Users\\DELL\\Desktop\\1.png"));
map.put("identifyImg",wordUtils.getImgStr("C:\\Users\\DELL\\Desktop\\2.png"));
//因为我的报表列数是根据实际数量变化的,所以这里和模板都用了列表
List<Map<String,String>> datalist = Lists.newArrayList();
datalist.add(map);
datalist.add(map);
maps.put("dataList",datalist);
wordUtils.saveWord(maps);
}
}
最终结果图: