Pentaho Report Designer


Pentaho Report Designer

 

https://blog.csdn.net/qq_41944754/article/details/81222180

Pentaho 報表使用指南
FOROSS
wushexu@163.com
2013/10
目錄
1  概述 ............................................................................................................................... 5
1.1  Pentaho .............................................................................................................................. 5
1.2  Pentaho Reporting ............................................................................................................. 5
1.3  示例數據庫 ....................................................................................................................... 5
1.4  一些資源 ........................................................................................................................... 6
2  設計報表 ........................................................................................................................ 7
2.1  簡單例子 ........................................................................................................................... 7
2.1.1  設置數據源 ................................................................................................................ 7
2.1.2  設置報表內容 ............................................................................................................ 8
2.2  報表結構 ........................................................................................................................... 9
2.3  文件格式 ......................................................................................................................... 10
2.3.1  文件格式 .................................................................................................................. 10
2.3.2  Schema ..................................................................................................................... 11
2.4  數據源 ............................................................................................................................. 12
2.4.1  JDBC .......................................................................................................................... 12
2.4.2  Metadata .................................................................................................................. 13
2.4.3  Pentaho Data Integration ......................................................................................... 14
2.4.4  OLAP ......................................................................................................................... 15
2.4.5  OLAP(Advanced) ....................................................................................................... 17
2.4.6  XML ........................................................................................................................... 18
2.4.7  Table ......................................................................................................................... 19
2.4.8  Advanced .................................................................................................................. 19
2.4.9  Community Data Access ........................................................................................... 21
2.5  表達式、函數 ................................................................................................................. 21
2.6  參數化報表 ..................................................................................................................... 23
2.7  子報表 ............................................................................................................................. 24
2.8  分組報表 ......................................................................................................................... 26
2.9  圖表 ................................................................................................................................. 28
2.10  國際化( i18n ) ........................................................................................................... 30
2.10.1  報表設置 .................................................................................................................. 30
2.10.2  資源加載 .................................................................................................................. 31
2.11  交叉報表 ...................................................................................................................... 31
2.11.1  Sql 查詢 .................................................................................................................... 32
2.11.2  報表設置 .................................................................................................................. 32
2.11.3  MDX 數據源 ............................................................................................................. 34
3  報表引擎 ...................................................................................................................... 36
3.1  libraries ............................................................................................................................ 36
3.2  報表模型 ......................................................................................................................... 36
3.2.1  接口 .......................................................................................................................... 36
3.2.2  類層次 ...................................................................................................................... 37
3.3  數據層 ............................................................................................................................. 39
3.3.1  TableModel .............................................................................................................. 39
3.3.2  DataFactory .............................................................................................................. 39
3.3.3  核心的 DataFactory 實現 ........................................................................................ 40
3.3.4  數據源擴展 .............................................................................................................. 41
3.3.5  DataRow 接口 .......................................................................................................... 42
4  嵌入應用 ...................................................................................................................... 43
4.1  引擎初始化 ..................................................................................................................... 43
4.2  加載報表 ......................................................................................................................... 43
4.3  讀取參數定義 ................................................................................................................. 43
4.4  注入參數 ......................................................................................................................... 44
4.5  報表輸出 ......................................................................................................................... 44
4.5.1  html .......................................................................................................................... 45
4.5.2  PDF ........................................................................................................................... 45
4.5.3  excel ......................................................................................................................... 46
4.6  編程方式創建報表 ......................................................................................................... 46
4.6.1  創建元素 .................................................................................................................. 46
4.6.2  預處理器 .................................................................................................................. 48
5  擴展報表 ...................................................................................................................... 49
5.1  表達式和函數 ................................................................................................................. 49
5.1.1  LibFormula ................................................................................................................ 49
5.1.2  報表表達式 .............................................................................................................. 49
5.1.3  報表函數 .................................................................................................................. 50
5.1.4  報表監聽器 .............................................................................................................. 50
5.2  實現表達式 ..................................................................................................................... 50
5.2.1  定義表達式類 .......................................................................................................... 50
5.2.2  定義元數據 .............................................................................................................. 51
5.2.3  使用及效果 .............................................................................................................. 53
5.3  實現函數 ......................................................................................................................... 55
5.3.1  定義函數類 .............................................................................................................. 55
5.3.2  定義函數描述類 ...................................................................................................... 56
5.3.3  資源文件 .................................................................................................................. 57
5.3.4  注冊函數 .................................................................................................................. 57
5.3.5  使用及效果 .............................................................................................................. 57
5.4  使用腳本語言 ................................................................................................................. 59
5.4.1  BSH ........................................................................................................................... 60
5.4.2  JavaScript .................................................................................................................. 60
5.5  實現報表元素 ................................................................................................................. 61
5.5.1  定義元素類型類 ...................................................................................................... 61
5.5.2  定義元素元數據 ...................................................................................................... 63
5.5.3  定義模塊類 .............................................................................................................. 64
5.5.4  定義讀寫處理器 ...................................................................................................... 64
5.5.5  使用及效果 .............................................................................................................. 65
1  概述
1.1  P ENTAHO
Pentaho 是 Java 平台上著名的商業智能(BI)項目。它包含多個產品以及產品插件、輔助工
具,包括 BI 平台(BI Platform)、ETL、報表、聯機分析、數據挖掘等。
Pentaho 有的產品分企業版(EE)和社區版(CE),主要的產品都有社區版,社區版的代碼和企業
版是一樣的。社區版已能提供完整的 BI 解決方案。
Pentaho 的 BI 平台,是一個 Java Web 應用(BI Server),通過插件方式擴展功能。它以流程
為中心,面向解決方案,增加一個需求就是增加一批(xml)配置文件,不需要寫代碼。
Pentaho 社區版官網:http://community.pentaho.com
1.2  P ENTAHO  R EPORTING
Pentaho Reporting 是 Pentaho 的報表解決方案。它原先是開源項目 JFreeReport,后來容納
進 Pentaho。Pentaho Reporting 采用的開源協議是 LGPL。
Pentaho 報表有兩種使用方式,一種是基於 BI Server(不需要寫代碼),一種是嵌入應用方
式(傳統 JFreeReport 的方式)。
報表主要通過報表設計器(Pentaho Report Designer, PRD)來定義。定義好的報表保存為后
綴為 prpt 的文件。
本文檔講述報表的結構、定義方式,報表引擎的報表模型、數據層,嵌入式報表引擎的使用
方式等。
Pentaho 報表可以使用多維分析(MDX 查詢)作為數據源,關於 MDX 查詢、多維分析方面
的內容,請參考文檔《Pentaho 多維分析使用指南》。
1.3  示例數據庫
PRD 本身帶了一個示例數據庫,在 resources/sampledata 目錄下,是一個 HSQL 數據庫(內
存數據庫)。這個數據庫可作為 Pentaho 報表的示例數據庫,也可作為 Pentaho Analysis(多
維分析)的示例數據庫。
這個數據庫或叫 SteelWheels,是一個銷售汽車模型的公司的銷售數據,包括雇員表、客戶
表、客戶地區表、產品表、銷售表等等。產品有產品線和供應商屬性。訂單有日期以及年份、
季度屬性。本文檔演示的例子只使用產品表(PRODUCTS)、銷售表(ORDERFACT)。
1.4  一些資源
官網  http://reporting.pentaho.com
文檔  http://wiki.pentaho.com/display/Reporting
代碼  https://github.com/pentaho/pentaho-reporting
API  http://javadoc.pentaho.com/reporting/
JIRA  http://jira.pentaho.com/browse/PRD
圖書  Pentaho Solutions: Business Intelligence and Data Warehousing with Pentaho and MySQL
圖書  Pentaho Reporting 3.5 for Java Developers
2  設計 報表
報 表 設 計 器 ( Pentaho Report Designer, PRD ) 是 一 個 Java 桌 面 程 序 。 從
http://reporting.pentaho.com/下載(在Report Creation Tools標題下)。Pentaho Report Designer
下載包已包含所有報表相關的庫。下載后解壓即可使用(假設預先設置了 JAVA_HOME 環境
變量)。
從 report-designer.bat(或 report-designer.sh)啟動 PRD。第一次啟動會顯示歡迎頁,右邊有
若干樣例,可供參考。歡迎頁也可從 Help 菜單打開(Welcome)。也可從歡迎頁進入新報
表向導(Report Wizard)開始體驗(或從 File 菜單進入)。
新建一個報表后,可看到如下界面:
最左邊是一列報表元素(可拖入報表),主區域是報表設計區域,右邊是 Structure(顯示報
表結構)、Data 信息,右下是 Style(元素樣式)、Attributes 設置區域。
2.1  簡單例子
這個例子使用示例數據庫 SampleData,查詢各產品線各年的銷售額。
2.1.1 設置數據源
打開右邊 Data 標簽頁,右鍵點擊 Data Sets 可看到可選擇的各種數據源類型。
這里選 JDBC,就可打開數據源、查詢設置界面。
左邊列出已定義的數據源,選擇第一個 SampleData 即可。PRD 會預先加載 SampleData 數據
庫,可通過 JNDI、 JDBC 或內存數據庫方式使用。
右邊是查詢設置區域。查詢關聯到某個數據源。
這里創建一個查詢 total_by_line_year:
SELECT
SUM("ORDERFACT"."QUANTITYORDERED") AS QUANTITYORDERED,
SUM("ORDERFACT"."TOTALPRICE") AS TOTALPRICE,
"PRODUCTS"."PRODUCTLINE",
"ORDERFACT"."YEAR_ID"
FROM
"ORDERFACT"  INNER  JOIN  "PRODUCTS"  ON  "ORDERFACT"."PRODUCTCODE"  =
"PRODUCTS"."PRODUCTCODE"
GROUP BY "PRODUCTS"."PRODUCTLINE","ORDERFACT"."YEAR_ID"
ORDER BY "PRODUCTS"."PRODUCTLINE","ORDERFACT"."YEAR_ID"
定義完后,在 Data Sets 下即可看到數據源和數據源下面的查詢。查詢可展開列出所有字段。
2.1.2 設置報表內容
先設置報表標題。從左邊的報表元素欄把 Label 拖到 Report Header,雙擊 Label 輸入標題。
再設置列表表頭。同樣是使用 Label 元素。
設置報表數據元素。可把從右邊查詢下的字段直接拖到 Details 中來,調整位置,和表頭對
齊。
設置后如下圖:
點擊左上角的預覽圖標(眼睛狀),可看到如下效果:
2.2  報表結構
從設計區以及 Structure 樹狀圖中可看出報表的結構,一般可分為這些部分:Page Header、
Report Header、Group Header、Detail Header、Detail/No Data、Detail Footer、Group Footer、
Report Footer、Page Footer、Watermark。
以下是一個典型的報表的結構圖:
Group 用來設置分組報表(在內存中對數據分組),每個報表都有一個 Group,即使沒有定
義。Detail 是根據數據行重復的部分,如果沒有數據,會顯示 No Data。Watermark 可用來
定義背景。
如果某個組件需要設置卻沒有在左邊顯示,可以設置它的屬性 hide-on-canvas 為 false,就可
以顯示出來。
2.3  文件格式
報表文件.prpt是一個.zip壓縮文件,內部使用 xml 文件,基本遵循 ODF規范(Open Document
Format)。
2.3.1 文件格式
.prpt 文件解壓縮后結構如下:
 layout.xml
