使用FreeMarker的模板技术快速实现动态生成word
实现思路是这样的:先创建一个word文档,按照需求在word中填好一个模板,然后把对应的数据换成变量${},然后将文档保存为xml文档格式,使用文档编辑器打开这个xml格式的文档,去掉多余的xml符号,使用Freemarker读取这个文档然后替换掉变量,输出word文档即可。
1.创建带有格式的word文档,将该需要动态展示的数据使用变量符替换。
2. 将刚刚创建的word文档另存为xml格式。
3.编辑这个XMl文档去掉多余的xml标记,如图中蓝色部分
4.从Freemarker官网【下载】最新的开发包,将freemarker.jar拷贝到自己的开发项目中。
5.新建DocUtil类,实现根据Doc模板生成word文件的方法
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.favccxx.secret.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
public class DocUtil {
privateConfiguration configure =null;
publicDocUtil(){
configure=new Configuration();
configure.setDefaultEncoding("utf-8");
}
/**
* 根据Doc模板生成word文件
* @param dataMap Map 需要填入模板的数据
* @param fileName 文件名称
* @param savePath 保存路径
*/
publicvoid createDoc(Map dataMap, String downloadType, StringsavePath){
try{
//加载需要装填的模板
Templatetemplate =null;
//加载模板文件
configure.setClassForTemplateLoading(this.getClass(),"/com/favccxx/secret/templates");
//设置对象包装器
configure.setObjectWrapper(newDefaultObjectWrapper());
//设置异常处理器
configure.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
//定义Template对象,注意模板类型名字与downloadType要一致
template= configure.getTemplate(downloadType +".xml");
//输出文档
FileoutFile =new File(savePath);
Writerout =null;
out=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"utf-8"));
template.process(dataMap,out);
outFile.delete();
}catch (Exception e) {
e.printStackTrace();
}
}
}
6.用户根据自己的需要,调用使用getDataMap获取需要传递的变量,然后调用createDoc方法生成所需要的文档。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 根据下载类型获取需要传递的Map参数
* @param oid 对象Id
* @param downloadType 下载类型
*/
private Map getDataMap(String oid,String downloadType){
Map dataMap =new HashMap();
if("Parameter1".equals(downloadType)){
...
...
dataMap = DataMapUtil.setObjToMap(Object1);
}else{
...
...
dataMap = DataMapUtil.setObjToMap(Object2);
}
return dataMap;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class DataMapUtil {
private static Map dataMap =new HashMap();
/**
* 将对象转换成Map
* @param obj 对象类
* @return
*/
public static Map setObjToMap(Object obj){
Class c;
try {
c = Class.forName(obj.getClass().getName());
Method[] methods = c.getMethods();
for(int i=0,l=methods.length;i
String method = methods[i].getName();
System.out.println("The method is:" + method);
if(method.startsWith("get")){
Object value = methods[i].invoke(obj);
if(value !=null){
if(value.getClass().getClassLoader() !=null){//处理自定义的对象类型
setObjToMap(value);
}
String key = method.substring(3);
key = key.substring(0,1).toLowerCase() + key.substring(1);
if("java.util.Date".equals(value.getClass().getName())){
value = DateUtil.dateToString((Date)value);
}
dataMap.put(key, value);
}
}
}
}catch (Exception e) {
e.printStackTrace();
}
return dataMap;
}
上述代码都很容易理解,最大的疑问就是QQ.ftl文件时怎么来的? 2.模板文件
(a):根据已经编辑好的word模板QQ.doc,选择另存为QQ.xml文件,新建freemaker类型文件QQ.ftl,将QQ.xml文件拷贝到QQ.ftl文件中。
(b):修改ftl模板文件,将需要替换的内容用${biaoduan}这样的标签替换。
(ftl文件太长,不列出来了)
3.运行程序,word文件将生成到制定位置。
个人认为这种生成方式相对于jacob要方便很多。