ireport 4.5教程之交叉表,本文介紹ireport中交叉表的具體實現方法
工具/原料
ireport
方法/步驟
一個CrossTabs是一種在設計的時候既不確定行數和也不確定列數的一種表格,在運行環境下它會像下面顯示的不同年份的一個銷售報表一樣。
CrossTabs在jasperresports中從1.1.0版本時開始提供,同時iReport也從1.1.0開始支持CrossTabs。
Jasperreports的CrossTabs工具允許對行和列的數據進行分組、彙總和自定義每一個cell裡的內容。填充CrossTab的數據可以來自主報表裡的dataset或來自subDataset。使用iReport裡提供的嚮導我們可以簡單快速的創建功能強大的交叉報表組件。
一個CrossTabs本質上是一個表格,行和列的數量取決於填充這個表格的數據。行和列也可以在groups裡做聚合操作。對於每一個行或列的group我們都可以得到一個細節信息和一個可選的行列數據的彙總。
交叉表嚮導 (Crosstab wizard)
為了說明怎麼讓一個crosstab工作起來,我們將使用嚮導創建一個crosstab,當我們在工具條裡選擇crosstab元素並將其添加到報表中時crosstab的嚮導會自動啟動。
還是以DoradoSample裡提供的hsql數據裡的employee報為例,我們使用包含下面查詢語句的空報表開始:
Select * from employee
我們把crosstab放在報表的底部:summary band
在第一步裡我們需要選擇一個dataset來填充crosstab,我們這裡使用主報表裡提供的dataset,點擊下一步繼續。
在第二步裡我們需要定義至少一個行分組.我們這裡選擇對所有記錄使用DEPT_ID進行分組。這樣就意味著crosstab的每一行將會採用一個明確的部門編號,這樣JasperReports將會使用部門編號對數據集裡的數據進行重新整理計算。使用嚮導,我們可以定義兩個行分組,這是使用嚮導的侷限性所在,事實上,如果你需要的話你可以通過Crosstab的屬性設置窗口定義若干個行和列的分組。點擊下一步繼續。
和定義行分組一樣,從這裡我們可以定義兩個列分組,這裡我們僅使用一個列分組,使用數據中的DEGREE字段對數據進行分組。該字段的含義是學歷,這就表示,我們要做的這個交叉報表是用來計算不同部門員工在學歷方面的人數分佈情況。
是時候定義detail 數據了,一般的,這個detail是使用類似根據country,year得到orders總數或者是相同組合的物品總數的一個聚合函數的計算出來的結果值。我們這裡選擇打印員工的數量(Detail field:ordered,function:count)。點擊下一步繼續。
最後一步我們可以為crosstab的佈局設定一個佈局。我們可以設置是否能看到表格線、或者是否包括行和列總數統計之類。我們這裡全部選擇。
點擊finish
注意當一個crosstab添加到一個報表中後,會自動在設計窗口中添加一個用來編輯當前crosstab的tab頁窗口。
當點擊crosstab的tab頁,兩個新的屬性窗口將會被添加在窗口的左邊和右邊:一個crosstab的結構樹,用來顯示crosstab的當前選中單元格和幫助相關信息。一個是crossstab對象列表用來顯示和該CrossTab相關的一些variables或fields等。
當點擊工具條上的啟動按鈕後,我們將可以看到引擎生成的如下效果的報表:
最後一列包含每一行交叉所有列的總計,最後一行包含每一列交叉所有行的總計。
列,行,單元格 (Columns,rows,cells)
一個crosstab至少必須有一個行分組和一個列分組,每一個行和列的分組都有一個可選的行/列的統計。
下面圖中所示的是一個基本的由一個行列分組構成的crosstab。
當再次添加一個行分組時,這個crosstab 將會顯示出如下效果:
行和列 (Rows and columns)
一個行或列的分組可能通過crosstab的屬性窗口來對它進行修改(在crosstab編輯器右鍵菜單裡選擇Crosstab properties)。
點擊“row and column groups”的標籤頁。在這裡我們可以看到已經定義好的行或列的分組。
添加一個新的分組請點擊名為Add的按鈕。
所有分組必須有一個唯一的名稱。當你添加或修改一個行分組時,你可以設置row group header的寬度。
“bucket”是分組的標準,它通過一個java類來定義。在一個bucket表達式裡,你可以使用主報表裡所有的fields/variables/parameters。但是,如果你選擇使用subdataset來填充crosstab,那麼必須使用subdataset裡提供的fields/variables/parameters。
一個header的單元格增長依賴於它所跨越的行數。你可以選擇多個元素放置在header裡。
最後,你可以選擇是否打印出總計的結果。這些選項是:
None : 沒有總計行被打印
Start : 總計行打印在detail行之前
End : 總計行打印在detail行之後
創建column的group 是非常簡單的。定義column group 時你可以定義column的高度來替代行高(看下圖)
當Bucket在行分組裡時,header的單元格內容的定位相似。但是在這個用例中, details可以改變header寬度而不是高度。
再一次,如果打印總計列的話,你可以做一些選擇。各選項如下:
None : 沒有總計列被打印
Start : 總計列在detail列之前打印
End : 總計列在detail列之後打印
列和行的高度可以很容易的在crosstab編輯器裡通過鼠標拖曳表格線的方式改變。
當一個行或列添加到crosstab裡時,一個特殊的用來引用bucket表達式的變量將要被創建。它和新的group有相同的名稱。你可以從crosstab objects 標籤裡通過查找綠色小點的方式來定位這個bucket variable。
iReport為group創建新的header cells是很簡單的,這個操作不需要添加任何新的額外元素到crosstab裡。你可以根據你的喜好來填充cells,最好的方式是通過拖曳把bucket從crosstab objects列表拖到新的單元格里。
在上圖中,你可以看到加在一個新加的嵌套在column group裡四個新添加到crosstab裡的單元格,group header單元格,group total header單元格。
你可以使用”up”和”down”按鈕來更改你的group的嵌套順序。
下圖中所示的crosstab就是在圖16.14在SEX 的group被向上移後的效果。
16.2.2、單元格 (cells)
每一個行和列的交叉處定義一個單元格,我們有header單元格,total單元格,detail單元格和一個可選的“when-no-data”單元格。單元格可以包含一個類似於textfields,static texts,rectangle,images之類元素的集合,但是他們不能包含一個SubReport, 一個chart,或者一個crosstab。
你可以去修改每一個單元格的背景色和單元格的borders:移動鼠標在一個單元格上並且按右鍵在彈出的菜單中選擇“cell properties”打開單元格屬性編輯窗口。
從這個對話框中你可以修改單元格的外觀。
16.2.3、特殊單元格 (Special cells)
如果一個crosstab不能包含一些數據,你可以選擇打印別的東西來替代。例如,你可以包含一條消息,方法是,你必須編輯“when-no-data”單元格。在crosstab上右鍵勾選彈出菜單中的“when-no-data default cell”複選框。這個操作完成後將會出現一種很明顯的編輯模式,你可以操作“when-no-data”單元格的內容。
“when-no-data”單元格和crosstab元素有相同的尺寸。如果沒有數據展示的話它將替代crosstab打印。單元格橙色的邊框標誌出你可以編輯的單元格區域。可以在這個單元格里添加一個或多個元素。
在一個crosstab裡,所有的元素關聯一個單元格,如果一個元素在單元格外面或部分在單元格外面,這是不正確的放置方式並且當編譯的時候jasperreports將會拋出異常。iReport在界面中標識這個錯誤會以紅色的框顯示。
16.2.4、度量 (Measures)
在crosstab裡每一個元素的表達式(如textfield 表達式)可以包含唯一的measure。在這種情況下,你可以直接使用fields,variables或parameters。
一個measure和variable一樣是一個對象。要建立一個measure,請打開crosstab屬性窗口(在crosstab編輯器上右擊,選擇crosstab properties)並且到measure標籤頁。
點擊Add按鈕,創建一個新的measure。Measure的屬性窗口將顯示,你最少應該去設置它的name,class type和expression。在measure裡你可以使用fields,variable和parameters
一個measure可以存儲一個來自你代碼中的實際的值(將calculation type設為nothing)或者一個類似於用count,sum等計算出來的值。
對於每一個measure 你可以提供一個自定義的incrementer類(一個繼承自
net.sf.jasperreports.engine.fil.JRIncrementerFactory
的類)去實現特定的increment 方法。
這裡的“percentage of”選項允許你選擇表現變量最終值的百分比。
你可以提供一個特殊類來計算百分比的值,此時這個類必須實現net.sf.jasperreports.crosstabs.fill.JRPercentageCalculator接口。
16.2.5、Crosstab element properties
在主設計窗口中雙擊crosstab元素將打開element properties窗口,點擊crosstab標籤。
Repeat column headers : 如果勾選,當crosstab完全添加到頁面中時列的header將會被重複打印。
Repeat row headers : 如果勾選,當crosstab完全添加到頁面中時這個行headers將會被重複打印。
Column break offset : 當crosstab超過頁面寬度時它指定上一塊的數據與下一塊之間的空白間隔。
16.2.6、交叉表參數 (Crosstab parameters)
你可以使用元素屬性窗口裡的crosstab parameter表格建立一個crosstab parameter並且設置一個crosstab的parameter同時為其設置一個默認的表達式(圖16.22),要添加一個parameter,請點擊Add按鈕,這個crosstab parameter 窗口將會出現。
對於一個parameter,你必須為其指定name,class type,同時你還可以為其指定一個可選的可以包含主報表中任意一個fields,variable,parameters的表達式。
警告:使用dataset的過濾查詢,你必須用定義在crosstab properties窗口裡的dataset 啟動parameters,不能用crosstab裡的parameters.
你可以在crosstab objects窗口裡看到crosstab parameters的列表,他們用紅色的點標記出來。
你可以在啟動時用一個MAP來設置crosstab parameters裡聲明的值。在這個用例中,你需要在element properties窗口裡提供一個合法的parameter map expression。
16.2.7、交叉表數據 (Crosstab data)
你可以用主報表或一個subdataset來填充一個crosstab。在後面的例子中,在crosstab properties窗口“crosstab data”標籤裡你必須指定要啟動的dataset。
如果你的數據是pre-sorted.你可以勾選“Data is presorted”的checkbox以使得填充數據的處理速度加快。
Reset type/group和increment type/group選項可以用來定義當集合類型的數據需要重置並且當添加一條記錄到你的dataset。
關於怎麼設置dataset的啟動參數請參考subdataset的相關章節。
16.2.8、交叉表合計變量 (crosstab total variables)
Crosstab variables 是內置的對象,可以結合數據在不同的聚合水平使用在crosstab textfield的表達式裡。
對於每一個尺寸,jasperreports創建variables根據每一行或列存儲measure的合計值。
下面的例子是一個用來顯示不同學歷不同部門的員工數的報表.
同為比較常用的java報表生成工具,FineReport對交叉表的解決方案和實現方法與ireport有所不同,因為本身工具的區別,ireport實現每個功能都需要大量的編碼,而finereport則對代碼需求量較少。具體實現思路和步驟如下,供ireport使用者借鑑:
交叉報表—數據橫向擴展
1. 概述
交叉表,也是常見的基本報表類型,分組報表只是從上到下將數據分組顯示,而交叉表則是從上到下、從左到右都將數據分組的報表,如下圖:
FineReport天然支持行列對稱,設計交叉表的方法也很簡單。
2. 製作步驟
2.1 新建工作簿,添加數據集
新建工作薄,添加數據集ds1,SQL語句為SELECT * FROM [銷量]。
2.2 製作交叉表
設計好表樣後,將數據列拖入對應單元格:
縱表頭:地區與銷售員默認縱向擴展實現從上到下分組;
橫表頭:將產品類型與產品設置為從左到右擴展,讓產品橫向分組,實現橫表頭;
數據:根據父子格的概念,銷量會以銷售員為左父格,產品為上父格,自動匹配出銷售員與產品對應的銷量。
預覽即可看到上圖交叉表。
注:此處銷售員與產品對應的銷量是唯一的,因此,直接將銷量拖入單元格即可。
另:若銷售員與產品對應的銷量不唯一,則將銷量數據列的顯示方式設為彙總-求和,詳細請查看數據顯示方式。
2.3 保存併發布
保存模板,預覽效果如上。
交叉表的累計
1. 問題描述
逐層累計與跨層累計都是縱方向上的累計,也可以橫向進行累計,如下圖各個銷售員每個月訂單金額的累計:
2. 示例
2.1 新建報表,設計表樣
新建工作薄,添加數據集,SQL語句為select 僱員ID, strftime('%m',訂購日期)as 月份, 應付金額 from 訂單 where strftime('%Y',訂購日期) = '2011',查詢出2011年每個僱員,每月訂單金額。
如下製作一張交叉表:
數據列設置如下:
2.2 橫向累計
在C3單元格中,寫入公式:=B3 + C3[;B2:-1]:當前月份的金額加上一月累計金額。
其中C3[;B2:-1]表示上父格B2擴展出來的上一格(上月)的C3的值。
2.3 保存與預覽
保存模板,預覽效果如上。