描述整個報表的布局,以及所有的報表元素。
 styles.xml
樣式定義文件。
 settings.xml
配置、運行時參數文件,可從 PRD 的 File 菜單 Configuration.. 配置。
 datadefinition.xml
數據定義文件,包括參數、數據源、函數。數據源會引用 da tasources 下的文件。
 datasources/
此目錄存放數據源及查詢設置文件。
2.3.2 S CHEMA
所有的 xml 文件都有相應的 schema(xsd)文件,可從 http://jfreereport.sourceforge.net/ 下
載。
目前核心模式文件有:
config-description.xsd  content.xsd  core-types.xsd datadefinition.xsd
dataschema.xsd  layout.xsd  settings.xsd  styles.xsd
模式中數據源部分是一個復雜類型
compounddatafactory.xsd
kettle-datasource.xsd
pmd-datasource.xsd
此外,為保持后向兼容,還支持遺留的模式
2.4  數據源
這里介紹在 PRD 中可定義的數據源類型
報表引擎一章),很容易增加新的實現
表示報表引擎不支持。
這次數據源的實現一般位於報表引擎的擴展包中
界面位於 PRD 的擴展包中(
關於報表引擎的數據源接口和實現
在 PRD 中可選擇的數據源類型如下
2.4.1 JDBC
Jdbc 是最常用的數據源類型
的數據源,可以修改,也可以新增數據源
模式中數據源部分是一個復雜類型,可以擴展。以下是預定義的數據源模式
compounddatafactory.xsd  hibernate-datasource.xsd  inlinedatasource.xsd
mondrian-datasource.xsd  olap4j-datasource.xsd
sqldatasource.xsd  staticdatasource.xsd
還支持遺留的模式(在遵循 ODF 規范之前的)。
中可定義的數據源類型。由於 Pentaho Reporting 的數據層接口很
很容易增加新的實現,或擴展已有的實現,因此在 PRD
這次數據源的實現一般位於報表引擎的擴展包中(engine/extensions-*),在
(designer/ datasource-editor-*)。
關於報表引擎的數據源接口和實現,見“報表引擎”一章“數據層”一節。
中可選擇的數據源類型如下(點 Data 菜單或在 Data Sets 上點右鍵):
是最常用的數據源類型。數據源設置界面(見“簡單例子”一節)的左邊列出了已定義
也可以新增數據源。新建/修改數據源的界面如下:
模式:
inlinedatasource.xsd
datasource.xsd
staticdatasource.xsd
的數據層接口很簡單(見
PRD 中不能定義並不
在 PRD 中的定義

):
的左邊列出了已定義
這里的 Jdbc 設置包含三種方式獲得數據源
接設置 Jdbc 驅動類、主機、數據庫名等的方式創建
驅動來連接已有的 ODBC 數據源
2.4.2 M ETADATA
Pentaho Metadata 允許數據庫管理員為終端用戶定義一個基於
戶要面對數據庫模式的復雜性
(Common Warehouse Metamodel
Language(MQL) 是一個基於
設置界面如下:
設置包含三種方式獲得數據源,JDBC(Native)、ODBC 和 JNDI。JDBC(Native)
數據庫名等的方式創建 Jdbc 數據源,ODBC 通過 JDBC
數據源,JNDI 通過名字查找已有的 JDBC 數據源。
允許數據庫管理員為終端用戶定義一個基於關系數據的業務層
戶要面對數據庫模式的復雜性。Pentaho Metadata 使用的基於 XML 的文件來描述
Common Warehouse Metamodel)標准,后綴為.XMI。 Pentaho 的
是一個基於 XML 的查詢模型,簡化了查詢數據庫的工作。
JDBC(Native)是直
JDBC-ODBC Bridge

關系數據的業務層,避免了用
的文件來描述,遵循 CWM
的 Metadata Query
Metadata (Custom)只是定義一個 Metadata 數據源,沒有定義查詢。
2.4.3 P ENTAHO  D ATA  I NTEGRATION
Pentaho Data Integration 即 Kettle,是 Pentaho 的 ETL 解決方案。此數據源類型允許從 ETL
過程讀取數據。設置界面如下:
需要選擇一個 Kettle 文件(
運行期時依賴於 Kettle,需要把
2.4.4 OLAP
OLAP 數據源允許從一個多維分析引擎后端查詢數據
2.4.4.1 OLAP4J 、P ENTAHO  A
olap4j 是連接多維分析引擎、
驅動。olap4j 也包含一個 XMLA
Pentaho Analysis,即 Mondrian
而不是使用 olap4j 的 API。
OLAP4J、Pentaho Analysis 類型
的 MDX 查詢結果。它會把 columns
最后得到的 TableModel,根據數據內容
直接用於展示。這跟 Denormalized
例如定義以下 MDX 查詢:
.ktr),選擇一個轉換步驟。
需要把 Kettle 的相關庫加入到運行期的類路徑中。
數據源允許從一個多維分析引擎后端查詢數據,使用 MDX 語句來查詢
A NALYSIS
、執行多維分析查詢的一套 Java 標准 API。Mondrian
XMLA 的客戶端實現,因此也可以連接任何 XMLA
Mondrian,是 Pentaho 的多維分析引擎。這里表示直接連接
類型(包括 Denormalized 類型)的數據源,可以處理任意軸數量
columns 軸映射到 TableModel 的列上,其他軸映射到行上
根據數據內容,會增加相應的列,因此可以跟 SQL
Denormalized 類型的不一樣。

來查詢。
Mondrian 實現了 olap4j
XMLA 服務器。
這里表示直接連接 Mondrian,
可以處理任意軸數量
其他軸映射到行上。
SQL 查詢結果一樣,
SELECT
[Product].[Line].Members on rows,
{[Year].Members} on columns
FROM [orders]
WHERE [Measures].[Sales]
預覽查詢,結果如下:
可以看到,2003、2004、2005 出現在了列上。列數多少跟有多少個年份有關。
查詢得到的字段如下:
如果已知年份是這些,可以這樣定義數據源,在表頭增加這些年份的列即可。否則,要使用
Denormalized 的 OLAP 數據源,並定義交叉報表。
2.4.4.2 (D ENORMALIZED )
OLAP4J(Denormalized)、 Pentaho Analysis (Denormalized)兩種類型和 OLAP4J、Pentaho Analysis
不太一樣。Denormalized 是“反規格化”的意思,它並不把數據轉換成列頭,列頭跟維度對
應。實際上比起非 Denormalized 的版本,它需要做更少的處理。
例如,前面的查詢會得到結果:
可以看到,沒有把 2003、2004、2005 轉換成列頭,只有 year 列。
得到字段如下:
分組報表或交叉報表可以按 year 字段來分組。
2.4.4.3 (L EGACY )
OLAP4J(Legacy)、Pentaho Analysis(Legacy)兩種類型是遺留實現,它只能適用於不超過兩個軸
的 MDX 查詢結果。TableModel 實現內部,只是簡單地將 MDX 結果集的 columns 軸和 rows
軸映射為 TableModel 的列和行,獲取某行某列的數據時,直接從結果集讀取。
2.4.5 OLAP(A DVANCED )
OLAP(Advanced)跟 OLAP 的數據源實現是一樣的
源下並不定義查詢,查詢語句直接定義在元素的
詢。Custom 是指查詢是可以定制的
2.4.6 XML
XML 數據源允許從一個 XML
以下是設置界面:
需要指定一個 xml 文件,然后定義查詢
這里 result_set.xml 文件的內容如下
<?xml version="1.0" encoding="
<ResultSet>
<Row>
的數據源實現是一樣的,只是用 OLAP(Advanced)的方式定義
查詢語句直接定義在元素的 query 屬性上,或者通過編程的方式設置查
是指查詢是可以定制的。
XML 文件中查詢數據,使用 XPath。
然后定義查詢,查詢內容是 XPath 表達式。
文件的內容如下:
encoding="UTF-8"?>
的方式定義,數據
或者通過編程的方式設置查
<NAME>LibBase</NAME>
<DESCRIPTION>Base library containing common functions</DESCRIPTION>
<SIZE>113210</SIZE>
</Row>
<Row>
<NAME>LibLoader</NAME>
<DESCRIPTION>Loading and caching library</DESCRIPTION>
<SIZE>53552</SIZE>
</Row>
</ResultSet>
/*/Row 表示查詢第二級的 Row 元素,作為數據行,Row 的子元素名就是列名,子元素的文
本值就是列的值。
2.4.7 T ABLE
Table 類型數據源用來定義一個靜態的二維表,表的數據都是預定義的。一個查詢是一個二
維表,列可以根據需要增、刪、改名,如下圖:
2.4.8 A DVANCED
Advanced 包含其他一些數據源。
其中 JDBC (Custom)跟前面類似
的 query 屬性上,或通過編程方式設置
2.4.8.1 S CRIPTABLE
Scriptable 數據源允許從一段腳本代碼返回數據
javax.swing.TableModel 類型
以下是設置界面,以及 groovy
2.4.8.2 J AVA  M ETHOD  I NVOCATION
Java Method Invocation 數據源類型允許通過反射的方式
數據。可以指定類的構造函數和方法的參數
設置界面如下:
跟前面類似,它同樣是使用 JDBC 數據源,只是查詢是定制的
或通過編程方式設置。
數據源允許從一段腳本代碼返回數據。腳本語言有多個選擇,腳本代碼要返回
類型。
groovy 腳本例子:
NVOCATION
數據源類型允許通過反射的方式,從一個 Java 類調用一個方法得到
可以指定類的構造函數和方法的參數。
只是查詢是定制的,寫在元素
腳本代碼要返回
類調用一個方法得到
2.4.9 C OMMUNITY  D ATA  A CCESS
Community Data Access 數據源類型允許從 Pentaho BI Server 獲取查詢定義。需要設置 BI
Server 的服務器 URL,登錄的用戶名、密碼,Solution 名,路徑,查詢名等。
2.5  表達式、函數
元素的數據可以設置為一個字段(Field 屬性),或一個表達式(Value 屬性)。
例如要把金額轉換為萬元,則可以把 Value 屬性設置為”=[TOTALPRICE]/10000.0”。在表達式
里用方括號引用變量、參數或函數。
要使用預定義函數,需要先加入到報表中。在Data頁里functions上右鍵點擊Add function…,
加入需要的函數。
下面是選擇函數的窗口,可以看到有這些分類:
有的函數需要參數,需在函數屬性里設置參數。所有函數都有兩個屬性:名字和依賴級別。
名字(Name),用於在表達式、公式或其他函數中引用它。依賴級別(Dependency Level),
用於確定執行的順序。
要在報表的頁腳顯示頁碼就需要使用函數,選擇 Common 下的 Page of Pages 函數,再把它
到 Page Footer,即可顯示頁碼、總頁數。
以下示例在 Report Footer 加入了總數、總金額、平均金額。用了 Count、Sum 兩個聚集函數。
平均金額則是設置表達式”=[TotalGroupSumFunction0] / [TotalItemCountFunction1]”
結果如下:
關於表達式、函數更多的內容,請參考“擴展報表一章”。
2.6  參數化報表
通常報表都需要參數化,比如需要傳入日期參數。
可從 Data 頁里 Parameters 增加報表參數。比如這里要給報表增加一個年份參數 year,按如
下設置:
years 是一個預先定義的查詢,用來列出可選的年份:
select distinct YEAR_ID from ORDERFACT
Display Type 指定候選列表的展現方式,創建參數錄入界面時可依照此。
定義好參數以后,可在查詢中引用參數,使用${year}的形式:
SELECT
SUM("ORDERFACT"."QUANTITYORDERED") AS QUANTITYORDERED,
SUM("ORDERFACT"."TOTALPRICE") AS TOTALPRICE,
"PRODUCTS"."PRODUCTLINE"
FROM
"ORDERFACT"  INNER  JOIN  "PRODUCTS"  ON  "ORDERFACT"."PRODUCTCODE"  =
"PRODUCTS"."PRODUCTCODE"
WHERE "ORDERFACT"."YEAR_ID" = ${year}
GROUP BY "PRODUCTS"."PRODUCTLINE"
預覽報表,效果如下:
2.7  子報表
Pentaho 報表支持子報表,子報表幾乎包含所有主報表的屬性和子元素。子報表也可以帶參
數,也有查詢屬性,用來設置數據。主報表定義的查詢子報表都可以看到。
增加一個子報表通過拖入一個子報表元素。子報表在主報表中的放置有兩種方式,Inline 和
banded,inline 會在行內顯示,banded 會占據一整欄(類似 css 里 display: block)。
以下是一個子報表的示例,主報表查出產品線,子報表查詢產品線下的產品。定義界面見下
圖:
子報表需要定義報表參數,並映射到主報表參數或運行時變量。
在 Parameters 上右鍵 Edit sub-report parameters...增加子報表參數參數,定義后如下圖所示:
結果如下:
2.8  分組報表
當需要對數據進行分組顯示時,就需要分組報表。數據是一次查詢的,但是在內存內分組。
這里演示按產品線分組的銷售報表。先創建查詢 total_by_prod:
SELECT
SUM("ORDERFACT"."QUANTITYORDERED") AS QUANTITYORDERED,
SUM("ORDERFACT"."TOTALPRICE") AS TOTALPRICE,
"ORDERFACT"."PRODUCTCODE",
"PRODUCTS"."PRODUCTNAME",
"PRODUCTS"."PRODUCTLINE"
FROM
"ORDERFACT"  INNER  JOIN  "PRODUCTS"  ON  "ORDERFACT"."PRODUCTCODE"  =
"PRODUCTS"."PRODUCTCODE"
WHERE "ORDERFACT"."YEAR_ID" = ${year}
GROUP  BY  "PRODUCTS"."PRODUCTLINE","ORDERFACT"."PRODUCTCODE",
"PRODUCTS"."PRODUCTNAME"
ORDER  BY  "PRODUCTS"."PRODUCTLINE","ORDERFACT"."PRODUCTCODE",
"PRODUCTS"."PRODUCTNAME"
注意排序是必須的,報表引擎會假設數據是排好序的。
然后創建分組,在報表結構的根節點 Master Report 右鍵 add group。需要指定分組的字段(一
個或多個),這是分組的最重要屬性。其他的設置一樣。效果如下:
下面試兩級分組的例子,先按產品線分組再按供應商分組。查詢如下:
SELECT
SUM("ORDERFACT"."QUANTITYORDERED") AS QUANTITYORDERED,
SUM("ORDERFACT"."TOTALPRICE") AS TOTALPRICE,
"ORDERFACT"."PRODUCTCODE",
"PRODUCTS"."PRODUCTNAME",
"PRODUCTS"."PRODUCTLINE",
"PRODUCTS"."PRODUCTVENDOR"
FROM
"ORDERFACT"  INNER  JOIN  "PRODUCTS"  ON  "ORDERFACT"."PRODUCTCODE"  =
"PRODUCTS"."PRODUCTCODE"
WHERE "ORDERFACT"."YEAR_ID" = ${year}
GROUP  BY  "PRODUCTS"."PRODUCTLINE","PRODUCTS"."PRODUCTVENDOR",
"ORDERFACT"."PRODUCTCODE", "PRODUCTS"."PRODUCTNAME"
ORDER  BY  "PRODUCTS"."PRODUCTLINE","PRODUCTS"."PRODUCTVENDOR",
"ORDERFACT"."PRODUCTCODE", "PRODUCTS"."PRODUCTNAME"
效果如下:
2.9  圖表
Pentaho Reporting 采用了開源圖表工具 JfreeChart 來實現圖表功能。
拖入一個 chart 元素即可增加一個圖表,雙擊圖表元素即彈出設置界面,支持多種圖標類型。
 折線圖
以下是一個折線圖的示例。設置界面如下:
左邊是與展示相關的屬性,右邊是數據源設置。數據源設置的屬性含義如下:
category-column:用於確定分類(X 軸)的數據源列名
value-column:用於確定數值(Y 軸)的數據源列名
series-by-value:如果設置,值會作為序列(即折線)名稱 If set, values entered act as the series name for the value columns provided.
series-by-field:如果設置,數據源列會作為序列名稱,設置此屬性會把數值列切分為序列組
If set, fields entered act as the series name for the value column provided. Setting this property will slice the value column into series groups.
運行效果:
 餅圖
以下是一個餅圖的示例。
效果如下:
2.10 國際化( I 18 N )
多語言支持采用的是 Java 標准的做法:bundle 和 properties 文件。
2.10.1 報表設置
properties 文件可以存放於.prpt 內部,也可以存放於外部(Classpath 中)。可以從 File 菜單
的 Resources .. 創建、編輯 properties,這樣 properties 會存放於.prpt 內部。
編輯非 ascii 字符的 properties 文件,需要自己處理 native2ascii。
顯示多語言的文本,使用 resource-label 元素。
屬性 value 設置為 properties 文件的 key。
屬性resource-indentifier指示properties文件。如果properties文件為translations.properties,
resource-indentifier 屬性可不用設置,否則要設置成 properties 文件名。屬性 name 指示 Locale
名稱。如下圖:
2.10.2 資源加載
Pentaho Reporting 定 義 了 ResourceBundleFactory 接 口 來 加 載 語 言 資 源 文 件 。
ResourceBundleFactory 定義了以下兩個方法:
public ResourceBundle getResourceBundle(String key);
public Locale getLocale();
一個報表默認配置為使用 ResourceBundleFactory 的實現類 DefaultResourceBundleFactory,它
使用了 Java 的 ResourceBundle 實現。DefaultResourceBundleFactory 包含了 setLocale 方法。
ResourceBundleFactory 的另一個實現類 LibLoaderResourceBundleFactory(位於 util 包),它
使 用 了 LibLoader 的 方 式 來 加 載 。 LibLoader 是 一 個 可 擴 展 的 資 源 加 載 框 架 。
LibLoaderResourceBundleFactory 也包含了 setLocale 方法。
DefaultResourceBundleFactory 和 LibLoaderResourceBundleFactory 都包含了 setLocale 方法。
如果要設置 Locale,通過 ReportEnvironment 接口的實現類 DefaultReportEnvironment 是不錯
的選擇,DefaultReportEnvironment 包含定義了 setLocale 方法。
2.11 交叉報表
交叉報表,或叫多維報表,是很重要的報表類型。見下圖:
年份放在了列表頭上,但 2003、2004 並不是數據庫表的一個字段名,而是數據。這樣的報
表有多少列預先是不知道的,須查出數據后才能知道。這樣的報表需要報表引擎、報表設計
器的支持。
交叉報表實際也是分組報表,同樣是把數據在內存中分組。
2.11.1 S QL 查詢
交叉報表可以使用任何數據源。上面的圖是個產品線在各年的銷售額,sql 查詢如下:
SELECT
PRODUCTCODE, YEAR_ID, SUM(TOTALPRICE) AS TOTALPRICE
FROM ORDERFACT
GROUP BY PRODUCTCODE,YEAR_ID
ORDER BY PRODUCTCODE,YEAR_ID
和分組報表一樣,排序同樣是必須的。
下面的例子增加一個“季度”的維度,sql 查詢如下:
SELECT
PRODUCTCODE, YEAR_ID, QTR_ID, SUM(TOTALPRICE) AS TOTALPRICE
FROM ORDERFACT
WHERE YEAR_ID < 2005
GROUP BY PRODUCTCODE,YEAR_ID,QTR_ID
ORDER BY PRODUCTCODE,YEAR_ID,QTR_ID
效果如下:
2.11.2 報表設置
交叉報表在 PRD 中是一項體驗功能,需要自己啟用。打開 Edit 菜單的 Preferences...,把 Other
settings 下的 Enable (unsupported) experimental features 勾選即可。
這時在報表元素樹的根節點 Master Report 上打開右鍵,可看到 Add Crosstab Group(非禁用
的)。
Crosstab Group 分為 Crosstab Row Group 和 Crosstab Column Group,Row Group 表示行頭,
Column Group 表示列頭,Column Group 嵌套在最內層(總是會有)。
Row Group 和 Column Group 都有一個最重要的屬性,group,指示按哪個字段分組。
創建 Crosstab Group 后,左邊報表結構會出現 crosstab 這一欄。在 crosstab 里是不能夠拖拽
元素的,可以在樹狀圖的相應容器下點右鍵 Add Element 來加入元素, 元素屬性在下邊屬
性頁編輯。如下圖:
正如前面“數據源”一節所述,如果數據源采用的非 Denormalized 的 MDX 數據源,並且已
知道要分組的數據維度有多少列(即所有的取值),則不需要定義成交叉報表,甚至不需要
定義成分組報表。不過這樣報表定義里列頭就寫死了。
2.11.3 MDX 數據源
MDX 是多維查詢分析語言,比較適合作為交叉報表的數據源。使用 MDX 查詢,需要使用
OLAP 引擎 Pentaho Analysis(Mondrian),不過 PRD 的 lib 目錄已經包含相關庫了。
使用 mdx 查詢,需要一個 Schema 文件,這是一個 xml 文件,定義了數據立方體、維度、度
量等信息(提供給 Mondrian)。簡單的 Schema 示例如下:
<Schema name="of">
<Cube name="orders">
<Table name="ORDERFACT"/>
<Dimension name="Product">
<Hierarchy hasAll="true">
<Level name="product" column="PRODUCTCODE"/>
</Hierarchy>
</Dimension>
<Dimension name="Time">
<Hierarchy hasAll="true">
<Level name="year" column="YEAR_ID"/>
</Hierarchy>
</Dimension>
<Measure name="Sales" column="TOTALPRICE" aggregator="sum"/>
</Cube>
</Schema>
Mondrian 數據源有非 Denormalized(Banded)、Denormalized(以及 Legacy)類型,前面數
據源部分已介紹。這里數據源類型選擇 Pentaho Analysis(Denormalized),設置界面如下:
與 JDBC 數據源相比多了 Schema File 文件的設置,寫 sql 的地方變成了寫 mdx。
報表展現和 sql 數據源的差不多。
以下查詢增加了“季度”的維度,mdx 如下:
SELECT
[Product].Members on pages,
{[Year].[2003],[Year].[2004]} on rows,
[Quarter].Members on columns
FROM [orders]
WHERE [Measures].[Sales]
結果跟前面“Sql 查詢”的結果一樣。
3  報表 引擎
Pentaho Reporting 包含幾大部分:
  基礎庫(libraries)
  報表引擎核心(engine core)
其依賴於基礎庫。代碼是 org.pentaho.reporting.engine.classic.core.**
  報表擴展(extentions),包括各種數據源適配器,腳本支持等
  報表設計器(designer)
3.1  LIBRARIES
基礎庫有十幾個,基本都是名為 lib*,看名字就可知道用途。主要的庫如下:
libbase 
libcss 
libdocbundle  zip 包
libfonts 
libformat  文本格式化
libformula-ui  公式可視化編輯
libformula  公式庫,實現了 OpenFormula
libloader  資源加載與緩存
librepository  層次化存儲
libserializer 
libswing  設計器支持
libxml 
3.2  報表模型
.prpt 文件只是一個報表的定義,要展現此報表,需要把它解析成報表對象。一個報表用一
個 MasterReport 對象表示,解析.prpt 的過程就是構造 MasterReport 對象的過程。
MasterReport 對象包含很多屬性,包括子元素對象,數據源,參數定義等等。
這 里 介 紹 與 報 表 元 素 相 關 的 類 , 涉 及 的 類 和 接 口 都 位 於
org.pentaho.reporting.engine.classic.core 包。
3.2.1 接口
相關的接口就下面三個:
  ReportElement (extends Cloneable, Serializable)
  ReportDefinition
  RootLevelBand
3.2.1.1 R EPORT E LEMENT
用來布局的構件。持有樣式和屬性,並允許建立對克隆對象的引用,如果通過 ID 對象來克
隆的話。
3.2.1.2 R EPORT D EFINITION
表示一個報表(包括子報表)。定義了獲取報表 ReportHeader 、ReportFooter、PageHeader、
PageFooter、DetailsHeader、DetailsFooter、ItemBand、NoDataBand、PageDefinition、Watermark、
組(按序號)、頂級組、查詢名等方法(get*方法)。
3.2.1.3 R OOT L EVEL B AND 
RootLevelBand 是直接連接到一個報表定義或一個組的元素。用於內容創建時的入口點。
3.2.2 類層次
類數量不是很多,都是容器元素,因為很多元素(內容元素)都沒有對應的類,如 text-field、
number-field、label、message 等,它們由 ElementFactory(的子類)創建 Element 類的實例。
3.2.2.1  層次圖
  Element (implements filter.DataTarget, ReportElement)
  Section
  Band
  AbstractRootLevelBand (implements RootLevelBand)
  GroupFooter
  GroupHeader
  ItemBand
  NoDataBand
  ReportFooter
  ReportHeader
  CrosstabSummaryFooter (implements RootLevelBand)
  CrosstabSummaryHeader (implements RootLevelBand)
  CrosstabTitleFooter (implements RootLevelBand)
  CrosstabTitleHeader (implements RootLevelBand)
  DetailsFooter (implements RootLevelBand)
  DetailsHeader (implements RootLevelBand)
  PageFooter (implements RootLevelBand)
  PageHeader (implements RootLevelBand)
  Watermark (implements RootLevelBand)
  Group
  CrosstabColumnGroup
  CrosstabGroup
  CrosstabOtherGroup
  CrosstabRowGroup
  RelationalGroup
  GroupBody
  CrosstabColumnGroupBody
  CrosstabOtherGroupBody
  CrosstabRowGroupBody
  GroupDataBody
  SubGroupBody
  AbstractReportDefinition (implements ReportDefinition)
  MasterReport
  SubReport
有相當一部分是*Header、*Footer 類。下面介紹最重要的幾個。
3.2.2.2 E LEMENT 
Element 所有報表元素的基類。
如果是內容元素,當調用方法 getValue(function.ExpressionRuntime)時產生可打印的值。
所有元素都有一個非空的名稱,並有一個私有樣式表。
元素可以從它的父元素繼承所有的樣式。每當元素的樣式表沒有定義相應鍵的自己的值時樣
式值就會繼承。有些樣式鍵是不能被繼承的,這是會使用缺省樣式表。
全局樣式表總是會在父樣式表之前被查詢。增加樣式表的順序是重要的,后增加的樣式表會
比先增加的優先。
報表元素不能在不用報表實例間共享,加入元素到一個 band 會從另一個原來所屬的 band
刪除。
3.2.2.3 S ECTION
一個 section 允許訪問子元素,沒有定義怎樣增加或組織子元素。定義合理的順序留給子類實現。
3.2.2.4 B AND
一個 band 是其他元素或 band 的集合,類似一個 AWT 容器。
3.2.2.5 I TEM B AND
用於顯示一行數據。
3.2.2.6 W ATERMARK
用於在報表每一頁的背景打印信息。有禁止在第一頁和最后一頁打印的選項。
3.2.2.7 G ROUP
組可以包含任意數量的(嵌套的)組。分組字段的順序是不重要的。如果組沒包含任何分組
字段,則會展開報表的所有行(這樣的組叫缺省組)。
組包含 GroupHeader、GroupFooter、GroupBody(某個子類)子元素。GroupHeader 和
GroupFooter 都是一個 Band。
3.2.2.8 M ASTER R EPORT
MasterReport 表示一個主報表。
主 報 表 包 含 setBundle 、 setResourceBundleFactory 、 setParameterDefinition 、
setResourceManager、setDataFactory 等 setter 方法。
AbstractReportDefinition 是 MasterReport 和 SubReport 的基類,提供了公共實現。
3.2.2.9 S UB R EPORT
SubReport 表示一個子報表。
子報表可以綁定到頂級 band 並將會打印。子報表有它自己的 tablemodel,也可以有它自己
的 dataFactory。
子報表可以導入導出參數。參數映射可以自由定義,並不要求和父報表列名相同。
如果定義了全局導入或導出(通過增加參數映射"*" => "*"),其他定義的參數會被忽略。
3.3  數據層
Pentaho Reporting 有一個很簡單的數據層,引擎核心通過這一數據層來訪問數據,從而屏蔽
不同數據源的差異並保持數據源類型的多樣化。只要實現數據層的相關接口,就可以增加任
意類型的數據源。
數據層只有兩個關鍵接口 TableModel 和 DataFactory。
3.3.1 T ABLE M ODEL
這個 TableModel 就是 javax.swing.table.TableModel,Pentaho Reporting 沒有定義一個新的接
口。
TableModel 表示一個二維數據集,根據行號和列號可以取到數據。主要有以下方法:
int getRowCount()
int getColumnCount()
Object getValueAt(int rowIndex, int columnIndex)
String getColumnName(int columnIndex)
其他如修改數據和增加 swing 事件監聽器的方法沒有被使用。
core 包的 MetaTableModel 接口繼承了 TableModel,增加了獲取表格、列、單元格屬性的能
力。
3.3.2 D ATA F ACTORY
DataFactory 表示一個數據工廠,根據請求創建返回一個 TableModel 對象。主要方法有:
String[] getQueryNames()
boolean isQueryExecutable(String query, DataRow parameters)
TableModel queryData(String query, DataRow parameters)
MasterReport 和 SubReport 都有 setDataFactory 方法。
3.3.2.1 C OMPOUND D ATA F ACTORY S UPPORT
同樣在 core 包,DataFactory 有一個子接口,CompoundDataFactorySupport。它可以組合多
個 DataFactory,根據情況用其中一個 DataFactory 來執行查詢。
3.3.3 核心的 D ATA F ACTORY 實現
引擎核心包含了一些 DataFactory 的實現類,類層次如下:
  DataFactory
  TableDataFactory
  ExternalDataFactory
  CachingDataFactory(cache)
  StaticDataFactory(modules.misc.datafactory)
  NamedStaticDataFactory(modules.misc.datafactory)
  SimpleSQLReportDataFactory(modules.misc.datafactory.sql)
  SQLReportDataFactory(modules.misc.datafactory.sql)
  CompoundDataFactorySupport
  CompoundDataFactory
3.3.3.1 T ABLE D ATA F ACTORY
TableDataFactory 提供了按鍵來訪問預定義的二維表,它不接收參數,因此不能用於參數化
查詢。
3.3.3.2 E XTERNAL D ATA F ACTORY
允許使用作為參數傳入的 tablemodel 作為數據源。
3.3.3.3 C ACHING D ATA F ACTORY
類 CachingDataFactory 實現了 DataFactory 的子接口 CompoundDataFactorySupport,增加了對
查詢結果緩存的能力。
3.3.3.4 S TATIC D ATA F ACTORY
使用 Java 反射機制來搜索報表數據源。查詢可以是以下格式:
<full-qualified-classname>#methodName(Parameters)
<full-qualified-classname>(constructorparams)#methodName(Parameters)
<full-qualified-classname>(constructorparams)
3.3.3.4.1  N AMED S TATIC D ATA F ACTORY
子類 NamedStaticDataFactory 提供了查詢別名機制來解耦報表定義和底層的數據源實現。報
表不再需要指定原始查詢,取而代之的是在報表定義中使用一個符號名稱。
3.3.3.5 S IMPLE SQLR EPORT D ATA F ACTORY
SimpleSQLReportDataFactory 使用 JDBC 執行 SQL 查詢的數據工廠。它需要提供一個
ConnectionProvider 以便從中獲得 JDBC 連接。
ConnectionProvider 是一個接口,有 DriverConnectionProvider、JndiConnectionProvider、
StaticConnectionProvider 這幾個實現類。
3.3.3.5.1  SQLR EPORT D ATA F ACTORY
子類 SQLReportDataFactory 增加了用腳本語言定義 SQL 的能力。
3.3.3.6 C OMPOUND D ATA F ACTORY
CompoundDataFactory是 CompoundDataFactorySupport的實現類。可以組合多個DataFactory,
返回第一個能執行特定查詢的 DataFactory 的查詢結果。
CompoundDataFactory 的子類 CascadingDataFactory 是一個內部實現類,不應該使用它。
3.3.4 數據源擴展
針對不同的數據源類型,報表引擎提供了若干個數據源實現的擴展包。這些擴展包不屬於引
擎核心,它們位於 engine/extensions-*包。
每個數據源實現包含:DataFactory 和相應的 TableModel 實現,數據源 xml 定義文件的解析,
把數據源定義串行化到 xml 文件等幾部分。
3.3.4.1 M ONDRIAN
Mondrian 數 據 源 提 供 了 BandedMDXDataFactory 、 DenormalizedMDXDataFactory 、
LegacyBandedMDXDataFactory 這 幾 個 DataFactory 。 相 應 的 , 它 們 分 別 返 回
BandedMDXTableModel、DenormalizedMDXTableModel、LegacyBandedMDXTableModel 這幾
個 TableModel。
Banded 即 對 應 PRD 界 面 中 OLAP4J 、 Pentaho Analysis 類 型 , Denormalized 對 應
OLAP4J(Denormalized)、Pentaho Analysis(Denormalized)類型,Legacy 對應 OLAP4J(Legacy)、
Pentaho Analysis(Legacy)類型。
關於 Banded、Denormalized、Legacy 的區別,在前面(設計報表/數據源/OLAP)已介紹。
3.3.4.2 OLAP4J
與 Mondrian 數 據 源 類 似 , olap4j 數 據 源 也 有 對 應 的 BandedMDXDataFactory 、
DenormalizedMDXDataFactory、LegacyBandedMDXDataFactory 這幾個 DataFactory,以及
BandedMDXTableModel、DenormalizedMDXTableModel、LegacyBandedMDXTableModel 這幾
個 TableModel。
Banded、Denormalized、Legacy 的含義跟 Mondrian 一樣。
3.3.4.3 M ETADATA
Pentaho Metadata 已在前面(設計報表/數據源/Metadata)介紹,該數據源提供了使用 MQL
來查詢數據的能力。
Pentaho Metadata 數 據 源 提 供 數 據 工 廠 SimplePmdDataFactory 。 它 需 要 提 供 一 個
IPmdConnectionProvider 以 獲 得 JDBC 連 接 。 IPmdConnectionProvider 有 一 個 實 現 類
PmdConnectionProvider , 根 據 元 數 據 定 義 從 DriverConnectionProvider/
JndiConnectionProvider/ StaticConnectionProvider 獲取連接。
SimplePmdDataFactory的子類PmdDataFactory提供了腳本支持,跟前面SQLReportDataFactory
類似。
Pentaho Metadata 數據源依賴於 pentaho-metadata 項目。
3.3.4.4 K ETTLE
Kettle 數據源支持通過 ETL 過程來加載數據,它定義了數據源工廠 KettleDataFactory。它定
義的查詢是 KettleTransformationProducer 類型。
3.3.4.5 S CRIPTING
Scripting 數據源支持從一段腳本程序中獲取數據,它定義了數據源工廠 ScriptableDataFactory。
它使用了 apache 的 BSF 項目來管理多腳本語言。
3.3.4.6 XP ATH
XPath 數據源支持用 XPath 的方式讀取 xml 文件,定義了數據源工廠 XPathDataFactory。
3.3.5 D ATA R OW 接口
DataRow 的目的是使用一個統一接口來訪問 TableModel、報表參數、表達式和函數的(一行,
對 TableModel 而言)數據。DataRow 由引擎核心使用,跟數據源實現無關。它只有以下三
個方法:
Object get(String col)
String[] getColumnNames()
boolean isChanged(String name)
4  嵌入應用
實際使用 Pentaho 報表都是嵌入到應用中,這也是傳統 JfreeReport 的用法。這就需要寫代
碼來加載、操作報表。
4.1  引擎初始化
使用報表引擎,首先要初始化,只要做一次即可:
ClassicEngineBoot.getInstance().start();
ClassicEngineBoot位於引擎核心org.pentaho.reporting.engine.classic.core包,它繼承了LibBase
庫的 AbstractBoot 類,而后者又實現了 SubSystem 接口。
這個過程會加載報表引擎核心模塊,同時也加載一批報表擴展模塊,根據配置,也會加載額
外的模塊。
4.2  加載報表
從報表文件加載報表,需要使用ResourceManager類。ResourceManager類位於Libloader庫,
全限定名是:org.pentaho.reporting.libraries.resourceloader.ResourceManager。
ClassLoader classloader = this.getClass().getClassLoader();
URL reportDefinitionURL = classloader.getResource("reporting/Sample1.prpt");
ResourceManager resourceManager = new ResourceManager();
resourceManager.registerDefaults();
Resource directly = resourceManager.createDirectly(reportDefinitionURL, MasterReport.class);
MasterReport report = (MasterReport)directly.getResource();
這樣就得到了 MasterReport 對象,加載包含了報表定義解析、構造報表對象的過程。
可是這里只用了 libraries . resourceloader 包下的類,作為基礎庫是不了解 MasterReport 的結
構的,怎么就能夠構造出 MasterReport 對象呢?
實際上構造報表是 engine.classic.core 里面做的,MasterReport 是個 final 類,它有一個
ResourceManagerBackend屬性(可以從構造函數傳入),它通過調用ResourceManagerBackend
的方法來注冊資源工廠(org.pentaho.reporting.libraries.resourceloader.ResourceFactory 接口
的實現),而資源工廠是通過配置文件得到的。
4.3  讀取參數定義
很多報表都會需要參數,參數一般需要由用戶輸入。為了構建參數輸入界面,需要讀取報表
的參數定義。
表示報表參數定義的對象是 ReportParameterDefinition,MasterReport 類有
getParameterDefinition()方法,返回 ReportParameterDefinition 對象。參數相關的類一般位於
parameters 包。
ReportParameterDefinition 有以下方法:
int getParameterCount()
ParameterDefinitionEntry getParameterDefinition(int parameter)
ParameterDefinitionEntry[] getParameterDefinitions()
ReportParameterValidator getValidator()
ParameterDefinitionEntry 表示一個參數定義,從中可獲得參數的名稱、類型、缺省值、是否
必須等信息,用於生成報表參數的表單。
如果是一個列表參數,需要構建表單中該參數的候選值列表(下拉列表),可以這樣:
ParameterDefinitionEntry pde=//...
ParameterContext context = new DefaultParameterContext(report)
ListParameter lp=( ParameterDefinitionEntry)pde;
ParameterValues values = lp.getValues(context);
從 ParameterValues 可以讀取行數、每一行的 keyValue 和 textValue,從而可以構造列表參數
的候選列表。
4.4  注入參數
先從獲得報表的 ReportParameterValues 對象,在調用 put 方法傳入參數:
Map<String, Object> reportParameters = // ...獲得報表參數
if (null != reportParameters) {
ReportParameterValues rpv= report.getParameterValues();
for (String key : reportParameters.keySet()) {
rpv.put(key, reportParameters.get(key));
}
}
注入參數時要保證參數類型正確,如果需要一個 Integer 而傳入了 String,就會報錯。
4.5  報表輸出
pentaho 報表有多種輸出格式支持,它使用 itext、POI 等開源工具支持輸出。寫代碼時要用
到 org.pentaho.reporting.engine.classic.core.modules.output 包及子包的相關類。
輸出報表首先要得到一個輸出流( java.io.OutputStream ),可以來自文件或
HttpServletResponse。
報表輸出的過程就是報表處理的過程,ReportProcessor 是報表處理器,調用 processReport()
開始處理報表。
下面試多種輸出格式的示例。注意代碼要放在 try 里,最后保證關閉 reportProcessor:
OutputStream outputStream = //...
MasterReport report = //...
AbstractReportProcessor reportProcessor = null;
try {
//...
// reportProcessor = ...
// reportProcessor.processReport();
} finally {
if (reportProcessor != null) {
reportProcessor.close();
}
}
4.5.1  HTML
這里 StreamRepository 為 org.pentaho.reporting.libraries.repository.stream.StreamRepository,
位於 librepository 庫。
StreamRepository targetRepository = new StreamRepository(outputStream);
ContentLocation targetRoot = targetRepository.getRoot();
HtmlOutputProcessor outputProcessor = new
StreamHtmlOutputProcessor(report.getConfiguration());
HtmlPrinter printer = new AllItemsHtmlPrinter(report.getResourceManager());
printer.setContentWriter(targetRoot, new DefaultNameGenerator(targetRoot, "index", "html"));
printer.setDataWriter(null, null);
printer.setUrlRewriter(new FileSystemURLRewriter());
outputProcessor.setPrinter(printer);
reportProcessor = new StreamReportProcessor(report, outputProcessor);
reportProcessor.processReport();
4.5.2 PDF
final PdfOutputProcessor outputProcessor = new PdfOutputProcessor(
report.getConfiguration(), outputStream, report.getResourceManager());
reportProcessor = new PageableReportProcessor(report, outputProcessor);
reportProcessor.processReport();
4.5.3  EXCEL
final FlowExcelOutputProcess or target = new FlowExcelOutputProcessor(
report.getConfiguration(), outputStream, report.getResourceManager());
reportProcessor = new FlowReportProcessor(report, target);
reportProcessor.processReport();
4.6  編程方式創建報表
MasterReport 對象一般從.prpt 文件加載得到,但也可以通過代碼構造。如果加載得到的
MasterReport 對象需要調整,也可以通過代碼方式修改報表定義。
4.6.1 創建元素
下面的代碼不需要加載.prpt 文件,通過代碼構造報表和報表元素。
MasterReport report = new MasterReport();
//設置數據源,為演示,使用一個靜態數據源
DefaultTableModel tableModel = new DefaultTableModel(new Object[][] {
{ "libloader", 13405 }, { "libformula", 456938 } },new String[] { "名稱", "大小" });
final TableDataFactory dataFactory = new TableDataFactory();
dataFactory.addTable("default", tableModel);
report.setDataFactory(dataFactory);
// 增加公式和表達式
FormulaExpression formula = new FormulaExpression();
formula.setName("SizeKilobytes");
formula.setFormula("=[Size] / 1024");
report.addExpression(formula);
// 增加 header、footer
ReportHeader reportHeader = new ReportHeader();
ReportFooter reportFooter = new ReportFooter();
report.setReportHeader(reportHeader);
report.setReportFooter(reportFooter);
// 增加 item band
ItemBand itemBand = new ItemBand();
report.setItemBand(itemBand);
// 增加一個標簽到報表頭(作為標題)
//注意使用 LabelElementFactory 創建 Label
LabelElementFactory labelFactory = new LabelElementFactory();
labelFactory.setText("庫信息");
labelFactory.setX(1f);
labelFactory.setY(1f);
labelFactory.setMinimumWidth(100f);
labelFactory.setMinimumHeight(20f);
labelFactory.setBold(true);
Element label = labelFactory.createElement();
reportHeader.addElement(label);
// 增加列表表頭:庫名
TextFieldElementFactory textFactory = new TextFieldElementFactory();
textFactory.setFieldname("Name");
textFactory.setX(1f);
textFactory.setY(1f);
textFactory.setMinimumWidth(100f);
textFactory.setMinimumHeight(20f);
Element nameField = textFactory.createElement();
itemBand.addElement(nameField);
// 增加列表表頭:大小
NumberFieldElementFactory numberFactory = new NumberFieldElementFactory();
numberFactory.setFieldname("SizeKilobytes");
numberFactory.setX(101f);
numberFactory.setY(1f);
numberFactory.setMinimumWidth(100f);
numberFactory.setMinimumHeight(20f);
Element sizeField = numberFactory.createElement();
itemBand.addElement(sizeField);
這樣一個報表已構造完畢,按前面的方法處理報表、輸出即可。
效果如下:
4.6.2 預處理器
報表預處理器允許在生成報表前對報表進行操作,通過實現 ReportPreProcessor 接口並加入
到報表預處理器列表中。AbstractReportDefinition 類有 addPreProcessor(ReportPreProcessor
preProcessor)方法,作為 AbstractReportDefinition 的子類,MasterReport 和 SubReport 自然
都可以增加報表預處理器。
下面是一個例子,使用關系數據庫數據源,查詢客戶信息。不手工創建 item band 的元素,
根 據 數 據 源 的 元 數 據 自 動 增 加 元 素 。 關 鍵 在 於 使 用 了 報 表 預 處 理 器
RelationalAutoGeneratorPreProcessor,它是接口 ReportPreProcessor 的實現類。
final String QUERY_NAME = "ReportQuery";
final String QUERY_SQL = "select CUSTOMERNAME, CITY, STATE, POSTALCODE, COUNTRY
from CUSTOMERS";
final MasterReport report = new MasterReport();
report.setQuery(QUERY_NAME);
final DriverConnectionProvider dcp = new DriverConnectionProvider();
dcp.setDriver("org.hsqldb.jdbcDriver");
dcp.setUrl("jdbc:hsqldb:./sql/sampledata");
dcp.setProperty("user", "sa");
dcp.setProperty("password", "");
final SQLReportDataFactory dataFactory = new SQLReportDataFactory(dcp);
dataFactory.setQuery(QUERY_NAME, QUERY_SQL, null, null);
report.setDataFactory(dataFactory);
report.addPreProcessor(new RelationalAutoGeneratorPreProcessor());
5  擴展報表
Pentaho Reporting 有一套擴展系統的方式,能夠無侵入性地增加功能。這主要是通過定義模
塊、加載模塊的方式來實現的。本章主要講述創建自定義表達式、函數、報表元素的方法和
步驟。示例參考了《 Pentaho Reporting 3.5 for Java Developers》一書 。
5.1  表達式和函數
5.1.1 L IB F ORMULA
LibFormula 是一個提供公式支持的基礎庫,包括:公式解析、公式運算以及一批預定義的表
達式和函數。公式的語法基於 OpenFormula 標准。
5.1.1.1 F UNCTION 接口
接口 Function 是 LibFormula 中所有預定義的函數實現的接口。一個函數是一個任意的運算,
返回的值類型只有在函數運算完成后才可用。函數必須是無狀態的,這意味着,使用完全相
同的參數調用相同的函數必須總是返回相同的計算結果。
當需要自定義函數時,如果函數跟報表狀態無關,並且內部不需要訪問報表的當前數據行,
那么可以選擇實現 LibFormula 的 Function 接口。
Function 接口只有兩個方法:
TypeValuePair evaluate(FormulaContext context, ParameterCallback parameters)
String getCanonicalName()
5.1.2 報表表達式
在報表引擎核心模塊的 function 包有一個 Expression 接口,表示一個表達式。表達式不維護
狀態,因此是輕量級的函數。表達式用於在報表的一行內計算值,可以用一個 dataRow 變
量來訪問這個報表內當前行的其他字段、表達式或函數。
Expression 接口主要的方法有:
int getDependencyLevel()
String getName()
Object getValue()
DataRow getDataRow()
ExpressionRuntime getRuntime()
ResourceBundleFactory getResourceBundleFactory()
Configuration getReportConfiguration()
getValue 是表達式運算的方法,實現自定義表達式/函數時要實現的關鍵方法。
getDependencyLevel、getName 也有相應的 set 方法,一般在 PRD 界面會有這兩個屬性。
getDataRow 可以訪問當前數據行。DataRow 包含的方法前面(報表引擎/數據層/DataRow 接
口)已經提過。
AbstractReportDefinition 有 addExpression、removeExpression、getExpressions 和 setExpressions
方法可以維護報表的表達式。
5.1.3 報表函數
同樣在報表引擎核心模塊的 function 包,也有一個 Function 接口,表示一個報表函數。它跟
LibFormula 庫的 Function 接口沒有關系。它繼承了 Expression 接口,因此也可以訪問報表的
當前行數據。
除此之外,Function 也繼承了 ReportListener 接口(位於 event 包,它繼承了標記接口
java.util.EventListener)。當報表在生成時,函數能接收到事件通知,允許函數檢測報表生成
的過程,並維護內部狀態。
函數是有狀態的表達式。每當報表在生成過程改變它的狀態時,報表函數就會被調用。為了
支持報表引擎的 ReportState 實現,在某些檢查點,函數的工作模型基於函數狀態的克隆。
Function 有以下直接子接口:AggregationFunction、 LayoutProcessorFunction、 OutputFunction、
StructureFunction。
5.1.4 報表監聽器
Function的父接口ReportListener的方法如下:
void groupFinished(ReportEvent event)
void groupStarted(ReportEvent event)
void itemsAdvanced(ReportEvent event)
void itemsFinished(ReportEvent event)
void itemsStarted(ReportEvent event)
void reportDone(ReportEvent event)
void reportFinished(ReportEvent event)
void reportInitialized(ReportEvent event)
void reportStarted(ReportEvent event)
5.2  實現表達式
這里以一個例子來說明自定義表達式的步驟。這個自定義表達式用正則表達式來提取想要的
內容。需要傳入兩個參數,一個是原始字符串,一個是包含一個分組的正則表達式,表達式
運算結果是正則表達式匹配的第一個分組。
5.2.1 定義表達式類
所有的表達式都要實現 Expression 接口,這里先實現一個正則表達式類。可以繼承
AbstractExpression 類,它包含了 Expression 接口所有方法的空實現。
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import org.pentaho.reporting.engine.classic.core.function.AbstractExpression;
public class RegexExpression extends AbstractExpression {
private String regex;
private String field;
//getter、setter...
public Object getValue() {
try {
final Pattern p = Pattern.compile(regex);
final Object o = getDataRow().get(getField());
if (o == null) {
return null;
}
final Matcher m = p.matcher(o.toString());
m.find();
return m.group(1);
} catch (Exception e) {
return e.getMessage();
}
}
}
5.2.2 定義元數據
5.2.2.1  資源 文件
這是一個標准的 Java 資源文件包,包含表達式顯示名稱和分組(在選擇表達式/函數對話框
中的分組),每個屬性以及 dependencyLevel 的顯示名和分組(在屬性編輯界面的分組)。
dependencyLevel 指示公式的運算優先級。
這個文件應該位於表達式實現類的相同目錄,並命名為<類名>Bundle.properties,這個例子
就是 RegexExpressionBundle.properties。
display-name=Regex Expression
grouping=Other
property.field.display-name=Field Name
property.field.grouping=Other
property.regex.display-name=Regex
property.regex.grouping=Other
property.name.display-name=Name
property.name.grouping=Common
property.dependencyLevel.display-name=Dependency Level
property.dependencyLevel.grouping=Common
5.2.2.2  元數據 XML
還需要提供一個表達式元數據 XML 文件。文件名是沒關系的,后面由自己的 Module 類來加
載。這里把它叫 meta-expressions.xml。
一個表達式定義是一個 expression 節點,下面元素是表達式的屬性。expression 和 property
的 hidden 屬性指示是否在 PRD 中可見。
property 的 value-role 屬性指示屬性值所用於的角色,這有助於 PRD 確定要顯示的編輯器類
型。這些是合法的選項:Value、Resource、ElementType、Query、Field 和 Group。
<meta-data xmlns="http://reporting.pentaho.org/namespaces/engine/classic/metadata/1.0">
<expression class="RegexExpression" bundle-name="RegexExpressionBundle"
result="java.lang.String" hidden="false">
<property name="dependencyLevel" mandatory="false"
value-role="Value" hidden="false"/>
<property name="field" mandatory="true" value-role="Field" hidden="false"/>
<property name="regex" mandatory="true" value-role="Value" hidden="false"/>
<property name="name" mandatory="true" value-role="Name" hidden="false"/>
</expression>
</meta-data>
5.2.2.3  定義模塊類
為了在報表引擎注冊這個 XML 文件,還需要定義一個 Module 類。Module 是一個接口,位
於 LibBase 庫中。繼承 AbstractModule 類簡化了定義 Module 類的工作。
一個 Module 類應該有一個缺省函數,並調用 AbstractModule 的 loadModuleInfo 方法。這樣
可以加載必要的模塊配置文件。
initialize 方法內引用了剛才定義的 XML 文件 meta-expressions.xml。
import org.pentaho.reporting.engine.classic.core.metadata.ElementMetaDataParser;
import org.pentaho.reporting.libraries.base.boot.AbstractModule;
import org.pentaho.reporting.libraries.base.boot.ModuleInitializeException;
import org.pentaho.reporting.libraries.base.boot.SubSystem;
public class ExModule extends AbstractModule {
public ExModule() throws ModuleInitializeException {
loadModuleInfo();
}
public void initialize(final SubSystem subSystem) throws ModuleInitializeException {
ElementMetaDataParser.
initializeOptionalExpressionsMetaData("meta-expressions.xml");
}
}
5.2.2.4  模塊屬性文件
除了模塊類,還必須定義一個描述這個模塊的屬性文件,名為 module.properties。
module.name: exmodule
module.producer: foross
module.description: ..
module.version.major: 1
module.version.minor: 0
module.version.patchlevel: 0
dependency.core.module: org.pentaho.reporting.engine.classic.core.ClassicEngineCoreModule
dependency.core.dependency-type: required
dependency.core.version.major: 3
dependency.core.version.minor: 9
dependency.core.version.patchlevel: 1
5.2.2.5  注冊模塊
定義了模塊實現之后,還需要在報表報表引擎中注冊這個模塊。做法是,在包含這個模塊的
JAR 根 目 錄 , 增 加 一 個 屬 性 文 件 叫 classic-engine.properties , 里 面 包 含 一 個 屬 性
org.pentaho.reporting.engine.classic.extensions.modules.<Module Name>.Module,屬性的值是
這個模塊實現類的包含包名的完整類名:
org.pentaho.reporting.engine.classic.extensions.modules.exmodule.Module=ExModule
5.2.3 使用及效果
前面的文件都准備好之后,就可以把它們編譯成一個 JAR 包,放到 PRD 的類路徑(lib 目錄)
中,啟動 PRD,就可以檢查結果。
打開一個報表,點出增加函數對話框,可以看到函數分組中多了一個 Other,下面有一個
Regex Expression 函數,這就是前面自定義的函數:
把這個函數加入報表,選擇函數,可以看到下面的屬性編輯界面:
屬性顯示名稱和分組是在文件 RegexExpressionBundle.properties 設置的。
這里使用前面出現過的產品銷售報表來演示。給報表增加一列,取值是從產品編碼中提取的
前面部分數字。
按上圖設置這兩個函數屬性的值。把函數拖入報表中,加入表頭,調整位置、樣式。最后可
得到下面的效果:
5.3  實現函數
現在自定義一個跟前面功能一樣的函數。因為不需要訪問報表狀態和數據行,所以可以通過
實現 LibFormula 庫 Function 接口的方式來自定義函數。
5.3.1 定義函數類
首先要實現一個函數類,這里是 RegexFunction。重點是實現 evaluate 方法。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.pentaho.reporting.libraries.formula.EvaluationException;
import org.pentaho.reporting.libraries.formula.FormulaContext;
import org.pentaho.reporting.libraries.formula.LibFormulaErrorValue;
import org.pentaho.reporting.libraries.formula.function.Function;
import org.pentaho.reporting.libraries.formula.function.ParameterCallback;
import org.pentaho.reporting.libraries.formula.lvalues.TypeValuePair;
import org.pentaho.reporting.libraries.formula.typing.TypeRegistry;
import org.pentaho.reporting.libraries.formula.typing.coretypes.TextType;
public class RegexFunction implements Function {
public TypeValuePair evaluate(FormulaContext context,
ParameterCallback parameters) throws EvaluationException {
if (parameters.getParameterCount() != 2) {
throw new EvaluationException (LibFormulaErrorValue.
ERROR_ARGUMENTS_VALUE);
}
final TypeRegistry typeRegistry = context.getTypeRegistry();
final String param1 = typeRegistry.convertToText(parameters.getType(0),
parameters.getValue(0));
final String param2 = typeRegistry.convertToText(parameters.getType(1),
parameters.getValue(1));
try {
final Pattern p = Pattern.compile(param1);
final Matcher m = p.matcher(param2);
m.find();
return new TypeValuePair(TextType.TYPE, m.group(1));
} catch (Exception e) {
return new TypeValuePair(TextType.TYPE, e.getMessage());
}
}
public String getCanonicalName() {
return "REGEX";
}
}
5.3.2 定義函數描述類
需要為函數定義一個函數描述類。需要調用父構造函數的方法,以加載資源。
import org.pentaho.reporting.libraries.formula.function.AbstractFunctionDescription;
import org.pentaho.reporting.libraries.formula.function.FunctionCategory;
import
org.pentaho.reporting.libraries.formula.function.userdefined.UserDefinedFunctionCategory;
import org.pentaho.reporting.libraries.formula.typing.Type;
import org.pentaho.reporting.libraries.formula.typing.coretypes.TextType;
public class RegexFunctionDescription extends AbstractFunctionDescription {
public RegexFunctionDescription() {
// 確保調用父構造函數,帶上函數名和函數資源包名
super("REGEX", "Regex-Function");
}
// 把函數放到用戶自定義函數分類
public FunctionCategory getCategory() {
return UserDefinedFunctionCategory.CATEGORY;
}
public int getParameterCount() {
return 2;
}
public Type getParameterType(int position) {
return TextType.TYPE;
}
public Type getValueType() {
return TextType.TYPE;
}
public boolean isParameterMandatory(int position) {
return true;
}
}
5.3.3 資源文件
需要定義一個資源文件用於界面顯示。這里叫 Regex-Function.properties。
display-name=REGEX
description=Executes a regular expression on a string, returning the first found group
parameter.0.display-name=Regular Expression
parameter.0.description=A Java Regular Expression string, with a grouping defined within the
string.
parameter.1.display-name=String Input
parameter.1.description=A string to parse.
5.3.4 注冊函數
為了把函數注冊到 LibFormula 模塊,需要增加一個名為 libformula.properties 的屬性文件,
內容如下:
org.pentaho.reporting.libraries.formula.functions.information.Regex.class=RegexFunction
org.pentaho.reporting.libraries.formula.functions.information.Regex.description=RegexFunction
Description
5.3.5 使用及效果
編譯並把目標文件加入 PRD 類路徑后,重啟 PRD。下面在前面的報表再加一列,取產品編
碼的后面部分數字。
增加 Minor 一列(原來加的一列改為了 Major),在 Detail 里加以 text-field。如下圖:
編輯這個 text-field 的 value 屬性,點后面 Expr 一列(如果改過,會變為筆狀):
彈出表達式編輯框:
可以在這里直接編輯,也可以點后面的按鈕彈出公式編輯器:
按上面輸入表達式,運行報表,可看到結果:
5.4  使用腳本語言
另一種實現自己的報表表達式的辦法是使用腳本語言。不過這樣的話表達式僅限於當前報表
使用。
下面的的例子仍然實現前面一樣的功能。
5.4.1 BSH
這里用 Bean-Scripting-Host(BSH)來實現一個表達式。打開函數對話框,展開 Script 分組,選
擇 Bean-Scripting-Host。
按下面設置 Expression 屬性:
import java.util.regex.*;
Object getValue() {
final Pattern p = Pattern.compile("S(\\d+)_.*");
final Matcher m = p.matcher(dataRow.get("PRODUCTCODE"));
m.find();
return m.group(1);
}
即設置完畢(未處理異常)。把函數拖入報表即可。
5.4.2 J AVA S CRIPT
用 Javascript 來實現。選擇 Script下面的 JavaScript 函數,或者選擇 Bean-Scripting
Framework(BSF)並把表達式編程語言屬性設置為 javascript。
Expression 屬性按如下設置:
dataRow.get("PRODUCTCODE").match(/S(\d+)_.*/)[1]
即可完成。
5.5  實現報表元素
Pentaho Reporting 同樣允許自定義報表元素。這個例子自定義一個多角星的元素,僅僅渲染
一個多角星。有幾個角、起始角度、內圓比例可以作為參數傳入。
5.5.1 定義元素類型類
首先定義一個 ElementType 實現類,在 getValue 方法內繪制一個星形。注意使用了名空間
http://reporting.pentaho.org/namespaces/pr4jd。
import java.awt.Polygon;
import java.util.Locale;
import org.pentaho.reporting.engine.classic.core.Element;
import org.pentaho.reporting.engine.classic.core.function.ExpressionRuntime;
import org.pentaho.reporting.engine.classic.core.metadata.ElementMetaData;
import org.pentaho.reporting.engine.classic.core.metadata.ElementType;
import org.pentaho.reporting.engine.classic.core.metadata.ElementTypeRegistry;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleKeys;
import org.pentaho.reporting.engine.classic.core.style.ElementStyleSheet;
import org.pentaho.reporting.engine.classic.core.util.StringUtil;
public class StarType implements ElementType {
private static String NAMESPACE = "http://reporting.pentaho.org/namespaces/pr4jd";
private transient ElementMetaData elementType;
public StarType() {
}
public ElementMetaData getMetaData() {
if (elementType == null) {
elementType = ElementTypeRegistry.getInstance().getElementType("star");
}
return elementType;
}
public Object getValue(final ExpressionRuntime runtime, final Element element) {
if (element == null) {
throw new NullPointerException("Element must never be null.");
}
final float innerPercent = parseParam(element, "inner-percent", 0.5f);
final float startAngle = parseParam(element, "start-angle", 0f);
final int points = (int) parseParam(element, "points", 5);
int outerRadius = 100;
int innerRadius = (int) (outerRadius * innerPercent);
double startingRotation = (startAngle - 90) * Math.PI / 180;
double angleIncrement = 2.0 * Math.PI / points;
double currRadians = startingRotation;
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
final Polygon p = new Polygon();
for (int i = 0; i < points; i++) {
double outerX = outerRadius + outerRadius * Math.cos(currRadians);
double outerY = outerRadius + outerRadius * Math.sin(currRadians);
double innerX = outerRadius + innerRadius
* Math.cos(currRadians + angleIncrement / 2);
double innerY = outerRadius + innerRadius
* Math.sin(currRadians + angleIncrement / 2);
p.addPoint((int) outerX, (int) outerY);
p.addPoint((int) innerX, (int) innerY);
currRadians += angleIncrement;
minX = Math.min((int)outerX, minX);
minY = Math.min((int)outerY, minY);
}
if (minX > 0 || minY > 0) {
final Polygon p2 = new Polygon();
for (int i = 0; i < p.npoints; i++) {
p2.addPoint(p.xpoints[i] - minX, p.ypoints[i] - minY);
}
return p2;
} else {
return p;
}
}
public Object getDesignValue(final ExpressionRuntime runtime, final Element element) {
return getValue(runtime, element);
}
public void configureDesignTimeDefaults(final Element element, final Locale locale) {
ElementStyleSheet style= element.getStyle();
style.setStyleProperty(ElementStyleKeys.SCALE, Boolean.TRUE);
style.setStyleProperty(ElementStyleKeys.DRAW_SHAPE, Boolean.TRUE);
style.setStyleProperty(ElementStyleKeys.MIN_WIDTH, new Float(100));
style.setStyleProperty(ElementStyleKeys.MIN_HEIGHT, new Float(100));
element.setAttribute(NAMESPACE, "inner-percent", 0.5f);
element.setAttribute(NAMESPACE, "start-angle", 0f);
element.setAttribute(NAMESPACE, "points", 5);
}
private float parseParam(final Element element, final String attrName, float defaultValue) {
final float val;
final Object attrib = element.getAttribute(NAMESPACE, attrName);
if (attrib != null) {
if (attrib instanceof Number) {
final Number n = (Number) attrib;
val = n.floatValue();
} else {
val = StringUtil.parseFloat(String.valueOf(attrib), defaultValue);
}
} else {
val = defaultValue;
}
return val;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
5.5.2 定義元素元數據
像自定義表達式一樣也需要元數據 XML。這里用文件名 meta-elements.xml。
<meta-data xmlns="http://reporting.pentaho.org/namespaces/engine/classic/metadata/1.0">
<include-globals
src="res://org/pentaho/reporting/engine/classic/core/metadata/global-meta-elements.xml"/>
<element name="star" hidden="false" bundle-name="metadata" implementation="StarType">
<attribute-group-ref ref="common-attributes"/>
<attribute-group-ref ref="interactivity"/>
<attribute namespace="http://reporting.pentaho.org/namespaces/pr4jd"
name="inner-percent" mandatory="true" hidden="false"
value-type="java.lang.Number" value-role="Value"/>
<attribute namespace="http://reporting.pentaho.org/namespaces/pr4jd"
name="start-angle" mandatory="true" hidden="false"
value-type="java.lang.Number" value-role="Value"/>
<attribute namespace="http://reporting.pentaho.org/namespaces/pr4jd" name="points"
mandatory="true" hidden="false"
value-type="java.lang.Number" value-role="Value"/>
<style-group-ref ref="borders"/>
<style-group-ref ref="common"/>
<style-group-ref ref="layout"/>
<style-group-ref ref="replaced-content"/>
</element>
</meta-data>
5.5.3 定義模塊類
和自定義表達式一樣,需要定義一個模塊類。如果跟別的自定義表達式同一個模塊,就用同
一個模塊類(ExModule),在 initialize 方法加上一行,meta-elements.xml 引用了剛才的文
件:
ElementMetaDataParser.initializeOptionalElementMetaData("meta-elements.xml");
5.5.4 定義讀寫處理器
讀寫處理器用於解析元素定義的 XML 和把元素定義串行化到 XML。
5.5.4.1  讀處理器
用類名 StarReadHandler:
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.layout.elements.
AbstractElementReadHandler;
import org.pentaho.reporting.libraries.xmlns.parser.ParseException;
public class StarReadHandler extends AbstractElementReadHandler {
public StarReadHandler() throws ParseException {
super("star");
}
}
5.5.4.2  寫處理器
用類名 StarWriteHandler:
import java.io.IOException;
import org.pentaho.reporting.engine.classic.core.Element;
import
org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleWriterException;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.BundleWriterState;
import org.pentaho.reporting.engine.classic.core.modules.parser.bundle.writer.
elements.AbstractElementWriteHandler;
import org.pentaho.reporting.libraries.docbundle.WriteableDocumentBundle;
import org.pentaho.reporting.libraries.xmlns.common.AttributeList;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriter;
import org.pentaho.reporting.libraries.xmlns.writer.XmlWriterSupport;
public class StarWriteHandler extends AbstractElementWriteHandler {
private static final String NAMESPACE = "http://reporting.pentaho.org/namespaces/pr4jd";
public StarWriteHandler() {
}
public void writeElement(final WriteableDocumentBundle bundle,
final BundleWriterState state, final XmlWriter xmlWriter,
final Element element) throws IOException, BundleWriterException {
if (bundle == null) {
throw new NullPointerException();
}
if (state == null) {
throw new NullPointerException();
}
if (xmlWriter == null) {
throw new NullPointerException();
}
if (element == null) {
throw new NullPointerException();
}
final AttributeList attList = createMainAttributes(element, xmlWriter);
if (xmlWriter.isNamespaceDefined(NAMESPACE) == false) {
attList.addNamespaceDeclaration("pr4jd", NAMESPACE);
}
xmlWriter.writeTag(NAMESPACE, "star", attList,
XmlWriterSupport.OPEN);
writeElementBody(bundle, state, element, xmlWriter);
xmlWriter.writeCloseTag();
}
}
5.5.5 使用及效果
加載目標文件,啟動 PRD 后,可看到元素選擇欄多了個星形圖標,這就是剛才自定義的元
素:
把它拖進報表,設置屬性。元素定義了三個自己的屬性:
設置好屬性,再在樣式里設上填充色,可看到以下效果(設計和預覽都是一樣的):


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM