`
jimmy.shine
  • 浏览: 389276 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JasperReport报表设计总结(一)(已完毕)

阅读更多

共三篇,下接:http://jimmy-shine.iteye.com/blog/123595

为了开发报表,已经拜读了一大堆的资料,其中大部分是重复的。可以看得出,国人还是比较热衷于copy&paste的工作。所以找了一大堆的资料都是相同的,或者可以用一个词来形容,换汤不换药的。
有必要对于jasper Report的学习进度进行一下总结,一来可以更新一下以前的资料中的一些旧得不能再旧的不再适用的东西,二来让后来者可以轻松的上手。
首先,jasperReport是一个以java实现的报表工具,(好像是句废话)。可以实现多种格式的报表。
再我们先理解一下jasperReport的实现过程。笔者不再画图,网上到处都是。
1)定制报表格式。
  有二种方式,一种就是写jrxml文件,其实就是xml文件,只不过是后缀名不一样罢了。另一种方式更直接,就是生成一个JasperDesign类的实例,在japsperDesign中自己定义模板。jrxml文件也是通过一个JRXmlLoad加载过来,转成JasperDesign类的实例。也就是说写jrxml文件还需要进行解析,加载。现实中我们使用的报表一般格式比较固定,因而可以通过先使用iReport工具生成模板,再加载解析的方式。这种方式简单,而且可见性强。
2)填充数据。
  在最新版(2007.4.30发布)的jasperReports1.3.3中,支持了很多的格式,包括了对于Hibernate的支持。填充数据对于我们经常使用的来说,一般是二种方式,一种方式是通过JDBC连接提供数据源,一种就是通过javaBean的集合提供数据源。当然还有web Service的xml文件提供的。我的建议是,如果你的程序中的统计直接使用Jdbc就可以完成,那么就使用jdbc数据源的方法,反之,使用javaBean的集合是不错的选择,因为这样不会在意你的数据的来源,你也可以任意处理,比如说,要通过权限检查的数据才在报表中生成的话,就可以过滤到不符合权限的数据。
3)显示或打印。
  显示,即将JasperReport生成的文件直接显示出来,打印所使用的方式其实就是生成文件,然后调用打印来对文件进行打印。
看起来是不是很简单,对,确实很简单。
笔者主要从事基于B/S模式的开发,相信大部分人的使用也是基于web进行使用。故笔者对于基于web的开发进行详细讲述。

1、工程环境配置。
将以下包加入WEB-INF/lib中。
commons-beanutils-1.7.jar;commons-collections-2.1.jar;commons-digester-1.7.jar;commons-logging-1.0.2.jar;commons-logging-api-1.0.2.jar;itext-1.3.1.jar;jasperreports-1.3.3.jar;jdt-compiler-3.1.1.jar;jxl-2.6.jar;png-encoder-1.5.jar;poi-2.0-final-20040126.jar
   以上包是jasperReport必须。
2、iReport的安装
   这个很简单,直接下一步就可以了。
3、使用iReport生成 .jasper文件
.jasper是经过编译的japserReport模板,即.jrxml编译后的。
对于iReport的使用网络上已经有了详细的中文的文档,具体可以下载附件查看。使用.jasper文件可以避免在系统中再进行编译,增加系统的压力。
4、数据填充
数据填充是相对于比较重要的一步,数据填充的目的是为了将数据填充进去,生成一个JapserPrint对象。笔者在之前已经阐述过,现在主要是基于关系型数据库(比较简单的,没有权限控制的),以及基于JavaBean Collection进行数据填充。进行数据填充的基本就是一定要实现JRDataSource,JRDataSource定义了二个方法,一个是指针移动的方法next(),另一个是取值的getFieldValue()方法,用来取值填充。
对于关系型数据库,即直接利用数据库的表来生成报表的,只需要传入一个Java Connection即可。JasperReport已经有了个默认的实现的JRDataSource的接口了。对于Java Conncetion的获得,笔者建议使用工厂方法或者使用Spring方式来获得。可以参照笔者写的如下:

java 代码
 
  1. /**  
  2.  * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.  
  3.  * @author Jimmy.Shine 2007-5-11  
  4.  */  
  5. package cn.com.reachway.framework.report;   
  6.   
  7. import java.sql.Connection;   
  8. import java.sql.DriverManager;   
  9.   
  10. import cn.com.reachway.framework.exception.JasperReportException;   
  11.   
  12. /**  
  13.  * Used for get a JDBC connection for Jasper Report  
  14.  */  
  15. public class JDBCConnection {   
  16.  /**  
  17.   * Which Jdbc driver were used. Like: "net.sourceforge.jtds.jdbc.Driver"  
  18.   */  
  19.  private String jdbcDriver;   
  20.  /**  
  21.   * The jdbc url,define which database server,which db. Like:  
  22.   * "jdbc:jtds:sqlserver://192.168.1.50:1433;DatabaseName=JAVA5;SelectMethod=Cursor"  
  23.   */  
  24.  private String jdbcUrl;   
  25.   
  26.  private String dbUser;   
  27.   
  28.  private String dbPassword;   
  29.   
  30.  public String getDbPassword() {   
  31.   return dbPassword;   
  32.  }   
  33.   
  34.  public void setDbPassword(String dbPassword) {   
  35.   this.dbPassword = dbPassword;   
  36.  }   
  37.   
  38.  public String getDbUser() {   
  39.   return dbUser;   
  40.  }   
  41.   
  42.  public void setDbUser(String dbUser) {   
  43.   this.dbUser = dbUser;   
  44.  }   
  45.   
  46.  public String getJdbcDriver() {   
  47.   return jdbcDriver;   
  48.  }   
  49.   
  50.  public void setJdbcDriver(String jdbcDriver) {   
  51.   this.jdbcDriver = jdbcDriver;   
  52.  }   
  53.   
  54.  public String getJdbcUrl() {   
  55.   return jdbcUrl;   
  56.  }   
  57.   
  58.  public void setJdbcUrl(String jdbcUrl) {   
  59.   this.jdbcUrl = jdbcUrl;   
  60.  }   
  61.   
  62.  public JDBCConnection() {   
  63.   super();   
  64.  }   
  65.  /**  
  66.   * Get the Connection   
  67.   * @return connection  
  68.   * @throws JasperReportException  
  69.   */  
  70.  public Connection getConnection() throws JasperReportException {   
  71.   Connection con;   
  72.   try {   
  73.    check();   
  74.    Class.forName(this.jdbcDriver);   
  75.    con = DriverManager.getConnection(this.jdbcUrl, this.dbUser, this.dbPassword);   
  76.    return con;   
  77.   } catch (Exception e) {   
  78.    e.printStackTrace();   
  79.    throw new JasperReportException("Get JDBC Connection Error");   
  80.   }   
  81.  }   
  82.     
  83.  /**  
  84.   * Check the Configure  
  85.   * @throws JasperReportException  
  86.   */  
  87.  private void check() throws JasperReportException {   
  88.   if (this.jdbcDriver == null || this.jdbcDriver.equals("") || this.jdbcUrl == null || this.jdbcUrl.equals("")   
  89.     || this.dbUser == null || this.dbUser.equals("") || this.dbPassword == null) {   
  90.    throw new JasperReportException("Jdbc Configure error!");   
  91.   }   
  92.  }   
  93.   
  94. }   
  95.   


java 代码
 
  1. /**  
  2.  * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.  
  3.  * @author Jimmy.Shine 2007-5-14  
  4.  */  
  5. package cn.com.reachway.framework.report.dataSource;   
  6.   
  7. import net.sf.jasperreports.engine.JRDataSource;   
  8. import net.sf.jasperreports.engine.JRException;   
  9. import net.sf.jasperreports.engine.JRField;   
  10.   
  11. /**  
  12.  * 报表的dataSource的基类,所有利用DataSource产生报表的继承此类  
  13.  */  
  14. public abstract class ReportDataSource implements JRDataSource {   
  15.   
  16.  /**  
  17.   * 取值  
  18.   */  
  19.  public abstract Object getFieldValue(JRField jrField) throws JRException;   
  20.   
  21.  /**  
  22.   * 指针移动  
  23.   */  
  24.  public abstract boolean next() throws JRException;   
  25.   
  26. }   
  27.   
  这样可以共用配置文件中的jdbc连接的相关参数。
对于其它的数据源,JavaBean Collection,笔者采用了一个抽象类,使用抽象类的目的,是为了使开发者尽可能不用直接接触jasperReport(此为笔者自己的方式,笔者是PM,为了考虑底下的人的开发)。以下为抽象类以及笔者提供的一个sample:
 
  1. /**  
  2.  * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.  
  3.  * @author Jimmy.Shine 2007-5-14  
  4.  */  
  5. package cn.com.reachway.framework.report.dataSource;   
  6.   
  7. import java.util.ArrayList;   
  8. import java.util.List;   
  9.   
  10. import net.sf.jasperreports.engine.JRException;   
  11. import net.sf.jasperreports.engine.JRField;   
  12.   
  13. /**  
  14.  * 利用JavaBean Collection生成ReportDataSource的例子  
  15.  */  
  16. public class ReportDataSourceSample extends ReportDataSource {   
  17.   
  18.  private List docs = new ArrayList();   
  19.   
  20.  private int index = -1;   
  21.   
  22.  public ReportDataSourceSample() {   
  23.   for (int i = 0; i < 10; i++) {   
  24.    Document doc = new Document("ViewTimes is:" + i, i);   
  25.    this.docs.add(doc);   
  26.   }   
  27.  }   
  28.   
  29.  // 内部类,作为demo时使用   
  30.  private class Document {   
  31.   private String name;   
  32.   
  33.   private int viewTimes;   
  34.   
  35.   public String getName() {   
  36.    return name;   
  37.   }   
  38.   
  39.   public void setName(String name) {   
  40.    this.name = name;   
  41.   }   
  42.   
  43.   public int getViewTimes() {   
  44.    return viewTimes;   
  45.   }   
  46.   
  47.   public void setViewTimes(int viewTimes) {   
  48.    this.viewTimes = viewTimes;   
  49.   }   
  50.   
  51.   public Document() {   
  52.   }   
  53.   
  54.   public Document(String name, int viewTimes) {   
  55.    this.name = name;   
  56.    this.viewTimes = viewTimes;   
  57.   }   
  58.  }   
  59.   
  60.  public List getDocs() {   
  61.   return docs;   
  62.  }   
  63.   
  64.  public void setDocs(List docs) {   
  65.   this.docs = docs;   
  66.  }   
  67.   
  68.  @Override  
  69.  public Object getFieldValue(JRField jrField) throws JRException {   
  70.   
  71.   String fieldName = jrField.getName();   
  72.   Document doc = this.docs.get(index);   
  73.   if ("name".equals(fieldName)) {   
  74.    return doc.getName();   
  75.   }   
  76.   if ("viewTimes".equals(fieldName)) {   
  77.    return doc.getViewTimes();   
  78.   }   
  79.   return null;   
  80.  }   
  81.   
  82.  @Override  
  83.  public boolean next() throws JRException {   
  84.   index++;   
  85.   return (index < this.docs.size());   
  86.  }   
  87. }   
  88.   
java 代码

以上的例子应当很清楚的写明了如何生成数据源。
对于数据源的填充,笔者使用了二个类,分别用来对应使用Connction及JavaBean Collection进行填充。

java 代码
 
  1. /**  
  2.  * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.  
  3.  * @author Jimmy.Shine 2007-5-12  
  4.  */  
  5. package cn.com.reachway.framework.report.jasperPrint;   
  6.   
  7. import java.io.File;   
  8. import java.sql.Connection;   
  9. import java.util.Map;   
  10.   
  11. import net.sf.jasperreports.engine.JRException;   
  12. import net.sf.jasperreports.engine.JasperFillManager;   
  13. import net.sf.jasperreports.engine.JasperPrint;   
  14. import net.sf.jasperreports.engine.JasperReport;   
  15. import net.sf.jasperreports.engine.util.JRLoader;   
  16. import cn.com.reachway.framework.exception.JasperReportException;   
  17.   
  18. /**  
  19.  * 使用报表模板及数据等来生成JapserPrint  
  20.  */  
  21. public class JasperPrintWithConnection {   
  22.  /** 传入的参数 */  
  23.  private Map params;   
  24.  /** 模板文件的地址 */  
  25.  private String reportFilePath;   
  26.  /** JDBC connection */  
  27.  private Connection con;   
  28.   
  29.  public Connection getCon() {   
  30.   return con;   
  31.  }   
  32.   
  33.  public void setCon(Connection con) {   
  34.   this.con = con;   
  35.  }   
  36.   
  37.  public Map getParams() {   
  38.   return params;   
  39.  }   
  40.   
  41.  public void setParams(Map params) {   
  42.   this.params = params;   
  43.  }   
  44.   
  45.  public String getReportFilePath() {   
  46.   return reportFilePath;   
  47.  }   
  48.   
  49.  public void setReportFilePath(String reportFilePath) throws JasperReportException {   
  50.   if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))   
  51.    throw new JasperReportException("您传入的模板文件格式不对,请传入以.jasper为后缀的文件!");   
  52.   this.reportFilePath = reportFilePath;   
  53.  }   
  54.   
  55.  public JasperPrintWithConnection() {   
  56.   super();   
  57.  }   
  58.   
  59.  public JasperPrintWithConnection(String reportFilePath, Map params, Connection con) throws JasperReportException {   
  60.   if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))   
  61.    throw new JasperReportException("模板文件格式不对,请传入以.jasper为后缀的文件!");   
  62.   if (con == null)   
  63.    throw new JasperReportException("Conncetion不应当为null!");   
  64.   this.setReportFilePath(reportFilePath);   
  65.   this.setParams(params);   
  66.   this.setCon(con);   
  67.  }   
  68.     
  69.  /**  
  70.   * 取得JasperPrint  
  71.   * @return  
  72.   * @throws JasperReportException  
  73.   */  
  74.  public JasperPrint getJasperPrint() throws JasperReportException {   
  75.   File reportFile = new File(this.reportFilePath);   
  76.   if (!reportFile.exists())   
  77.    throw new JasperReportException("传入的模板文件不存在!");   
  78.   
  79.   try {   
  80.    // Load编译好的模板   
  81.    JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());   
  82.    // 进行数据填充   
  83.    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, this.params, this.con);   
  84.    return jasperPrint;   
  85.   
  86.   } catch (JRException jre) {   
  87.    jre.printStackTrace();   
  88.    throw new JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!");   
  89.   }   
  90.   
  91.  }   
  92. }   
  93.   
 
  1. /**  
  2.  * @copyRight Beijing Tsing-Tech Reachway Software Co.,Ltd.  
  3.  * @author Jimmy.Shine 2007-5-14  
  4.  */  
  5. package cn.com.reachway.framework.report.jasperPrint;   
  6.   
  7. import java.io.File;   
  8. import java.util.Map;   
  9.   
  10. import net.sf.jasperreports.engine.JRDataSource;   
  11. import net.sf.jasperreports.engine.JRException;   
  12. import net.sf.jasperreports.engine.JasperFillManager;   
  13. import net.sf.jasperreports.engine.JasperPrint;   
  14. import net.sf.jasperreports.engine.JasperReport;   
  15. import net.sf.jasperreports.engine.util.JRLoader;   
  16. import cn.com.reachway.framework.exception.JasperReportException;   
  17.   
  18. /**  
  19.  *   
  20.  */  
  21. public class JasperPrintWithDataSource {   
  22.  /** 传入的参数 */  
  23.  private Map params;   
  24.  /** 模板文件的地址 */  
  25.  private String reportFilePath;   
  26.  /** dataSrouce */  
  27.  private JRDataSource dataSource;   
  28.   
  29.  public JRDataSource getDataSource() {   
  30.   return dataSource;   
  31.  }   
  32.   
  33.  public void setDataSource(JRDataSource dataSource) {   
  34.   this.dataSource = dataSource;   
  35.  }   
  36.   
  37.  public Map getParams() {   
  38.   return params;   
  39.  }   
  40.   
  41.  public void setParams(Map params) {   
  42.   this.params = params;   
  43.  }   
  44.   
  45.  public String getReportFilePath() {   
  46.   return reportFilePath;   
  47.  }   
  48.   
  49.  public void setReportFilePath(String reportFilePath) throws JasperReportException {   
  50.   if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))   
  51.    throw new JasperReportException("您传入的模板文件格式不对,请传入以.jasper为后缀的文件!");   
  52.   this.reportFilePath = reportFilePath;   
  53.  }   
  54.   
  55.  public JasperPrintWithDataSource() {   
  56.   super();   
  57.  }   
  58.   
  59.  public JasperPrintWithDataSource(String reportFilePath, Map params, JRDataSource dataSource)   
  60.    throws JasperReportException {   
  61.   if (reportFilePath == null || !reportFilePath.endsWith(".jasper"))   
  62.    throw new JasperReportException("模板文件格式不对,请传入以.jasper为后缀的文件!");   
  63.   if (dataSource == null)   
  64.    throw new JasperReportException("DataSource不应当为null!");   
  65.   this.setReportFilePath(reportFilePath);   
  66.   this.setParams(params);   
  67.   this.setDataSource(dataSource);   
  68.  }   
  69.  /**  
  70.   * 取得JasperPrint  
  71.   * @return  
  72.   * @throws JasperReportException  
  73.   */  
  74.  public JasperPrint getJasperPrint() throws JasperReportException {   
  75.   File reportFile = new File(this.reportFilePath);   
  76.   if (!reportFile.exists())   
  77.    throw new JasperReportException("传入的模板文件不存在!");   
  78.   
  79.   try {   
  80.    // Load编译好的模板   
  81.    JasperReport jasperReport = (JasperReport) JRLoader.loadObject(reportFile.getPath());   
  82.    // 进行数据填充   
  83.    JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, this.params, this.dataSource);   
  84.    return jasperPrint;   
  85.   
  86.   } catch (JRException jre) {   
  87.    jre.printStackTrace();   
  88.    throw new JasperReportException("在进行数据填充时发生了错误中,请检查是否是数据库连接错误或者是用来填充的参数map有误!");   
  89.   }   
  90.   
  91.  }   
  92. }   
  93.   
java 代码

其中使用的JasperReportException为笔者定义的异常,用来统一处理报表异常。

5、报表产生
报表产生是程序中最终可见的一部分,在jasperReport的demo中,大部分中使用了jasperReport的net.sf.jasperreports.j2ee.servlets.*中的类来生成。其实这也算是开源的产品的一个问题,其实jasperReport提供的report的工具,只能算是demo级别的,不能算是产品级别的。相信很多的朋友在使用的时候就碰上无法生成的问题。笔者在此基础上封装了一下。
具体参见以下:

分享到:
评论
46 楼 iris_1992 2015-04-30  
2005年以前,国外开原报表完全碾压国产软件,但是现在国内软件,像帆软、FineBI,都比较牛掰了,设计模式和数据处理方面优于开源报表,真犯不着再用Jasperreport了,
45 楼 zwj1533 2013-11-09  
下载的附件服务解压!
44 楼 perfect101 2013-07-22  
楼主,自定义报表有什么好办法吗? 你给的都是基础入门的, 能否搞点高级的, 比如Web打印方面的?
43 楼 yuyangsho7925 2008-03-26  
太烂了

没深度 


实效性也差  

总是list 到 jasper的数据传递断掉

要写就详细点
42 楼 jimmy.shine 2007-10-15  
Re Isabel19851220  :
附件是iReport的使用文档。do
41 楼 Isabel19851220 2007-10-15  
写得真好啊...可是我下不到附件
40 楼 alven_lee 2007-09-14  
我现在又有一个问题了。想了很长时间,都解决不了。
我要一次打印很多报表,最容易的方法,就是分别打印。每个报表都填充成一个jasperPrint,然后打印。这样很麻烦,因为要给打印机传很多次明令。如果能把我要一口气打印出的报表,合成一个jasperPrint的话,就只用给打印机传一次命令就可以解决了。
现在就是不知道怎么才能把这些jasperPrint数据,合成一个jasperPrint。
39 楼 1948asd 2007-09-11  
我现在要用JasperReport+iReport对一些输出的内容进行分类,不知道老大有什么高招呀,我也前没用过的,谢谢!111
38 楼 alven_lee 2007-09-06  
哥,我又有问题了。
1.我怎么才能提高报表的速度?
现在,我用JasperFillManager.fillReport填充报表的时候总是很慢。要等上大概5-8秒钟。无法容忍。不知道有没有什么方法可以让填充报表的速度提高一些?1-2秒钟内完成。(已经解决)
2.我想把报表保存成图片.jpg不知道该怎么做。(已经解决)
37 楼 alven_lee 2007-09-05  
我现在的方法是,把整个sql文作为一个变量$P!{sql},通过程序hashmap("sql","select...")传过去。这样可以得到结果。请问,还有更轻巧的方法呢?这个方法总觉得有点愣:)
36 楼 alven_lee 2007-09-05  
又有了一个初级问题。
我在设计好了报表,但是没有在设计器中写sql语句,我想把sql语句在程序中生成,然后传给报表,然后打印。
JasperDesign jasperDesign = new JasperDesign();
JRDesignQuery query = new JRDesignQuery();
query.setText("SELECT DISTINCT a1 as a, b1 as b from table1 where a1 = 'xxx'");
jasperDesign.setQuery(query);
我是这样写的,但是御览报表后发现,报表好像并没有执行sql文。运行的结果和没有sql文的结果一样。
请指点我一下。
35 楼 jimmy.shine 2007-09-02  
To alven_lee:

Good luck!
34 楼 alven_lee 2007-08-31  
谢谢哥,这么关心我的事。
首先说,我不会用iReport预览:)
不过,还是很感谢老大们的帮助。
自己问题自己解决。已经解决了一个问题。但是,jar打包后,运行不能显示的问题还是没有办法解决。我要继续努力。方法我已经想到了。正在努力尝试。
33 楼 jimmy.shine 2007-08-31  
To alven_lee:
why do not you used iReport view your report?
because of jasperviewer is used GUI to view it,so if you close it,the event will told the system exit the program!
I suggest you use iReport to design and view your report,it is easy to design and easy to view,also it is easy to change your design!

ea
32 楼 alven_lee 2007-08-30  
老大,我刚开始用这个做报表。我现在有一个问题。我的程序,在eclipse环境下,点run运行程序,可以用JasperViewer预览报表。报表的路径是c:\report。
可是,我把程序用fatjar打包成jar后,报表就不能预览了。这是怎么回事?能给与解答么?谢谢了。

还有一个问题,我在eclipse环境下,运行程序。预览报表。可是,关闭预览窗体JasperViewer后,为什么我的程序也会自动关闭???
31 楼 fushaoping2003 2007-08-07  
期待下文更加详细的讲解
30 楼 snowpiaojuan 2007-07-28  
dennis_zane 写道
这帖子也就是整理资料,设计总结谈不上,只是介绍了一些最基本的东西。也没有跟ireport结合起来谈,以及如何与hibernate整合等等。有一本专门的电子书讲jasperreport的,有兴趣的话我可以发上来。

怎么还没发上来呀?
我现在要用hibernate做一个柱形的报表,都不知道要怎么入手呀!
请各位大哥大姐们多多帮助呀!
29 楼 tangyuanjian 2007-07-26  
这种资料比较多,自己去找嘛!
28 楼 ganfei1983 2007-07-26  
强烈建议出一个例子
1:如何形成.jsper
2:如何jsp 报表输出
27 楼 wdl123 2007-07-26  
楼主,能不能把整个例子上传一下呀,省得我们在去调试了,谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics