Java 动态实现word导出功能
1.word模板:xx.ftl生成,ftl文件就是word的源代码,类似html一样是拥有标签和样式的代码。
- 把需要导出的doc文件模板用office版本的word工具打开。
- 把doc文件另存为xx.xml文件
- 把xx.xml文件重命名为xx.ftl文件
2.编写后台代码,生成word文件
package com.server.common.util.word; import java.io.*; import java.net.URLEncoder; import java.util.Map; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import freemarker.template.Configuration; import freemarker.template.Template; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class WordUtils { //配置信息,代码本身写的还是很可读的,就不过多注解了 private static Configuration configuration = null; //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置 private static String path = null; //这是word模板的存放位置private String templateFolder; //这是生成word的路径private String reportPath; private boolean connection(HttpServletRequest request) { try { System.out.println(templateFolder); configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); configuration.setDirectoryForTemplateLoading(new File(templateFolder)); return true; } catch ( IOException e ) { e.printStackTrace(); return false; } } /** * * @param request * @param response * @param map 数据集合 * @param title 生成的word名字 * @param ftlFile word模板的名字 * @throws IOException */ public void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException { if (connection(request) == false) { return; } Template freemarkerTemplate = configuration.getTemplate(ftlFile); File file = null; InputStream fin = null; ServletOutputStream out = null; try { // 调用工具类的createDoc方法生成Word文档 file = createDoc(title, map, freemarkerTemplate); fin = new FileInputStream(file); response.setCharacterEncoding("utf-8"); response.setContentType("application/msword"); // 设置浏览器以下载的方式处理该文件名 String fileName = title + ".doc"; response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8")))); out = response.getOutputStream(); byte[] buffer = new byte[512]; // 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } } finally { if (fin != null) fin.close(); if (out != null) out.close(); if(file != null) file.delete(); // 删除临时文件 } } /** * * @param name //生成的word名字 * @param dataMap //生成的word的数据 * @param template //获取模板后实例 * @return */ private File createDoc(String name, Map<?, ?> dataMap, Template template) { File f = new File(reportPath + name); Template t = template; try { // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开 Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); t.process(dataMap, w); w.close(); } catch ( Exception ex ) { ex.printStackTrace(); throw new RuntimeException(ex); } return f; } }
3.ftl文件赋值,ftl赋值和el表达式很相似都是${}模式
${data.name} :字符串
${data.name!"-"}:代表当data.name是空的时候用“-”代替这个字符展示
${data.name?html}:转化为html格式
if判断
??代表的是?前方的字符不是空的时候,?size常用语list数据,判断?前方数据的size是不是小于0 <#if data.list?? && (data.list?size > 0) > 和if是功效是一样的 <# else if (data.list?size < 10) > </#if>
list循环输出
<#list data.list as list>
${list_index} :表示集合的位置或者下标,初始为0
</#list>
ftl标签
<w:vMerge w:val="restart"/>:表示要合并单元格 <w:vMerge w:val="continue"/>:表示被合并的单元格 <w:t xml:space="preserve">:表示需要格式化的特殊字符