Java生成word/pdf解決方案
首先介紹幾種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>
<!-- 迴圈結束 -->
<!-- 迴圈開始 -->
<#list personnelView as e> // personnelView為迴圈集合
<w:tr wsp:rsidR="001E023B" wsp:rsidTr="004E45BD">
<w:tblPrEx>
<w:tblCellMar>
<w:top w:w="0" w:type="dxa"/>
<w:bottom w:w="0" w:type="dxa"/>
</w:tblCellMar>
</w:tblPrEx>
<w:trPr>
<w:trHeight w:val="405"/>
</w:trPr>
<w:tc>
<w:tcPr>
<w:tcW w:w="1920" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:pPr>
<w:jc w:val="center"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e_index +1}</w:t> //e_index 為索引從0 開始
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1083" w:type="dxa"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_1}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1142" w:type="dxa"/>
<w:gridSpan w:val="3"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:pPr>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_2}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1578" w:type="dxa"/>
<w:gridSpan w:val="3"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_3}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="1168" w:type="dxa"/>
<w:gridSpan w:val="2"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_4}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2181" w:type="dxa"/>
<w:gridSpan w:val="3"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="001E023B" wsp:rsidRDefault="001D2E3B" wsp:rsidP="004E45BD">
<w:r>
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${e.COLUMN_5}</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</#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);
}
下面再說幾種匯出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的樣式 |