1 创建word模板
2 动态数据占位
格式:${xxxxx}
3 点击另存为xml格式
4 修改后缀名为ftl
5 导入到idea中
6 修改文件编码为utf-8
7 复制模板内容在线代码格式化
8 编辑模板中内容
如果有空值会报错,可以 ${xxxx !''}处理,网上查看可以在配置文件中配置,但是我试了总是不生效
spring.freemarker.settings.classic_compatible=true
有需要遍历的表格
9 导出
因为使用ftl模板,需要引入jar包
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency>
模板取值需要从map中取值,对象转map就可以了
public void exportReport(HttpServletResponse response, Integer receiptId) throws IOException, TemplateException { Map<String, Object> dataMap = new HashMap<>(); //获取,可忽略 PrintReceiptInfoVO printReceiptInfoVO = this.getPrintReceiptInfo(receiptId); if(printReceiptInfoVO != null) { String ecpNoticeId = printReceiptInfoVO.getEcpNoticeId(); if(!StringUtils.isEmpty(ecpNoticeId)) { String ecpResult = ecpApi.getOrderNoticeInfoMain(ecpNoticeId); if(!StringUtils.isEmpty(ecpResult)) { RemoteResult remoteResult = JSON.parseObject(ecpResult, new TypeReference<RemoteResult>() {}); if ("200".equals(remoteResult.getStatus()) && remoteResult.getData() != null && !"[]".equals(remoteResult.getData().toString())){ List<EcpPrintInfoVO> ecpReceiptVOS = JSON.parseObject(remoteResult.getData().toString(),new TypeReference<List<EcpPrintInfoVO>>(){}); if(!CollectionUtils.isEmpty(ecpReceiptVOS)) { EcpPrintInfoVO ecpPrintInfoVO = ecpReceiptVOS.get(0); if(ecpPrintInfoVO != null) { BeanUtils.copyProperties(ecpPrintInfoVO,printReceiptInfoVO); printReceiptInfoVO.setConsignorRemark("样机"); } } } } } dataMap = MapBeanUtil.object2Map(printReceiptInfoVO); } //获取数据end PrintWriter out = response.getWriter(); //配置对象 Configuration configuration = new Configuration(); //设置配置的字符编码为utf-8,避免字符集问题 configuration.setDefaultEncoding("UTF-8"); //获取resources下指定的文件夹路径,如果项目需要打成jar包, //此举很重要,别的方式可能无法获取到模板文件夹的相对路径 configuration.setClassForTemplateLoading(this.getClass(), "/templates"); // 获取模板实例,上行配置了模板文件所在路径 Template t = configuration.getTemplate("exportReceipt.ftl", "utf-8");//以utf-8的编码读取ftl文件 //设置响应类型为word response.setContentType("application/msword"); //设置响应头,注意如果导出的word名含有汉字则需要将文件名 //变成byte并且指定字符集为gbk,表示将GBK汉字转为byte //然后将其转为iso8859-1的字符串 response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(("导出报告.doc").getBytes("GBK"), "iso8859-1") + "\""); //此句非常关键,不然word文档全是乱码 response.setCharacterEncoding("utf-8"); //使用数据填充模板 t.process(dataMap, out); //以流的输出到浏览器,即下载 out.close(); }
import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; /** * map转bean,bean转map */ public class MapBeanUtil { /** * 实体对象转成Map * * @param obj 实体对象 * @return */ public static Map<String, Object> object2Map(Object obj) { Map<String, Object> map = new HashMap<>(); if (obj == null) { return map; } Class clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); try { for (Field field : fields) { field.setAccessible(true); map.put(field.getName(), field.get(obj)); } } catch (Exception e) { e.printStackTrace(); } return map; } /** * Map转成实体对象 * * @param map 实体对象包含属性 * @param clazz 实体对象类型 * @return */ public static Object map2Object(Map<String, Object> map, Class<?> clazz) { if (map == null) { return null; } Object obj = null; try { obj = clazz.newInstance(); Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) { int mod = field.getModifiers(); if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) { continue; } field.setAccessible(true); field.set(obj, map.get(field.getName())); } } catch (Exception e) { e.printStackTrace(); } return obj; } }