java 根据freemarker模板导出word
freemarker导出word 文档list 集合遍历数据和图片
技术: freemarker 技术---我们word 高级版本(ftl 的制作)
1 首先要准备ftl 文档
打开word 编辑,有图片的话插入一张图片,变为下面形式(注意,下面为表格插入,一行一列)
然后将word 另存为xml 文档 -- word.xml 注意:(${}可能被分开或换行,最好是生成xml之前不加${},生成xml文档之后再补上${})。
打开xml 文档,下面我们就更改四处,
一 加入 <w:tr>前<#list list as list> 第一个list 不能变 第二个list 为变量名 第三个list 为别名
二 将${fieldname} 改为${list.fieldname}
三 将${fieldname} 改为${list.fieldname}
四 </w:tr>后加入</#list>
<#list list as list> <w:tr> <w:tblPrEx> <w:tblBorders> ....... <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${list.fieldname}</w:t> </w:r> </w:p> ....... <w:rPr> <w:rFonts w:hint="eastAsia"/> <w:lang w:val="en-US" w:eastAsia="zh-CN"/> </w:rPr> <w:t>${list.field}</w:t> </w:r> </w:p> <w:p> </w:p> </w:tc> </w:tr> </#list>
这是freemarker循环行的处理语法;
将改好的xml 保存,如果notepad++报错不用理会,将xml 改为ftl 文件,就得到我们需要的ftl了, 编译后的不要用word打开
2 java 代码的实现
引入jar 包
<properties> <!--freemarker--> <freemarker.version>2.3.23</freemarker.version> </properties> <dependencies> <!--freemarker--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>${freemarker.version}</version> </dependency>
导出word工具类代码:
package com.linewell.sjj; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.URLEncoder; import java.util.Date; import java.util.List; 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; public class WordUtils { //配置信息,代码本身写的还是很可读的,就不过多注解了 private static Configuration configuration = null; //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置 private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templates/doc"; //private static final String templateFolder = "F:\\hebei4\\jgj\\WebRoot\\WEB-INF\\templates\\doc"; static { configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); try { configuration.setDirectoryForTemplateLoading(new File(templateFolder)); } catch (IOException e) { e.printStackTrace(); } } private WordUtils() { throw new AssertionError(); } public static void exportMillCertificateWord( HttpServletResponse response,Map map,String title,String ftlFile) throws IOException { Template freemarkerTemplate = configuration.getTemplate(ftlFile); File file = null; InputStream fin = null; ServletOutputStream out = null; try { // 调用工具类的createDoc方法生成Word文档 file = createDoc(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(); // 删除临时文件 } } public static void exportMillCertificateWord2( Map dataMap,String title,String ftlFile) throws IOException { Template freemarkerTemplate = configuration.getTemplate(ftlFile); File file = null; InputStream fin = null; OutputStream out = null; try { // 调用工具类的createDoc方法生成Word文档 file = createDoc(dataMap,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 = new FileOutputStream(file); //out = OutputStream(); 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(); // 删除临时文件 } } private static File createDoc(Map<?, ?> dataMap, Template template) { String name = templateFolder+"/后置现场审查表.doc"; //String name = "f://后置现场审查表.doc"; File f = new File(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; } }
调用方法实例:注意(map中的key要与ftl文件中变量对应上,图片必须转成Base64格式)
private static String document="hzxcscb.ftl";
Map dataMap = new HashMap(); dataMap.put("txtEnterpriseName",txtEnterpriseName ); dataMap.put("zs", zs); dataMap.put("txtzsbh", txtzsbh); dataMap.put("rr", txtEnterpriseName); dataMap.put("qq", zs); dataMap.put("qymc", qymc); dataMap.put("qymcqkms", qymcqkms); dataMap.put("qydz", qydz); dataMap.put("qydzqkms", qydzqkms); dataMap.put("zsmx", zsmx); dataMap.put("zsmxqkms", zsmxqkms); dataMap.put("qysfcysczt", qysfcysczt); dataMap.put("qysfcyscztqkms", qysfcyscztqkms); dataMap.put("hcjl", hcjl); dataMap.put("hcjlqkms", hcjlqkms); dataMap.put("qyfzr", qyfzr); dataMap.put("scy", scy); dataMap.put("xzry", xzry); dataMap.put("gcy", ""); dataMap.put("list", mapList); try { WordUtils.exportMillCertificateWord(response,dataMap,"后置现场审查表",document); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }
ftl文件中的图片处理:(多张图片的话,标红的部分必须动态)
<w:pict> <w:binData w:name="${"wordml://"+list_index+".jpg"}">${list.ss!}</w:binData> <v:shape id="${list_index}" o:spt="75" alt="" type="${list_index}" style="height:119.5pt;width:79.7pt;" filled="f" o:preferrelative="t" stroked="f" coordsize="21600,21600"> <v:path/> <v:fill on="f" focussize="0,0"/> <v:stroke on="f"/> <v:imagedata src="${"wordml://"+list_index+".jpg"}" o:title="${list_index}"/> <o:lock v:ext="edit" aspectratio="t"/> <w10:wrap type="none"/> <w10:anchorlock/> </v:shape> </w:pict>
结束。