??? 首先網上有一份JasperReport收費文檔, 不過老實說,這份文檔收費的話顯得太單薄了。
????1.1 為什么要自定義數據源
??? 簡單的報表,當然用不著自定義數據源。但查詢復雜起來時,還死守著一條SQL寫完會讓SQL變得又長又難讀,從來都最討厭別人在SQL上炫技。 這時候,把查詢分開執行,每個查詢只負責向VO(值對象Bean)賦值若干個列,程序就會清晰很多。而且,相近的查詢還可以進一步封裝在一個Reporter類里,提供給報表內或者報表之間重用。更何況,有些情況根本不可能一條SQL里寫完,而放在Java程序里處理卻輕松自在。
??? 搞定了可分解重用的數據源后,我才真正敢把JasperReports用在我們的系統上,否則,無法想象怎么維護那么多的SQL.
??? 1.2 自定義數據源的機制
dori.jasper.engine.JRDataSource 接口非常簡單,只要實現兩個方法:
public boolean next() throws JRException;
public Object getFieldValue(JRField jrField) throws JRException;
?????? 另外Hibernate的HQL查詢,如果返回多個對象時,每一row是Object[],只能按index而不能按名取值,也就不支持getFileldValue(field)了,hibernate.org上有折衷的方法,但都不好。
???? 1.3 Sample代碼與解釋
//封裝了大量查詢的reporter類
MooncakeReporter mooncakeReporter = new MooncakeReporter();
//建立VO的Map,因為需要多次執行查詢,需要快速找回VO來賦值,因此采用Map.
Map map = new HashMap();
rs = mooncakeReporter.findAllVaildProduct();
while (rs.next())
{
MooncakeVO mooncakeVO = new MooncakeVO();
String goods_no = rs.getString("goods_no");
String goods_name = rs.getString("name");?
???????mooncakeVO.setName(goods_name);
???????mooncakeVO.setCode(code);
?????? map.put(goods_no, mooncakeVO);
}
//調用Reporter封裝好的查詢函數獲取數據,并通過主鍵goods_no獲得VO來賦值。
rs = mooncakeReporter.findSaleOrderByShopType("shop");
while (rs.next())
{
?? String goods_no = rs.getString("goods_no");
?? MooncakeVO mooncakeVO = (MooncakeVO) map.get(goods_no);
?? if (mooncakeVO != null)
?? {
??? ? mooncakeVO.setShopCount(new Integer(rs.getInt("count")));
?? }
}
//如此重復執行查詢若干步
.....
//因為JRBeanCollectionDataSource需要Collection或者Array,把Map轉化為List。
List result = new ArrayList(map.values());
//對result進行排序,通過BeanUtils的beanComparator來實現,在下一小節會講到。
Collections.sort(result, new BeanComparator("code"));
//最后把result賦給JRBeanCollectionDataSource
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JRBeanCollectionDataSource(result));
??? 1.4 擴展
??? 1.用BeanComparator進行排序
????? 用map來存放的VO是沒有順序的,必須對其進行排序。 用jakata commons-beanutils的BeanComparator類,可以動態改變排序的列,比自己實現Compare()接口好。
??Collections.sort(result, new BeanComparator("code"));???? 對于"Order by lastName, firstName"的情形,還可以寫成這樣,其中ComparatorChain屬于jakata commons-collections包。
??? ArrayList sortFields = new ArrayList();
???? sortFields.add(new BeanComparator("lastName"));
???? sortFields.add(new BeanComparator("firstName"));
???? ComparatorChain multiSort = new ComparatorChain(sortFields);
???? Collections.sort(rows,multiSort);
3.iReport報表的快速設計
2.
?? iReports終于出了0.41版,支持 JasperReports 0.64.
???? JasperReports 0.64為什么這么重要?因為從0.63開始,JasperReports支持了千呼萬喚始出來的box屬性,可以像其他商業報表工具那樣,設置表格的四周是否有線.而在以前,雖然人人都說神仙好,但一想起要手工劃線, 還要精確的在兩個field之間在留1個像素,就頭皮一陣陣發麻.
???? 另外,新的box在excel下也表現良好,不再需要為Html和Excel制作兩個不同的模版文件.
??? ?? 2.1 快速整理,對齊報表內的元素
?? ?? 這里示范最快捷的方法:
????? 1.點擊隨便一個要對齊的元素,左邊的文檔結構列表里相應的report session會打開
????? 2.用shift鍵選擇該session里的所有元素
??????3.ctrl+shift+l, ctrl+shift+向上箭頭
????? 原來雜亂無章的元素一下子排齊了。
????? 在報表里增加或刪除元素后,用此法都可快速重新對齊頁面。
????? 其中第1,2步是快速批量選擇所有元素,你也可以用鼠標拉框框選,或者按shift鍵一個一個選。
????? 第3步分別是左對齊和上對齊,都會向第一個選擇的元素看齊。
?????? 2.2 批量修改元素屬性
?????? 和很多網頁編輯器一樣,可以同時選擇多個元素然后點選屬性批量修改。
???????2.3 iReport,UltraEdit雙管齊下修改報表變量
?????? 當變量比較多時,用Ultraedit直接Copy Paste就要比用iReport來增加filed和varible快很多。但用UltraEdit要注意以下兩個問題:一是要注意Encoding,二是一個很奇怪的現象,iReport編譯后,UltraEdit打開的文件第一句最左邊的"
4.導出Excel文件
????剛開始導出的Excel文件叫人無比失望, 一個交得出去的Excel文件起碼應該:
?? 1.所有的Field要撐滿所在Band的高度,不要留空隙
?? 2.所有對象選成透明Transparent
???3.設置參數
???? exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
??????????????????? Boolean.TRUE);
???? exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
??????????????????? Boolean.FALSE);
???
5.JasperReports的一些補充?????
?5.1?輸出GBK字符集
?????????
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK");
? 5.2 定義filed顯示的Pattern
????????比如取小數后兩位,財務計數法(每3位一個,號)等,如果ireport提供的pattern不爽,還可以直接改Xml文件
? 5.3 Expresstion用三目運算符實現簡單的if-else選擇
??????? 有些情況比如分母不能為0的判斷,可以用三目運算符搞定,不一定要勞煩VO來計算。?
? 5.4 批量編譯文件
??????? ireport的Plug-in里有批量編譯目錄下所有文件的命令
??? 首先網上有一份JasperReport收費文檔, 不過老實說,這份文檔收費的話顯得太單薄了。
????1.1 為什么要自定義數據源
??? 簡單的報表,當然用不著自定義數據源。但查詢復雜起來時,還死守著一條SQL寫完會讓SQL變得又長又難讀,從來都最討厭別人在SQL上炫技。 這時候,把查詢分開執行,每個查詢只負責向VO(值對象Bean)賦值若干個列,程序就會清晰很多。而且,相近的查詢還可以進一步封裝在一個Reporter類里,提供給報表內或者報表之間重用。更何況,有些情況根本不可能一條SQL里寫完,而放在Java程序里處理卻輕松自在。
??? 搞定了可分解重用的數據源后,我才真正敢把JasperReports用在我們的系統上,否則,無法想象怎么維護那么多的SQL.
??? 1.2 自定義數據源的機制
dori.jasper.engine.JRDataSource 接口非常簡單,只要實現兩個方法:
public boolean next() throws JRException;
public Object getFieldValue(JRField jrField) throws JRException;
?????? 另外Hibernate的HQL查詢,如果返回多個對象時,每一row是Object[],只能按index而不能按名取值,也就不支持getFileldValue(field)了,hibernate.org上有折衷的方法,但都不好。
???? 1.3 Sample代碼與解釋
//封裝了大量查詢的reporter類
MooncakeReporter mooncakeReporter = new MooncakeReporter();
//建立VO的Map,因為需要多次執行查詢,需要快速找回VO來賦值,因此采用Map.
Map map = new HashMap();
rs = mooncakeReporter.findAllVaildProduct();
while (rs.next())
{
MooncakeVO mooncakeVO = new MooncakeVO();
String goods_no = rs.getString("goods_no");
String goods_name = rs.getString("name");?
???????mooncakeVO.setName(goods_name);
???????mooncakeVO.setCode(code);
?????? map.put(goods_no, mooncakeVO);
}
//調用Reporter封裝好的查詢函數獲取數據,并通過主鍵goods_no獲得VO來賦值。
rs = mooncakeReporter.findSaleOrderByShopType("shop");
while (rs.next())
{
?? String goods_no = rs.getString("goods_no");
?? MooncakeVO mooncakeVO = (MooncakeVO) map.get(goods_no);
?? if (mooncakeVO != null)
?? {
??? ? mooncakeVO.setShopCount(new Integer(rs.getInt("count")));
?? }
}
//如此重復執行查詢若干步
.....
//因為JRBeanCollectionDataSource需要Collection或者Array,把Map轉化為List。
List result = new ArrayList(map.values());
//對result進行排序,通過BeanUtils的beanComparator來實現,在下一小節會講到。
Collections.sort(result, new BeanComparator("code"));
//最后把result賦給JRBeanCollectionDataSource
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, new JRBeanCollectionDataSource(result));
??? 1.4 擴展
??? 1.用BeanComparator進行排序
????? 用map來存放的VO是沒有順序的,必須對其進行排序。 用jakata commons-beanutils的BeanComparator類,可以動態改變排序的列,比自己實現Compare()接口好。
??Collections.sort(result, new BeanComparator("code"));???? 對于"Order by lastName, firstName"的情形,還可以寫成這樣,其中ComparatorChain屬于jakata commons-collections包。
??? ArrayList sortFields = new ArrayList();
???? sortFields.add(new BeanComparator("lastName"));
???? sortFields.add(new BeanComparator("firstName"));
???? ComparatorChain multiSort = new ComparatorChain(sortFields);
???? Collections.sort(rows,multiSort);
3.iReport報表的快速設計
2.
?? iReports終于出了0.41版,支持 JasperReports 0.64.
???? JasperReports 0.64為什么這么重要?因為從0.63開始,JasperReports支持了千呼萬喚始出來的box屬性,可以像其他商業報表工具那樣,設置表格的四周是否有線.而在以前,雖然人人都說神仙好,但一想起要手工劃線, 還要精確的在兩個field之間在留1個像素,就頭皮一陣陣發麻.
???? 另外,新的box在excel下也表現良好,不再需要為Html和Excel制作兩個不同的模版文件.
??? ?? 2.1 快速整理,對齊報表內的元素
?? ?? 這里示范最快捷的方法:
????? 1.點擊隨便一個要對齊的元素,左邊的文檔結構列表里相應的report session會打開
????? 2.用shift鍵選擇該session里的所有元素
??????3.ctrl+shift+l, ctrl+shift+向上箭頭
????? 原來雜亂無章的元素一下子排齊了。
????? 在報表里增加或刪除元素后,用此法都可快速重新對齊頁面。
????? 其中第1,2步是快速批量選擇所有元素,你也可以用鼠標拉框框選,或者按shift鍵一個一個選。
????? 第3步分別是左對齊和上對齊,都會向第一個選擇的元素看齊。
?????? 2.2 批量修改元素屬性
?????? 和很多網頁編輯器一樣,可以同時選擇多個元素然后點選屬性批量修改。
???????2.3 iReport,UltraEdit雙管齊下修改報表變量
?????? 當變量比較多時,用Ultraedit直接Copy Paste就要比用iReport來增加filed和varible快很多。但用UltraEdit要注意以下兩個問題:一是要注意Encoding,二是一個很奇怪的現象,iReport編譯后,UltraEdit打開的文件第一句最左邊的"
4.導出Excel文件
????剛開始導出的Excel文件叫人無比失望, 一個交得出去的Excel文件起碼應該:
?? 1.所有的Field要撐滿所在Band的高度,不要留空隙
?? 2.所有對象選成透明Transparent
???3.設置參數
???? exporter.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS,
??????????????????? Boolean.TRUE);
???? exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND,
??????????????????? Boolean.FALSE);
???
5.JasperReports的一些補充?????
?5.1?輸出GBK字符集
?????????
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "GBK");
? 5.2 定義filed顯示的Pattern
????????比如取小數后兩位,財務計數法(每3位一個,號)等,如果ireport提供的pattern不爽,還可以直接改Xml文件
? 5.3 Expresstion用三目運算符實現簡單的if-else選擇
??????? 有些情況比如分母不能為0的判斷,可以用三目運算符搞定,不一定要勞煩VO來計算。?
? 5.4 批量編譯文件
??????? ireport的Plug-in里有批量編譯目錄下所有文件的命令