JasperReport報表開發之轉置交叉表
使用Jasper或BIRT等報表工具時,常會碰到一些很規的統計,用報表工具本身或SQL都難以處理,比方源數據不符合交叉表的要求,須要轉置後再呈現。
集算器具有結構化強計算引擎,集成簡單。能夠協助報表工具方便地實現此類需求。以下通過一個樣例來說明轉置交叉表的實現過程。
數據庫表booking匯總著各年度商品的預定數據。有四個字段,包含年份和三種預定狀態,部分數據例如以下:
報表要求呈現指定年份及上一年的預定情況。當中行組有三項,即三種預定狀態,列組是年份。測度是當年的預定數據。此外要匯總出指定年份各預定狀態的增長率。表例子如以下:
能夠看到,這張報表的難點是:源數據無法直接用於交叉表,匯總列要用相對位置來動態計算。
假設能將源數據轉置。並將匯總列事先計算出來,則會顯著減少難度,比方以下這樣:
以下用集算器準備報表所需的數據,代碼例如以下:
A1=yearBegin=yearEnd-1
yearEnd是來自報表的參數,表示用戶指定的年份,比方2014。A1中的代碼用來計算上一年(比方2013),為了方便引用,上一年定義為yearBegin。
A2=myDB1.query(“select * from booking where year between ? and ?
order by year desc”,yearBegin,yearEnd)
這句代碼用來從數據庫查出指定年份及上一年的數據。myDB1是數據源名,指向MYSQL。函數query可運行SQL語句,也能夠接受參數。如果yearEnd=2014,則A2的計算例如以下:
A3=create(row,col,value)
這句代碼用來新建序表A3。
A3有三個字段:row、col、value,將來可存儲整理之後的數據。新建後的A3例如以下:
須要註意的是。序表類似數據庫結果集,也是結構化二維表。但序表是泛型的,同一個字段能夠存儲不同的數據類型,序表也是有序的,能夠按序號訪問數據。
利用序表的這些特點能夠方便地實現本案例。
A4: for ["visits","bookings","successfulbookings"]
這句代碼對集合["visits","bookings","successfulbookings"]進行循環訪問,在循環中向A3追加數據。終於準備出報表須要的數據。
for語句的作用範圍是B4-C7,用自然的縮進就能夠表示。無需括號或begin/end等標記。
在作用範圍裏能夠用A4來引用循環變量,即for語句所在單元格的格名。比方進行第一遍循環時。A4的值等於”visits”。
以下看循環體中的代碼。
B4=endValue=eval(“A2(1).”+A4)
這句代碼可從A2動態地取出第一條記錄的預定狀態數據。
函數eval可將字符串解析為表達式,比方第一遍循環時。“A2(1).”+A4會被解析為A2(1).visits,計算結果是500。當中“A2(1)”表示第一條記錄,“.visits”表示取出該記錄的visits字段。即下圖紅框處:
C4=beginValue=eval(“A2(2).”+A4)
和endValue類似,beginValue從A2中動態地取出第二條記錄的預定狀態數據。第一遍循環時,endValue等於400。
B5=A3.insert(0,A4,A2(1).year,endValue)
C5=A3.insert(0,A4,A2(2).year,beginValue)
這兩句代碼向A3追加記錄。函數insert能夠向序表插入記錄。第一個參數能夠指定插入的位置,假設這個參數為0,則表示在最後追加記錄。
比方第一遍循環時,B5追加的記錄是:”visits”、2014、500,C5追加的記錄是”visits”、2013,400。追加後A3例如以下:
B6=endValue/beginValue-1
這句代碼計算指定年份的增長率,比方第一遍循環時,B6=500/400-1=0.25。
C6=if(B6>0:”+”,B6<0:”-”)+string(B6,”#%”)
這句代碼用來格式化B6。算法是:假設B6大於0,則在百分數前面加“+”號,假設小於0,則加“-”號。比方第一遍循環時,C6=”+25%”。註意:格式化數據適合用報表實現,所以本步驟並不是必須。
B7=A3.insert(0,A4,string(yearEnd)+”/”+string(yearBegin),C6)
這句代碼向A3追加新記錄,比方第一遍循環時,插入的記錄是”visits”,”2014/2013”,”+25%”。例如以下圖:
值得註意的是。這次插入的記錄都是字符串。和之前的類型不同。
整個循環運行後,報表須要的數據就會所有追加在A3中,例如以下:
result A3
這句代碼將A3返回給報表工具。集算器對外提供JDBC接口。報表工具會將集算器識別為普通數據庫,集成方案請參考相關文檔。
接下來以JasperReport為例設計一張簡單的交叉表。模板例如以下:
報表中須要定義一個參數pyearEnd,用來相應集算器中的參數。
預覽後能夠看到報表結果:
報表調用集算器的方法和調用存儲過程一樣。比方將本腳本保存為booking.dfx,則在JasperReport的SQL設計器中能夠用booking $P{pendYear}來調用。
JasperReport報表開發之轉置交叉表