在项目中使用它完成的功能是按照固定的模板将数据导出到Word。比如台账。在完成后将处理过程按照台账的要求导出,有时程序中需要实现生成标准Word文档,要求能够打印,并且保持页面样式不变。
这个功能就是由XML+Freemarder来实现的,Word从2003开始支持XML格式,大致的步骤:用office2003或者以上的版本编辑 好 word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。
一、模板的制作
先用Word做一个模板,如下图:
然后另存为XML文件,可以利用高亮显示的notepad++打开xml,主要是有高亮显示,和元素自动配对
也可以用foxe_CHS打开xml,是一个简洁、快速的 XML 编辑器,还提供F8对齐排版功能。
保存后,修改后缀名为ftl,至此模板制作完毕。
二、编程实现
首先引入freemarker的开源包
1 import freemarker.template.Configuration; 2 import freemarker.template.Template; 3 import freemarker.template.TemplateException;
编写java类,主要实现对模板的赋值以及生成流,用于导出。
1 package com.test.freemarker.report; 2 import java.io.BufferedWriter; 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.OutputStreamWriter; 7 import java.io.Writer; 8 import java.util.HashMap; 9 import java.util.Map; 10 import freemarker.template.Configuration; 11 import freemarker.template.Template; 12 import freemarker.template.TemplateException; 13 14 public class DocumentHandler { 15 private Configuration configuration = null; 16 17 public DocumentHandler() { 18 configuration = new Configuration(); 19 configuration.setDefaultEncoding("utf-8"); 20 } 21 22 public void createDoc() { 23 // 要填入模本的数据文件 24 Map dataMap = new HashMap(); 25 getData(dataMap); 26 // 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载, 27 // 这里我们的模板是放在com.havenliu.document.template包下面 28 configuration.setClassForTemplateLoading(this.getClass(), "/com/test/freemarker/report"); 29 Template t = null; 30 try { 31 // test.ftl为要装载的模板 32 t = configuration.getTemplate("test.ftl"); 33 t.setEncoding("utf-8"); 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 // 输出文档路径及名称 38 File outFile = new File("D:/test.doc"); 39 Writer out = null; 40 try { 41 FileOutputStream fos = new FileOutputStream(outFile); 42 OutputStreamWriter oWriter = new OutputStreamWriter( 43 fos,"UTF-8");//这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。 44 out = new BufferedWriter(oWriter); 45 /** out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); **/ 46 } catch (Exception e1) { 47 e1.printStackTrace(); 48 } 49 try { 50 t.process(dataMap, out); 51 out.close(); 52 } catch (TemplateException e) { 53 e.printStackTrace(); 54 } catch (IOException e) { 55 e.printStackTrace(); 56 } 57 } 58 59 /** 60 * 注意dataMap里存放的数据Key值要与模板中的参数相对应 61 * @param dataMap 62 */ 63 private void getData(Map dataMap) { 64 dataMap.put("title_name", "用户信息"); 65 dataMap.put("user_name", "张三"); 66 dataMap.put("org_name", "微软公司"); 67 dataMap.put("dept_name", "事业部"); 68 } 69 }
三、生成的Word结果如下:
对于复杂的报表样式可以在Word中编辑后保存,如果需要输出列表类型数据可以参考Freemarker的循环或逻辑控制。
四、总结
这个工具生成word确实很方便,但是还是有些不足的地方,FreeMarker三宗罪->http://www.iteye.com/topic/17468