| 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.<box>元素,终于不用手工划表格线了 
   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里有批量编译目录下所有文件的命令                                                                                                                                        江南白衣  
 
  |