一、 iReport 与 JasperReport 简介
1.1 简介
JasperReport 是报表的引擎部分,界面设计是用 iReport 。为什么选择这两个软件呢?因为这两个软件都是开源的,即免费的 ( 虽然某些文档收费,但是磨灭不了我们使用它的理由 ) 。
JasperReport 是一个报表制作程序,用户按照它制定的规则编写一个 XML 文件,然后得到用户需要输出的格式文件。它支持输出的文件格式包括 PDF , HTML , XML , XLS , CSV 等等。
用 JasperReport 做报表,可以分为两种方式:
1、 直接利用程序定义一个报表
2、 写一个 xml 文件来描述这个报表,通常需要借助于 iReport
JasperReport 做报表时用的都是底层的东西,如线条、静态文本等,底层的好处就是强大、容易控制报表,但缺点就是编写很麻烦。庆幸的是,我们有 iReport 这个软件,这个软件完全是弥补 JasperReport 的不足,将底层编写推向可视化,大大的方便了我们。
1.2 工作流程简介
JasperReport 的工作流程:首先有个 xml 文件,从 xml 文件编译出 .jasper 类型的文件,而以后我们真正要使用的就是编译后的 jasper 文件。
上图为 JasperReport 的 API 示意图,可作为学习的参考。由 iReport 输出的文件中,对 WEB 应用可能有用的是 jasper 文件,当 JAVA 程序进行调用的时候,将把 jasper 文件转换成 print 类型,从而进一步到达其他格式的输出 ( 如上图 ) 。
二、 安装与配置
2.1 下载相关软件
对于较古老的版本,这里不做过多介绍,请参考本目录下其他文献。这里提一下,古老版本需要额外下载 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 带有字体包,不需另下。
2.2 安装软件
首先安装 JDK ,一路 NEXT 即可。
其次,安装 iReport ,由于新版本对 windows 支持较好,所以和 JDK 一样,一路 NEXT 即可。
注:旧版本需要对环境变量进行配置,此篇文章介绍的版本以及更新的版本均不需要手动配置环境变量。
2.3 其他相关
您还需要准备一个数据源 ( 如果需要做动态报表的话 ) ,大部分情况是一个数据库。笔者使用的是 Oracle 9i 的数据库。
三、 iReport 的基本使用
先看使用界面:
下面开始初步尝试。
1. 新建报表
弹出对话框如下:
还有许多其他的选项,中文可以理解。有个 XML 编码,可以手动输入,也可保持默认,点击 ”OK” 创建新表完成。
注: iReport 不会自动保存,需要手动保存,建议多保存。
2. 报表的结构
新建的报表如下:
一个报表的结构大致是几个部分: 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 :放置组的统计或是说明
3. 添加对象
可以通过工具栏的工具添加静态对象与动态对象。点击 可以创建静态对象,点击 可以创建动态对象。之后在报表的空白处单击,如此即可把对象添加到报表,然后拖动对象的边框,使它的大小合适,双击即可对对象中的文本进行快速编辑。
仔细观察,会发现对象的边框有两种颜色,一为蓝色,二为红色,蓝色为符合布局要求,红色反之。
注:一个对象不能横跨两个区域,即不能既在 columnHeader 里又在 detail 里。
鼠标右击对象,弹出如下菜单:
点击 ” 属性 ” ,编辑对象的属性。
这里面有很多属性,可以依据要求来更改其中的部分或所有。其中,重要的可能是关于 PDF 的,如下图。
红框框起来的部分要注意,当要输出中文的时候,需要类似设置。新版本对边框的更新,使我们操作起来更为方便。注意下面红框里的部分,这可以对每一个边进行分开的设置,人性化的为我们解决了大量问题。
注: JasperReport 没有现成的表格,最好的方法就是用一个一个对象的边框堆积起来,组成一个表格。但是,对象的边框不能覆盖,否则 HTML 、 EXCEL 等不能正常输出。
对于动态对象,属性如下。
主要属性如图所示。在 Pattern 里,可以定义输出的格式,在输出时间和日期或者货币时尤为有用。上图中的 ”stretch with overflow” 表示当填充值超出定义的大小时,自动换行; ”blank when null” 表示当数据为 null 时不显示数据,这两个在某些时候很有用处。
而在表达式一栏中,如果字体为蓝色,则表示不正确,当输入正确的时候,会呈现绿色,如图。
4. 设置数据来源
首先,需要添加一个数据源,此处选用 Oracle 数据库,步骤如下。
如下图,点击 ” 连结 / 资料来源 ” 。
弹出下面对话框,点击 ”New” 。 ( 图中已有数据源乃是笔者添加 )
选择一个数据来源,这里选择第一个 JDBC 连接数据库的方式,点击 ” 下一步 ” 。
按照图中的介绍填写相关信息,并测试信息是否正确,然后保存。 iReport 可以添加保存多个数据源连接信息。
注:如提示找不到相关驱动,则需要将驱动的 JAR 包复制到 iReport 的 lib 文件夹下。
5. 变量、参数及字段
在使用 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} 。
字段
编辑字段的方式与变量、参数类似,打开 ” 字段 ” 界面。
在点击 ” 新增 ” 后,出现如上页面,根据情况填写字段名称、字段类型 ( 一般与数据来源类型相匹配 ) 和字段的描述等。这种是手动添加字段,另一种更为方便的方法是从数据源直接读出,将在后面介绍。
字段用于动态对象里,即 。它的主要功用在于动态连接数据源,完成数据源的读出显示,所以在有动态对象的报表里,执行的时候一般采用 ” 执行报表 ( 使用动态连接 )” ,如图。
6. 动态数据源
从上图中,选择默认的动态连接。
弹出如下界面,各部分功能介绍如图。
这便是上面所说的另一种更为方便的添加字段的方法,从数据源直接复制到字段里,方便、快捷。
如上图所示,还有三种连接数据源的方式: JavaBean 、 DataSource 、 CSV 。多种不同的方式给我们添加了很多便利。
7. 组
组是一个很重要的概念,一个报表可以多个组,每个组以一个关键字为标记,比如希望统计是根据项目(或是产品)进行统计的。那么可以设立一个项目标记的组。如图。
组的参数设定可以看界面即可理解部分,其中最主要的是“ Group expression ”,这里必须输入格式正确的并且存在的字段名称 ,本文的“ Name ”是【字段】中的一个元素。依此类推,建立其他的组对象。每建立一个组,在报表的界面上都会出现该组对应的段,组的 Header 与 Footer 是对应出现的 。如图。
8. 风格化
如图。
点击 ”Styles” ,弹出如下界面。
在这里,我们可以定义许多个常用的格式,按照个人喜好进行定义,定义后,在对象属性的页面上可以选择使用哪种风格,所设置的属性会自动继承。如图:
9. 界面介绍
在 iReport 的界面上,处于人性化的考虑,设置了很多快捷按钮供用户使用,如图。
上图包括文档的基本操作,线条与图形的绘画,静态与动态对象的添加,图表图像报表的插入,报表、栏等的属性,也包括编译、执行等按钮。
上图包括字体字号,一些对象内部的基本排列操作和数据源设置等。
上图包括对象的对齐、排列、规格化等操作。
所有这些快捷按钮给用户提供了很大的便利,熟悉之后,用起来会更加顺手。
10. 预览
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 方 式执 行的 , 不必 太担心 性能问题 注意 : 参数是不能 嵌套 的 , 比如 $P{a} =''$P{b}'' , $P{b}=''value'', 不要 指 望 $P{a} 能 被替换 成 ''value''
如何 使 用图表 (Graph)
JasperReport 本 身 没有图表功能 , 只 有显示 Image 的功能, iReport 里有个 Graph 向导 , 其实 质 是 通 过 jFreeChart 生成 Image. 另外 , 更直 接的 做法 是 放 一个 Image 控件 , Image Express Class 设置成 java.awt.Image, 在 Image Expression 里 通 过自定义的 类返回 java.awt.Image 对 象 .
例 如 GraphProvider.getImage($P{REPORT_DATASOURCE},title, subtitle.....);GraphProvider 是自己的 类 , public static Image getImage(JRDataSource, ....)
如果显示多个图表
在一 张 报表上显示一个图表和显示多个图表是不同的 . 假 设 Query 是 selectname,price,qty from xxx, 第 一 张 图显示 name-price, 第二张 图显示 name-qty, 如果还是按上面的方 法 , 第二张 图 根 本显示不出来 ! 为 什 么 因为传入的是 JRDataSource, 而 JRDataSource 仅仅 是对 ResultSet 的简单 封 装 , 在 第 一 张 图 处理 完后 , 游标已 经到了 eof 位 置了 , 在开 始处理第二张 图的时候 , 就必然 抛 出 游标耗尽 的 异常 ! 怎 么 办 ? 自己 写 个 JRDataSourceAdapter, 把 JRDataSource 对 象 里面的 值 预先保存到一个 Collection ( 相当于一个 Offline 的数据 集 ), 然后 把 这个 Collection 传个 getImage 方 法 . 具 体是 , 建一个 Variable mydate, 类型 是 java.util.Map, Calculation Type- System,Initial Value Expression 是 JRDataSourceAdapter.JRDataSource2Map($P{REPORT_DATA_SOURCE}, new String[]{"NAME","PRICE","QTY"},
new Class[]{java.lang.String.class,java.lang.Double.class,java.lang.Double.class}); JRDataSource2Map 是自己 写 的一个 Adapter. 然后在 Image 的 Expression 里面 换 成如 GraphProvider.getImage(mydata,title, other params...), 当然得 修改 getImage 方 法
Export 到 Excel 的问题
如何去掉报表头
直 接 把 不需要的 Band 删除 ( 把 其 高度 设为 0). 如果 仅仅 是 export 到 Excel 的时候不需要报表 头 , 而输出到 PDF 等 仍 然需要保 留 , 那么 使 用 print when expression, 见 前面
如何让 Excel 看起来整齐
不要有空白 地 方,首先 把 所有的 Field 设成一 样高 , 对 齐 ! 把 所在 Band 的 高度 也设成和 Field 一 样高 , 让 Field 正 好 放 入 Band. 然后 调整 Field 的 宽度 , 让每 个 Field 都相 邻 , 没有空 隙 .( 如果设置 正确 ,所有的 Field 边框在 鼠标 点中的时候显示 蓝 色,否则是 绿 色 ) 最后 , 记 得设置参数 :
exporter.setParameter(JRXlsExporterParameter. IS_REMOVE_EMPTY_SPACE_BETWEEN _ROWS , Boolean.TRUE);
如何保留 GridLine
首先 , 设置参数 exporter.setParameter (JRXlsExporterParameter. IS_WHITE_PAGE_BACKGROUND , Boolean.FALSE); 然后 , 把每个 Field 或者 Static Text 框的 ''Transparent'' 属性都勾上
如何使字段名只显示一次
如果把字段名放在 ColumnHead 区域 , 那么输出到 Excel, 会每个 Page 都显示一遍 . 在设计 Report 时候 , 一般会设定 Page 大小 . 然而对于 Excel, 这个 Page 设定仍然存在 , 而且往往很讨厌 , 因为在 Excel 里 , 通常希望得到连续的数据 , 然而 Jasper 仍然会 '' 自作多情 '' 进行分页 . 比如说 , 设计 JasperReport 的时候 , 设定 page size 为 Letter, Portrait, 那么输出到 Excel 的时候每隔大约 30 行 ( 具体取决于 Field 的高度 ), page header, column header, column foot, page foot 会被重复一次 , 而且还附带一个高度为 0 的 Excel Row, 表示 Page Break 的地方 . 把字段名放在 title band 里 , 可以解决字段名重复的问题 , 当然 page header 也不要显示了 . 如果需要 , 可以把 title band 的 print when expression 设成只有输出 Excel 的时候才显示为什么 Excel 里面的数据是从第二行 , 第 B 列开始显示的。
因为第一行和第 A 列分别是用来表示 page top margin 和 page left margin 的 . 对于 Excel 来说 , 纯粹多余 . 解决方法是把 page margin 设成 0. 不过如果这个 report 还需要以 PDF 等显示 , 那么设成 0 就不好看了 . 最好能动态的改变 pagemargin. 当然 , 这个改变只能在外部 ( 调用 eport 的地方 ) 进行 , 在设计 Report 的时候是无能为力的 . 不幸的是 , JasperReport 类居然没有 setMargin 的方法 , 只有 getter. 折中的方法只能是 reflect 了 . 代码示意如下 :
//use reflect to set the private field of JRBaseReport
java.lang.reflect.Field margin =
JRBaseReport.class.getDeclaredField("leftMargin");
margin.setAccessible(true);
margin.setInt(jasperReport,0);
margin =
JRBaseReport.class.getDeclaredField("topMargin");
margin.setAccessible(true);
margin.setInt(jasperReport,0);
margin =
JRBaseReport.class.getDeclaredField("bottomMargin");
margin.setAccessible(true);
margin.setInt(jasperReport, 0);
如何去掉 Excel 中隐藏的行
如前说述 , 由于 page break 的关系 , Excel 中每隔几十行 , 就有一个高度为 0 的 row, 即使把 page botom margin 设为 0, 把 page footer 去掉都没有办法 . 唯一的解决办法是把 page height 设为很大 . 同上面一样 , 不得不使用 reflect:
java.lang.reflect.Field pageHeight=
JRBaseReport.class.getDeclaredField("pageHeight");
pageHeight.setAccessible(true);
pageHeight.setInt(myRpt, Integer.MAX_VALUE);
八、 HTML 的 Bar3D 图表输出心得
图表在 ireport 中是利用其他开源包生成的图片插入而生成,本人使用的版本是使用 jfreechart1.0.0 开源包实现。 Ireport 对 jfreechart 的支持不算完美,只是实现了部分的图表生成,但对于一般项目,也是足够用的。
对于图表的数据来源,和报表一样,也有多种来源,并不局限于数据库,而本人推荐的依然是 javabean 。用户只要在定义好图表的各项数据 ( 比如:横坐标数据,纵坐标数据,横坐标标签,纵坐标标签,分类标准等等 ) , jasperreport+jfreechart 会自动进行数据的分类统计输出,这点是很人性化的。
看过 jasperreport 的源代码,发现,图表在 HTML 格式输出的时候,首先是输出一张图片,或者放在具体目录下,或者放在临时的 response 里,然后进行调用、输出展示。 ( 如果选用后者的输出方式,需要注意: 1.x 版本后的输出需要对 web.xml 进行配置,配置一个 servlet 进行输出 。 ) 这样就造成了一个问题,就是当多用户同时访问页面的时候,用户看到的数据是正确的,但是图片却可能是别人产生的图片!
这可能是由于 HTML 浏览器对图片的引用时机不对,解决的方案是这样的:由于 HTML 格式的输出是字符形式的 (PDF 是二进制流形式的 ) ,所以我们选择首先把整个图表输出到字符缓冲区中,然后进行一次性输出,这样,我们辅助浏览器完成对图片引用时机的修正。 当然,也可以这样做:通过修改源代码,把图片输出到不同的临时目录,这样的话,想引用错基本都不可能了 J
在 HTML 输出的时候,一定要记得设置编码格式,通过 exporter 的 CHARACTER_ENCODING 属性来设置。而且,在 HTML 中输出的时候,可以不对报表进行分页操作,即取消分页。
还有, jfreechart 默认输出的图片是进行抗锯齿处理过的。对于图形来说,这样会让图像显示的更圆润,而对于文字来说,可能就会显示变得模糊。解决方案:修改源代码。可以修改 jasperreport 的源代码,也可以修改 jfreechart 的源代码,只需按照如下代码进行改进即可:
jfreechart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
上面的代码将图片输出的文本抗锯齿关闭,而图像依然有抗锯齿处理,所以图片相对好看。不过,有一点需要注意:字体尽量是宋体,字号最好在 12 到 14 之间,这样能达到最好的显示效果。