JFreeReport使用方法总结

一、JFreeReport简介
JFreeReport是由JFree组织开发的一个基于java的报表组件。利用JFreeReport组件可以完成大多数样式的报表,并且能够将其输出为pdf、xls、cvs、html等不同格式的文件和打印,为程序开发人员解决报表问题提供了很大的方便。
现在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(00));
           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 >
其中,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(00));
           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();
       }
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();
       }

以上就是我对JFreeReport组件的总结,写的不好希望对大家有所

 

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值