在项目中使用它完成的功能是按照固定的模板将数据导出到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三宗罪-