最近学习了JasperReports,小结一下,并附上代码。
(一) 基本概念 如果没有接触过报表,刚开始往往摸不着头脑。做个比喻就简单了:如果说网络应用是把数据送到屏幕上,报表则一般是将数据送到文件。文件有多种格式,如 pdf, xml, html, xls 等等。不同的是,网络应用一般是用 html 来表现数据,而报表则用 xml 来表现。为了打印方便,报表当然也需要对数据进行定位和修饰。
JasperReports 是目前较流行的开源报表框架。它的做法是把报表分成了两部分:一是报表样板(template)的制作;一是对样板的数据填充和输出到指定媒介。本文讨论一下 JasperReports 2.0.4 的情况。
报表样板的制作,可利用 iReport 来完成。最简单的概念是定义一些变量(variable),参数(parameter)及字段(field);还可能要定义分组(group)。字段直接对应于填充数据的名称;变量常用来对报表数据依分组地不同进行求和,求平均值等的计算;而参数则用于填充数据是直接输入到报表。
报表样板是 xml 文件,JasperReports 的样板文件后缀是 "jrxml"。这个编辑好的样板文件经编译后,就变成了 Java 类了,其后缀是 "jasper"。为什么要编译呢?编译后成为 Java 类才能与其他类一起工作来完成报表。这就象是 xml Data Binding,不是吗?
好了,样板编译后,就考虑如何注入数据。JasperReports 提供多种选择。一种是在样板的制作时,就直接定义好 sql 语句,并定一好数据源(Data Source)。这样,填充程序只需提供一个 Connection 即可。例子在后。
但上述配置并不太好,就如同在 jsp 中直接访问数据库一样,不太好。本文觉得较好的方式是将数据封装在 JavaBean 中,并利用 JRBeanCollectionDataSource 来填充数据。例子在后。
这样,报表的源文件大概有样板文件(.jrxml),样板编译文件(.jasper)和数据注入文件(.java)三种。而样板编译文件是中间产物,一般可以缓存起来,不一定每次现编译。
(二)举例
假设数据库中有个表格“student”,其内容如下:
-
- test02=# select * from student;
- sid | name | age | dept
- -----+-----------+-----+------------------
- 6 | liang | 69 | cs
- 7 | zhen | 70 | cs
- 8 | zhao | 69 | cs
- 10 | zhong | 79 | cs
- 11 | michael | 7 | cs
- 12 | david | 9 | cs
- 13 | ben | 8 | cs
- 14 | roylin | 7 | cs
- 15 | dabin | 7 | cs
- 16 | nathon | 7 | management
- 17 | johnathon | 8 | management
- 1 | john | 30 | computer science
- 2 | jason | 7 | computer science
- 3 | tracey | 31 | computer science
- 4 | mary | 37 | computer science
- 5 | yang | 40 | education
- (16 rows)
报表的内容就是对各系学生的平均年龄进行报表,并输出到 pdf,xls 格式的文件。
1:样板文件有两个 “student_report_sql_pie.jrxml”及“student_report_pie.jrxml”。样板文件包含一个大饼图(pie chart -- 呵呵):利用 iReport 很容易设置其属性,插入该图后,点击鼠标右键,选择“Chart Properties”>“Chart Data”>“Details”>“Section Value”。其中“Key Expression”是指根据什么来分饼 -- $F{dept},“Value Expression”就是数值,多是从承担计算结果的变量来 -- $V{avg_age},“Lable Expression”只是饼图标签 -- $F{dept}。第一个样本直接包含了 sql query;第二个样本没有 sql query,但注入程序将报表的标题(title)作为参数(parameter)传入。
2:数据注入程序有两个,如下:
-
- package myreport;
-
- import java.io.ByteArrayOutputStream;
- import java.io.FileOutputStream;
- import java.util.HashMap;
- import java.util.List;
-
- import net.sf.jasperreports.engine.JRExporterParameter;
- import net.sf.jasperreports.engine.JasperCompileManager;
- import net.sf.jasperreports.engine.JasperExportManager;
- import net.sf.jasperreports.engine.JasperFillManager;
- import net.sf.jasperreports.engine.JasperPrint;
- import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
- import net.sf.jasperreports.engine.export.JRXlsExporter;
- import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
-
-
-
- public class MyReport {
-
- // test embedding an sql query in template and pass a database connection for it.
- public static void test01() {
-
- System.out.println("----- test01 started: passing connection for embedded sql query in template -----");
- try {
- String template_file = "src/myreport/template/student_report_sql_pie.jrxml";
- String report_file = "src/myreport/jasper/student_report_sql_pie.jasper";
- String dest_file = "src/myreport/exp/student_report_sql_pie.pdf";
-
- // 1. compile template to JasperReport
- JasperCompileManager.compileReportToFile(template_file, report_file);
- System.out.println(">>> template compiled to report file: " + report_file);
-
- // 2. fill the report with data
- JasperPrint print = JasperFillManager.fillReport(report_file, null, StudentReportDAO.getConnection());
- System.out.println(">>> report filled: " + print.toString());
-
- // 3. output filled report to file
- JasperExportManager.exportReportToPdfFile(print, dest_file);
- System.out.println(">>> pdf file exported: " + dest_file);
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
-
- // test using a data source to fill report.
- private static void test02() {
-
- System.out.println("----- test02 started: no sql query embedded in report template -----");
-
- try {
- // this set of report has no pie chart and aggregation functions
- // String template_file = "src/myreport/template/student_report.jrxml";
- // String report_file = "src/myreport/jasper/student_report.jasper";
- // String dest_file_pdf = "src/myreport/exp/student_report.pdf";
- // String dest_file_xls = "src/myreport/exp/student_report.xls";
-
- // this set of report has pie chart
- String template_file = "src/myreport/template/student_report_pie.jrxml";
- String report_file = "src/myreport/jasper/student_report_pie.jasper";
- String dest_file_pdf = "src/myreport/exp/student_report_pie.pdf";
- String dest_file_xls = "src/myreport/exp/student_report_pie.xls";
-
- // 1. compile template to report object
- JasperCompileManager.compileReportToFile(template_file, report_file);
- System.out.println(">>> template compiled to report file: " + report_file);
-
- // 2. fill the report with data to create print object
- List studentlist = new StudentReportDAO().getStudentList();
- JRBeanCollectionDataSource datasource = new JRBeanCollectionDataSource(studentlist);
-
- // pass the report title as a parameter "myTitle"
- HashMap params = new HashMap();
- params.put("myTitle", "My Student Average Age Report");
-
- JasperPrint print = JasperFillManager.fillReport(report_file, params, datasource);
- System.out.println(">>> report filled: " + print.toString());
-
- // 3. output filled report to file
- JasperExportManager.exportReportToPdfFile(print, dest_file_pdf);
- System.out.println(">>> pdf file exported: " + dest_file_pdf);
-
- // 4. ouput filled resprt to excel file
- exportExcel(print, dest_file_xls);
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void exportExcel(JasperPrint print, String filename) throws Exception {
- JRXlsExporter exp = new JRXlsExporter(); // excel exporter
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- try {
- exp.setParameter(JRExporterParameter.JASPER_PRINT, print);
- exp.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
- exp.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, Boolean.TRUE);
- exp.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.FALSE);
- exp.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);
- exp.exportReport(); // start exporting to the output stream.
-
- new FileOutputStream(filename).write(out.toByteArray());
-
- System.out.println(">>> xls file exported: " + filename);
- }
- catch (Exception e) {
- throw e;
- }
- }
-
- public static void main(String[] a) {
- test01();
- test02();
- }
- }
-
- package myreport;
-
- import java.sql.Connection;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.List;
-
- import org.postgresql.jdbc3.Jdbc3PoolingDataSource;
-
-
- public class StudentReportDAO {
-
- private static final Jdbc3PoolingDataSource ds = new Jdbc3PoolingDataSource();
-
- private static String select = "select * from student order by dept";
-
- static {
- ds.setDataSourceName("JwangDataSource");
- ds.setServerName("localhost");
- ds.setDatabaseName("test02");
- ds.setUser("john");
- ds.setPassword("password");
- ds.setMaxConnections(10);
- }
-
- public static Connection getConnection() throws SQLException {
- return ds.getConnection();
- }
-
- public List getStudentList() throws Exception {
-
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- try {
- conn = getConnection();
- ps = conn.prepareStatement(select);
- rs = ps.executeQuery();
-
- ArrayList list = new ArrayList();
- while(rs.next()) {
- list.add(create(rs));
- }
-
- return list;
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- finally {
- rs.close();
- ps.close();
- conn.close();
- }
-
- return null;
- }
-
- private MutableStudent create(ResultSet rs) throws SQLException {
- return new MutableStudent( rs.getInt("sid"),
- rs.getString("name"),
- rs.getString("dept"),
- rs.getInt("age")
- );
- }
- }
-
-
- package myreport;
-
- import java.io.Serializable;
-
- /**
- * Value object for table "student"
- */
- public class MutableStudent implements Serializable {
-
- // Note: Data fields must match the "fields" defined in report template.
- private int sid;
- private String name;
- private String dept;
- private int age;
-
- public MutableStudent() {}
-
- public MutableStudent(int sid, String name, String dept, int age) {
- this.sid = sid;
- this.name = name;
- this.dept = dept;
- this.age = age;
- }
-
- public int getSid() {
- return this.sid;
- }
-
- public int getAge() {
- return this.age;
- }
-
- public String getName() {
- return this.name;
- }
-
- public String getDept() {
- return this.dept;
- }
- }
-
-
注:上传了样本文件:“student_report_pie.jrxml” and pdf output. 附件:student_report_pie.jrxml(15K) 附件:student_report_pie.pdf(20K)
|
|