使用子報表有以下的優點:
簡化複雜報表邏輯
我們能將邏輯分散到不同的子報表中,每個子報表專注於不同的資料展示,可以有效降低主報表的複雜度。會使用子報表通常是讓主報表的資料作為匯總資料,而細部或不同邏輯的資料由子報表佈局。
提高維護性
如果有需求變更時,修改單個子報表會比重新設計整個報表更容易。尤其在報表欄位非常多的狀況下,光是調整每個欄位的位置就很花時間,如果將相同邏輯的資料放入子報表,只要移動子報表就可以一次移動所有同類型的資料,提高了報表的維護性。
處理多個資料來源
子報表也是一張報表,因此主報表和子報表可以分別使用不同的資料來源,在使用不同API的回傳資料彙整到同一張報表上的時候很好用。
接下來用一個簡單的情境來看看子報表如何使用
這次我想查看學校各科系的學生,在各科目的平均成績,希望的格式如下:
在課程與成績平均欄位顯示各科系所修的課程與成績平均,現在DB的資料很簡單,各科系修的課都一樣,但如果修的課不同,每個科系對應的資料數量就會不同,如果是不用子報表的情況(模板如下圖),Detail中即使科系是相同的資料,也會因為與每個不同的課程資料是同一個dataSource而重複顯示
因此想做到希望的格式,有合併儲存格的效果的話,要將「科系」放在主報表,而「課程」與「成績平均」放到子報表,用不同的dataSource放入報表中。
有很多種設定屬性的方式都能成功配置子報表,我介紹的方法不是唯一的方式。
Expression: 現在子報表與主報表是兩個還沒有關聯的模板,要如何將子報表模板指定到主報表中,可以利用「Expression」屬性。
JasperCompileManager.compileReport()
來編譯,其實也可以用Jaspersoft Studio自己的編譯功能,可以直接點選模板上方的icon來編譯,編譯後會產生一個xxx.jasper的檔案,就是編譯後的jasper文件,後端程式處理報表生命週期時要使用xxx.jasper這個檔案的路徑Parameters Map Expression: 這是用來對應子報表自己的REPORT_PARAMETERS_MAP到主報表的,這次的範例沒有用到,要設定的話我也是用主報表的參數來對應
Connection Expression: 這似乎是用來讓子報表與資料庫連結的,我沒有用過,就交給其他報表大師介紹囉
Data Source Expression: 這是用來對應子報表的dataSource的,要讓多種不同dataSource彙總在主報表就是靠這個屬性
考量子報表的「課程」與「成績平均」是用主報表的「科系」歸類在一起,因此我想利用departmentId讓同一類的子報表資料能順利對應到正確的科系,大致上的過程如下圖:
$P{REPORT_PARAMETERS_MAP}.get($F{departmentId})
,在報表編譯時JasperReports會自動取得主報表中departmentId這個Field的數值,以map.get()
取得此departmentId對應到的子報表dataSource報表模板的準備就到這告一個段落,光是Jaspersoft Studio的設定就有點複雜了,後端的邏輯就留給下一篇吧