FreeMarker之生成復(fù)雜word(包含圖片) (二)
來源:程序員人生 發(fā)布時(shí)間:2014-12-06 16:02:12 閱讀次數(shù):6653次
上1篇博客中講FreeMarker做了簡單的介紹,這篇博客就來使用它來完成兩個(gè)例子。
在項(xiàng)目中使用它完成的功能是依照固定的模板將數(shù)據(jù)導(dǎo)出到Word。比如臺(tái)賬。在完成后將處理進(jìn)程依照臺(tái)賬的要求導(dǎo)出,有時(shí)程序中需要實(shí)現(xiàn)生成標(biāo)準(zhǔn)Word文檔,要求能夠打印,并且保持頁面樣式不變。
這個(gè)功能就是由XML+Freemarder來實(shí)現(xiàn)的,Word從2003開始支持XML格式,大致的步驟:用office2003或以上的版本編輯好 word的樣式,然后另存為xml,將xml翻譯為FreeMarker模板,最后用java來解析FreeMarker模板并輸出Doc。
上1篇博客中提到,使用Freemarker其實(shí)就只準(zhǔn)備模板和數(shù)據(jù)。下面的步驟其實(shí)概括起來就兩步:第1步是制作模板,第2步是準(zhǔn)備數(shù)據(jù).
具體實(shí)現(xiàn)進(jìn)程如 下:
1、 制作模板
首先用office【版本要2003以上,以下的不支持xml格式】編輯文檔的樣式,將需要?jiǎng)討B(tài)填充的內(nèi)容使用Freemarker標(biāo)簽替換:Word文檔樣式以下:

將Word文檔另存為XML格式,將后綴名“xml”修改成“ftl”,模板制作完成
圖片處理:
我們可以看到上面的模板中有圖片,當(dāng)我們將xml修改成ftl以后打開文件可以看到原來圖片的位置全部都是亂碼。這是由于ftl不能夠辨認(rèn)圖片,我們只要將這些亂碼用${image}替換掉既可以了。
循環(huán)處理:
模板中明細(xì)表中的數(shù)據(jù)是1個(gè)集合,我們需要循環(huán)遍歷才能夠?qū)?shù)據(jù)全部注入,這個(gè)時(shí)候我們就會(huì)用到了FreeMarker本身的語法了。
循環(huán):
<#list array as bean>
${bean.property}
</#list>
代碼放在表格的開頭和結(jié)尾,也即是將表格中的標(biāo)簽包括在循環(huán)里面,這模樣就能夠了。
在制作模板的進(jìn)程中遇到的1個(gè)問題:${xxx}這些標(biāo)記在ftl中被拆成1個(gè)1個(gè)的,讓我很無語。最后我還是手動(dòng)的將這些又重新拼到1起了。
2. 準(zhǔn)備數(shù)據(jù),將上面模板中的${}的標(biāo)簽放上對(duì)應(yīng)的數(shù)據(jù)
首先要講freemarker的jar包放到程序中,然后將上面制作好的模板放到程序中;

最后加上下面的代碼就能夠了
package com.ftl;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Encoder;
public class DocumentHandler {
private Configuration configuration = null;
public DocumentHandler() {
configuration = new Configuration();
configuration.setDefaultEncoding("utf⑻");
}
public void createDoc() {
// 要填入模本的數(shù)據(jù)文件
Map dataMap = new HashMap();
getData(dataMap);
// getTest(dataMap);
// 設(shè)置模本裝置方法和路徑,FreeMarker支持多種模板裝載方法。可以重servlet,classpath,
數(shù)據(jù)庫裝載,
// 這里我們的模板是放在com.template包下面
configuration.setClassForTemplateLoading(this.getClass(),
"/com/template");
Template t = null;
try {
// test.ftl為要裝載的模板
t = configuration.getTemplate("temple.ftl");
t.setEncoding("utf⑻");
} catch (IOException e) {
e.printStackTrace();
}
// 輸出文檔路徑及名稱
File outFile = new File("D:/test.doc");
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(outFile), "utf⑻"));
} catch (Exception e1) {
e1.printStackTrace();
}
try {
t.process(dataMap, out);
out.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 注意dataMap里寄存的數(shù)據(jù)Key值要與模板中的參數(shù)相對(duì)應(yīng)
* @param dataMap
*
*/
@SuppressWarnings("unchecked")
private void getData(Map dataMap) {
dataMap.put("image", getImageStr());
dataMap.put("name", "張3");
List<Map<String, Object>> newsList=new ArrayList<Map<String,Object>>();
for(int i=1;i<=5;i++){
Map<String, Object> map=new HashMap<String, Object>();
map.put("purchaseTime", "進(jìn)貨日期"+i);
map.put("product", "產(chǎn)品名稱"+i);
map.put("factory", "生產(chǎn)廠家"+i);
map.put("spec", "產(chǎn)品規(guī)格"+i));
map.put("number", "進(jìn)貨數(shù)量"+i);
newsList.add(map);
}
dataMap.put("newsList",newsList);
}
private String getImageStr() {
String imgFile = "d:/1.png";
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
}
package com.ftl;
public class main {
/**
* @param args
*/
public static void main(String[] args) {
DocumentHandler dh=new DocumentHandler();
dh.createDoc();
System.out.println("end");
}
}
3. 生成的結(jié)果展現(xiàn)
4. 總結(jié)
這個(gè)工具生成word確切很方便,但是通過這兩天查找資料也發(fā)現(xiàn)這個(gè)工具也是有很多不足的地方的,畢竟不是甚么都是10全10美的。在網(wǎng)上找到1個(gè)帖子簡單的總結(jié)了1下這個(gè)工具的3個(gè)不好的地方,下面是連接地址有肯定的可以去看看。http://www.iteye.com/topic/17468
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)