在公司的项目中用JapserReport也做了不少报表了,现在也做个记录吧,很多东西都从网上而来,总结一下而已。
注意:本文由 bangke 所撰写 版权归属于bangke  转载请注明出处
1.下载不说了,需要JapserReport和iReport,要pdf支持中文的话需要itextasian.jar(google!)
2.资源:The JasperReports Ultimate Guide.pdf(google!)
 http://jasperreports.sourceforge.net/
 http://plateau.sicool.com (good!)
 源代码包下面的examples
3.先集中说一下中文支持问题:
   1)iReport中文显示:去掉iReport lib目录下的tinylaf.jar,会丑点儿:)
   2)要在pdf中显示中文:如下图设置字体或定义字体
      注意:在iReport中新建一个TextField会自动把pdf字体设为CP1252,需要修改,否则pdf输出会报错说找不到字体

4.明确需求:
  JasperReport(0.5.2)目前支持Tabular形式的报表,分组,子报表
  不支持cross report(交叉表)和单元格合并。
5.JasperReport简述:
  JasperReport总的来说采用报表样式和数据相分离的设计,在报表杨始中定义好和数据源的映射关系,然后在实际应用的时候再用数据源填充样式得到最终的报表输出。
  1)数据源:
  在JasperReport中可以定义多种数据源,都实现了dori.jasper.engine.JRDataSource接口。
  接口有两个方法:
  public boolean next() throws JRException;
  public Object getFieldValue(JRField jrField) throws JRException;
  各个数据源简介:
  dori.jasper.engine.JRResultSetDataSource封装了一个java.sql.ResultSet
  dori.jasper.engine.JREmptyDataSource在没有实际数据源的数据的时候可以使用它
  dori.jasper.engine.data.JRTableModelDataSource封装了javax.swing.table.TableModel
  dori.jasper.engine.data.JRBeanArrayDataSource封装了an array of JavaBeans and uses reflection to retrieve report field values.
  dori.jasper.engine.data.JRBeanCollectionDataSource封装了java.util.Collection of JavaBeans,和上面的JRBeanArrayDataSource用法相像(强烈推荐,我一直都用它)
  简而言之就是JRDataSource中封装了一个循环的集合,在报表中一后会通过(属性名)反射来取得每个数据项的内容
  为什么选择JRBeanCollectionDataSource后面会解释。
  构造数据源,采用数据工厂(针对JRBeanCollectionDataSource来说),工厂方法:
  

public static JRDataSource getJRDataSource(String name,HttpServletRequest request) throws Exception
{
    InterCustomerDS ds = null;//InterCustomerDS是一个interface!

    try 
{
      ds = (InterCustomerDS) Class.forName(name).
          newInstance();
      ds.createDS(request);//这里需要request中的一些parameter来生成数据源
      return new JRBeanCollectionDataSource(ds.getBeanCollection());
    }

    catch (ClassNotFoundException ex) 
{
      throw new Exception(ex.getMessage());
    }

    catch (IllegalAccessException ex) 
{
      throw new Exception(ex.getMessage());
    }

    catch (InstantiationException ex) 
{
      throw new Exception(ex.getMessage());
    }

  }


 
  一个简单的数据源需要两个类,一个POJO,一个InterCustomerDS的实现
  POJO:

public class TestVO 
{
  private String portfolio;
  private String year;
  private String period;


  public CCSPVO() 
{
  }

  public String getPeriod() 
{
    return period;
  }

  public String getPortfolio() 
{
    return portfolio;
  }

  public String getYear() 
{
    return year;
  }

  public void setPeriod(String period) 
{
    this.period = period;
  }

  public void setPortfolio(String portfolio) 
{
    this.portfolio = portfolio;
  }

  public void setYear(String year) 
{
    this.year = year;
  }
 }
 


 
 TestDateSource:

public class TestDataSource implements InterCustomerDS 
{

  private Collection co;

  public CCSPDataSource() 
{
  }


  public void createDS(HttpServletRequest request) throws Exception
{
    co=new ArrayList();

    /**//*
    这之中做数据库查询,然后使用查询出来的结果生成TestVO,再把TestVO放入co中
    */
  }
  

  public Object[] getBeanArray() 
{
    return co.toArray();
  }


