一、JFreeReport简介
JFreeReport是由JFree组织开发的一个基于java的报表组件。利用JFreeReport组件可以完成大多数样式的报表,并且能够将其输出为pdf、xls、cvs、html等不同格式的文件和打印,为程序开发人员解决报表问题提供了很大的方便。
JFreeReport组件包括一个核心包以及几个扩展包,可以到
www.jfree.org网站下载。由于是开源的,所以可以直接得到其源代码。(后面关于PDF输出中文方面就需要修改其源代码)
现在JFreeReport加入到了Pentaho,所以JFreeReport的最新版本只到jfreereport-0.8.7-9.jar,之后就以Pentaho Report Designer命名了。
二、JFreeReport组件的结构
JFreeReport组件的核心对象就是JFreeReport对象,我将其视两部分:一部分是报表格式定义,另一部分是数据存储。
JFreeReport组件的数据使用的是java.swing.table.TableModel类,我们对它都非常熟悉了,用JTable做表格时都会用到,所以在此不再累述。我主要讲讲JFreeReport的报表格式定义以及输出方法。
JFreeReport将报表分为以下几个部分:报头(ReportHeader)、报尾(ReportFooter)、页头(PageHeader)、页尾(PageFooter)、分组头(GroupHeader)、分组尾(GroupFooter)和数据域。
l 表头(ReportHeader)——内容显示在整个报表的开头,可以包括报表名称等内容。
l 表尾(ReportFooter)——内容显示在整个报表的末尾。
l 页首(PageHeader)——内容显示在每一页的首部,第一页则显示在ReportHeader下面,可以包括报表日期、填表人等内容。
l 页尾(PageFooter)——内容显示在每一页的末尾,可以包括页号等信息。
l 分组头(GroupHeader)——如果将数据分组,则GroupHeadar内容会显示在每一组分组的头部。
l 分组尾(GroupFooter)——如果将数据分组,则GroupHeadar内容会显示在每一组分组的头部。
l 数据域——报表数据,一般位于每页的中间部分。
三、报表格式定义
知道了JFreeReport组件的报表结构,下面该介绍如何定义了。有两种方法:一种是使用java代码实现,另一种是使用xml定义。
1、代码方式实现报表格式定义
使用代码方式实现步骤很简单,就是分别构造报头(ReportHeader)、报尾(ReportFooter)、页头(PageHeader)、页尾(PageFooter)、分组头(GroupHeader)和分组尾(GroupFooter)对象,然后使用set方法加入JFreeReport对象就可以了。
上面这几个对象我们一般只会用到其addElement(Element element)方法,即将一个元素(Element)加入到指定部分。在这里,元素的意义就是显示在报表中的内容,包括文本、表格、图形、图片等等。Element是一个抽象类,他有几个子类,但我们不必直接使用这些子类,而是通过org.jfree.report.elementfactory包中的工厂类来构建。:
l LabelElementFactory——标签元素工厂类,定义报表中显示的固定文本内容。
l TextElementFactory——文本元素工厂类,根据定义的域名,显示其域名下的内容。比如:tableModel中的“编号”字段下的内容。
l StaticShapeElementFactory——图形元素类,可以绘制直线、矩形等图形。
其他的元素我没用过,大家可以查看JFreeReport的API文档。他们的用法请看下面的例子。
public static final int ROW_HEIGHT
=
20
;
//
报告:行高度
public static final int HEADER_HEIGHT = 40 ; // 报告:报头高度
JFreeReport report = new JFreeReport(); // 构造JFreeReport对象
report.setName( " Report Name " );
PageDefinition pd = report.getPageDefinition(); // 取得报告页面定义
float pageWidth = pd.getWidth(); // 取得打印材质的页宽
// 定义页头
PageHeader header = new PageHeader();
LabelElementFactory title = new LabelElementFactory(); // 标题元素
title.setText( " 统计报表 " ); // 设置文本内容
title.setColor(Color.BLACK); // 设置颜色
title.setAbsolutePosition( new Point2D.Float( 0 , HEADER_HEIGHT)); // 设置显示位置
title.setMinimumSize( new FloatDimension(pageWidth, 36 )); // 设置尺寸
title.setHorizontalAlignment(ElementAlignment.LEFT);
title.setVerticalAlignment(ElementAlignment.MIDDLE);
title.setDynamicHeight( true ); // 设置是否动态调整高度(如果为true,当文本内容超出显示范围时高度自动加长)
header.addElement(title.createElement());
report.setPageHeader(header);
String[] columnNames = getColumnNames(); // 取得报表数据域的所有列名
if (columnNames != null && columnNames.length > 0 ) ... {
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0)); //绘制表格的横线
//定义报表头
ReportHeader reportHeader = new ReportHeader();
for (int i = 0; i < columnNames.length; i++) ...{
//字段名元素
LabelElementFactory col = new LabelElementFactory();
col.setName(columnNames[i]);
col.setColor(Color.BLACK);
col.setHorizontalAlignment(ElementAlignment.CENTER);
col.setVerticalAlignment(ElementAlignment.MIDDLE);
col.setDynamicHeight(true);
col.setAbsolutePosition(new Point2D.Float((pageWidth
/ (columnNames.length))
* i, 0));
col.setMinimumSize(new FloatDimension(pageWidth
/ (columnNames.length), ROW_HEIGHT)); //设置最小尺寸
col.setBold(true); //设置是否粗体显示
col.setText(columnNames[i]);
reportHeader.addElement(col.createElement());
reportHeader.addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), col.getAbsolutePosition().getX())); //元素左侧竖线
reportHeader.addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0)); //元素上方横线
reportHeader.addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), pageWidth)); //元素右侧竖线
report.setReportHeader(reportHeader);
//字段内容元素
TextFieldElementFactory data = new TextFieldElementFactory();
data.setName(columnNames[i]);
data.setColor(Color.BLACK);
data.setAbsolutePosition(new Point2D.Float((pageWidth
/ (columnNames.length))
* i, 0));
data.setMinimumSize(new FloatDimension(pageWidth
/ (columnNames.length), ROW_HEIGHT));
data.setHorizontalAlignment(ElementAlignment.CENTER);
data.setVerticalAlignment(ElementAlignment.MIDDLE);
data.setDynamicHeight(true);
data.setWrapText(new Boolean(true));
data.setNullString("-"); //如果字段内容为空,显示的文本
data.setFieldname(columnNames[i]);
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
report.getItemBand().addElement(data.createElement());
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), -100));
report.getItemBand().addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), data.getAbsolutePosition().getX()));
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
}// end for(int i=0;i<columnNames.length;i++)
//最后的竖线
report.getItemBand().addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), pageWidth));
PageFooter footer = new PageFooter();
//设置页号
PageOfPagesFunction pageFunction = new PageOfPagesFunction("PAGE_NUMBER"); //构造一个页号函数对象
pageFunction.setFormat("{0} / {1}页"); //设置页号显示格式(此处显示的格式为“1/5页”)
report.addExpression(pageFunction);
TextFieldElementFactory pageCount = new TextFieldElementFactory();
pageCount.setFieldname("PAGE_NUMBER");
pageCount.setColor(Color.black);
pageCount.setAbsolutePosition(new Point2D.Float(0, 0));
pageCount.setMinimumSize(new FloatDimension(pageWidth, 0));
pageCount.setHorizontalAlignment(ElementAlignment.RIGHT);
pageCount.setVerticalAlignment(ElementAlignment.MIDDLE);
pageCount.setDynamicHeight(true);
footer.addElement(pageCount.createElement());
report.setPageFooter(footer);
ReportFooter reportFooter = new ReportFooter();
reportFooter.addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
report.setReportFooter(reportFooter);
public static final int HEADER_HEIGHT = 40 ; // 报告:报头高度
JFreeReport report = new JFreeReport(); // 构造JFreeReport对象
report.setName( " Report Name " );
PageDefinition pd = report.getPageDefinition(); // 取得报告页面定义
float pageWidth = pd.getWidth(); // 取得打印材质的页宽
// 定义页头
PageHeader header = new PageHeader();
LabelElementFactory title = new LabelElementFactory(); // 标题元素
title.setText( " 统计报表 " ); // 设置文本内容
title.setColor(Color.BLACK); // 设置颜色
title.setAbsolutePosition( new Point2D.Float( 0 , HEADER_HEIGHT)); // 设置显示位置
title.setMinimumSize( new FloatDimension(pageWidth, 36 )); // 设置尺寸
title.setHorizontalAlignment(ElementAlignment.LEFT);
title.setVerticalAlignment(ElementAlignment.MIDDLE);
title.setDynamicHeight( true ); // 设置是否动态调整高度(如果为true,当文本内容超出显示范围时高度自动加长)
header.addElement(title.createElement());
report.setPageHeader(header);
String[] columnNames = getColumnNames(); // 取得报表数据域的所有列名
if (columnNames != null && columnNames.length > 0 ) ... {
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0)); //绘制表格的横线
//定义报表头
ReportHeader reportHeader = new ReportHeader();
for (int i = 0; i < columnNames.length; i++) ...{
//字段名元素
LabelElementFactory col = new LabelElementFactory();
col.setName(columnNames[i]);
col.setColor(Color.BLACK);
col.setHorizontalAlignment(ElementAlignment.CENTER);
col.setVerticalAlignment(ElementAlignment.MIDDLE);
col.setDynamicHeight(true);
col.setAbsolutePosition(new Point2D.Float((pageWidth
/ (columnNames.length))
* i, 0));
col.setMinimumSize(new FloatDimension(pageWidth
/ (columnNames.length), ROW_HEIGHT)); //设置最小尺寸
col.setBold(true); //设置是否粗体显示
col.setText(columnNames[i]);
reportHeader.addElement(col.createElement());
reportHeader.addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), col.getAbsolutePosition().getX())); //元素左侧竖线
reportHeader.addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0)); //元素上方横线
reportHeader.addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), pageWidth)); //元素右侧竖线
report.setReportHeader(reportHeader);
//字段内容元素
TextFieldElementFactory data = new TextFieldElementFactory();
data.setName(columnNames[i]);
data.setColor(Color.BLACK);
data.setAbsolutePosition(new Point2D.Float((pageWidth
/ (columnNames.length))
* i, 0));
data.setMinimumSize(new FloatDimension(pageWidth
/ (columnNames.length), ROW_HEIGHT));
data.setHorizontalAlignment(ElementAlignment.CENTER);
data.setVerticalAlignment(ElementAlignment.MIDDLE);
data.setDynamicHeight(true);
data.setWrapText(new Boolean(true));
data.setNullString("-"); //如果字段内容为空,显示的文本
data.setFieldname(columnNames[i]);
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
report.getItemBand().addElement(data.createElement());
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), -100));
report.getItemBand().addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), data.getAbsolutePosition().getX()));
report.getItemBand().addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
}// end for(int i=0;i<columnNames.length;i++)
//最后的竖线
report.getItemBand().addElement(StaticShapeElementFactory.createVerticalLine(null, Color.BLACK, new BasicStroke(1), pageWidth));
PageFooter footer = new PageFooter();
//设置页号
PageOfPagesFunction pageFunction = new PageOfPagesFunction("PAGE_NUMBER"); //构造一个页号函数对象
pageFunction.setFormat("{0} / {1}页"); //设置页号显示格式(此处显示的格式为“1/5页”)
report.addExpression(pageFunction);
TextFieldElementFactory pageCount = new TextFieldElementFactory();
pageCount.setFieldname("PAGE_NUMBER");
pageCount.setColor(Color.black);
pageCount.setAbsolutePosition(new Point2D.Float(0, 0));
pageCount.setMinimumSize(new FloatDimension(pageWidth, 0));
pageCount.setHorizontalAlignment(ElementAlignment.RIGHT);
pageCount.setVerticalAlignment(ElementAlignment.MIDDLE);
pageCount.setDynamicHeight(true);
footer.addElement(pageCount.createElement());
report.setPageFooter(footer);
ReportFooter reportFooter = new ReportFooter();
reportFooter.addElement(StaticShapeElementFactory.createHorizontalLine(null, Color.BLACK, new BasicStroke(1), 0));
report.setReportFooter(reportFooter);
2、XML方式实现报表格式定义
对于简单的报表,我们可以使用代码来实现,但对于复杂的报表,代码可能就无能为力了(虽然也可以实现,但对于读代码的人来说可能将是场灾难),那么我们就可以通过定义XML来实现报表格式的定义。这种方法非常方便而且清晰。
JFreeReport定义了两种XML实现方法。这里我只介绍一种,因为另一种我没有用过。我直接通过例子来解释如何实现:
<?
xml version="1.0" encoding="GB2312"
?>
< report name ="My Report" pageformat ="A4" leftmargin ="40" rightmargin ="40" >
< configuration >
< property name ="com.jrefinery.report.preview.PreferredWidth" > 1024 </ property >
< property name ="com.jrefinery.report.preview.PreferredHeight" > 768 </ property >
</ configuration >
<!-- 报头 -->
< reportfooter height ="20" fontname ="宋体" fontsize ="12" >
</ reportfooter >
<!-- 页首 -->
< pageheader fontname ="宋体" fontsize ="12" >
<!-- 文本域,用于显示表数据中某列的内容 -->
<!-- x,y: 为坐标点(以页首区域的左上角为(0, 0)点) -->
<!-- width, height: 为文本域的宽度和高度,如果为数值则表示为绝对尺寸,如果为百分数,则自动以百分比方式调整尺寸大小 -->
<!-- alignment: 排列方式 -->
<!-- fieldname: 域名,即数据域的列名 -->
<!-- nullstring: 当数据域内容为空时显示的字符串内容 -->
<!-- alignment: 水平排列方式center,left或right -->
<!-- vertical-alignment: 竖直排列方式top、middle或bottom -->
<!-- dynamic: 是否动态调整单元格高度,如果为true,当文本内容不足以在当前尺寸中显示时将自动增加单元格高度 -->
< string-field x ="0" y ="0" width ="100%" height ="30" alignment ="center" fontname ="黑体" fontsize ="15" fieldname ="report.title" nullstring ="" ></ string-field >
<!-- 标签域,用于在报表中显示固定文本内容 -->
< label x ="0" y ="20" width ="100%" height ="20" alignment ="center" fontname ="黑体" fontsize ="15" > 报表 </ label >
< label x ="5%" y ="80" width ="100%" height ="20" alignment ="left" > 统计时间: </ label >
< string-field x ="90" y ="80" width ="30%" height ="18" alignment ="left" fieldname ="report.time" nullstring ="" />
< label x ="70%" y ="80" width ="100%" height ="20" > 统计日期: </ label >
<!-- 时间域,用于显示时间 -->
<!-- report.date: 下面<function>中定义的函数,显示当前时间 -->
<!-- format: 日期格式 -->
< date-field fieldname ="report.date" format ="yyyy/M/d" x ="0%" y ="80" width ="95%" height ="20" alignment ="right" ></ date-field >
</ pageheader >
<!-- 页尾 -->
< pagefooter height ="20" fontname ="宋体" fontsize ="12" >
< string-field fieldname ="pageXofY" x ="0" y ="4" width ="100%" height ="18" alignment ="right" />
</ pagefooter >
<!-- 分组 -->
< groups >
< group name ="group1" >
<!-- 分组头 -->
< groupheader fontname ="宋体" fontsize ="10.5" >
< label x ="0%" y ="5" width ="20%" height ="40" alignment ="center" vertical-alignment ="middle" > 结 论 </ label >
< rectangle x ="0%" y ="0" width ="20%" height ="50" color ="#000000" draw ="true" fill ="false" />
< label x ="20%" y ="5" width ="40%" height ="20" alignment ="center" vertical-alignment ="middle" > 上 年 度 </ label >
<!-- 图形:矩形 -->
<!-- color: 颜色 -->
<!-- fill: 是否填充 -->
< rectangle x ="20%" y ="0" width ="40%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="20%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 人 数 </ label >
< rectangle x ="20%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="40%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 占比(%) </ label >
< rectangle x ="40%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="60%" y ="5" width ="40%" height ="20" alignment ="center" vertical-alignment ="middle" > 本 年 度 </ label >
< rectangle x ="60%" y ="0" width ="40%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="60%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 人 数 </ label >
< rectangle x ="60%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="80%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 占比(%) </ label >
< rectangle x ="80%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
</ groupheader >
<!-- 可以还有分组尾<groupfooter> -->
</ group >
</ groups >
<!-- 数据域 -->
< items fontname ="宋体" fontsize ="12" >
<!-- 图形:直线 -->
< line x1 ="0" y1 ="0" x2 ="0" y2 ="100%" />
< string-field fieldname ="年度体检结论" x ="0%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="20%" y1 ="0" x2 ="20%" y2 ="100%" /> <!-- 结论 -->
< string-field fieldname ="上年度" x ="20%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="40%" y1 ="0" x2 ="40%" y2 ="100%" /> <!-- 上年度人数 -->
< string-field fieldname ="上年度(%)" x ="40%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="60%" y1 ="0" x2 ="60%" y2 ="100%" /> <!-- 上年度占比 -->
< string-field fieldname ="本年度" x ="60%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="80%" y1 ="0" x2 ="80%" y2 ="100%" /> <!-- 本年度人数 -->
< string-field fieldname ="本年度(%)" x ="80%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="100%" y1 ="0" x2 ="100%" y2 ="100%" /> <!-- 本年度占比 -->
< line x1 ="0" y1 ="100%" x2 ="100%" y2 ="100%" />
</ items >
<!-- 函数定义 -->
< functions >
<!-- 显示当前时间的函数用法 -->
< property-ref name ="report.date" />
<!-- 显示当前页码的函数用法 -->
< function name ="PageNumber" class ="org.jfree.report.function.PageFunction" deplevel ="1" />
<!-- 显示总页数的函数用法 -->
< function name ="PageTotal" class ="org.jfree.report.function.PageTotalFunction" deplevel ="1" />
<!-- 表达式,次表达式定义一个显示页码格式的用法 -->
< expression name ="pageXofY" class ="org.jfree.report.function.TextFormatExpression" >
< properties >
< property name ="pattern" > {0}/{1}页 </ property >
< property name ="field[0]" > PageNumber </ property >
< property name ="field[1]" > PageTotal </ property >
</ properties >
</ expression >
</ functions >
</ report >
< report name ="My Report" pageformat ="A4" leftmargin ="40" rightmargin ="40" >
< configuration >
< property name ="com.jrefinery.report.preview.PreferredWidth" > 1024 </ property >
< property name ="com.jrefinery.report.preview.PreferredHeight" > 768 </ property >
</ configuration >
<!-- 报头 -->
< reportfooter height ="20" fontname ="宋体" fontsize ="12" >
</ reportfooter >
<!-- 页首 -->
< pageheader fontname ="宋体" fontsize ="12" >
<!-- 文本域,用于显示表数据中某列的内容 -->
<!-- x,y: 为坐标点(以页首区域的左上角为(0, 0)点) -->
<!-- width, height: 为文本域的宽度和高度,如果为数值则表示为绝对尺寸,如果为百分数,则自动以百分比方式调整尺寸大小 -->
<!-- alignment: 排列方式 -->
<!-- fieldname: 域名,即数据域的列名 -->
<!-- nullstring: 当数据域内容为空时显示的字符串内容 -->
<!-- alignment: 水平排列方式center,left或right -->
<!-- vertical-alignment: 竖直排列方式top、middle或bottom -->
<!-- dynamic: 是否动态调整单元格高度,如果为true,当文本内容不足以在当前尺寸中显示时将自动增加单元格高度 -->
< string-field x ="0" y ="0" width ="100%" height ="30" alignment ="center" fontname ="黑体" fontsize ="15" fieldname ="report.title" nullstring ="" ></ string-field >
<!-- 标签域,用于在报表中显示固定文本内容 -->
< label x ="0" y ="20" width ="100%" height ="20" alignment ="center" fontname ="黑体" fontsize ="15" > 报表 </ label >
< label x ="5%" y ="80" width ="100%" height ="20" alignment ="left" > 统计时间: </ label >
< string-field x ="90" y ="80" width ="30%" height ="18" alignment ="left" fieldname ="report.time" nullstring ="" />
< label x ="70%" y ="80" width ="100%" height ="20" > 统计日期: </ label >
<!-- 时间域,用于显示时间 -->
<!-- report.date: 下面<function>中定义的函数,显示当前时间 -->
<!-- format: 日期格式 -->
< date-field fieldname ="report.date" format ="yyyy/M/d" x ="0%" y ="80" width ="95%" height ="20" alignment ="right" ></ date-field >
</ pageheader >
<!-- 页尾 -->
< pagefooter height ="20" fontname ="宋体" fontsize ="12" >
< string-field fieldname ="pageXofY" x ="0" y ="4" width ="100%" height ="18" alignment ="right" />
</ pagefooter >
<!-- 分组 -->
< groups >
< group name ="group1" >
<!-- 分组头 -->
< groupheader fontname ="宋体" fontsize ="10.5" >
< label x ="0%" y ="5" width ="20%" height ="40" alignment ="center" vertical-alignment ="middle" > 结 论 </ label >
< rectangle x ="0%" y ="0" width ="20%" height ="50" color ="#000000" draw ="true" fill ="false" />
< label x ="20%" y ="5" width ="40%" height ="20" alignment ="center" vertical-alignment ="middle" > 上 年 度 </ label >
<!-- 图形:矩形 -->
<!-- color: 颜色 -->
<!-- fill: 是否填充 -->
< rectangle x ="20%" y ="0" width ="40%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="20%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 人 数 </ label >
< rectangle x ="20%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="40%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 占比(%) </ label >
< rectangle x ="40%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="60%" y ="5" width ="40%" height ="20" alignment ="center" vertical-alignment ="middle" > 本 年 度 </ label >
< rectangle x ="60%" y ="0" width ="40%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="60%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 人 数 </ label >
< rectangle x ="60%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
< label x ="80%" y ="30" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" > 占比(%) </ label >
< rectangle x ="80%" y ="25" width ="20%" height ="25" color ="#000000" draw ="true" fill ="false" />
</ groupheader >
<!-- 可以还有分组尾<groupfooter> -->
</ group >
</ groups >
<!-- 数据域 -->
< items fontname ="宋体" fontsize ="12" >
<!-- 图形:直线 -->
< line x1 ="0" y1 ="0" x2 ="0" y2 ="100%" />
< string-field fieldname ="年度体检结论" x ="0%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="20%" y1 ="0" x2 ="20%" y2 ="100%" /> <!-- 结论 -->
< string-field fieldname ="上年度" x ="20%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="40%" y1 ="0" x2 ="40%" y2 ="100%" /> <!-- 上年度人数 -->
< string-field fieldname ="上年度(%)" x ="40%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="60%" y1 ="0" x2 ="60%" y2 ="100%" /> <!-- 上年度占比 -->
< string-field fieldname ="本年度" x ="60%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="80%" y1 ="0" x2 ="80%" y2 ="100%" /> <!-- 本年度人数 -->
< string-field fieldname ="本年度(%)" x ="80%" y ="5" width ="20%" height ="20" alignment ="center" vertical-alignment ="middle" nullstring ="" dynamic ="true" />
< line x1 ="100%" y1 ="0" x2 ="100%" y2 ="100%" /> <!-- 本年度占比 -->
< line x1 ="0" y1 ="100%" x2 ="100%" y2 ="100%" />
</ items >
<!-- 函数定义 -->
< functions >
<!-- 显示当前时间的函数用法 -->
< property-ref name ="report.date" />
<!-- 显示当前页码的函数用法 -->
< function name ="PageNumber" class ="org.jfree.report.function.PageFunction" deplevel ="1" />
<!-- 显示总页数的函数用法 -->
< function name ="PageTotal" class ="org.jfree.report.function.PageTotalFunction" deplevel ="1" />
<!-- 表达式,次表达式定义一个显示页码格式的用法 -->
< expression name ="pageXofY" class ="org.jfree.report.function.TextFormatExpression" >
< properties >
< property name ="pattern" > {0}/{1}页 </ property >
< property name ="field[0]" > PageNumber </ property >
< property name ="field[1]" > PageTotal </ property >
</ properties >
</ expression >
</ functions >
</ report >
其中,pageformat属性定义了打印纸张样式。如果横向打印,其值为“landscape”。
另一种方法我没有用过,以后了解了再补充。
四、输出
定义完JFreeReport对象,就可以进行输出了。下面介绍几种输出方法。
1、通过预览窗口对象输出
该方式只能在Application环境中使用。通过预览窗口,用户可以自行选择打印、排版或生成各种格式的文件,这也是我们在Application中常用的方式。代码示例如下:
PreviewDialog preview
=
null
;
//
预览窗口对象
try ... {
// 将生成的报表放到预览窗口中
preview = new PreviewDialog(report);
} catch (ReportProcessingException e) ... {
e.printStackTrace();
}
if (preview != null ) ... {
preview.pack();
preview.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// 设置报表起始点及长宽
preview.setLocation(new Point(0, 0));
Dimension screen = getToolkit().getScreenSize();
int width = (int) (screen.getWidth() - 2 * preview.getLocation().x);
int height = (int) (screen.getHeight());
preview.setSize(new Dimension(width, height));
// 显示报表预览窗口
preview.setVisible(true);
preview.requestFocus();
// preview.addWindowListener(new CloseHandler());
}
try ... {
// 将生成的报表放到预览窗口中
preview = new PreviewDialog(report);
} catch (ReportProcessingException e) ... {
e.printStackTrace();
}
if (preview != null ) ... {
preview.pack();
preview.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
// 设置报表起始点及长宽
preview.setLocation(new Point(0, 0));
Dimension screen = getToolkit().getScreenSize();
int width = (int) (screen.getWidth() - 2 * preview.getLocation().x);
int height = (int) (screen.getHeight());
preview.setSize(new Dimension(width, height));
// 显示报表预览窗口
preview.setVisible(true);
preview.requestFocus();
// preview.addWindowListener(new CloseHandler());
}
2、输出HTML文本。
这种方法可以将报表输出为HTML语言形成的文本,这种方式适用于在浏览器中显示报表内容。示例代码如下:
ByteArrayOutputStream bo
=
null
;
StreamHtmlFilesystem filesystem = null ;
try ... {
// 生成Html
bo = new ByteArrayOutputStream();
final HtmlProcessor processor = new HtmlProcessor(report);
processor.setGenerateBodyFragment(true);
processor.setEncoding ("UTF-8");
filesystem = new StreamHtmlFilesystem(bo);
processor.setFilesystem(filesystem);
processor.processReport();
String htmlCode = new String(bo.toByteArray(), "UTF-8");
bo.close();
bo = null;
filesystem.close();
filesystem = null;
} catch (FileNotFoundException e) ... {
e.printStackTrace();
} catch (SecurityException e) ... {
e.printStackTrace();
} catch (ReportProcessingException e) ... {
e.printStackTrace();
} catch (IOException e) ... {
e.printStackTrace();
}
StreamHtmlFilesystem filesystem = null ;
try ... {
// 生成Html
bo = new ByteArrayOutputStream();
final HtmlProcessor processor = new HtmlProcessor(report);
processor.setGenerateBodyFragment(true);
processor.setEncoding ("UTF-8");
filesystem = new StreamHtmlFilesystem(bo);
processor.setFilesystem(filesystem);
processor.processReport();
String htmlCode = new String(bo.toByteArray(), "UTF-8");
bo.close();
bo = null;
filesystem.close();
filesystem = null;
} catch (FileNotFoundException e) ... {
e.printStackTrace();
} catch (SecurityException e) ... {
e.printStackTrace();
} catch (ReportProcessingException e) ... {
e.printStackTrace();
} catch (IOException e) ... {
e.printStackTrace();
}
3、输出PDF文件
PDF的输出方式跟HTML的差不多,但有一点,JFreeReport本身无法输出中文字符,如果想要输出中文,我没有找到更好的方法,所以更改了JFreeReport包中org.jfree.report.modules.output.support.itext.BaseFontSupport类的源码,将
final BaseFont f = BaseFont.createFont(BaseFont.HELVETICA, stringEncoding, embedded,
false, null, null)中的BaseFont.HELVETICA改为“STSong-Light”,另外需要到
www.lowagie.com/iText网站下载iText.jar包以支持STSong-Light字体编码,这样,就可以输出中文了。示例代码如下所示:
这里注意,必须将target的字体编码设为“
UniGB-UCS2-H”而且使用Java1.5进行编译
PDFOutputTarget target
=
null
;
try ... {
//生成pdf
FileOutputStream fos = new FileOutputStream("PDF.pdf");
target = new PDFOutputTarget(fos);
target.configure(report.getReportConfiguration());
target.setFontEncoding("UniGB-UCS2-H");
target.open();
final PageableReportProcessor proc = new PageableReportProcessor(report);
proc.setOutputTarget(target);
proc.processReport();
target.close();
target = null;
} catch (FileNotFoundException e) ... {
e.printStackTrace();
} catch (SecurityException e) ... {
e.printStackTrace();
} catch (OutputTargetException e) ... {
e.printStackTrace();
} catch (ReportProcessingException e) ... {
e.printStackTrace();
}
try ... {
//生成pdf
FileOutputStream fos = new FileOutputStream("PDF.pdf");
target = new PDFOutputTarget(fos);
target.configure(report.getReportConfiguration());
target.setFontEncoding("UniGB-UCS2-H");
target.open();
final PageableReportProcessor proc = new PageableReportProcessor(report);
proc.setOutputTarget(target);
proc.processReport();
target.close();
target = null;
} catch (FileNotFoundException e) ... {
e.printStackTrace();
} catch (SecurityException e) ... {
e.printStackTrace();
} catch (OutputTargetException e) ... {
e.printStackTrace();
} catch (ReportProcessingException e) ... {
e.printStackTrace();
}
以上就是我对JFreeReport组件的总结,写的不好希望对大家有所