Sung in Blog

                     一些技術文章 & 一些生活雜碎
          JasperReports+iReports ,??類似于CrystalReport的開源報表系統,最主要能幫助我們在設計時把數據和表示分開,幫助我們實現Web報表的分頁打印,分組合計,變量的加減處理,輸出的格式化,還有導出Excel、pdf等,反正用過了的人都不肯回去重新自己畫html頁面出報表了。
          ????google上有入門教程,非常容易。但一遇到復雜的報表,入門那套很快就玩不轉了,如果沒有中級的研究,可能又得乖乖回去用html畫報表。
          ??? 首先網上有一份JasperReport收費文檔, 不過老實說,這份文檔收費的話顯得太單薄了。
          ???
          ????1.自定義數據源

          ????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;
          ???????看函數名字都知道其意義了。所幸,我們連這兩個方法都不用實現,Jaspert已經有兩個關于VO Bean的實現了。它們是dori.jasper.engine.data.JRBeanArrayDataSource和dori.jasper.engine.data.JRBeanCollectionDataSource
          ???????看名字可知,一個用Array來放bean,一個用Collection 。
          ?
          ?????? 很可惜如果VO有內嵌對象,也不能用$F{order.customer.name}這樣的語法讀取。
          ?????? 另外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里有批量編譯目錄下所有文件的命令

          JasperReports+iReports ,??類似于CrystalReport的開源報表系統,最主要能幫助我們在設計時把數據和表示分開,幫助我們實現Web報表的分頁打印,分組合計,變量的加減處理,輸出的格式化,還有導出Excel、pdf等,反正用過了的人都不肯回去重新自己畫html頁面出報表了。
          ????google上有入門教程,非常容易。但一遇到復雜的報表,入門那套很快就玩不轉了,如果沒有中級的研究,可能又得乖乖回去用html畫報表。
          ??? 首先網上有一份JasperReport收費文檔, 不過老實說,這份文檔收費的話顯得太單薄了。
          ???
          ????1.自定義數據源

          ????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;
          ???????看函數名字都知道其意義了。所幸,我們連這兩個方法都不用實現,Jaspert已經有兩個關于VO Bean的實現了。它們是dori.jasper.engine.data.JRBeanArrayDataSource和dori.jasper.engine.data.JRBeanCollectionDataSource
          ???????看名字可知,一個用Array來放bean,一個用Collection 。
          ?
          ?????? 很可惜如果VO有內嵌對象,也不能用$F{order.customer.name}這樣的語法讀取。
          ?????? 另外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里有批量編譯目錄下所有文件的命令

          ]]>
          posted on 2005-09-13 10:38 Sung 閱讀(1859) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 开化县| 台北市| 广水市| 北流市| 叶城县| 蓬莱市| 清镇市| 新津县| 会东县| 景洪市| 长沙市| 台安县| 绥中县| 盐津县| 高州市| 洛南县| 墨脱县| 封丘县| 阿城市| 通榆县| 东乡族自治县| 台中县| 湘乡市| 奈曼旗| 德阳市| 锦州市| 阳西县| 长武县| 黑河市| 济南市| 阳信县| 镇巴县| 淳化县| 马边| 芷江| 德格县| 美姑县| 应城市| 昌都县| 将乐县| 永安市|