  public Collection getBeanCollection() 
{
    return co;
  }
}


 
 
  2)报表样式:
  JasperReport将一张报表分为了几个Sections,又叫bands(按照一张报表的内容来划分的):title, pageHeader, columnHeader, detail, columnFooter, pageFooter, summary, (如果有group的话,还有groupHeader和groupFooter)。用iReport画报表的工作简单得说就是把特定的内容放在特定的section中。
  title和summary在整个报表中只显示一次(不过有个选项可以设置为每页显示一次)
  column和page是每页显示一次
  detail才是最关键的地方,循环显示数据源的内容,直到全部显示完为止。
  在样式中的3个变量:fields,variables,parameters
  fields:从数据源传入样式的属性名(日后通过反射取值使用,所以fields名一定要和数据源中的属性名一样!比如使用JRBeanCollectionDataSource的话,fields名就要和javabean中对应的属性名一样!)
  parameters:应用程序向报表传入得非数据源形式的数据。
  variables:对fields,parameters,也包括所有java对象进行合法运算后得到的变量。(通常用做对数据源某个属性的统计,比如求和什么等等)
  
  具体使用iReport设计报表样式不说了,网上很多资料.
  需要注意的是
  在报表样式中可以输入表达式,也就是合法的java scriptlet
  在JasperReport中存在的都是java object所以某个textfield和对应数据的object类型一定要相同。
  parameters除了iReport默认的那些类型外其实可以使用任何java类型的。
  每个band在print when expression中输入返回Boolean的表达式可以控制是否显示
  可以使用group来添加bands,group其实并不需要和某个field对应,也就是说group没有expression是可以的,只不过又expression的话会按照expression(通常的fields)来动态分组(这里又需要注意,效果上和sql的group by相当,但并不需要在查询数据源的sql中写group by, JasperReport回自己帮你做好的)
  在输出数据的时候可以套用pattern,也就是正则表达式,比如输出Double的时候使用 #,##0.00 表示金额:1,234.00, #0.00表示1234.00
  
  3)输出报表
  采用一个Helper类,分别使用不同的方法得到填充了数据源的JasperPrint比如:
  

public JasperPrint getPrinterbyBeanCollection(File reportFile,Map reportParameters,JRBeanCollectionDataSource bean) throws Exception
{

   try 
{

     if(!reportFile.exists())
{
       throw new Exception("the jasper file is not exist");
     }
     JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.
         getPath());
     JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
         reportParameters, bean);
     return jasperPrint;
   }

   catch (JRException ex) 
{
     logger.error("report",ex);
     throw new Exception(ex.getMessage());
   }
 }

 
  
  然后使用JasperPrint得到报表输出,比如html输出:
  

public void htmlExport(JasperPrint print,Map imagesMap,Object out) throws Exception
{

    try
{
      JRHtmlExporter exporter = new JRHtmlExporter();
      exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
      exporter.setParameter(JRExporterParameter.OUTPUT_WRITER, out);
      exporter.setParameter(JRHtmlExporterParameter.BETWEEN_PAGES_HTML, "");
      exporter.setParameter(JRHtmlExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
      exporter.setParameter(JRHtmlExporterParameter.IMAGES_MAP, imagesMap);
      exporter.setParameter(JRHtmlExporterParameter.IMAGES_URI, "image?image=");
      exporter.exportReport();

    }catch(Exception ex)
{
      logger.error("report",ex);
      throw new Exception(ex.getMessage());
    }
  }

 
    
  
 
6.普通报表开发:
  开发3步骤
  1.定义POJO,写DataSource查询数据库生成一个Collection of POJOs
  2.使用iReport设计报表,定义和POJO属性一样的fields等
  3.用户输入web页面及输出的Servlet开发
7.SubReport
  其实和普通报表开发一样,只不过多写几个报表样式,POJO和DateSource。
  关键是在masterreport中对子报表的subreport选项卡中的Connection/DataSource Expression要选DataSource,然后填入你子报表的DataSource,当然先要把子报表的DataSource作为parameter传入masterreport。(这里JasperReport的example全是Connection的example,害的我想了半天,呵呵,实际上在J2EE这个要求解藕程度很高的范围内将sql写在报表样式中是不适合使用的)
8.最后说说为什么使用JRBeanCollectionDataSource,原因上面其实很多地方都说明了
  1。使用POJO和Collection简单,规范
  2。充分的解除报表样式和数据库之间的耦合,假如我要查询的sql变了,我只需要修改sql和结果集存入POJO的对应处,报表样式是不用修改的。
9.喝咖啡,休息,(其实我更喜欢喝雪碧,呵呵)!                                                                         
                                                                               本文由 bangke 所撰写 版权归属于bangke  转载请注明出处
	posted on 2005-04-01 17:14 
蚌壳 阅读(6849) 
评论(11)  编辑  收藏  所属分类: 
Java In Work