1. 程式人生 > >Java生成word/pdf解決方案

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的樣式