新闻资讯 | 控件产品 | 技术文章 | 购物车 | 合作伙伴 | 问题解答 | 电子简报 | PDF论坛 | 资源下载
您现在的位置:技术文章>PDF开发篇 首页|PDF应用篇|PDF开发篇|解决方案

怎样用iReport制作Web报表

发布日期:2007-9-12 作者:未知 出处:互联网

 

用iReport开发Web报表功能强大,容易上手使用。由于iReport支持JasperReport,它是纯Java程序,所以用于Web的最佳引擎是JSP,首选Tomcatt。报表开发平台使用Windows平台即可。iReport早期在Windows系统上安装只要直接解压即可,而目前最新的版本是1.3.1,可在其官方网站下载http://ireport.sf.net/,支持安装程序。

安装时需要预先安装java jre,可打开DOS窗口输入java-version看使用的是哪个版本的jre。实用中,安装Oracle 10g客户端自带的Java 1.4.2最适合当前的iReport版本,使用Jbuilder2006自带的Java 1.5.0在打开某些交叉报表时可能出现死机现象,建议在Windows系统上安装Java1.4,它支持最新iReport。

iReport开发文档是收费的,虽然网上可找到较多例子供参考,还有完整的简单报表开发指南,稍加研究即可开发简单报表。但如果要开发中小企业级各类Web报表,就需要深入研究,反复测试了。

在报表中显示中文

iReport内部使用Unicode UTF-8编码,设置正确就可支持所有中文报表需求。界面选项支持简体中文。为了在报表中显示中文,在报表字体或较新版本的Style,选择宋体字体。为了正确显示中文,必须安装亚洲语言包,可以从网上下载iTextAsian.jar考入开发机iReport安装目录/lib之下和服务器端WEB-INF/lib目录下。还必须将服务器端的Java汉化,Java1.4比较麻烦,除拷贝宋体字库外,还要修改几个属性文件。Java1.5汉化非常简单,只要在jre/lib/fonts下建立fallback目录,将宋体字库考入该目录即可。为了以PDF格式输出中文,需要在“PDF Font Name”选项中选择“STSong-Light”,在中文字体定义中勾选“Default”、“PDF Embedded”,“PDF Encoding”选择“UniGB-UCS2-H (Chinese Simplified)”。

在报表中插入图形

适当的插图在报表中起到画龙点睛作用,可以使枯燥冗长的数据趋势、比例等一目了然。iReport内置基于jfreechart的Chart Tool工具可以方便绘制常用的柱状图、饼图、曲线图等,可满足一般报表的需求。

如果需要插入静态图片,则要用image工具,要在图片的“Image Expression”中写图片文件的绝对路径。为了便于在PC上调试并可用于服务器,文件路径应写成“$P{imagePath}+文件名”的形式,参数$P{imagePath}在PC上设为PC机上的DOS路径,注意因为“\”是转义符号,DOS路径的“\”要写成“\\”。在Web输出图片时将服务器上的文件路径作为参数$P{imagePath}传递给输出程序,就可输出正确图片。在以下设定子报表绝对路径等场合,为了增加灵活性,都需要这样做。

iReport内置的Chart工具并没有支持jfreechart的全部功能,绘图存在局限性,例如,1.2.7之后的版本才实现标记label的旋转,旋转90度可使标记字符垂直显示,以免水平项目过多时标记显示重叠在一起而显示不出来。又如图片中的category各个项目只能是查询结果集各个记录垂直方向的项目,如果要显示同一记录中水平方向各个项目就无法绘图。另外,至今最新版本饼图还不能显示百分比。为了显示更为灵活的图片,应该使用第三方绘图工具。自行开发jfteechart绘图程序可解决这些问题。jfreeChart也是纯Java工具,一般设计Servlet用于绘图,使用image工具,在“Image Expression”中用URL表示对绘图程序Servlet的调用,new java.net.URL(URL?参数),其中URL绘图Servlet的调用路径,问号后用于传递各种绘图参数。其中为了正确传递中文参数,中文字符串应该使用标准的URL编码,即定义一个变量值为java.net.URLEncoder.encode("中文字符串","GB2312"),在image的URL中使用变量名传递中文。

