1、原理:
数据 + freemaker doc/html.ftl 模板 ---> doc/html
2、具体实现:
生成过程doc和html类似,下面以Freemark用于导出word文档多图为例
一、模板准备
1、使用word新建文档,修改成需要的格式,另存为xml格式
2、使用nopad++打开,找到相应的参数的位置,在需要循环添加的地方加入<list>循环,修改图片部分的name与src修改为:w:name="wordml://${img_index}.png" ,用对应参数替换,如${title}。
3、修改xml文件为ftl文件,模板准备大功告成。
备注:
如果使用这个步骤制作模版,遇到多图的情况会出问题,问题有很多,根据解决的深度表现形式不一样。反正就是很难正确成功表达。
经过多次验证,正常的word文档图片的显示是在三个部分做了标志。首先是图片显示的位置,会引用rId,在图片存储区会有name做为标志,在word的开头部分会把rId与name进行关联,所以要正确的显示图片需要三个部分都改并进行对应。这是非常非常让人头疼的事情。
不过在网上找到了另外一种方式,把图片存储区的图片数据放在图片显示区内,使用name与src进行关联,只需要保证name与src属性一样即可成功显示。如下:
<w:r>
<w:pict>
<w:binData w:name="wordml://${img.title}.png">${img.image}</w:binData>
<v:shape id="_x0000_s1026" o:spt="75" alt="" type="#_x0000_t75" style="height:250.05pt;width:438.1pt;" 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://${img.title}.png" o:title="wordml://${img.title}.png"/>
<o:lock v:ext="edit" aspectratio="t"/>
<w10:wrap type="none"/>
<w10:anchorlock/>
</v:shape>
</w:pict>
</w:r>
二、代码部分
将ftl文件放到项目相关目录下,然后进行下面代码逻辑:
private static Configuration configuration = null;
private static final String basePackagePath = "/com/topcom/cms/yuqing/template";
static {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
//增加自定义函数,去除html标签
configuration.setSharedVariable("cleanHtml", new CleanHtmlMethodModel());
}
/**
* @param dataMap 数据map
* @param outFile 生成的文件
* @param templateName 模板名
* @throws UnsupportedEncodingException
*/
public static void processTemplateIntoFile(Map<String, Object> dataMap, File outFile,
String templateName) throws Exception {
// dataMap 要填入模本的数据文件
// 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
// 这里我们的模板是放在com.havenliu.document.template包下面
configuration.setClassForTemplateLoading(FreemarkerUtil.class,
basePackagePath);
Template t = null;
try {
// test.ftl为要装载的模板
t = configuration.getTemplate(templateName);
} catch (IOException e) {
e.printStackTrace();
}
Writer out = null;
FileOutputStream fos = null;
fos = new FileOutputStream(outFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
// 这个地方对流的编码不可或缺,使用main()单独调用时,应该可以,但是如果是web请求导出时导出后word文档就会打不开,并且包XML文件错误。主要是编码格式不正确,无法解析。
// out = new BufferedWriter(new OutputStreamWriter(new
// FileOutputStream(outFile)));
out = new BufferedWriter(oWriter);
System.out.println("dataMap:"+dataMap);
t.process(dataMap, out);
out.close();
fos.close();
}