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

將Word文檔另存為XML格式,將后綴名“xml”修改成“ftl”,模板制作完成
圖片處理:
我們可以看到上面的模板中有圖片,當我們將xml修改成ftl以后打開文件可以看到原來圖片的位置全部都是亂碼。這是由于ftl不能夠辨認圖片,我們只要將這些亂碼用${image}替換掉既可以了。
循環處理:
模板中明細表中的數據是1個集合,我們需要循環遍歷才能夠將數據全部注入,這個時候我們就會用到了FreeMarker本身的語法了。
循環:
<#list array as bean>
${bean.property}
</#list>
代碼放在表格的開頭和結尾,也即是將表格中的標簽包括在循環里面,這模樣就能夠了。
在制作模板的進程中遇到的1個問題:${xxx}這些標記在ftl中被拆成1個1個的,讓我很無語。最后我還是手動的將這些又重新拼到1起了。
2. 準備數據,將上面模板中的${}的標簽放上對應的數據
首先要講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() {
// 要填入模本的數據文件
Map dataMap = new HashMap();
getData(dataMap);
// getTest(dataMap);
// 設置模本裝置方法和路徑,FreeMarker支持多種模板裝載方法。可以重servlet,classpath,
數據庫裝載,
// 這里我們的模板是放在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里寄存的數據Key值要與模板中的參數相對應
* @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", "進貨日期"+i);
map.put("product", "產品名稱"+i);
map.put("factory", "生產廠家"+i);
map.put("spec", "產品規格"+i));
map.put("number", "進貨數量"+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. 生成的結果展現
4. 總結
這個工具生成word確切很方便,但是通過這兩天查找資料也發現這個工具也是有很多不足的地方的,畢竟不是甚么都是10全10美的。在網上找到1個帖子簡單的總結了1下這個工具的3個不好的地方,下面是連接地址有肯定的可以去看看。http://www.iteye.com/topic/17468
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