JasperReport是报表的引擎部分,界面设计是用iReport。为什么选择这两个软件呢?因为这两个软件都是开源的,即免费的(虽然某些文档收费,但是磨灭不了我们使用它的理由)。
JasperReport是一个报表制作程序,用户按照它制定的规则编写一个XML文件,然后得到用户需要输出的格式文件。它支持输出的文件格式包括PDF,HTML,XML,XLS,CSV等等。
用JasperReport做报表,可以分为两种方式:
1、 直接利用程序定义一个报表
2、 写一个xml文件来描述这个报表,通常需要借助于iReport
JasperReport做报表时用的都是底层的东西,如线条、静态文本等,底层的好处就是强大、容易控制报表,但缺点就是编写很麻烦。庆幸的是,我们有iReport这个软件,这个软件完全是弥补JasperReport的不足,将底层编写推向可视化,大大的方便了我们。
JasperReport的工作流程:首先有个xml文件,从xml文件编译出.jasper类型的文件,而以后我们真正要使用的就是编译后的jasper文件。
上图为JasperReport的API示意图,可作为学习的参考。由iReport输出的文件中,对WEB应用可能有用的是jasper文件,当JAVA程序进行调用的时候,将把jasper文件转换成print类型,从而进一步到达其他格式的输出(如上图)。
对于较古老的版本,这里不做过多介绍,请参考本目录下其他文献。这里提一下,古老版本需要额外下载ANT(JAVA的build工具)以及iTextAsian.jar(用以支持中文的jar包)等。
iReport http://www.jasperforge.org/jaspersoft/opensource/business_intelligence/ireport/下载
JasperReport http://www.jasperforge.org/jaspersoft/opensource/business_intelligence/jasperreports/下载
JDK http://java.sun.com/下载
本人用的产品版本:iReport 2.0.5-windows版本;JasperReport 2.0.5版本;JDK 1.5.0_4版本。
注:在新的iReport版本中,已经包含了JasperReport的jar包,不需要下载JasperReport包了,但是,要更多的了解JasperReport,还是推荐下载完整的软件包,以学习它的源代码和例子。还有,新版本的iReport带有字体包,不需另下。
首先安装JDK,一路NEXT即可。
其次,安装iReport,由于新版本对windows支持较好,所以和JDK一样,一路NEXT即可。
注:旧版本需要对环境变量进行配置,此篇文章介绍的版本以及更新的版本均不需要手动配置环境变量。
您还需要准备一个数据源(如果需要做动态报表的话),大部分情况是一个数据库。笔者使用的是Oracle 9i的数据库。
先看使用界面:
下面开始初步尝试。
弹出对话框如下:
还有许多其他的选项,中文可以理解。有个XML编码,可以手动输入,也可保持默认,点击”OK”创建新表完成。
注:iReport不会自动保存,需要手动保存,建议多保存。
新建的报表如下:
一个报表的结构大致是几个部分:title、pageHeader、columnHeader、detail、columnFooter、pageFooter、lastPageFooter、summary以及groupHeader、groupfooter。
·Title:每个报表一般会有一个名字,比如×××销售报表,title就是搁置这个名称的最好地方了,当然你也可以根据需要搁置在合适的地方。Title只在第一页出现。
·pageHeader:报表的一些公共要素,比如页码、创建时间、创建人等信息放置在这里是比较好的选择。
·columnHeader:无可非议的这里是放置列的名称,记住不是列数据。
·detial:放置需要循环输出的数据,比如销售记录数据。
·columnFooter:放置列级别的统计计算值或是列的说明。
·pageFooter:放置页级别的统计值或是页的说明。
·lastPageFooter:最后一页特殊的格式,可以放置总结等。
·Summary:可能需要对几页(你的报表可能有几个页组成)的统计值。比如50个销售记录共占用了3页,那么放置这些统计记录的统计值最好的地方就是summary。Summary只在最后一页出现。
·groupHeader:每个表的内容可能需要根据某个属性进行划分显示内容和计算内容,比如希望以月份为单位每组分开显示销售记录,那么就可以定义一个组(组的定义参考后文),groupHeader就是放置组说明或是组标志最好的地方。
·Groupfooter:放置组的统计或是说明
可以通过工具栏的工具添加静态对象与动态对象。点击可以创建静态对象,点击可以创建动态对象。之后在报表的空白处单击,如此即可把对象添加到报表,然后拖动对象的边框,使它的大小合适,双击即可对对象中的文本进行快速编辑。
仔细观察,会发现对象的边框有两种颜色,一为蓝色,二为红色,蓝色为符合布局要求,红色反之。
注:一个对象不能横跨两个区域,即不能既在columnHeader里又在detail里。
鼠标右击对象,弹出如下菜单:
点击”属性”,编辑对象的属性。
这里面有很多属性,可以依据要求来更改其中的部分或所有。其中,重要的可能是关于PDF的,如下图。
红框框起来的部分要注意,当要输出中文的时候,需要类似设置。新版本对边框的更新,使我们操作起来更为方便。注意下面红框里的部分,这可以对每一个边进行分开的设置,人性化的为我们解决了大量问题。
注:JasperReport没有现成的表格,最好的方法就是用一个一个对象的边框堆积起来,组成一个表格。但是,对象的边框不能覆盖,否则HTML、EXCEL等不能正常输出。
对于动态对象,属性如下。
主要属性如图所示。在Pattern里,可以定义输出的格式,在输出时间和日期或者货币时尤为有用。上图中的”stretch with overflow”表示当填充值超出定义的大小时,自动换行;”blank when null”表示当数据为null时不显示数据,这两个在某些时候很有用处。
而在表达式一栏中,如果字体为蓝色,则表示不正确,当输入正确的时候,会呈现绿色,如图。
首先,需要添加一个数据源,此处选用Oracle数据库,步骤如下。
如下图,点击”连结/资料来源”。
弹出下面对话框,点击”New”。(图中已有数据源乃是笔者添加)
选择一个数据来源,这里选择第一个JDBC连接数据库的方式,点击”下一步”。
按照图中的介绍填写相关信息,并测试信息是否正确,然后保存。iReport可以添加保存多个数据源连接信息。
注:如提示找不到相关驱动,则需要将驱动的JAR包复制到iReport的lib文件夹下。
在使用iReport 的过程中会碰到很多与变量(Variables)、参数(Parameters)、字段(Fields)这些有关的内容,我们要介绍这些对象的使用和意义:
·字段(Fields):是数据源抽取出来的,希望在报表中出现的数据库内容。比如一个ID的所有值,$F{ filedsName }。
·参数(Parameters):这是你的应用需要提供给报表的入口,比如你希望在报表被解释的时候提供Where语句的条件值,那么就可以使用参数(Parameters),$P{ parameterName }。
·变量(Variables):这是报表中一些逻辑运算的表现,比如统计值,$V{ variablesName }。
可以通过以下方式添加、修改和删除。
弹出如下对话框:
红框里的是iReport自带的供用户使用的变量,用于计算数量和总值等。点击”新增”,可以增加用户自己的变量,如图。
各个部分功能如标注所示。
定义参数的按钮就在定义变量的旁边,如上节,不赘述。
上图中,红框里的是系统内置的参数,供用户调用,其中包括一些常用的参数,如连接、最大值等等。点击”新增”按钮后,出现如下页面。
在新增参数对话框中输入参数的名称、数据类型、缺省值以及参数的描述信息等。需要注意的是,根据不同的参数类型,在设置参数的缺省值时要使值能与参数类型匹配,即字符型的参数在设置缺省值时要用””把值括起来,如果是数据值型的则不能加””。
参数的引用方式有两种,,一种是$P{},另一种是$P!{},前者可以出现在任意的表达式位置,而后者则只能出现在SQL脚本里,用来替换查询语句,用以按照不同的需求替换查询语句。同时,在脚本里,也有些许区别:前者只能替换语句的部分字段,如SELECT * FROM bugs where name=$P{Name} order by proname, modulename,而对于$P!{},则可以直接在SQL脚本框里输入$P!{SQL}。
编辑字段的方式与变量、参数类似,打开”字段”界面。
在点击”新增”后,出现如上页面,根据情况填写字段名称、字段类型(一般与数据来源类型相匹配)和字段的描述等。这种是手动添加字段,另一种更为方便的方法是从数据源直接读出,将在后面介绍。
字段用于动态对象里,即。它的主要功用在于动态连接数据源,完成数据源的读出显示,所以在有动态对象的报表里,执行的时候一般采用”执行报表(使用动态连接)”,如图。
从上图中,选择默认的动态连接。
弹出如下界面,各部分功能介绍如图。
这便是上面所说的另一种更为方便的添加字段的方法,从数据源直接复制到字段里,方便、快捷。
如上图所示,还有三种连接数据源的方式:JavaBean、DataSource、CSV。多种不同的方式给我们添加了很多便利。
组是一个很重要的概念,一个报表可以多个组,每个组以一个关键字为标记,比如希望统计是根据项目(或是产品)进行统计的。那么可以设立一个项目标记的组。如图。
组的参数设定可以看界面即可理解部分,其中最主要的是“Group expression”,这里必须输入格式正确的并且存在的字段名称,本文的“Name”是【字段】中的一个元素。依此类推,建立其他的组对象。每建立一个组,在报表的界面上都会出现该组对应的段,组的Header与Footer是对应出现的。如图。
如图。
点击”Styles”,弹出如下界面。
在这里,我们可以定义许多个常用的格式,按照个人喜好进行定义,定义后,在对象属性的页面上可以选择使用哪种风格,所设置的属性会自动继承。如图:
在iReport的界面上,处于人性化的考虑,设置了很多快捷按钮供用户使用,如图。
上图包括文档的基本操作,线条与图形的绘画,静态与动态对象的添加,图表图像报表的插入,报表、栏等的属性,也包括编译、执行等按钮。
上图包括字体字号,一些对象内部的基本排列操作和数据源设置等。
上图包括对象的对齐、排列、规格化等操作。
所有这些快捷按钮给用户提供了很大的便利,熟悉之后,用起来会更加顺手。
iReport支持多种输出格式,其中包括PDF,HTML,XML,XLS,CSV等等。介绍一下如何进行预览和输出。
iReport默认是JRViewer输出预览,用户可以在上述菜单中进行调整和选择。
在这里,但是只在此设置输出格式了,还没有完成设置,还有一个必需的设置就是,为每一种设置选择执行“环境”,例如,如果你选择以PDF 输出,那么你需要为其指明Adobe Reader 的路径,如图选择菜单Options/选项,则会弹出如下属性页:
选择之后,保存即可,iReport会自动调用相关程序来完成输出和预览。
正如前面所说,报表有很多种输出方式,这里挑选一些常用的进行介绍。
在iReport中,我们可以对报表进行预览,而此时,是iReport帮助我们完成了绝大部分的工作,我们并不需要输入代码来完成输出,而这里我们所说的输出是输出到文件或者输出到WEB页面等。
我们将以输出html格式为例子讲述。有人会问:这html不是静态页面吗?我说,的确是这样的。不过,html有普遍适用性,我们可以把它插入到动态页面里面去,比如说JSP或者ASP等。
动态页面的技术细节不在这里赘述,这里我们只介绍jasperReport相关,下面我们以JSP相关技术为基底来叙述。
1) 读取.jasper文件
通过iReport软件,我们可以把已经定义好的XML编译成.jasper文件,供以后使用。本人把.jasper文件放置在站点根目录下的reports文件夹内,读取文件的代码如下:
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/report/done.jasper");
2) 转换成JasperReport类型
查找到.jasper文件的绝对路径后,可以对其进行读取,有很多种方式可以读取,不过笔者推荐如下方式(这也是官方例子中推荐并使用的):
JasperReport jasperReport = (JasperReport)JRLoader.loadObject(realPath);
3) 建立数据源
前面介绍过,jasperReport支持多种数据来源,比如说:数据库连接Connection、JavaBean、CVS数据源等等。不过jasperReport提供一种通用数据源类型JRDataSource,它很多子类实现,即为多种数据来源类型。
这里,我们介绍两种普遍数据源:数据库Connection和JavaBean。
首先是Connection。通过数据库的URL、用户名、密码和驱动类来进行数据库的连接,返回Connection即可,当然,此种情况需要在iReport中定义SQL查询语句。另一种方法是,直接从Connection中完成数据库的查询,返回结果集ResultSet,继而把ResultSet封装成JRDataSource的子类JRResultSetDataSource。两种方式没有孰优孰劣,凭喜好使用即可。两种方式代码如下:
一、
Class.forName("******Driver");
conn = DriverManager. getConnection ("***Driver:// localhost:***; DatabaseName =***; user=***; password=***");
二、
ResultSet set = statement.executeQuery();//=new ResultSet();
JRResultSetDataSource source = new JRResultSetDataSource(set);
对于JavaBean来说。需要定义标准的JavaBean格式,即它的每一个属性都要有对应的getter/setter方法,而且,需要定义一个Factory类,其中包含一个静态的方法,返回Collection类型或者Array类型的JavaBean结果集。相比较Connection来说,JavaBean要麻烦许多,不过也要灵活许多,这才是灵活性的体现(因为有时候,查询语句会很复杂,数据来源一样会很复杂,而JavaBean无视这一切)。JavaBean代码如下:
JRBeanCollectionDataSource dataSource;
Collection rows = NumFactory.generateCollection();
dataSource = new JRBeanCollectionDataSource(rows);
上面语句的功能应该很明显了,不赘述。
4) 生成JasperPrint对象
当数据来源确定后,下一步是生成JasperPrint对象。简单的说,JasperPrint对象就是jasperReport对象的动态填充,即把相关数据插入到报表当中。
JasperPrint rptPnt = JasperFillManager.fillReport(jasperReport, params, dataSource);
JasperFillManager类有许多的填充方法,基本囊括了各种参数的填充,包括Connection、DataSource等的填充。
5) 输出
动态填充数据完成后,就可以进行输出了。输出时,有几种方式:输出到流,输出到文件,也可以直接生成视图等。
对于每种输出格式,JasperReport都提供一个特定的Exporter,比如JRXlsExporter、JRHtmlExporter等等。这些Exporter中,可以定义相关的输出格式,有一些是必须要定义的,比如:
exporter.setParameter(JRExporterParameter.JASPER_PRINT, rptPnt);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, httpOut);
当然,这是流输出的例子。JRExporterParameter中有所有格式的通用属性,而对于每种格式,有不同的ExporterParameter对象,对应着不同的参数。用户所需要的参数定义完毕后,调用exportReport()方法输出即可。
下面是一个格式化的报表:
然后是运行之后的截图:
前面可能把整个过程讲述的很复杂,其实,在整个建立与输出报表过程中,是一气呵成的。iReport与JasperReport是紧密相关的,而除此之外,它们的独立性非常好。
利用jasperReport+iReport生成并输出报表,可以方便的嵌入“胖客户端”以及WEB工程,以公安项目为例。
此项目是基于Struts结构的,浏览器端的请求是通过ActionServlet来传递的,依照项目要求,我们只要把已经做好的jasperReport实例导入到项目里即可。导入方法可参考如下:
首先,把相关jar包导入到工程的lib文件夹下,搭建必需的环境;
其次,新建Action类,并将其对应的路径等相关信息加入xml配置文件中;
然后,如同输出html文件一样,将输出代码拷贝到Action类中,实现流的输出即可;
最后,将原实例中的相关处理类拷贝到项目中,调整包的路径,使之正常运作即可。
这时,只要修改某些页面的链接即可完成报表的输出。
如何使用图片?
很容易,用Image控件就可以了. 在Image Express 里面可以用String来表示图片的路径, 或者用InputStream, File 对象.不过不管用File 还是String 对象, 都不得不用绝对路径, 这显然很不灵活.解决办法是,穿入一个$P 的参数,表示图片所在的目录,然后用$P 和文件名拼接出完整的绝对路径. 或者通过代码来控制,比如System.getProperty("user.dir")+"""report.jpg"就表示图片的绝对路径。更好的方法是用InputStream, 例如his.getClass().getResourceAsStream ("report.jpg") ,这时只要把图片放在当前.jasper所在的目录就可以了,不必考虑什么参数,什么路径。
动态控制某些Field 是否显示
每个Static Text, Text Field 甚至整个Band 的属性里面都有Print When Expression, 比如设成new boolean(!$P{isDisplay}.equalsIgnoreCase("yes")), 那么只有当参数display的值为yes 的时候才显示。
使用Sub Report, 如何使用相对路径
和使用图片类似,最好使用InputStream 或者传入参数。
Query里面如何使用参数
$P!{xxx} 或者$P{xxx} 后者只能用于类似PreparedStatement参数绑定, 而前者可替换Sql 的任意部分. 在需要动态排序的时候, 前者特别有用. 比如select a,b,c from t order by $P!{orderClause} 不管用$P 还是$P!, SQL最终是以PreparedStatement 方