对数据源的支持

iReport报表引擎需要从数据源获取报表中的数据。而最基本的查询数据源的方法就是SQL查询语句,一个报表只支持一个查询结果集,设计一个报表的核心内容就是设计SQL语句。如果一个报表在不同条件使用完全不同的数据表查询语句,一般在报表程序中形成SQL语句,并查询得到结果集,再将所得结果集传递给报表引擎形成报表。这样虽然很灵活,但使报表程序冗长复杂,不便维护。最好是将SQL写在报表数据源内,运行时将数据库连接和其他必要参数传递给报表引擎,由报表引擎执行SQL语句并生成报表。

由于报表只支持单一结果集,对较为复杂的报表,SQL语句的设计就需要较高技巧。简单的参数如数字可直接传递,在报表的SQL语句中用参数表示,如查询条件where x=$P{y},实际使用时程序中直接将参数值如“10”传递给报表引擎,执行时就可以当做where x=10执行。较为复杂的参数可用$P!{param},可用于替代SQL语句的任何部分,如在不同条件下使用不同的字段排序,可在报表SQL中写order by $P!{y},实际使用报表时可将实际的值如“a,b”或“b desc”传递给报表引擎,实际执行时就当做“order by a,b”或“order by b desc”排序子句执行,参数使用是SQL语句灵活支持多种需要的最重要手段。

绝大部分参数是字符串格式,偶然需要日期格式的参数,iReport中设缺省值比较复杂,如“2007年2月28日”要写成“(new SimpleDateFormat("yyyy-MM-dd")).parse("2003-01-01")”,要使用Java函数形式,实际上iReport中所有设定表达式都要显式使用Java函数。

对于涉及多个表查询的情况,需要使用联合查询语句join和union,join用语横向联结多个表,而union用于纵向合并相同结构表的结果集。可以使用子查询技术,即将一个查询语句当做临时表再进行查询,或与其他表联合查询。

通过以上各种技术,在各种条件下,最终形成一个单一数据结果集,形成报表。对于报表各个记录来自完全不同来源的情况,可考虑使用非SQL基本数据源,如可用“JavaBean Data Source”。定义一个基本类,声明各个字段类型及getXXX()、setXXX()方法。测试报表时,建一个数据类,用JRBeanCollectionDataSource(list)封装,其中用list加入测试数据。将class打包考入iReport/lib目录下,在iReport新建数据源,类型为JRDataSourceProvider,类名为刚才定义的类,就可用该类提供测试数据测试报表。打包时注意两点,编译和打包使用的jar的Java版本要与安装iReport时Java版本一致,特别在电脑上装有多个版本的Java时。实际使用报表时,也是使用list先动态填充数据,fill报表时传递数据源为new JRBeanCollectionDataSource(list)即可生成动态报表。

iReport还支持其他数据源,一般使用SQL数据源就足够了。

实现交叉报表

较为复杂的报表需求是交叉报表和子报表。

交叉报表是国内数据统计报表最常使用的形式之一。通常用于将在数据库中记录的数据字段按不同分类水平汇总显示。有两种实现方式:1.用交叉查询形成交叉结果集,最终用简单报表实现;2.使用iReport的交叉报表直接实现。

并非所有数据库都支持交叉查询,Oracle10g中通过sum和decode函数可以实现交叉查询,汇总使用函数sum(decode(key,KEY1,value,0)) as Field1、sum(decode(key,KEY2,value,0)) as Field2,等等,将具有(…key,value…)形式的简单结果集汇总为有(…Feild1,Field2,…),其中Field1是按key值为KEY1汇总值, Field2按key值为KEY2汇总值,依次类推。iReport可将该交叉结果集当做普通结果集处理形成交叉报表形式。

