在JAVA项目中,使用JasperReports与iReport,
直接连接打印机可打印(word excel xml pdf )文档
JasperReports 与iReport 简介
简介 JasperReports 是一款开源的报表打印组件,是开源代码组织 sf.net 中的 一个java报表打印工程 ,可以以 PDF, HTML 或XML 等多种形式 产生报表 , 支持分页打印 ,并且可以制作各种类型的图表。 Jasperreport 是按照一个预定义的 xml 文档来组织报表的数据,这些数据来源多样,包括关系数据库(通过配置 JDBC 连接)、 java 容器对象 ( collection 和 arrays )。要完成报表的填充,必须 先完成 用于报表的 xml 文件 ,其过程是 先 产生报表设计对象 , 再 序列化该对象 , 存储 在 磁盘或者网络 ,用于 产生 特定应用的表格数据 。事实上,表单的 设计过程 就是用 定义 于xml文件中的java表达式 来表现报表的设计 。编辑过程中会有各种保证数据一致性的验证,最终会产生相关数据文档或填充数据的准备。 iReport 也是开源组织 sf.net 中的一款免费软件,其主要作用是以可视化的方式升级生成 JasperReport 所使用的报表格式文件,因为 JasperReport 本身 没有提供 很好的可视化 报表设计工具 , iReport 正好 弥补 了这个缺陷 ,因此我们常常将这两个工具结合起来使用。
JasperReports 可以在这个地址得到: http://jasperreports.sourceforge.net/
iReport 可以在这个地址得到: http://ireport.sourceforge.net/
iReport 的使用 iReport 的安装 安装 iReport
首先 需要在本机安装 JDK ,并对环境进行配置,最新版的 JDK 可以从 http://www.sun.com 处下载并安装,然后配置 windows 环境变量,在 path 后面加入 “;java 的安装目录 ” ,新建环境变量 JAVA_HOME : “java 的安装目录 ” CLASSPATH : “java 的安装目录 /bin” 如果已经安装过 JDK ,则可以跳过这些步骤。
然后 从 iReport 的站点下载最新的版本的 iReport , 解压 iReport 在任意目录,解压后的文件里面有一个 iReport.bat ,通过双击,过大约 30 秒钟如果可以 弹出iReport 的主窗体即表明你的系统已经可以运行 iReport 了,如果不能弹出主窗体,一般是因为 JDK 没有正确被安装。
在 iReport 中配置数据库使用 iReport 的第一步是配置数据库连接,选择菜单 “ 资料来源 / 连接资料来源 ” ,打开如下的对话框, 点击 “New” ,打开如下对话框,可以创建数据连接, 我们以创建 JDBC 数据源为例,在 “Type of connection / datasource” 列表中,选择 “Database.JDBC.connection” ,在 “Name” 中,为创建的新的 连接取 一个需要的 名字 ,在 JDBC Driver 中, 选择一个驱动 ,我们以 Oracle 为例,选择 “oracle.jdbc.driver.OracleDriver” ,在 JDBC URL 中输入 JDBC 连接,例如: “jdbc:oracle:thin:@localhost:1521:TANGO” ,同时请在 Username 和 Password 中输入连接数据库的用户和密码。注意一点 OracleJDBC 的包必须在环境变量的 CLASS_PATH 中配置。全都创建好后,点击 “ Test ” 可以进行对数据库 连接的测试 。
建立连接后 ,就可以对数据表进行查询,选择菜单 “ 资料来源 / 报表查询 ” ,打开如下对话框: 在 “ Report SQL query ” 页中,可以 输入 任意的 sql 数据 来得到数据 ,当输完完整的 sql 语句后, iReport 自动将所有字段列表列出,这些 字段就是 可以在报表制作过程中 可以使用的变量 。另外需要注意的是:当我们创建了多个数据源的时候,需要设定一个当前的数据源,选择菜单: “ 设定 / 设置当前数据源 ” ,打开如下对话框: 可以在所有建立的数据源中设置当前使用的数据源。从 java 容器获得数据 通过 JDBC 获得数据非常方便,但我们通常不会在设计期就确定完整的 sql 语句,通常我们在运行期都需要构造一些动态的 sql ,当然,我们可以通过编程的方式来构造 sql 并传递给 iReport ,但是复杂的 sql 语句不便于维护,也容易出错。 JasperReports 允许从 java 容器中获得数据,首先告诉 iReport , java 容器类的路径,选择菜单: “ 工具 /classpath ” ,如图: 设置完路径后,再次选择菜单 “ 资料来源 / 报表查询 ” ,到 “JavaBean Datasource” 页,在 Class Name 中输入容器类的全路径,如下图: 点击 “Read javabeans attributes” ,容器中的 字段就全部被读取 了出来。至此为止,我们已经可以开始制作报表了。开始使用 iReport iReport 的开发界面和我们熟悉的 delphi 著名插件 quickreport 比较相似,整个页面由若干个 band 组成,每个 band 实现不同的显示方式。界面如下: 新建报表 单击工具栏的第一个按钮 “New Report” ,或者通过菜单 “ 报表 / 新增 ” 进入创建报表菜单,如下图: 在报表名称栏内给创建的报表 取 个 名字 ,然后是 定义纸张的大小 , iReport 提供了多种预设尺寸,当然也可以选择 自定义的页面尺寸 ,并提供两种定位方式,也即横向和竖向。在对话框的下半页,还可以设置页边距,列等等。当都设置完成, 点击 “ OK ” ,完成新建动作。
报表结构创建了一个新的报表后,我们来看看报表的结构。 一个报表 的结构大致是几个部分: title 、 pageHeader 、 columnHeader 、 detial 、 columnFooter 、 pageFooter 、 summary 、 groupHeader 、 groupfooter 。
Title :每个报表一般会有一个名字,比如 ××× 销售报表, title 就是搁置这个名称的最好地方了,当然你也可以根据需要搁置在合适的地方。
pageHeader :报表的一些公共要素,比如页码、创建时间、创建人等信息放置在这里是比较好的选择。在每页头都会打印一遍
columnHeader :这里是放置列的名称,记住不是列数据。
Detial :放置需要循环的数据,比如销售记录数据。
columnFooter :放置列级别的统计计算值或是列的说明。
pageFooter :放置页级别的统计值或是页的说明。
Summary :可能需要对几页(你的报表可能有几个页组成)的统计值。比如 50 个销售记录共占用了 3 页,那么放置这些统计记录的统计值最好的地方就是 summary 。
groupHeader :每个表的内容可能需要根据某个属性进行划分显示内容和计算内容,比如希望以月份为单位每组分开显示销售记录,那么就可以定义一个组(组的定义参考后文), groupHeader 就是放置组说明或是组标志最好的地方。
Groupfooter :放置组的统计或是说明。报表的动态对象变量、参数、字段在使用 iReport 的过程中会碰到很多与变量( Variables )、参数( Parameters )、字段( Fields )这些有关的内容,所以我们还是要先介绍这些对象的使用和意义:字段( Fields ):来自数据库,或是 java 容器对象。这些内容是报表显示的主体内容,语法为 $F{ filedsName } 。参数( Parameters ):这是你的应用需要提供给报表的入口,比如你希望在报表被解释的时候提供 Where 语句的条件值,那么就可以使用参数( Parameters )。语法为 $P{ parameterName } ,可以给报表提供多个参数,通过一个 HashMap 传入。使用参数前,参数必须在 iReport 中进行配置,如,我们需要在打印时得到打印操作人,我们创建一个参数打印人: printOperator 。选择菜单 “ 预览 —— 报表参数 ” ,打开如下对话框: 在参数页面,点击 “ 新增 ” 按钮,继续打开如下新增参数对话框: 在 “Parameter name” 内,填入参数名称: “printOperator” ,在 “Paramenter class type” 选择框中,选择参数的类型,我们这里选择 “java.lang.String” ,在 “Default value expression” 中填入当传入的值缺失时的缺省值,因为 iReport 是纯 java 语言开发,因此支持任何 java 语句。在 “Paramenter description” 中可以对该参数进行一些描述。点击 “OK” 完成参数的创建。
下面给出简单的程序调用实例 :
HashMap map = new HashMap();
Map.put(“printOperator”,” 陈宁 ”); JasperFillManager.fillReport(jasperReport,map,ds);
变量( Variables ):这是报表中一些逻辑运算的表现,比如统计值(求和,最大值,最小值等等)。语法为 $V{ variablesName } ,例如我们要对定单金额进行求和,假设定单金额的数据库字段为 amt ,我们现在创建变量名为 totalAmt 的对定单金额进行汇总的变量,点击菜单 “ 预览 / 报表变量 ” ,打开如下对话框: 我们看到 iReport 已经为我们预先定义了五个有用的变量,供我们使用,具体含义如下: • $V{REPORT_COUNT}: 报表处理的记录笔数 • $V{PAGE_NUMBER}: 打印时的页码 • $V{PAGE_COUNT}: 本页处理的记录笔数 • $V{COLUMN_NUMBER}: 报表的直栏数目 • $V{COLUMN_COUNT}: 本栏的处理笔数 • $V{ 群组名 _COUNT}: 群组 Band 的处理笔数,建立群组时会自动产生的变量其中最后一个变量是根据分组情况自动生成的。我们现在新增一个自己定义的变量,点击 “ 新增 ” ,打开新增变量对话框: 在 “Variable name” 中,输入变量名: “totalAmt” ,在 “variable class type” 中选择变量的类型 “java.math.BigDecimal” ,在 “Calculation type” 中选择计算的类型,这里是求和 “Sum” ,在 “Variable expression” 中输入变量的表达式,我们这里是取数据库中的字段 amt ,所以写成 “$F{amt}” ,请注意。当我们正确的配置了数据来源后,当我们输入的表达式正确,那么显示的颜色是绿色的的,当不能正确写对表达式的时候,是如图所示的蓝色。然后我们在 “initial value expression” 中输入初始化的值,这里同样输入 java 语句: “new java.math.BigDecimal(0)” 。点击 “OK” ,完成参数的设置。在报表页面放置元素 iReport 的工具栏提供了丰富的元素,从简单的内容到包括图形,分组报表都支持。我们主要介绍两类,一类为静态文本,一类为动态文本。这两个工具按钮如下: 点击 “T” 的工具按钮,打开添加 “ 静态文本 ” 的对话框。 他的用法比较简单,有一些计算机使用经验的人都能看懂,就不在这里介绍了。这里只说一点:要显示的内容是在 Static Text 页面中输入,在 Print when expression 中,可以接受返回类型为 Boolean 的 java 表达式,当返回 Boolean.TRUE ,才会打印该静态文本,当返回为 Boolean.FALSE 则不打印,在本文后面会介绍利用这个特性打印黑白交替的行显示效果。我们再看看动态文本,点击 “F” ,打开如下对话框: 动态与静态文本大致类似,动态文本在 “Text Field” 中接受表达式,在 “Textfield expression” 中,输入动态表达式 “$F{s_data_1}” ,如图,绿色代表输入正确。在 Pattern 中,还可以输入数据显示的格式。制作报表有了上面的基本知识,我们就可以开始制作报表了。我在制作报表中,考虑了以下的思路。首先,取数据通过 java 容器,而不是直接连接数据库,这是因为我们制作的报表通常都比较复杂,很难直接通过一个简单的 sql 语句来实现,就算我们可以写一个复杂的 select 语句来实现一个报表的查询,但是对于以后的维护和排错也是相当困难的,因此不建议这样的做法。从另一个角度考虑,报表的很多查询条件是根据用户的输入来动态的创建的,我们在后台对数据进行整理和加工都会使程序的调试和实现变得简单。我创建了数据容器类:
ReportBaseObject ,非常简单,部分代码如下:
public class ReportBaseObject {
private String s_data_1;
private String s_data_2;
private String s_data_3;
……
private String s_data_20;
private BigDecimal b_data_1;
private BigDecimal b_data_2;
private BigDecimal b_data_3;
……
private BigDecimal b_data_20;
private Date d_data_1;
private Date d_data_2;
private Date d_data_3;
……
private Date d_data_10;
private Integer i_data_1;
……
private Integer i_data_10;
public BigDecimal getB_data_1() {
return b_data_1;
}
public void setB_data_1(BigDecimal b_data_1) {
this.b_data_1 = b_data_1;
}
……
public Date getD_data_1() {
return d_data_1;
}
public void setD_data_1(Date d_data_1) {
this.d_data_1 = d_data_1;
}
……
public Integer getI_data_1() {
return i_data_1;
}
public void setI_data_1(Integer i_data_1) {
this.i_data_1 = i_data_1;
}
……
public String getS_data_1() {
return s_data_1;
}
public void setS_data_1(String s_data_1) {
this.s_data_1 = s_data_1;
}
……
}
这是一个通用的数据容器,容器中定义了20个字符类型的字段,20个数字类型的字段,10个日期和10个整型,这个容器对于任何报表都适合,这样做是基于以下考虑。我把报表制作分为两个部分,第一部分是用iReport制作报表界面,第二部分在后台根据用户传入条件取得报表需要的数据。而第一部分可以由项目人员在现场制作后后期进行修改,而第二部分由开发人员完成,因此要求这两部分的工作可以分离,通过提供一个通用对象,我们可以实现这一目的。工程人员在现场和客户洽谈需求,并在没有数据的情况下,开始制作报表界面,他们所要做的就是用一张表格列出他们需要的数据的含义:如: baseObject 对应字段 说明 报表编号:01_001 S_data_1 单号 S_data_2 单据类型 D_data_1 要货日期 D_data_2 批准时间 B_data_1 应付金额 B_data_2 已付金额 在与用户确认了界面后,工程人员将表格传递给开发人员,开发人员就根据表格所标注的字段意义给容器填写数据。以下是我画的报表截图: 显示不同的背景如下图所示,我们希望打印出灰白相间的行效果,可以利用上文提到的“print when expresssion”属性来实现,具体做法有两种: 在同一列上放相同字段的TextField,一个不设背景(预设为白色),另一个设背景(淡黄色) 白色背景的Print when expression输入new Boolean((($V{PAGE_COUNT}.intValue()) % 2)==0) 灰色背景的Print when expression输入new Boolean((($V{PAGE_COUNT}.intValue()) % 2)==1) 另一个方法是先在Detail Band上拉一个矩形,设其背景为淡黄色,设其Print when expression为new Boolean((($V{PAGE_COUNT}.intValue()) % 2)==1),意即奇数列时才要印出这个淡黄底色的矩形。再设其前景为白色,使矩形边界的黑框消失。在矩形上放需要的Text Field,并将其Transparent打勾,意即此Text field是透明的。