最近在我公司drp(運(yùn)營分銷系統(tǒng))開發(fā)中,需要大量報(bào)表,由于本人有過jasperReport的開發(fā)經(jīng)驗(yàn),所以選用了它,jr確實(shí)不錯(cuò),開源,可擴(kuò)展性很好,缺點(diǎn)就是免費(fèi)的文檔很少,更可氣的是,代碼中的doc少的可憐,基本上沒有參考價(jià)值.
?????? 由于我們的產(chǎn)品是用于服裝行業(yè)的,在服裝行業(yè)有一個(gè)尺碼組,非常的麻煩,在制作含有尺碼組的報(bào)表時(shí),表頭的各種尺碼不能寫死,要從數(shù)據(jù)庫查詢出來.但是,一般的報(bào)表工具都是不支持表頭動(dòng)態(tài)化的(我理解,報(bào)表嘛,是呈現(xiàn)給特定人物如老板看的特定內(nèi)容,表頭應(yīng)該是設(shè)計(jì)好的,不會(huì)經(jīng)常性的更改),jasperReport也是一樣,并不直接支持,細(xì)究它的實(shí)現(xiàn)過程,我們還是可以擴(kuò)展從而解決這個(gè)問題的.
????? 先看jasperReport的流程圖.
??
????????從上圖可看到,jrxml文件要通過JRXmlLoader解析為一個(gè)JasperDesign的對(duì)象,從源碼中可以看出,此對(duì)象用java類去描述了報(bào)表的整個(gè)設(shè)計(jì),比如,columnHeader,detail,columnFooter等等.然后由JasperCompileManager編譯為一個(gè)JasperReport對(duì)象,其實(shí),如果你用ireport(jasperReport報(bào)表的可視化設(shè)計(jì)器)制作報(bào)表,你完全可以不必理會(huì)怎樣生成jaserReport對(duì)象.ireport對(duì)此有很好的支持.
???????了解了以上過程,我們可以看出,如果要?jiǎng)討B(tài)的加入設(shè)計(jì)元素,只能在JasperDesign對(duì)象中下手.加入需要的動(dòng)態(tài)元素,我的需求是在columnHeader中加入一個(gè)尺碼組的表頭,代碼實(shí)現(xiàn)如下.
- package ?com.webstone.drp.report.common.dynamicHeader; ??
- ??
- import ?java.io.File; ??
- import ?java.lang.reflect.InvocationTargetException; ??
- import ?java.util.Iterator; ??
- import ?org.apache.commons.beanutils.BeanUtils; ??
- import ?net.sf.jasperreports.engine.JRException; ??
- import ?net.sf.jasperreports.engine.JasperCompileManager; ??
- import ?net.sf.jasperreports.engine.JasperReport; ??
- import ?net.sf.jasperreports.engine.design.JRDesignBand; ??
- import ?net.sf.jasperreports.engine.design.JRDesignStaticText; ??
- import ?net.sf.jasperreports.engine.design.JasperDesign; ??
- import ?net.sf.jasperreports.engine.xml.JRXmlLoader; ??
- ??
- /** ?
- ?*?@author?yaer ?
- ?*/ ??
- @SuppressWarnings ( "unchecked" ) ??
- public ? class ?ReportDesignProcess?{ ??
- ???? private ? static ? final ?String?flagTextKey?=? "customFlagText" ; ??
- ??
- ???? public ? static ?JasperReport?getJasperReport(String?xmlFilePath, ??
- ????????????String[][]?sizeGroup)? throws ?JRException?{ ??
- ????????JasperDesign?design?=?getJasperDesign(xmlFilePath); ??
- ????????JRDesignBand?columnHeader?=?(JRDesignBand)?design.getColumnHeader(); ??
- ??
- ????????reSetColumnHeaderHeight(columnHeader,?sizeGroup); ??
- ????????reSetshapeAndPosition(columnHeader,?sizeGroup); ??
- ????????addElementToColumnHeader(columnHeader,?sizeGroup); ??
- ???????? return ?JasperCompileManager.compileReport(design); ??
- ????} ??
- ???? private ? static ?JasperDesign?getJasperDesign(String?filePath) ??
- ???????????? throws ?JRException?{ ??
- ???????? return ?JRXmlLoader.load( new ?File(filePath)); ??
- ????} ??
- ???? private ? static ? void ?reSetColumnHeaderHeight(JRDesignBand?columnHeader, ??
- ????????????String[][]?sizeGroup)?{ ??
- ????????columnHeader.setHeight(columnHeader.getHeight()?*?sizeGroup.length); ??
- ????} ??
- ???? private ? static ?JRDesignStaticText?getFlagTextInDesign( ??
- ????????????JRDesignBand?columnHeader)?{ ??
- ???????? return ?(JRDesignStaticText)?columnHeader.getElementByKey(flagTextKey); ??
- ????} ??
- ???? private ? static ? void ?reSetshapeAndPosition(JRDesignBand?columnHeader, ??
- ????????????String[][]?sizeGroup)?{ ??
- ????????JRDesignStaticText?flagText?=?getFlagTextInDesign(columnHeader); ??
- ????????Iterator<jrdesignstatictext></jrdesignstatictext>?children?=?columnHeader.getChildren() ??
- ????????????????.iterator(); ??
- ????????JRDesignStaticText?element; ??
- ???????? while ?(children.hasNext())?{ ??
- ????????????element?=?children.next(); ??
- ???????????? if ?(element.getX()?>?flagText.getX())?{ ??
- ????????????????element.setX(flagText.getX()?+?flagText.getWidth() ??
- ????????????????????????*?sizeGroup[ 0 ].length); ??
- ????????????} ??
- ???????????? if ?(!flagTextKey.equals(element.getKey()))?{ ??
- ????????????????element.setHeight(element.getHeight()?*?sizeGroup.length); ??
- ????????????} ??
- ????????} ??
- ????} ??
- ???? private ? static ? void ?addElementToColumnHeader(JRDesignBand?columnHeader, ??
- ????????????String[][]?sizeGroup)?{ ??
- ????????JRDesignStaticText?flagText?=?getFlagTextInDesign(columnHeader); ??
- ????????columnHeader.removeElement(flagText); ??
- ???????? for ?( int ?i?=? 0 ;?i?<?sizeGroup.length;?i++)?{ ??
- ???????????? for ?( int ?j?=? 0 ;?j?<?sizeGroup[i].length;?j++)?{ ??
- ???????????????? try ?{ ??
- ????????????????????JRDesignStaticText?newElement?=?(JRDesignStaticText)?BeanUtils ??
- ????????????????????????????.cloneBean(flagText); ??
- ????????????????????newElement.setText(sizeGroup[i][j]); ??
- ????????????????????newElement.setX(flagText.getX()?+?flagText.getWidth()?*?j); ??
- ????????????????????newElement.setY(flagText.getY()?+?flagText.getHeight()?*?i); ??
- ????????????????????columnHeader.addElement(newElement); ??
- ????????????????}? catch ?(IllegalAccessException?e)?{ ??
- ????????????????????e.printStackTrace(); ??
- ????????????????}? catch ?(InstantiationException?e)?{ ??
- ????????????????????e.printStackTrace(); ??
- ????????????????}? catch ?(InvocationTargetException?e)?{ ??
- ????????????????????e.printStackTrace(); ??
- ????????????????}? catch ?(NoSuchMethodException?e)?{ ??
- ????????????????????e.printStackTrace(); ??
- ????????????????} ??
- ????????????} ??
- ????????} ??
- ????} ??
- }??
????? 很遺憾,沒有寫注解,原因是我看了一本書叫<<測(cè)試驅(qū)動(dòng)開發(fā)>>,里面有一句話"意圖導(dǎo)向編程",意思是說,用手段比如容易理解,貼切的類名,方法名,屬性達(dá)到讓讀者輕易理解代碼.從而少寫注解,讓代碼更簡(jiǎn)捷.如果大家不大明白以上代碼的意思,那就是我寫的不夠好,還要繼續(xù)努力.
此類只有一個(gè)方法,根據(jù)傳來的報(bào)表文件路徑和一個(gè)二維數(shù)組式的尺碼組生成一個(gè)jaserReport的對(duì)象.有三個(gè)關(guān)鍵方法.重新設(shè)置columnHeader的height;重新設(shè)置靜態(tài)內(nèi)容的形狀和大小,添加新的元素到columnHeader中,其實(shí),這兒有一個(gè)不太容易理的東西:類中有一個(gè)flagTextKey的屬性,它是標(biāo)識(shí)報(bào)表設(shè)計(jì)中動(dòng)態(tài)內(nèi)容的一個(gè)樣板元素,為什么要這個(gè)樣板元素了,因?yàn)橛盟休d動(dòng)態(tài)內(nèi)容的樣式,要比在用代碼實(shí)現(xiàn)方便的多.請(qǐng)看BeanUtils.coloneBean()方法,實(shí)際上是克隆樣板元素對(duì)象.
??????? 這個(gè)類設(shè)計(jì)的太具體于應(yīng)用,應(yīng)該寫成一個(gè)抽象方法,讓子類來具體實(shí)現(xiàn)加入動(dòng)態(tài)元素的過程,我相信大家的需求和我不太一樣.由于時(shí)間關(guān)系,我沒有仔細(xì)考究.畢竟這只是一個(gè)參考實(shí)現(xiàn).
最后,在用于ireport畫報(bào)表時(shí)就要注意了,一呈不變的元素該怎么畫就怎么畫,但樣板元素的位置一定要放好.動(dòng)態(tài)內(nèi)容起始的位置和樣式就靠它來定義,大多數(shù)時(shí)候,它是一個(gè)標(biāo)簽.只不過它的"key"屬性和上面類的"flagTextKey"要保持一致.
這個(gè)話題就到這兒了,我這兒還有一個(gè)我包裝的工具類,我們公司的同事都認(rèn)為對(duì)開發(fā)報(bào)表有幫助.
- package ?com.webstone.drp.report.common; ??
- ??
- import ?java.util.ArrayList; ??
- import ?java.util.Collection; ??
- import ?java.util.HashMap; ??
- import ?java.util.Map; ??
- import ?javax.servlet.http.HttpServletRequest; ??
- import ?javax.servlet.http.HttpSession; ??
- import ?javax.faces.context.FacesContext; ??
- import ?org.apache.commons.lang.ArrayUtils; ??
- import ?com.webstone.drp.report.common.dataSource.JRArrayCollectionDataSource; ??
- import ?com.webstone.drp.report.common.dynamicHeader.ReportDesignProcess; ??
- import ?net.sf.jasperreports.engine.JRException; ??
- import ?net.sf.jasperreports.engine.JasperFillManager; ??
- import ?net.sf.jasperreports.engine.JasperPrint; ??
- import ?net.sf.jasperreports.engine.JasperReport; ??
- import ?net.sf.jasperreports.engine.data.JRBeanCollectionDataSource; ??
- import ?net.sf.jasperreports.engine.JRDataSource; ??
- import ?net.sf.jasperreports.engine.util.JRLoader; ??
- ??
- /** ?
- ?*?使用jasperReport做報(bào)表時(shí)的工具支持類.有兩個(gè)用途,生成jasperPrint對(duì)象,和設(shè)置導(dǎo)出時(shí)的session ?
- ?*? ?
- ?*?@author?yaer ?
- ?*?@date?2006-8-26? ?
- ?*?@modify?date?2006-12-8 ?
- ?*/ ??
- public ? class ?ReportUtils?{ ??
- ???? public ? static ? final ?String?XLS?=? "xls" ; //?導(dǎo)出為xls文件; ??
- ???? public ? static ? final ?String?PDF?=? "pdf" ; //?導(dǎo)出為pdf文件; ??
- ???? private ? static ? final ?String?JASPER?=? "jasper" ; //?編譯過后的報(bào)表文件; ??
- ???? private ? static ? final ?String?JRXML?=? "jrxml" ; //?原始的報(bào)表文件(xml格式); ??
- ???? private ?HttpServletRequest?request; ??
- ???? private ?HttpSession?session; ??
- ???? private ?String?rootPath; //?報(bào)表文件路徑 ??
- ??
- ???? /** ?
- ?????*?在jsf環(huán)境下時(shí)構(gòu)造些工具類對(duì)象 ?
- ?????*? ?
- ?????*?@param?context ?
- ?????*????????????jsf的上下文對(duì)象 ?
- ?????*/ ??
- ??
- ???? public ?ReportUtils(FacesContext?context)?{ ??
- ????????request?=?(HttpServletRequest)?context.getExternalContext() ??
- ????????????????.getRequest(); ??
- ????????session?=?(HttpSession)?context.getExternalContext().getSession( true ); ??
- ???????? this .createRootPath(request); //?生成報(bào)表文件的絕對(duì)路徑 ??
- ????} ??
- ???? /** ?
- ?????*?在其它web環(huán)境下構(gòu)造此工具類對(duì)象 ?
- ?????*? ?
- ?????*?@param?req ?
- ?????*????????????request請(qǐng)求對(duì)象 ?
- ?????*/ ??
- ???? public ?ReportUtils(HttpServletRequest?req)?{ ??
- ???????? this .request?=?req; ??
- ???????? this .session?=?req.getSession(); ??
- ???????? this .createRootPath(request); //?生成報(bào)表文件的絕對(duì)路徑 ??
- ????} ??
- ???? /** ?
- ?????*?獲得報(bào)表文件的絕對(duì)路徑 ?
- ?????*? ?
- ?????*?@return?rootPath ?
- ?????*/ ??
- ???? public ?String?getRootPath()?{ ??
- ???????? return ?rootPath; ??
- ????} ??
- ???? /** ?
- ?????*?獲得JasperPrint對(duì)象;?jasperPrint對(duì)象在jasperReport中是填充了報(bào)表數(shù)據(jù)后的一個(gè)實(shí)體,打印,導(dǎo)出,顯示都要使用它. ?
- ?????*?此方法含有java5.0支持的'可變參數(shù)'特性.params其實(shí)質(zhì)是一個(gè)對(duì)象數(shù)組.在調(diào)用些方法時(shí)要注意它可能的參數(shù)順序. ?
- ?????*?此方法參數(shù)描述: ?
- ?????*?1、最多只有四個(gè)參數(shù)。 ?
- ?????*?2、固定參數(shù)filePath表示報(bào)表文件的路徑,為了支持drp系統(tǒng)中動(dòng)態(tài)尺碼組做表頭的特性,?filePath包括兩類: ?
- ?????*????編譯過后的文件擴(kuò)展名為'.jasper'和未編譯的原始xml文件'.jrxml'; ?
- ?????*????若報(bào)表中有動(dòng)態(tài)尺碼組作表頭,則filePath為擴(kuò)展名是'.jrxml'的文件。 ?
- ?????*????若報(bào)表中不涉及動(dòng)態(tài)尺碼組,則filePath為擴(kuò)展名是'.jasper'的文件。 ?
- ?????*?3、可變參數(shù)params的完整列表是(注意順序):Object?obj/Collection?dataSource,String?seprator,String[][]?sizeGroup. ?
- ?????*????這三個(gè)參數(shù)中,有一個(gè)例外,Object?obj/Collection?dataSource必須有一個(gè),此參數(shù)表示填充報(bào)表的數(shù)據(jù),可以是一個(gè)Collection式的集合, ?
- ?????*????也可以是一個(gè)model對(duì)象(有且只有一個(gè)Collection的屬性); ?
- ?????*????String?seprator表示分隔符,如果數(shù)據(jù)源是一個(gè)Array的集合,則需此參數(shù)。String[][]sizeGroup表款尺碼組的二維數(shù)組。 ?
- ?????*? ?
- ?????*?@param?filePath ?
- ?????*?@param?params ?
- ?????*?@return?jasperPrint ?
- ?????*/ ??
- ???? public ?JasperPrint?getJasperPrint(String?filePath,?Object...?params)?{ ??
- ????????JasperReport?jasperReport?=? null ; ??
- ???????? try ?{ ??
- ???????????? if ?(JASPER.equals(filePath.substring(filePath.indexOf( "." )?+? 1 , ??
- ????????????????????filePath.length())))?{ //?jasper式文件的處理 ??
- ????????????????jasperReport?=?getReportTemplate(filePath); ??
- ????????????} ??
- ???????????? if ?(JRXML.equals(filePath.substring(filePath.indexOf( "." )?+? 1 , ??
- ????????????????????filePath.length())))?{ //?jrxml式文件的處理 ??
- ????????????????jasperReport?=?ReportDesignProcess.getJasperReport(filePath, ??
- ????????????????????????(String[][])?params[params.length?-? 1 ]); //?重新設(shè)置表頭,編譯 ??
- ????????????????params?=?ArrayUtils.remove(params,?params.length?-? 1 ); //?刪除參數(shù)中的sizeGroup ??
- ????????????} ??
- ???????????? return ?fillReport(jasperReport,?params); ??
- ????????}? catch ?(JRException?e)?{ ??
- ????????????e.printStackTrace(); ??
- ????????} ??
- ???????? return ? null ; ??
- ????} ??
- ???? /** ?
- ?????*?獲得JasperPrint對(duì)象;自定義填充報(bào)表時(shí)的parameter和dataSource.?參數(shù)說明和動(dòng)態(tài)表頭的用法參考上一方法 ?
- ?????*?@param?filePath ?
- ?????*?@param?parameter ?
- ?????*?@param?dataSource ?
- ?????*?@param?sizeGroup ?
- ?????*?@return ?
- ?????*/ ??
- ???? public ?JasperPrint?getJasperPrint(String?filePath,?Map?parameter, ??
- ????????????JRDataSource?dataSource,?Object...?sizeGroup)?{ ??
- ????????JasperReport?jasperReport?=? null ; ??
- ???????? try ?{ ??
- ???????????? if ?(sizeGroup.length?==? 0 )?{ ??
- ????????????????jasperReport?=?getReportTemplate(filePath); ??
- ????????????} ??
- ???????????? if ?(sizeGroup.length?==? 1 )?{ ??
- ????????????????jasperReport?=?ReportDesignProcess.getJasperReport(filePath, ??
- ????????????????????????(String[][])?sizeGroup[sizeGroup.length?-? 1 ]); //?重新設(shè)置表頭,編譯 ??
- ????????????} ??
- ???????????? return ?JasperFillManager.fillReport(jasperReport,?parameter, ??
- ????????????????????dataSource); ??
- ????????}? catch ?(JRException?e)?{ ??
- ????????????e.printStackTrace(); ??
- ????????} ??
- ???????? return ? null ; ??
- ????} ??
- ???? public ? void ?setAttrToPage(JasperPrint?jasperPrint,?String?report_fileName, ??
- ????????????String?report_type)?{ ??
- ????????session.setAttribute( "REPORT_JASPERPRINT" ,?jasperPrint); ??
- ????????session.setAttribute( "REPORT_FILENAME" ,?report_fileName); ??
- ????????session.setAttribute( "REPORT_TYPE" ,?report_type); ??
- ????} ??
- ???? private ?JasperPrint?fillReport(JasperReport?jasperReport,?Object[]?params) ??
- ???????????? throws ?JRException?{ ??
- ????????Map?parameters?=? null ; ??
- ????????JRDataSource?ds?=? null ; ??
- ???????? if ?(params.length?==? 0 )?{ ??
- ???????????? return ? null ; ??
- ????????} ??
- ???????? if ?(params.length?==? 1 ?&&?params[ 0 ].getClass()?==?ArrayList. class )?{ //其實(shí)質(zhì)是要判斷是否是集合 ??
- ????????????ds?=? new ?JRBeanCollectionDataSource((Collection)?params[ 0 ]); ??
- ????????} ??
- ???????? if ?(params.length?==? 1 ?&&?params[ 0 ].getClass()?!=?ArrayList. class )?{ ??
- ????????????ClassAnalysis?ca?=? new ?ClassAnalysis(params[ 0 ]); ??
- ????????????parameters?=?ca.getFields(); ??
- ????????????ds?=? new ?JRBeanCollectionDataSource(ca.getSet()); ??
- ????????} ??
- ???????? if ?(params.length?==? 2 ?&&?params[ 0 ].getClass()?==?ArrayList. class )?{ ??
- ????????????ds?=? new ?JRArrayCollectionDataSource((Collection)?params[ 0 ], ??
- ????????????????????params[ 1 ].toString()); ??
- ????????} ??
- ???????? if ?(params.length?==? 2 ?&&?params[ 0 ].getClass()?!=?ArrayList. class )?{ ??
- ????????????ClassAnalysis?ca?=? new ?ClassAnalysis(params[ 0 ]); ??
- ????????????parameters?=?ca.getFields(); ??
- ????????????ds?=? new ?JRArrayCollectionDataSource(ca.getSet(),?params[ 1 ] ??
- ????????????????????.toString()); ??
- ????????} ??
- ???????? return ?JasperFillManager.fillReport(jasperReport, ??
- ????????????????parameters?==? null ??? new ?HashMap()?:?parameters,?ds); ??
- ????} ??
- ???? private ? void ?createRootPath(HttpServletRequest?request)?{ ??
- ????????rootPath?=?request.getSession().getServletContext().getRealPath( "/" ) ??
- ????????????????+? "WEB-INF\\classes\\com\\webstone\\drp\\report\\jaser\\" ; ??
- ????} ??
- ???? private ?JasperReport?getReportTemplate(String?jasperPath) ??
- ???????????? throws ?JRException?{ ??
- ???????? return ?(JasperReport)?JRLoader.loadObject(rootPath?+?jasperPath); ??
- ????} ??
- } ??
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