使用iReport的交叉报表工具,可以制作更为丰富的交叉报表,过程较复杂。要点是,在主报表的Detail栏目插入crosstable,需要编辑交叉报表属性决定交叉报表内容,交叉报表设计决定报表的外观。

在主报表中定义SQL查询语句,将结果集传递给交叉报表。这样就只需要进行一次数据库查询操作,不过也只能支持一个交叉报表,且不能自动绘图,因为交叉报表会将结果集的游标指向尾部,这样可满足单一交叉报表需要。为实现上述要求,在交叉报表属性中点选“use a dataset to fill the crosstable”,选择并命名一个subdataset,并且在连接数据源表达式中输入系统参数“$P{REPORT_DATA_SOURCE}”。定义行列分组和Measure。Measure就是交叉报表需要进行汇总的目标字段。行列分组写入分组需要依据的字段,类似交叉查询汇总的key字段,可支持嵌套多重分组,适用多级树型管理分别需要统计的情况。属性设置完毕,就可以使用报表设计,可视化进行报表外观设计,每个字段或汇总字段的长度、颜色、线条等,可以做出相当专业的交叉报表。

实现子报表

子报表也常用于多级管理的情况,需要知道按最高级别部门的统计数据,有时同时也需要查看高级别下属的按较低级别部门的统计数据。与交叉报表不同的是,子报表是独立的报表,子报表还可以嵌套子报表。在主报表的detail栏目中插入子报表,事先子报表应作为独立报表调试好。主报表通过修改子报表属性建立联系,传递数据。在subreport中连接数据源属性中选择“$P{REPORT_CONNECTION”。子报表通常多达3级以上,每级传递数据库连接说明显示每级报表都需要执行各自的数据库查询,通常认为这样做是低效的。但如果采用数据结果集的话,一次子报表调用就将游标移至底部,导致主报表只能显示一行。如果使用数据库连接做参数,各报表进行各自查询,则没有这个问题,而且最后还可以使用自动绘图。其次要指定子报表绝对路径表达式,为方便调试和实际使用,也应采用“$P{路径参数}+文件名.jasper”的形式。子报表参数中填入字段名作为参数,子报表将利用这些参数进行它的子查询,当然这些参数也要在子报表中有相应定义。

最后子报表的显示结果是,每显示一行主报表数据,就根据“显示表达式”真假值决定是否显示相应的子报表数据,如果含嵌套子报表,依次类推。最后在汇总栏可用主报表结果集自动绘制图形。

显示表达式

为了制作灵活显示的报表,显示表达式是必不可少的。例如,多级子报表到底显示哪些级,同一个字段在不同的值范围用不同的颜色字体显示,这些都需要显示表达式。iReport所有的项目都有显示表达式“Print When Expression”,显示表达式是个逻辑表达式,运行时计算出真假值,决定相应项目是否被显示出来。例如,常用的报表中某数字字段用黑色显示,超过预定值用红色显示。需要在相同位置定义两个相同的字段,分别显示黑色和红色,每个都设定显示表达式,确定显示的条件。实际运行时,可得到彩色报表,红色值显示超过预设范围的值。

写显示表达式的要点是所有值要使用Java的类型,所有表达式内的项目都要显式使用Java函数,否则容易得到编译错误。要求这样做的原因是iReport编译选项中缺省使用“JasperReport Default”编译报表,运算时使用JasperReport定义的数据类型,如使用Java编译器情况可能不同,设置会更简洁。

输出例程

每张不同的报表最后利用iReport产生过程都是大同小异的。就是根据程序参数获取数据源fill报表,并按程序的要求以各种形式输出。所以,所有报表使用公共的报表输出程序可以大大简化和方便报表程序的设计。

输出程序要点如下,必须使用Servlet,例如ExportReport为输出报表Servlet的名字:

public class ExportReport extends HttpServlet {“key”,value}

缺省JSP报表程序调用ExportReport采用GET。不同报表调用公用报表输出程序,需要将数据结果集和参数传递给ExportReport,GET方式调用参数传递只能使用会话对象,session.setAttribute(“key”,value),当用户在同一会话中打开多个报表或多次以不同参数打开同一报表时,参数就会相互覆盖产生错误,尤其当刷新报表时,参数改变会使用户看到的报表不是想要的报表。

解决多用户传递参数的办法是使用请求对象传递参数request.setAttribute(“key”,value),则每个报表发出的请求互相没有冲突,用户每次刷新都可得到参数正确的报表。在调用时,不能使用response.sendRedirect(exportURL),这样只能以GET调用,且无法传递request对象中的参数。

输出HTML图文报表

HTML格式输出是Web程序最基本的要求。在输出有图片的报表时,使用PDF格式输出是最好的,HTML很容易出现各种图片显示问题。根据网上资料,在早期iReport0.5以前版本HTML输出图片没有问题,从iReport1.1.0到最新的iReport1.3.0,首先必须在报表输出Servlet中设置参数exporter.setParameter(JRHtmlExporterParameter.IS_OUTPUT_IMAGES_TO_DIR,Boolean.TRUE),还必须设置“IMAGES_DIR_NAME”、“IMAGES_URI”参数,输出报表时才能在上述参数指定的目录下生成临时图片文件,用户在上才能看到图片。但是问题产生了,当多用户以不同参数使用同一报表的情况下,临时文件名一般是一样的,用户看到的报表数据是正确的,但插图有可能是别人生成的临时图片。

经过深入研究,笔者发现问题出在输出设置上,目前几乎所有资料在输出HTML格式文件时,都沿用与输出PDF格式文件相同的设置,可通过以下设置实现:

exporter.setParameter(JRExporterParameter.OUTPUT_STREAM,outputStream);

最后动作是将jprint文件直接输出到Servlet的输出流中,而根据分析,PDF图片是在二进制输出流中输出,而HTML输出流中对图片只是一个URL引用。图片虽已作为独立文件生成,以二进制方式在outputStream输出HTML文件时,浏览器不能正确掌握引用图片的时机。为了正确输出图片,根据HTML是文本文件的特性,先将HTML文件输出到一个字符缓冲区当中,再调用outputStream.println()方法以字符流方式打印HTML文件,println()函数以字符方式打印HTML文件,浏览器接受到输出Servlet以println()发来的字符行形式的HTML文件时,可以正确地对已生成的临时图片文件进行引用,从而为用户显示出正确插图的HTML文档。

发布人:管理员 【报告错误】·【推荐好友】·【打印文章】
相关评论 本文现有 0 条评论 评分人数: 0 平均分: 0
相关评论
用户名: 密  码:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
注意:请不要在评论中含与内容无关的广告链接,违者封ID
文章搜索
推荐文章
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
循序渐进学习iTextShar
热门点击
一个简单的PDF文件结构的分析(22609)
PHP的FDF文档支持(16221)
用C#制作PDF文件全攻略(13660)
Word转换PDF格式的C#或(12174)
pdfMaker文章:PDF加(11664)
ITextRenderer学习(11472)
PDF文件加密仿真(11088)
怎样用iReport制作Web(10445)
iText PDF概述(1)(9975)
循序渐进学习iTextShar(9901)
热门评论
从pdf文档中提取出文本(8)
PDFlib开发:创建超文本元(2)
客户端自动打印PDF(Prin(2)
浅谈PDFlib中文输出(一)(2)
xml的转换之pdf 2 ((1)
xml的转换之pdf 1 (x(1)
PDF知识讲座(1)(1)
PDFBox使用简介(1)
使用正则表达式计算PDF文档的(1)
word转pdf(1)