FreeMarker + xml 導出word
首先介紹幾種java導出word方案
1、Jacob是Java-COM Bridge的縮寫,它在Java與微軟的COM組件之間構建一座橋梁。使用Jacob自帶的DLL動態鏈接庫,并通過JNI的方式實現了在Java平臺上對COM程序的調用。DLL動態鏈接庫的生成需要windows平臺的支持。
2、 Apache POI包括一系列的API,它們可以操作基于MicroSoft OLE 2 Compound Document Format的各種格式文件,可以通過這些API在Java中讀寫Excel、Word等文件。他的excel處理很強大,對于word還局限于讀取,目前只能實現一些簡單文件的操作,不能設置樣式。
3、 Java2word是一個在java程序中調用 MS Office Word 文檔的組件(類庫)。該組件提供了一組簡單的接口,以便java程序調用他的服務操作Word 文檔。
這些服務包括: 打開文檔、新建文檔、查找文字、替換文字,插入文字、插入圖片、插入表格,在書簽處插入文字、插入圖片、插入表格等。填充數據到表格中讀取表格數據 ,1.1版增強的功能: 指定文本樣式,指定表格樣式。如此,則可動態排版word文檔。
4、 iText操作Excel還行。對于復雜的大量的word也是噩夢。用法很簡單, 但是功能很少, 不能設置打印方向等問題。
5、 JSP輸出樣式基本不達標,而且要打印出來就更是慘不忍睹。
6、 用XML做就很簡單了。Word從2003開始支持XML格式,大致的思路是先用office2003或者2007編輯好word的樣式,然后另存為 xml,將xml翻譯為FreeMarker模板,最后用java來解析FreeMarker模板并輸出Doc。經測試這樣方式生成的word文檔完全符合office標準,樣式、內容控制非常便利,打印也不會變形,生成的文檔和office中編輯文檔完全一樣。
看過方案后就知道了 第 6 種方案效果好點,下面我們就舉個例子介紹下這個方案
首先要制作模板 模板里的需要傳入的數據用${data} 填充,在代碼里給其賦值即可
模板制作好后 ,點擊另存為 xml 文件 如:data.xml
如果xml需要動態填充 可以用
<!-- 循環開始 --> <#list personnelView as e></#list>
<!-- 循環結束 -->
下面是代碼
package com.asiainfo.boms.machineroom.action; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Map;
import org.apache.struts2.ServletActionContext;
import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; public class DocumentHandler {
private Configuration configuration = null;
public DocumentHandler() { configuration = new Configuration(); configuration.setDefaultEncoding("utf-8"); }
public Template getTemplate(){ configuration.setClassForTemplateLoading(this.getClass(), "/com/asiainfo/boms/machineroom/template"); Template t = null; try { // test.ftl為要裝載的模板 t = configuration.getTemplate("sg.xml"); t.setEncoding("utf-8"); } catch (IOException e) { e.printStackTrace(); } return t; }
public Writer getWriter(String jobId){ // 輸出文檔路徑及名稱 String savePath = ServletActionContext.getServletContext().getRealPath("/"); File file = new File(savePath+"upload"); if(!file.exists()){ file.mkdirs(); } File outFile = new File(savePath+"upload/machine"+jobId+".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(outFile), "utf-8")); } catch (Exception e1) { e1.printStackTrace(); } return out; }
public void createDoc(Template t,Map dataMap,Writer out) { try { t.process(dataMap, out); out.close(); } catch (TemplateException e) { e.printStackTrace();
} catch (IOException e) {
e.printStackTrace(); }
}
// private void getData(Map dataMap) { // // dataMap.put("title_name", "用戶信息"); // // dataMap.put("user_name", "李四"); // // dataMap.put("org_name", "微軟公司"); // // dataMap.put("dept_name", "事業部"); // // }
}
public String personnelImportWord() throws Exception{ String path = ServletActionContext.getServletContext().getRealPath("/"); String jobId = getStringParameter("job_id"); Map<String, Object> paraMap = new HashMap<String, Object>(); Map dataMap = new HashMap(); paraMap.put("jobId", jobId); DocumentHandler dh = new DocumentHandler(); Template t = dh.getTemplate(); Writer out = dh.getWriter(jobId); Map queryWFjobObj = ............. dataMap.put("COLUMN_1", queryWFjobObj.get("COLUMN_1")); dataMap.put("COLUMN_2", queryWFjobObj.get("COLUMN_2")); dataMap.put("COLUMN_3", queryWFjobObj.get("COLUMN_3")); dataMap.put("CLOB_1", queryWFjobObj.get("CLOB_1")); dataMap.put("DATE_1", queryWFjobObj.get("DATE_1")); dataMap.put("DATE_2", queryWFjobObj.get("DATE_2")); dataMap.put("COLUMN_4", queryWFjobObj.get("COLUMN_4")); Map mobileObj = ................. dataMap.put("CALLER", mobileObj.get("CALLER")); dataMap.put("STARTDATE", mobileObj.get("STARTDATE")); dataMap.put("MSISDN", mobileObj.get("MSISDN")); Map machineroomObj = ....................... dataMap.put("CALLER1", machineroomObj.get("CALLER")); dataMap.put("STARTDATE1", machineroomObj.get("STARTDATE")); dataMap.put("MSISDN1", machineroomObj.get("MSISDN")); List<Map> personnelView = ......................... dataMap.put("personnelView", personnelView); dh.createDoc(t, dataMap, out); fileName = "machine"+jobId+".doc";
return "personnelImportWord"; }
public InputStream getInputStream() throws Exception { String path = ServletActionContext.getServletContext().getRealPath("/"); File file = new File(path+"upload"); if(!file.exists()){ file.mkdirs(); } return new FileInputStream(path+"upload/"+fileName); }</pre>
下面再說幾種導出pdf 的方案
java生成pdf方案總結
1. Jasper Report生成pdf:設計思路是先生成模板,然后得到數據,最后將兩者整合得到結果。但是Jasper Report的問題在于,其生成模板的方式過于復雜,即使有IDE的幫助,我們還是需要對其中的眾多規則有所了解才行,否則就會給調試帶來極大的麻煩。
2. openoffice生成pdf:openoffice是開源軟件且能在windows和linux平臺下運行。
3. itext + flying saucer生成pdf:itext和flying saucer都是免費開源的,且與平臺無關,結合css和velocity技術,可以很好的實現。
一般使用第三種方案比較多,它實現的步驟是非常簡單的。
JAVA生成word優缺點對比
所用技術 |
優點 |
缺點 |
Jacob |
功能強大 |
代碼量大,設置樣式繁瑣;需要windows平臺支持,無法跨平臺 |
Apache POI |
讀寫excel功能強大、操作簡單 |
一般只用它讀取word,能夠創建簡單的word,不能設置樣式,功能太少 |
Java2word |
功能強大,操作簡單 |
能滿足一般要求,不支持07格式,國人開發的,參考資料較多,需要windows平臺支持 |
iText |
功能全,能滿足一般要求 |
不能直接生成或操作doc文檔,只能生成rtf格式的文檔,rtf也可以用word打開 |
JSP |
操作簡單,代碼量少 |
能把當前頁面導出簡單的word,不能設置樣式,美觀性差,無法操作word |
XML(最佳) |
代碼量少,樣式、內容容易控制,打印不變形,完全符合office標準 |
需要提前設計好word模板,把需要替換的地方用特殊標記標出來 |
JAVA生成pdf優缺點對比
所用技術 |
優點 |
缺點 |
openoffice |
本身就是office軟件,很容易設計一些文檔模板,支持java調用實現word轉換成pdf |
需要先安裝,設計好pdf模板樣式,然后用程序來填充那些預留好的變量 |
itext |
能滿足要求,本身提供了一些api |
無法識別很多html的tag和attribute,無法識別css,需要用其api函數來設置樣式 |
Jasper Report |
能滿足要求,市面上使用的比較多,相關文檔多 |
復雜,很難完全掌握,需要先設計模板,強依賴于IDE進行可視化編輯 |
flying sauser(最佳) |
能解析html和css輸出成image、pdf等格式,操作簡單,api強大 |
需要編寫freemarker或velocity模板,打造html,勾畫pdf的樣式 |