最好是能发点代码看看,谢谢了!

解决方案 »

  1.   

    Jasperreport程序库是一个灵活,功能强大的报表产生工具,可以以PDF, HTML或XML等多种形式产生报表,并有希望支持CSV, XLS, RTF等格式报表。该引擎由Java编写,支持多种形式应用程序产生动态报表,如J2EE,网络报表等。其主要目的是产生页面导向、方便打印的报表文档。Jasperreport是按照一个预定义的xml文档来组织报表的数据,这些数据来源多样,包括关系数据库、java容器对象(collection和arrays),后面我们将介绍,用户通过简单的接口来实现数据源与报表引擎的使用。要完成报表的填充,必须先完成用于报表的xml文件,其过程是先产生报表设计对象,再序列化该对象,存储在磁盘或者网络,用于产生特定应用的表格数据。事实上,表单的设计过程就是用定义于xml文件中的java表达式来表现报表的设计。编辑过程中会有各种保证数据一致性的验证,最终会产生相关数据文档或填充数据的准备。报表引擎必须先接受数据(通过参数等多种形式)来产生报表,更多的是来自数据源,引擎直接接收用于填充表格的数据源对象,或者通过自身提供的JDBC连接对象来处理数据库的数据。报表最终要产生一个新的对象来进行填充操作从而产生打印文档对象,这也是一个存储在磁盘或网络传输介质的序列化对象。Jasperreport的内置浏览器能直接查看结果或者以PDF, HTML,XML形式导出。2、API概览人们更多的是使用Jasperreport类库的部分内容而不是全部来实现它的特点与功能。这一部分我们介绍一下如何利用这些重要的类和接口来实现Jasperreport提供的报表功能。 类net.sf.jasperreports.engine.design.JasperDesign    之所以从这个类开始,是因为它的实例是jasperreport用于报表产生的原始类,比如,该类实例在用于产生报表的xml文件被解析后获得,或者不产生xml文档而是由调用jasperreport的应用程序产生。在所给的例子中有一个(noxmldesign)就是在不产生xml文件的情况下动态生成该实例的一个例子。所有该类的实例都属于报表的填充和产生以前产生的,所以我们称之为原始类。 类net.sf.jasperreports.engine.design.jasperreport     该类实例表现了报表设计对象,是作为报表的编译过程的结果而被实例化,是向报表中填充数据的准备。在报表的编译过程中协同验证报表元素的合法性,一致性;同时创建了临时文件存储报表中所有的变量,表达式。编译过程中会先查找classpath中tools.jar或者Ant进行编译,编译结果以字节码的形式存储,并且在填充数据时用于判断多种产生报表的形式
      

  2.   

    JapertReports & iReport的开源报表实战      JasperReports+iReports ,  类似于CrystalReport的开源报表系统,最主要能帮助我们在设计时把数据和表示分开,帮助我们实现Web报表的分页打印,分组合计,变量的加减处理,输出的格式化,还有导出Excel、pdf等,反正用过了的人都不肯回去重新自己画html页面出报表了。 
        google上有入门教程,非常容易。但一遇到复杂的报表,入门那套很快就玩不转了,如果没有中级的研究,可能又得乖乖回去用html画报表。 
        首先网上有一份JasperReport收费文档,不过老实说,这份文档收费的话显得太单薄了。
       
        1.自定义数据源,传入VO数组而不直接在JasperReports里查询SQL.
        1.1 为什么要自定义数据源
              简单的报表,当然用不着自定义数据源,直接在JasperReports里编写SQL就可以了。
              但查询复杂起来时,还死守着一条SQL写完会让SQL变得又长又难读,从来都最讨厌  别人在SQL上炫技。这时候,在JasperReport外部的Java程序里进行数据的采集(还可以进一步把相近的查询封装到一个数据采集类中),把结果通过自定义数据源传入JasperReports,而JasperReport只负责数据的显示,更符合数据与显示分开这个普适的模式。
        搞定了可分解重用的数据源后,我才真正敢把JasperReports用到系统上。否则,无法想象怎么在JasperReport文件里维护那么多的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而不能像ResultSet那样按名取值,也就不支持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赋给JRBeanCollectionDataSourceJasperPrint 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); 
    2.<box>元素, 终于不用手工划表格线了   iReports终于出了0.41版, 支持 JasperReports 0.64。   为什么这么重要呢? 因为从0.63开始,JasperReports支持了千呼万唤始出来的box属性,可以像其他商业报表工具那样,设置表格的四周是否有线。而在以前,虽然人人都说神仙好,但一想起要手工划表格线,还要精确的在两个field之间在留1个像素,头皮就一阵阵发麻。    另外,新的box在excel下也表现良好,不再需要为Html和Excel制作两个不同的模版文件.
    3.iReport报表的快速设计   一开始什么都不懂,对着满屏的元素,拖拉半天才把它对齐,差点就用不下去了。 
       3.1 快速整理,对齐报表内的元素
          这里示范最快捷的方法:
          1.点击随便一个要对齐的元素,左边的文档结构列表里相应的session会打开
          2.用shift键选择该session里的所有元素
          3.ctrl+shift+l, ctrl+shift+向上箭头      原来杂乱无章的元素一下子排齐了。
          在报表里增加或删除元素后,用此法都可快速重新对齐页面。
          其中第1,2步是快速批量选择所有元素,你也可以用鼠标拉框框选,或者按shift键一个一个选。
          第3步分别是左对齐和上对齐,都会向第一个选择的元素看齐。   3.2 批量修改元素属性
           和很多网页编辑器一样,可以同时选择多个元素然后点选属性批量修改。 
       3.3 iReport,UltraEdit双管齐下修改报表变量
           当变量比较多时,用Ultraedit直接Copy Paste就要比用iReport来增加filed和varible快很多。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里有批量编译目录下所有文件的命令