前些日子做了一個WEB報表工具類庫,功能是在Word中定製表格。下文是設計文檔。這個工具不大,而且有重新發明輪子的嫌疑,唉!不過既然已經做出來了,總不能扔掉吧。如有興趣可以下載試試看。共同進步!
下載地址:http://icecloud.51.net/soft/ireport.rar
iReporter包設計文檔
冰雲 2004.1.5
版權所有 (C) 冰雲
1 目標功能
目前項目中的報表等方面都是直接通過IE打印。將數據轉換成一個長字符串,然後經過JavaScript分割並填充到表格中。這種方法效率低並且難以進行格式定製。
有的客戶希望能夠通過Word來打印,並且能夠定製表頭等方面。在每頁都要顯示固定的表頭。並且支持多個表格打印在同一文件中。
系統需要一個通用的模塊來完成這項任務。
本模塊就是爲了這一目標來設計。
2 用例說明
A 可通過一個模版來定製一份報表
B 用戶輸入若干List數據,可以將每個List轉換成一個表格
C 可定製頁面頭腳
D 可定製多個表格的頭,並且表頭固定於每一頁
E 多個表格之間要進行分頁
F 模版中可以定義表格樣式
G 可以通過一個URL生成一份報表
3 關鍵技術
A Doc文件的生成:
DOC文件格式是微軟專利,用Java很難直接生成doc文件。經過討論與試驗,發現IE可以將任意一個後綴名爲doc的HTML文檔當作Word來打開。因此,採用生成HTML的方式來取代word生成。待生成doc文件格式不是難題的時候,可以通過修改實現來完成。
B 固定表頭
經過試驗,在Word中固定表頭可以通過<THEAD>標籤來完成。而將<Caption>標籤放入<THEAD>,可以實現每頁都顯示錶名在頂部。
C 表間分頁
表間分頁在Word中是通過一個樣式來指定的。<P style=”page-break:always”>
D 對任意List生成表格
對任意List生成表格,要求List中的對象必須是標準的JavaBean對象,即只有get,set方法的對象。生成表格將依照模版中對該JavaBean的屬性名稱的引用而成。如getName(),則在模版中寫#name#。這項功能通過jakarta的commons-beanutils包來實現。
E XML模版
定製模版採用XML文件,其格式參見下文。XML解析通過DOM4J來實現。這個包的特點是靈活易用,速度比JDOM要快。
4 接口設計
本包主要由Report,ReportBuilder和TemplateParser三個接口組成。其中Report是最終返回給用戶的結果。ReportBuilderFactory是建立ReportBuilder的工廠。ReportFacade是提供給調用者的代理方法。本包主要異常爲ReportException,是Unchecked Exception。
5 使用方式
使用實例請參見DemoServlet.java
A 通過模版建立文檔報表
PrintWriter out = response.getWriter();
// 建立新的DocumentBuilder,工廠方法,現在僅支持Word參數 ReportBuilder builder = ReportBuilderFactory.getBuilder("Word");
// 爲Template建立InputStream InputStream is = new FileInputStream(new File("d:\\template.xml"));
// 將is給builder builder.setTemplate(is);
// 建造List List list = new ArrayList();
// 構造數據,其中的數據必須是JavaBean形式 ... list.add(JavaBean) ...
// simpletable應改與模版中的表格名稱一致,如id="simpletable" builder.addData(list1, "simpletable"); builder.addData(list2, "styledtable");
// 構造並返回內容,默認將採用ISO-8859-1編碼 Report doc = builder.buildReport();
// 輸出或保存 doc.save(new File("d:\\a.doc"), "ISO-8859-1"); doc.print(out);
|
B 通過URL建立文檔
// 建立新的DocumentBuilder,工廠方法,現在僅支持Word參數 ReportBuilder builder = ReportBuilderFactory.getBuilder("Word");
// 構造report Report report = builder.buildReport(new URL("http://www.hjsm.net"));
// 輸出 report.print(System.out);
|
6 設計類圖
com.zotn.util.report.wordimpl是上述接口的Word/XHTML實現。其主要是運用DOM4J解析模版,將數據與模版拼裝,生成最終XHTML代碼的過程。
Tree用於構建一個樹形結構,保存模版生成的節點信息。XMLTree是其實現類
TreeNode,保存每個模版節點,XMLTreeNode是其實現類
NodeVisitor,遍歷每個節點的Visitor,每個功能對應一個NodeVisitor
GenericXMLParser,是TemplateParser的實現類,用於分析模版
DataHolder,用於保存原始輸入數據
ReportHandler,實現了DataHandler,用於處理輸出結果並構造Report
WordTableReportBuilder,ReportBuilder的實現類
下圖是實現的簡圖。
7 已知缺陷
A 當前版本無法處理動態頁碼的問題。
B 不支持其他格式的輸出
C 對於URL的解析,無法處理相對路徑的圖片,樣式表等。
8 第三方庫
Dom4J; 用於xml解析
Jakarta Commons Logging; 用於記錄日誌
Jakarta Commons Lang; 用於字符串共用方法
Jakarta Commons BeanUtils; 用於處理JavaBean
Jakarta Commons Collections; BeanUtils需要
Jakarta ORO; 處理正則表達式
9 相關軟件
在主提供能已經完成的後,我偶然注意到了JasperReport這個開源項目。它是一個專業報表庫,可將數據轉換爲HTML,XML,PDF,XLS等格式報表。也是通過定義一個模版來定製格式。因此,很不幸,我重新發明了輪子,而且還是個不圓的輪子。
模版文件
<?xml version='1.0' encoding='ISO-8859-1'?>
<!-- 默認採用ISO-8859-1編碼 -->
<!-- ROOT元素,一般不需要變 -->
<word>
<!-- 頁面頭,內容可以寫任意HTML,但尖括號應用<>代替 -->
<header><![CDATA[
<P align="center">頁頭</P>
]]></header>
<!-- 第一個表格,表格別名用id表示 -->
<table id="simpletable">
<!-- 表格數據 -->
<tbody>
<!-- 每個TD單元格內,寫 #屬性名# ,name屬性表示表頭-->
<td name="名稱">#name#</td>
<td name="顏色">#color#</td>
<td name="顏色">#price#</td>
</tbody>
</table>
<!-- 第二個表格,表格參數(與HTML相同)可作爲屬性或節點添加 -->
<table id="styledtable" width="600">
<!-- 表格的樣式,如邊框寬度等可當作節點 -->
<style>color:blue;border:1px solid black</style>
<!-- 複雜表頭表格,TR表示行,TH表示單元表格 -->
<thead>
<!-- 固定表格頭 -->
<caption style="color:red"><![CDATA[
<font size="+2">固定表格頭</font>
]]></caption>
<tr><th colspan="2" style="color:green">屬性</th><th>價值</th></tr>
<tr><th colspan="2">屬性2</th><th>價值2</th></tr>
</thead>
<!-- 數據 -->
<tbody>
<td name="名稱" style="color:red">#name#</td>
<td name="顏色" width="12">#color#</td>
<td name="價格" width="10%">#price#</td>
</tbody>
</table>
<!-- 頁面腳 -->
<footer><![CDATA[
<p>頁腳</P>
]]></footer>
</word>