ireport使用教程
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JasperReport那些事儿
如果你还不知道jasperreport和ireport,那你可以参考我的上一篇文章,或者谷歌百度一下。
好了,废话少说,Let’s start,Go!
我的环境是iReport3.0+JDK6.0。
先看看效果。
1)准备数据源,这里使用XML文件(使用UTF8编码)作为数据源。
2)打开iReport,新建一个空的模版文件。
3)加入一个静态文本(StaticText),右击属性(Property),编辑字体属性和内容。
关于Font Name 属性和PDF Font Name属性需要PMingLiu字体(下载)(将PMingLi u字体放在ireport安装目录的font文件夹下)或者你可以选择其他字体,例如宋体,PDF Font Name 选STSong-Light。
4)接下来就要做表格部分,新建一个子报表(subreport),除了第二步选择No C onnection or datasource,基本上只要点Next就行了。
5)完成上一步后就会跳到子报表NameList_subreport0的视图,其实子报表也是一个独立的报表。
但是你现在只能看到一个叫Detail的区域(band)。
我们还需要更多的区域来结合完成表格的制作。
调出区域管理器(菜单View->Bands),将column header 和column footer的高度(height)设为20.
6)在column header加入三个静态文本(StaticText),字体属性和之前的一样,分别加入内容姓名,性别,年龄。
在detail区域加入三个文本(textField),在column fo oter加入一个文本,字体属性和StaticText保持一样。
然后设置所有静态文本和文本的边框,如图。
现在的textField都是没有数据的,那么怎么填充数据呢?现在我们来看怎么配置数据源和填充数据。
7)菜单data->connections/datasource,新建一个XML datasouce,目录位置指向之前建立的XML文件。
选择Use the report Xpathxpression when filling the report.
8)打开NameList模版,菜单data->report query,配置XPATH如图。
9)配置NameList模板的subreport, 編輯屬性Connection/Data Source Expression,輸入((net.sf.jasperreports.engine.data.JRXmlDataSource)$P{REPORT_DATA_SOURC E}).dataSource("/NameList/Person")。
这一步主要是将数据源传给子报表。
10)打开NameList_subreport0模板,先配置XPATH,然后右击节点Name,选A dd node as field.同样将Gender和Age节点加入field。
点OK。
然后你可以看到左边的结构视窗多了三个Field。
11)编辑Table里的文本(textfield),右击选Edit Expression,输入表达式(Fiel d的表达式,$F{Field_Name})。
$V{REPORT_COUNT}是jasperreport内建的变量,用于计算detail区域的行数。
12)保存模板,菜单build->Compile,编译两个模板。
打开NameList模板,带数据源运行(build->Execute with active connection)。
大功告成。
JasperReport那些事儿(二)——从对象到XML数据源。
记得刚学Jasperreport的时候,在谷歌和百度上搜到的大多数入门文章都是教授如何使用数据库来做报表的。
对于只采用简单数据集和那些直接面向数据的报表,使用数据库作为数据源是合适的;但是也有很多的报表不是直接面向原始数据的,例如财务报表,都是需要计算和做后续处理;也有一些报表引用的数据粒度小,但是数量多,使用数据库做数据源是不合适的。
XML一直被认为是一种很好的描述结构化数据的语言。
首先XML文件的数据结构非常清晰。
可以把报表所需要的数据集成到一个XML文件上,然后再通过在文件内查询,这比每需要一条数据就使用SQL来查询要显得更高效和简单。
试想一下,你的同事A告诉你,“报表的数据都在这份XML文件里哦”。
而同事B则对你说:”那些数据在某个数据库里,你自己去查吧。
“,你更喜欢听到哪一句呢?(当然我的语气上的差别就说明了我的喜好,我老怀疑后者在背向我的那一刻有在奸笑。
)
其次,现在对象映射到XML的工具很多。
哦?你知道我在暗示什么吗?没错,你可以面向对象,而不用面向丑陋的表格。
在上一篇文章中,我给出这样一个数据源。
1 <?xml version="1.0" encoding="utf-8" ?>
2 <NameList>
3 <Person>
4 <Name>强尼</Name>
5 <Gender>男</Gender>
6 <Age>56</Age>
7 </Person>
8 <Person>
9 <Name>阿美</Name>
10 <Gender>女</Gender>
11 <Age>23</Age>
12 </Person>
13 <Person>
14 <Name>李丽</Name>
15 <Gender>女</Gender>
16 <Age>58</Age>
17 </Person>
18 <Person>
19 <Name>杰森</Name>
20 <Gender>男</Gender>
21 <Age>32</Age>
22 </Person>
23 <Person>
24 <Name>刘三</Name>
25 <Gender>男</Gender>
26 <Age>21</Age>
27 </Person>
28 </NameList>
如果你是个典型的面向对象的思考者,应该马上想到一个叫Person的Java类。
大概像下面这样。
1 package com.blogjava.heis.jasper.chapter2;
2
3 public class Person {
4
5 private String name;
6 private String gender;
7 private int age;
8
9 private String getName() {
10 return name;
11 }
12 private void setName(String name) {
13 = name;
14 }
15 private String getGender() {
16 return gender;
17 }
18 private void setGender(String gender) {
19 this.gender = gender;
20 }
21 private intgetAge() {
22 return age;
23 }
24 private void setAge(int age) {
25 this.age = age;
26 }
27 }
想像一下,把一个个对象排着队跳进模板,然后一张完整的报表就出来了,不用管那些烦人的Sql,那应该是多么美好的一件事儿。
面向对象果然是我们的福音。
接下来看看我们如何把对象转换成XML文件。
package com.blogjava.heis.jasper.chapter2;
importjava.io.File;
importjava.io.FileWriter;
importjava.io.StringWriter;
importjava.util.ArrayList;
mons.betwixt.io.BeanWriter;
public class BeanToXMLConverter {
private final static String FILE_PATH="c:/test.xml";
/**
* Create an example bean and then convert it to xml.
*/
public static final void main(String [] args) throws Exception {
Person person1=new Person();
person1.setName("张三");
person1.setGender("男");
person1.setAge(35);
Person person2=new Person();
person2.setName("李四");
person2.setGender("女");
person2.setAge(25);
ArrayList<Person> al=new ArrayList<Person>();
al.add(person1);
al.add(person2);
NameListnameList=new NameList();
nameList.setList(al);
try{
BeanToXMLConverterwea=new BeanToXMLConverter();
wea.writeToXMLFile(nameList);
}catch(Exception e){
e.printStackTrace();
}
}
private void writeToXMLFile(Object obj)throws Exception{ StringWriteroutputWriter = new StringWriter();
outputWriter.write("<?xml version='1.0' ecoding='UTF-8' ?> "); BeanWriterbeanWriter = new BeanWriter(outputWriter);
beanWriter.getXMLIntrospector().getConfiguration().setAttributesForPrimitives(false); beanWriter.getBindingConfiguration().setMapIDs(false);
beanWriter.enablePrettyPrint();
beanWriter.write(obj);
String xmlFilePath=FILE_PATH;
File xmlFile=new File(FILE_PATH);
if(!xmlFile.exists()){
xmlFile.createNewFile();
}
FileWriterfw=new FileWriter(xmlFilePath);
fw.write(outputWriter.toString().toCharArray());
fw.flush();
System.out.println(outputWriter.toString());
outputWriter.close();
}
}
NameList类代码。
运行以上的代码需要四个包,commons-betwixt.jar,commons-logging.jar, com mons-collections.jar, commons-beanutils-core.jar。
这些都可以从http://commons.apache. org/下载。
JDK需要1.5或以上。
看到这里你心里也许开始矛盾(或者不屑),对,同事Q也是这样想的。
Q:“这不是摆明更麻烦么?对象转换为XML,再从XML查数据,你这瞎折腾我,浪费资源在转换上!!”
俺:“也许是多了一些功夫,多占用了点资源。
但是这可以让报表的数据可读性更强,更重要的是报表制作可以和SQL说拜拜,他和对象走得更密切了。
”
Q:“但是你的XML文件不是还是需要查询么?你能保证那些查询语句比SQL更简单么?”
俺:“我能给你肯定的回答。
但是XML的查询就要留到下一章去介绍了。
这星期O T比较多,先溜啦,88。
”
Q:“哎,你给我说清楚点再走……”
JasperReport那些事儿(三)——使用XPATH查询XML。
同事Q:“小黑,你上次说一半不说一半,这次可得老实交待怎么从XML查询数据了吧。
”
俺:“好好,我这就交待。
你看我这星期不是忙得焦头烂额么?”(注:忙永远是程序员的借口)
其实JasperReport使用的也不是什么神秘的东西,就是XPATH。
XPath是一门在XML 文档中查找信息的语言。
XPath可用来在XML 文档中对元素和属性进行遍历(从w3cshool抄来的)。
关于XPATH,我就不详细讲了,因为对于普通的报表,只需要掌握几个常用的查询;如果想深究网上有更好的教程(教程可以点这里)。
我这里只简单地讲解XPATH的一些概念和常用的一些查询。
(1)什么是绝对路径和相对路径?
我这里那是拿出我的NameList做例子吧。
例如我要选取所有的Person节点,那绝对路径应该这样写:
现在以Person作为根路径,如果要选取所有Person节点下的Name节点,那相对路径可以这样写:
所谓的相对路径是不以/开头,相对与一个绝对路径的路径。
如果用绝对路径选取所有Name节点,可以这样写:
(2)带条件的XPATH查询
XPATH的条件是写在路径后的一个方括号内,条件支持XPATH的函数和一些逻辑运算符号。
常用的逻辑运算符号有+,<,=,or,and等。
以下是一些例子。
选取第一个Person节点
选取Age小于50的Person节点
选取Gender是女的Person节点
(3)XPATH的函数
count()函数主要是计算节点数量,可以带一个参数,例如
查询Person的节点数量,结果返回3
position() 函数主要是用于条件查询,返回节点的定位,例如
选取前两个Person节点
简单介绍完XPATH,下面我们来看XPATH怎么在JasperReport里运用。
我在Jasp erReport那些事儿(一)里曾经介绍过XPATH的使用,但是没有做详细介绍。
现在我们再来看其中的一个步骤。
看第十步,其实这里就是配置了一个根路径/NameList/Person,下面几个field的Des cirption其实也是XPATH表达式,配置了相对路径。
通过XPATH表达式,field会获取到匹配节点的值,这就是XML数据填充的过程。
10)打开NameList_subreport0模板,先配置XPATH,然后右击节点Na me,选Add node as field.同样将Gender和Age节点加入field。
点OK。
然后你可以看到左边的结构视窗多了三个Field。
图片看不清楚?请点击这里查看原图(大图)。
程序员的一生其实可短暂了,这电脑一开一关,一天过去了,嚎;电脑一开不关,那就成服务器了,嚎……
本文示例源代码或素材下载
最近在想《JasperReport那些事儿》系列的写作方向的问题,是要先写Jasper的原理和基础方面,还是写怎么制作报表实例。
如果你想我写一些你感兴趣的部分,可以在文章后面加评论告诉我。
这周先写一篇制作报表实例的文章吧。
看到一篇总结报表图例的文章/2009-03/1236247537110450.htm l。
总结的相当不错,如果你不知道什么是标签式报表,可以看看。
1.先上效果图
图片看不清楚?请点击这里查看原图(大图)。
2.数据源还是沿用NameList XML数据源,关于怎么配置数据源可以看这里。
<?xml version="1.0"encoding="utf-8"?> <NameList>
<Person>
<Name>强尼</Name>
<Gender>男</Gender>
<Age>56</Age>
</Person>
<Person>
<Name>阿美</Name>
<Gender>女</Gender>
<Age>23</Age>
</Person>
<Person>
<Name>李丽</Name>
<Gender>女</Gender>
<Age>58</Age>
</Person>
<Person>
<Name>杰森</Name>
<Gender>男</Gender>
<Age>32</Age>
</Person>
<Person>
<Name>刘三</Name>
<Gender>男</Gender>
<Age>21</Age>
</Person>
</NameList>
3.制作报表的思路
在制作标签报表的时候,我们先来理清一下思路。
可以发现,其实标签式报表的每个小标签内的内容类型都是一样的,这样可以认为报表是由多个标签组成的。
这样就可以分离出主体报表和子报表的概念,这与Jasperreport里的subreport(子报表)概念是一样的。
这样就可以大概抽象出一个标签式报表的模型了,在主体报表上使用两个subreport元素指向同一个标签报表。
那为什么要使用两个subreport元素?我们先来看我们期待输出的标签模型的顺序。
但是在Jasperreport里,报表的渲染是从上到下的。
所以我们期待的顺序是先渲染1号标签,然后渲染2号标签,这是从左到右的渲染,在Jasperreport里面是做不到的。
但是我们可以采用同时渲染1号和2号标签,这就需要两个subreport元素。
4.具体步骤(关于子报表的制作,可以参考我的第一篇文章)a)建立一个主模板,加入两个subreport。
图片看不清楚?请点击这里查看原图(大图)。
b)建立一个子模板(标签模板)。
图片看不清楚?请点击这里查看原图(大图)。
c)配置subreport的XPATH。
左边的subreport的Datasource配置
图片看不清楚?请点击这里查看原图(大图)。
右边的subreport的Datasource配置
图片看不清楚?请点击这里查看原图(大图)。
上一篇文章就有人评论说Jasperreport不适合中国式报表。
我就很奇怪了,我从来没说Ja sperreport适合中国式报表(当然我也没说不适合)。
我写文章的初衷就是分享技术,工具这种东西向来是以需求为导向的,合适就用,不合适没钱买好的,也凑合用用。
但是程序员往往是没权去决定那些事儿的,程序员应该是一群能用有限的资源去解决问题的人,何况开源产品使用成本和学习成本都比较低,不用白不用。
要一些人看着刺眼或打着打广告的心态,我就劝你别看,方正我是会继续写下去的。
扯远了,回到正题吧。
最近博客留言有问怎么做“单元格合并的报表”,单看这定义,无从下手啊,我也不知道我理解的意思对不对,上星期做了一个我理解的“单元格合并的报表,希望和那位留言的博友的意思有一点重合就好了。
看一下效果吧。
图片看不清楚?请点击这里查看原图(大图)。
数据源结构:
<?xml version="1.0"encoding="utf-8"?> <DepartmentList>
<list>
<Department>
<name>行政部</name>
<personList>
<person>
<age>35</age>
<gender>男</gender>
<name>张三</name>
</person>
</personList>
</Department>
<Department>
<name>技术部</name>
<personList>
<person>
<age>30</age>
<gender>男</gender>
<name>李四</name>
</person>
<person>
<age>28</age>
<gender>女</gender>
<name>王五</name>
</person>
</personList>
</Department>
</list>
</DepartmentList>
都说中国的报表是大表中有小表,这其实和关系数据库的表格概念有很大的不同。
关系数据库的表格是简单的二维表格,不会在表格里再嵌套表格。
那遇到这类型的表格应该怎么处理呢?我在前面的文章有讲怎么制作简单的二维表格,所以这篇主要是解决表格前面的单元格合并的问题。
这里还要借助子报表,子报表是Jasperreport最为强大的功能,也是最具扩展性的功能组件(纯粹个人意见)。
做这样的表格我是用了三个报表模板。
第一个,DepartmentList.jrxml.(编译后为jasper后缀名)
图片看不清楚?请点击这里查看原图(大图)。
第二个,DepartmentList_department.jrxml.
图片看不清楚?请点击这里查看原图(大图)。
第三个,DepartmentList_department_person.jrxml.
图片看不清楚?请点击这里查看原图(大图)。
调用关系是第一个模板调用第二个,第二个模板再调用第三个。
在第二个报表给子报表传递数据源时,表达式要像下面这样写。
这样写主要目的是选择当前department节点下的所有person节点。
REPORT_COUNT变量是指当前detail band内的计数器。
例如,从父报表传过来的数据源的节点数是3,则REPORT_COUNT会从1到3遍历,detail band也会渲染3次。
这里的XPATH是遍历了第一个到第三个Department下的所有person节点。
这里值得一提的是在第二张报表的部门那个textfield里有个属性需要注意,Stretch Ty pe设置为"relative to band height",就是让textfield自动往下延伸,延伸到与其所在的区域(band)相同的高度。
说句实话,在Jasperreport里面处理表格的确是一件很麻烦的事(指以XML为数据源),像上文提到的表格是很简单的例子,但是却要用到三个模板。
而且Jasperreport报表是线性渲染(由上到下),所以无论从灵活性和还是效率来说,都比不上像Excel那种以表格为导向类型的报表工具。
但是还是那句话,工具这种东西向来是以需求为导向的,合适就用,不合适没钱买好的,也凑合用用。
JasperReport那些事儿(六)——制作分页式报表。
本文示例源代码或素材下载
之前介绍的一些报表都是单页式的报表,就是格式都一样。
如果要生成一份有不同样式的报表,这要怎么做呢?就像一份保险公司保单,可能有产品介绍、收益表、建议书、最后还有合同,这都要求不同的报表分页显示。
这一篇将给你介绍怎么让报表分页。
先来看一下效果。
图片看不清楚?请点击这里查看原图(大图)。
这份报表沿用了上一篇的报表,只是在这个基础上加了分页功能。
实际上我只改动了DepartmentList_department.jrxml这张报表。
就在detail区域top= 0处加入一个分页符(page break),因为分页符需要占用1像素的高度,所以要将原来d etail内的内容往下移一个像素,就是top=1.
图片看不清楚?请点击这里查看原图(大图)。
在Jasperreport里,强制分页有两种方法。
第一种是加入分页符(page break),就是上文提到的方式;第二种只适用group的区域(band),可以设定当区域延伸到一定的高度就分页。