共三篇,下接:http://jimmy-shine.iteye.com/blog/123595
为了开发报表,已经拜读了一大堆的资料,其中大部分是重复的。可以看得出,国人还是比较热衷于copy&paste的工作。所以找了一大堆的资料都是相同的,或者可以用一个词来形容,换汤不换药的。
有必要对于jasper Report的学习进度进行一下总结,一来可以更新一下以前的资料中的一些旧得不能再旧的不再适用的东西,二来让后来者可以轻松的上手。
首先,jasperReport是一个以java实现的报表工具,(好像是句废话)。可以实现多种格式的报表。
再我们先理解一下jasperReport的实现过程。笔者不再画图,网上到处都是。
1)定制报表格式。
? 有二种方式,一种就是写jrxml文件,其实就是xml文件,只不过是后缀名不一样罢了。另一种方式更直接,就是生成一个JasperDesign类的实例,在japsperDesign中自己定义模板。jrxml文件也是通过一个JRXmlLoad加载过来,转成JasperDesign类的实例。也就是说写jrxml文件还需要进行解析,加载。现实中我们使用的报表一般格式比较固定,因而可以通过先使用iReport工具生成模板,再加载解析的方式。这种方式简单,而且可见性强。
2)填充数据。
? 在最新版(2007.4.30发布)的jasperReports1.3.3中,支持了很多的格式,包括了对于Hibernate的支持。填充数据对于我们经常使用的来说,一般是二种方式,一种方式是通过JDBC连接提供数据源,一种就是通过javaBean的集合提供数据源。当然还有web Service的xml文件提供的。我的建议是,如果你的程序中的统计直接使用Jdbc就可以完成,那么就使用jdbc数据源的方法,反之,使用javaBean的集合是不错的选择,因为这样不会在意你的数据的来源,你也可以任意处理,比如说,要通过权限检查的数据才在报表中生成的话,就可以过滤到不符合权限的数据。
3)显示或打印。
? 显示,即将JasperReport生成的文件直接显示出来,打印所使用的方式其实就是生成文件,然后调用打印来对文件进行打印。
看起来是不是很简单,对,确实很简单。
笔者主要从事基于B/S模式的开发,相信大部分人的使用也是基于web进行使用。故笔者对于基于web的开发进行详细讲述。
1、工程环境配置。
将以下包加入WEB-INF/lib中。
commons-beanutils-1.7.jar;commons-collections-2.1.jar;commons-digester-1.7.jar;commons-logging-1.0.2.jar;commons-logging-api-1.0.2.jar;itext-1.3.1.jar;jasperreports-1.3.3.jar;jdt-compiler-3.1.1.jar;jxl-2.6.jar;png-encoder-1.5.jar;poi-2.0-final-20040126.jar
? 以上包是jasperReport必须。
2、iReport的安装
?? 这个很简单,直接下一步就可以了。
3、使用iReport生成 .jasper文件
.jasper是经过编译的japserReport模板,即.jrxml编译后的。
对于iReport的使用网络上已经有了详细的中文的文档,具体可以下载附件查看。使用.jasper文件可以避免在系统中再进行编译,增加系统的压力。
4、数据填充
数据填充是相对于比较重要的一步,数据填充的目的是为了将数据填充进去,生成一个JapserPrint对象。笔者在之前已经阐述过,现在主要是基于关系型数据库(比较简单的,没有权限控制的),以及基于JavaBean Collection进行数据填充。进行数据填充的基本就是一定要实现JRDataSource,JRDataSource定义了二个方法,一个是指针移动的方法next(),另一个是取值的getFieldValue()方法,用来取值填充。
对于关系型数据库,即直接利用数据库的表来生成报表的,只需要传入一个Java Connection即可。JasperReport已经有了个默认的实现的JRDataSource的接口了。对于Java Conncetion的获得,笔者建议使用工厂方法或者使用Spring方式来获得。可以参照笔者写的如下:
- /** ?
- ?*?@copyRight?Beijing?Tsing-Tech?Reachway?Software?Co.,Ltd. ?
- ?*?@author?Jimmy.Shine?2007-5-11 ?
- ?*/??
- package?cn.com.reachway.framework.report; ??
- ??
- import?java.sql.Connection; ??
- import?java.sql.DriverManager; ??
- ??
- import?cn.com.reachway.framework.exception.JasperReportException; ??
- ??
- /** ?
- ?*?Used?for?get?a?JDBC?connection?for?Jasper?Report ?
- ?*/??
- public?class?JDBCConnection?{ ??
- ?/** ?
- ??*?Which?Jdbc?driver?were?used.?Like:?"net.sourceforge.jtds.jdbc.Driver" ?
- ??*/??
- ?private?String?jdbcDriver; ??
- ?/** ?
- ??*?The?jdbc?url,define?which?database?server,which?db.?Like: ?
- ??*?"jdbc:jtds:sqlserver://192.168.1.50:1433;DatabaseName=JAVA5;SelectMethod=Cursor" ?
- ??*/??
- ?private?String?jdbcUrl; ??
- ??
- ?private?String?dbUser; ??
- ??
- ?private?String?dbPassword; ??
- ??
- ?public?String?getDbPassword()?{ ??
- ??return?dbPassword; ??
- ?} ??
- ??
- ?public?void?setDbPassword(String?dbPassword)?{ ??
- ??this.dbPassword?=?dbPassword; ??
- ?} ??
- ??
- ?public?String?getDbUser()?{ ??
- ??return?dbUser; ??
- ?} ??
- ??
- ?public?void?setDbUser(String?dbUser)?{ ??
- ??this.dbUser?=?dbUser; ??
- ?} ??
- ??
- ?public?String?getJdbcDriver()?{ ??
- ??return?jdbcDriver; ??
- ?} ??
- ??
- ?public?void?setJdbcDriver(String?jdbcDriver)?{ ??
- ??this.jdbcDriver?=?jdbcDriver; ??
- ?} ??
- ??
- ?public?String?getJdbcUrl()?{ ??
- ??return?jdbcUrl; ??
- ?} ??
- ??
- ?public?void?setJdbcUrl(String?jdbcUrl)?{ ??
- ??this.jdbcUrl?=?jdbcUrl; ??
- ?} ??
- ??
- ?public?JDBCConnection()?{ ??
- ??super(); ??
- ?} ??
- ?/** ?
- ??*?Get?the?Connection? ?
- ??*?@return?connection ?
- ??*?@throws?JasperReportException ?
- ??*/??
- ?public?Connection?getConnection()?throws?JasperReportException?{ ??
- ??Connection?con; ??
- ??try?{ ??
- ???check(); ??
- ???Class.forName(this.jdbcDriver); ??
- ???con?=?DriverManager.getConnection(this.jdbcUrl,?this.dbUser,?this.dbPassword); ??
- ???return?con; ??
- ??}?catch?(Exception?e)?{ ??
- ???e.printStackTrace(); ??
- ???throw?new?JasperReportException("Get?JDBC?Connection?Error"); ??
- ??} ??
- ?} ??
- ? ??
- ?/** ?
- ??*?Check?the?Configure ?
- ??*?@throws?JasperReportException ?
- ??*/??
- ?private?void?check()?throws?JasperReportException?{ ??
- ??if?(this.jdbcDriver?==?null?||?this.jdbcDriver.equals("")?||?this.jdbcUrl?==?null?||?this.jdbcUrl.equals("") ??
- ????||?this.dbUser?==?null?||?this.dbUser.equals("")?||?this.dbPassword?==?null)?{ ??
- ???throw?new?JasperReportException("Jdbc?Configure?error!"); ??
- ??} ??
- ?} ??
- ??
- } ??
- ??
- /** ?
- ?*?@copyRight?Beijing?Tsing-Tech?Reachway?Software?Co.,Ltd. ?
- ?*?@author?Jimmy.Shine?2007-5-14 ?
- ?*/??
- package?cn.com.reachway.framework.report.dataSource; ??
- ??
- import?net.sf.jasperreports.engine.JRDataSource; ??
- import?net.sf.jasperreports.engine.JRException; ??
- import?net.sf.jasperreports.engine.JRField; ??
- ??
- /** ?
- ?*?报表的dataSource的基类,所有利用DataSource产生报表的继承此类 ?
- ?*/??
- public?abstract?class?ReportDataSource?implements?JRDataSource?{ ??
- ??
- ?/** ?
- ??*?取值 ?
- ??*/??
- ?public?abstract?Object?getFieldValue(JRField?jrField)?throws?JRException; ??
- ??
- ?/** ?
- ??*?指针移动 ?
- ??*/??
- ?public?abstract?boolean?next()?throws?JRException; ??
- ??
- } ??
- ??
对于其它的数据源,JavaBean Collection,笔者采用了一个抽象类,使用抽象类的目的,是为了使开发者尽可能不用直接接触jasperReport(此为笔者自己的方式,笔者是PM,为了考虑底下的人的开发)。以下为抽象类以及笔者提供的一个sample:
- /** ?
- ?*?@copyRight?Beijing?Tsing-Tech?Reachway?Software?Co.,Ltd. ?
- ?*?@author?Jimmy.Shine?2007-5-14 ?
- ?*/??
- package?cn.com.reachway.framework.report.dataSource; ??
- ??
- import?java.util.ArrayList; ??
- import?java.util.List; ??
- ??
- import?net.sf.jasperreports.engine.JRException; ??
- import?net.sf.jasperreports.engine.JRField; ??
- ??
- /** ?
- ?*?利用JavaBean?Collection生成ReportDataSource的例子 ?
- ?*/??
- public?class?ReportDataSourceSample?extends?ReportDataSource?{ ??
- ??
- ?private?List?docs?=?new?ArrayList(); ??
- ??
- ?private?int?index?=?-1; ??
- ??
- ?public?ReportDataSourceSample()?{ ??
- ??for?(int?i?=?0;?i?<?10;?i++)?{ ??
- ???Document?doc?=?new?Document("ViewTimes?is:"?+?i,?i); ??
- ???this.docs.add(doc); ??
- ??} ??
- ?} ??
- ??
- ?//?内部类,作为demo时使用 ??
- ?private?class?Document?{ ??
- ??private?String?name; ??
- ??
- ??private?int?viewTimes; ??
- ??
- ??public?String?getName()?{ ??
- ???return?name; ??
- ??} ??
- ??
- ??public?void?setName(String?name)?{ ??
- ???this.name?=?name; ??
- ??} ??
- ??
- ??public?int?getViewTimes()?{ ??
- ???return?viewTimes; ??
- ??} ??
- ??
- ??public?void?setViewTimes(int?viewTimes)?{ ??
- ???this.viewTimes?=?viewTimes; ??
- ??} ??
- ??
- ??public?Document()?{ ??
- ??} ??
- ??
- ??public?Document(String?name,?int?viewTimes)?{ ??
- ???this.name?=?name; ??
- ???this.viewTimes?=?viewTimes; ??
- ??} ??
- ?} ??
- ??
- ?public?List?getDocs()?{ ??
- ??return?docs; ??
- ?} ??
- ??
- ?public?void?setDocs(List?docs)?{ ??
- ??this.docs?=?docs; ??
- ?} ??
- ??
- ?@Override??
- ?public?Object?getFieldValue(JRField?jrField)?throws?JRException?{ ??
- ??
- ??String?fieldName?=?jrField.getName(); ??
- ??Document?doc?=?this.docs.get(index); ??
- ??if?("name".equals(fieldName))?{ ??
- ???return?doc.getName(); ??
- ??} ??
- ??if?("viewTimes".equals(fieldName))?{ ??
- ???return?doc.getViewTimes(); ??
- ??} ??
- ??return?null; ??
- ?} ??
- ??
- ?@Override??
- ?public?boolean?next()?throws?JRException?{ ??
- ??index++; ??
- ??return?(index?<?this.docs.size()); ??
- ?} ??
- } ??
- ??
以上的例子应当很清楚的写明了如何生成数据源。
对于数据源的填充,笔者使用了二个类,分别用来对应使用Connction及JavaBean Collection进行填充。
- /** ?
- ?*?@copyRight?Beijing?Tsing-Tech?Reachway?Software?Co.,Ltd. ?
- ?*?@author?Jimmy.Shine?2007-5-12 ?
- ?*/??
- package?cn.com.reachway.framework.report.jasperPrint; ??
- ??
- import?java.io.File; ??
- import?java.sql.Connection; ??
- import?java.util.Map; ??
- ??
- 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.util.JRLoader; ??
- import?cn.com.reachway.framework.exception.JasperReportException; ??
- ??
- /** ?
- ?*?使用报表模板及数据等来生成JapserPrint ?
- ?*/??
- public?class?JasperPrintWithConnection?{ ??
- ?/**?传入的参数?*/??
- ?private?Map?params; ??
- ?/**?模板文件的地址?*/??
- ?private?String?reportFilePath; ??
- ?/**?JDBC?connection?*/??
- ?private?Connection?con; ??
- ??
- ?public?Connection?getCon()?{ ??
- ??return?con; ??
- ?} ??
- ??
- ?public?void?setCon(Connection?con)?{ ??
- ??this.con?=?con; ??
- ?} ??
- ??
- ?public?Map?getParams()?{ ??
- ??return?params; ??
- ?} ??
- ??
- ?public?void?setParams(Map?params)?{ ??
- ??this.params?=?params; ??
- ?} ??
- ??
- ?public?String?getReportFilePath()?{ ??
- ??return?reportFilePath; ??
- ?} ??
- ??
- ?public?void?setReportFilePath(String?reportFilePath)?throws?JasperReportException?{ ??
- ??if?(reportFilePath?==?null?||?!reportFilePath.endsWith(".jasper")) ??
- ???throw?new?JasperReportException("您传入的模板文件格式不对,请传入以.jasper为后缀的文件!"); ??
- ??this.reportFilePath?=?reportFilePath; ??
- ?} ??
- ??
- ?public?JasperPrintWithConnection()?{ ??
- ??super(); ??
- ?} ??
- ??
- ?public?JasperPrintWithConnection(String?reportFilePath,?Map?params,?Connection?con)?throws?JasperReportException?{ ??
- ??if?(reportFilePath?==?null?||?!reportFilePath.endsWith(".jasper")) ??
- ???throw?new?JasperReportException("模板文件格式不对,请传入以.jasper为后缀的文件!"); ??
- ??if?(con?==?null) ??
- ???throw?new?JasperReportException("Conncetion不应当为null!"); ??
- ??this.setReportFilePath(reportFilePath); ??
- ??this.setParams(params); ??
- ??this.setCon(con); ??
- ?} ??
- ? ??
- ?/** ?
- ??*?取得JasperPrint ?
- ??*?@return ?
- ??*?@throws?JasperReportException ?
- ??*/??
- ?public?JasperPrint?getJasperPrint()?throws?JasperReportException?{ ??
- ??File?reportFile?=?new?File(this.reportFilePath); ??
- ??if?(!reportFile.exists()) ??
- ???throw?new?JasperReportException("传入的模板文件不存在!"); ??
- ??
- ??try?{ ??
- ???//?Load编译好的模板 ??
- ???JasperReport?jasperReport?=?(JasperReport)?JRLoader.loadObject(reportFile.getPath()); ??
- ???//?进行数据填充 ??
- ???JasperPrint?jasperPrint?=?JasperFillManager.fillReport(jasperReport,?this.params,?this.con); ??
- ???return?jasperPrint; ??
- ??
- ??}?catch?(JRException?jre)?{ ??
- ???jre.printStackTrace(); ??
- ???throw?new?JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!"); ??
- ??} ??
- ??
- ?} ??
- } ??
- ??
- /** ?
- ?*?@copyRight?Beijing?Tsing-Tech?Reachway?Software?Co.,Ltd. ?
- ?*?@author?Jimmy.Shine?2007-5-14 ?
- ?*/??
- package?cn.com.reachway.framework.report.jasperPrint; ??
- ??
- import?java.io.File; ??
- import?java.util.Map; ??
- ??
- import?net.sf.jasperreports.engine.JRDataSource; ??
- 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.util.JRLoader; ??
- import?cn.com.reachway.framework.exception.JasperReportException; ??
- ??
- /** ?
- ?*? ?
- ?*/??
- public?class?JasperPrintWithDataSource?{ ??
- ?/**?传入的参数?*/??
- ?private?Map?params; ??
- ?/**?模板文件的地址?*/??
- ?private?String?reportFilePath; ??
- ?/**?dataSrouce?*/??
- ?private?JRDataSource?dataSource; ??
- ??
- ?public?JRDataSource?getDataSource()?{ ??
- ??return?dataSource; ??
- ?} ??
- ??
- ?public?void?setDataSource(JRDataSource?dataSource)?{ ??
- ??this.dataSource?=?dataSource; ??
- ?} ??
- ??
- ?public?Map?getParams()?{ ??
- ??return?params; ??
- ?} ??
- ??
- ?public?void?setParams(Map?params)?{ ??
- ??this.params?=?params; ??
- ?} ??
- ??
- ?public?String?getReportFilePath()?{ ??
- ??return?reportFilePath; ??
- ?} ??
- ??
- ?public?void?setReportFilePath(String?reportFilePath)?throws?JasperReportException?{ ??
- ??if?(reportFilePath?==?null?||?!reportFilePath.endsWith(".jasper")) ??
- ???throw?new?JasperReportException("您传入的模板文件格式不对,请传入以.jasper为后缀的文件!"); ??
- ??this.reportFilePath?=?reportFilePath; ??
- ?} ??
- ??
- ?public?JasperPrintWithDataSource()?{ ??
- ??super(); ??
- ?} ??
- ??
- ?public?JasperPrintWithDataSource(String?reportFilePath,?Map?params,?JRDataSource?dataSource) ??
- ???throws?JasperReportException?{ ??
- ??if?(reportFilePath?==?null?||?!reportFilePath.endsWith(".jasper")) ??
- ???throw?new?JasperReportException("模板文件格式不对,请传入以.jasper为后缀的文件!"); ??
- ??if?(dataSource?==?null) ??
- ???throw?new?JasperReportException("DataSource不应当为null!"); ??
- ??this.setReportFilePath(reportFilePath); ??
- ??this.setParams(params); ??
- ??this.setDataSource(dataSource); ??
- ?} ??
- ?/** ?
- ??*?取得JasperPrint ?
- ??*?@return ?
- ??*?@throws?JasperReportException ?
- ??*/??
- ?public?JasperPrint?getJasperPrint()?throws?JasperReportException?{ ??
- ??File?reportFile?=?new?File(this.reportFilePath); ??
- ??if?(!reportFile.exists()) ??
- ???throw?new?JasperReportException("传入的模板文件不存在!"); ??
- ??
- ??try?{ ??
- ???//?Load编译好的模板 ??
- ???JasperReport?jasperReport?=?(JasperReport)?JRLoader.loadObject(reportFile.getPath()); ??
- ???//?进行数据填充 ??
- ???JasperPrint?jasperPrint?=?JasperFillManager.fillReport(jasperReport,?this.params,?this.dataSource); ??
- ???return?jasperPrint; ??
- ??
- ??}?catch?(JRException?jre)?{ ??
- ???jre.printStackTrace(); ??
- ???throw?new?JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!"); ??
- ??} ??
- ??
- ?} ??
- } ??
- ??
其中使用的JasperReportException为笔者定义的异常,用来统一处理报表异常。
5、报表产生
报表产生是程序中最终可见的一部分,在jasperReport的demo中,大部分中使用了jasperReport的net.sf.jasperreports.j2ee.servlets.*中的类来生成。其实这也算是开源的产品的一个问题,其实jasperReport提供的report的工具,只能算是demo级别的,不能算是产品级别的。相信很多的朋友在使用的时候就碰上无法生成的问题。笔者在此基础上封装了一下。
具体参见以下:
出现中文的乱码的情况是由于编码的问题,检查一下,你的程序,确保所有的都是使用UTF-8进行编码,尤其是对于.java的源文件的检查。
原因应当在于你在编码的时候,对于源程序没有使用UTF-8编码。
email: tdty630@163.com
我想做主从报表,点击主报表上的一个数据链接后
在一个弹出窗口中打对应的从报表,jasper能实现吗?
谢谢!
1:如何形成.jsper
2:如何jsp 报表输出
这帖子也就是整理资料,设计总结谈不上,只是介绍了一些最基本的东西。也没有跟ireport结合起来谈,以及如何与hibernate整合等等。有一本专门的电子书讲jasperreport的,有兴趣的话我可以发上来。
怎么还没发上来呀?
我现在要用hibernate做一个柱形的报表,都不知道要怎么入手呀!
请各位大哥大姐们多多帮助呀!
可是,我把程序用fatjar打包成jar后,报表就不能预览了。这是怎么回事?能给与解答么?谢谢了。
还有一个问题,我在eclipse环境下,运行程序。预览报表。可是,关闭预览窗体JasperViewer后,为什么我的程序也会自动关闭???
why do not you used iReport view your report?
because of jasperviewer is used GUI to view it,so if you close it,the event will told the system exit the program!
I suggest you use iReport to design and view your report,it is easy to design and easy to view,also it is easy to change your design!
ea
首先说,我不会用iReport预览:)
不过,还是很感谢老大们的帮助。
自己问题自己解决。已经解决了一个问题。但是,jar打包后,运行不能显示的问题还是没有办法解决。我要继续努力。方法我已经想到了。正在努力尝试。
Good luck!
我在设计好了报表,但是没有在设计器中写sql语句,我想把sql语句在程序中生成,然后传给报表,然后打印。
JasperDesign jasperDesign = new JasperDesign();
JRDesignQuery query = new JRDesignQuery();
query.setText("SELECT DISTINCT a1 as a, b1 as b from table1 where a1 = 'xxx'");
jasperDesign.setQuery(query);
我是这样写的,但是御览报表后发现,报表好像并没有执行sql文。运行的结果和没有sql文的结果一样。
请指点我一下。
1.我怎么才能提高报表的速度?
现在,我用JasperFillManager.fillReport填充报表的时候总是很慢。要等上大概5-8秒钟。无法容忍。不知道有没有什么方法可以让填充报表的速度提高一些?1-2秒钟内完成。(已经解决)
2.我想把报表保存成图片.jpg不知道该怎么做。(已经解决)
我要一次打印很多报表,最容易的方法,就是分别打印。每个报表都填充成一个jasperPrint,然后打印。这样很麻烦,因为要给打印机传很多次明令。如果能把我要一口气打印出的报表,合成一个jasperPrint的话,就只用给打印机传一次命令就可以解决了。
现在就是不知道怎么才能把这些jasperPrint数据,合成一个jasperPrint。
附件是iReport的使用文档。do
没深度
实效性也差
总是list 到 jasper的数据传递断掉
要写就详细点