談談Java報表之JasperReport改造一,動態報表

xf發表於2006-06-30
我本對JasperReport一殼不同,只是公司在做產品時選用了JasperReport,主要原因還是免費吧!由於公司是做物流系統,所以對於報表的要求非常高,大體在使用JasperReport過程中分為兩類,一類是類似表單形式,還有一類就是傳統的彙總報表。其中表單形式十分多,主要用於物流行業中的各種單據列印,比如報關單,發票等等。
國內客戶有一個很奇怪的需求,就是喜歡在列印預攬時修改單據的資料(有可能是要做假脹的原因)或者修改具體的表單佈局,我們公司遇到這樣的情況非常多。JasperReport是透過xml檔案記錄具體的佈局資訊,一般也是用同樣開源的IReport產生編輯一個具體的JasperReport的佈局xml資訊。如果我們需要實現客戶的功能,乍看起來,等於是要實現一個IReport中的編輯功能。老闆要求我來實現,經過幾天的研究,發現其實不然,實現在JasperReport良好的封裝的基礎上實現這樣的功能不用很費力。
下面我介紹一下簡單原理:
JasperReport提供一個JRViewer的預攬元件,是一個JPanel物件。在JRViewer繪製預攬效果時,會呼叫
JasperPrintManager.printPageToImage(jasperPrint, pageIndex, realZoom, viewer.isDesignMode);方法得到一個Image物件(雙緩衝),然後再將Image物件setIcon給JRViewer上面的顯示元件。所以預攬效果最終是靠Image物件呈現,需要動態抓取Image物件中具體的報表資料元素的位置是非常困難,我沒有走這條路。其實在JasperReport中每一個圖形元素都是一個JRPrintElement介面的例項物件,圖形元素的位置,資料,字型等等資訊都放在JasperPrint中都包含了這些物件。JasperPrintManager.printPageToImage(jasperPrint, pageIndex, realZoom, viewer.isDesignMode);最終會呼叫JRGraphics2DExporter中的exportElements(Collection elements)遍例JasperPrint物件中的JRPrintElement分別透過最後輸出的Graghic2D控制程式碼繪製圖形,文字。我的解決方案就是從JasperPrint物件下手。
1)給JRViewer上面的顯示圖例元件加MouseListener,MouseMotionAdapter
2)在mousePress中,透過MouseEvent得到當前滑鼠的位置,並且透過遍例當前JasperPrint中的所有JRPrintElement的getX,getY,getWidth,getHeight來拿到當前的JRPrintElement物件,並且記入下來(在使用橡皮帶技術時需要重化上一個圖形的位置,具體演算法太過複雜這裡忽略介紹)。
3)在mouseDragged方法中,實現橡皮帶技術(其實就是畫一個虛框,感覺圖形在跟著滑鼠動)。
4)在mouseRelease方法中,得到release的位置,包括x,y座標和最後釋放矩形的width,height。
5)JRPrintElement物件中沒有setX,setY,setWidth,setHeight介面,所以需要改動原始碼,加上這些方法。在JRTemplatePrintElement或者JRBasePrintElement中改變例項的x,y,width,height。
6)重新呼叫JasperPrintManager.printPageToImage(jasperPrint, pageIndex, realZoom, viewer.isDesignMode);雙緩衝使頁面重新整理不會有多大抖動的感覺。
這樣就可以動態調整圖形元素的位置佈局。
7)在mousePress中加入e.getClickCount==2的雙擊判斷,對於大多數顯示文字的JRPrintElement都是JRPrintText的子類,(JRPrintText在最早的原始碼有沒有setText我記不清了,如果沒有的話也加上setText介面)JRPrintTemplateText和JRBasePrintText都有text這個變數,在setText改變text的值,同樣呼叫JasperPrintManager.printPageToImage(jasperPrint, pageIndex, realZoom, viewer.isDesignMode);就可以看到改變後的效果。
小結:這裡我只是簡單介紹一下動態報表的實現,其實只要看清JasperReport原始碼的一些結構會發現,其物件導向設計做的非常好,還可以有很多改造的餘地。後面我還會介紹如何實現將修改後的佈局保留成新的xml,以及無窮層子報表的實現。
順便說一句:客戶使用動態報表和開心,他們甚至要我們在開發財務發票模組時,提供一張空白報表,只留一些空白的資料圖形元素,然後列印發票前直接填入發票金額,估計這種事情也只有國內客戶才做得出來,呵呵!

相關文章