1. JasperReports概述
JasperReports是一个基于Java的开源报表工具,它可以在Java环境下像其它IDE报表工具 一样来制作报表。JasperReports支持PDF、HTML、XLS、CSV和XML等文件输出格式。JasperReports是当前Java开发者最常用的报表工具。
JasperReports采用LGPL开源协议。
2. JasperReports的一些特性
灵活的报表布局
JasperReports允许你将报表分割成多个部分:报表标题、表头、报表内容、表尾和汇总,这样你就可以分开进行处理,以达到灵活布局的效果。
多种方式显示数据
JasperReports可以以文本或者图形的方式显示数据,可以通过使用表达式来产生显示动态数据的报表。
多种方式提供数据
JasperReports可以以传参数的方式将数据传给报表,这个参数可以是任一Java类的实例;也可以通过数据源的方式传递。
支持多种数据源
JasperReports可以通过多种数据源产生报表:JDBC、XML文件、POJOs(Plain Old Java Objects)以及任何实现了java.util.Map或者javax.swing.TableModel接口的Java类。
水印功能
JasperReports可以在产生的报表上生成背景图或者文字。
子报表功能
JasperReports可以产生子报表、嵌套报表。
支持多种文件输出格式
JasperReports支持多种文件输出格式:PDF、XLS(Excel)、RTF、HTML、XML、CSV等。
3. 实战JasperReports
准备:
1. 首先在实战前,我们需要下载JasperReports。
您可以通过
http://www.jasperforge.org/index.php?option=com_content&task=section&id=16&Itemid=277下载到最新版本的JasperReports 1.3.4(下载前,您首先需要注册、登录)。
2. 解压下载的jasperreports-1.3.4-project.zip,将dist和lib目录下的所有jar文件添加到项目的CLASSPATH中。
HelloWorld
在开始我们第一个JasperReports程序之前,让我们先来了解下使用JasperReports创建报表的典型流程:
创建一个XML格式的报表模板文件(JRXML文件),这个文件的后缀是.jrxml。JRXML文件,可以手工编辑完成,也可以使用可视化的设计工具来完成,例如JasperReports的官方图形化报表设计器——iReport。
通过调用JasperReports类库中的相应方法(compileReportToFile())或者使用自定义的ant任务,把JRXML文件编译成JasperReports本地二进制模板,这个模板通常被称为Jasper文件。
通过为Jasper文件提供所需的数据,产生最终的报表。
导出生成的报表。
Ok,让我们开始HelloWorld吧!
建立一个JRXML文件,HelloReportWorld.jrxml:
<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="HelloReportWorld">
<parameter name="reportTitle" class="java.lang.String"/>
<parameter name="author" class="java.lang.String"/>
<parameter name="startDate" class="java.lang.String"/>
<title>
<band height="60">
<textField>
<reportElement x="0" y="10" width="500" height="40"/>
<textElement textAlignment="Center">
<font size="24"/>
</textElement>
<textFieldExpression class="java.lang.String">
<![CDATA[$P{reportTitle}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="40" width="500" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.String">
<![CDATA["Run by: " + $P{author}
+ " on " + $P{startDate}]]>
</textFieldExpression>
</textField>
</band>
</title>
<detail>
<band height="200">
<staticText>
<reportElement x="0" y="0" width="500" height="20"/>
<text><![CDATA[Hello Report World!]]></text>
</staticText>
</band>
</detail>
</jasperReport>
这个文件中,使用了<parameter>、<title>等模板元素,下面来具体介绍JRXML模板元素:
<jasperReport>:根元素
<import>:用于导入Java类或包
<reportFont>:用于定义显示在报表上的文本的字体
<parameter>:用于定义报表参数。参数值通过调用JasperReports API中的相关方法,利用
java.util.Map来提供。
<queryString>:用于定义从数据库中得到数据的SQL查询语句。
<field>:用于将利用数据源或者查询得到的数据映射到报表模板中。
<variable>:用于简化报表模板。将报表中多次使用的报表表达式指定给variable。
<group>:用于报表分组。
<background>:用于定义报表中的页面背景。
<title>:用于定义报表标题。只在报表的开头出现一次。
<pageHeader>:用于定义表头。在报表每个页面的开头都出现。
<columnHeader>:用于定义列头部分。
<detail>:用于定义报表的细节部分。
<columnFooter>:用于定义列尾部分。
<pageFooter>:用于定义表尾。在报表每个页面的底部都出现。
<lastPageFooter>:用于定义报表最后一个页面的表尾。
<summary>:用于报表汇总。
看完了各个模板元素的具体含义,下面让我们看看如何利用这个模板产生报表。
建立一个Java类文件,HelloReportWorld.java:
import java.util.HashMap;
import java.util.Map;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
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.JasperReport;
import net.sf.jasperreports.view.JasperViewer;
public class HelloReportWorld {
public HelloReportWorld() {
}
public static void main(String[] args) {
String reportSource = "./report/templates/HelloReportWorld.jrxml";
String reportDest = "./report/results/HelloReportWorld.html";
Map<String, Object> params = new HashMap<String, Object>();
params.put("reportTitle", "Hello Report World");
params.put("author", "Thomas Qi");
params.put("startDate", (new java.util.Date()).toString());
try {
JasperReport jasperReport =
JasperCompileManager.compileReport(reportSource);
JasperPrint jasperPrint =
JasperFillManager.fillReport(
jasperReport, params, new JREmptyDataSource());
JasperExportManager.exportReportToHtmlFile(
jasperPrint, reportDest);
JasperViewer.viewReport(jasperPrint);
}
catch (JRException ex) {
ex.printStackTrace();
}
}
}
通过以下代码:
try {
JasperReport jasperReport =
JasperCompileManager.compileReport(reportSource);
JasperPrint jasperPrint =JasperFillManager.fillReport(jasperReport, params, new JREmptyDataSource());
JasperExportManager.exportReportToHtmlFile(jasperPrint, reportDest);
JasperViewer.viewReport(jasperPrint);
}
可以看出使用JasperReports创建报表典型流程中的2、3、4步骤,分别对应于JasperCompileManager.compileReport()、JasperFillManager.fillReport()、
JasperExportManager.exportReportToHtmlFile()。
我们将报表导出成HTML格式。
JDBC数据源报表
重点还是JRXML文件:
<?xml version="1.0"?>
<!DOCTYPE jasperReport
PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="DbReport">
<parameter name="reportTitle" class="java.lang.String"/>
<parameter name="author" class="java.lang.String"/>
<parameter name="startDate" class="java.lang.String"/>
<queryString>
<![CDATA[SELECT * FROM user ORDER BY id]]>
</queryString>
<field name="id" class="java.lang.Integer"/>
<field name="email" class="java.lang.String"/>
<field name="password" class="java.lang.String"/>
<title>
<band height="60">
<textField>
<reportElement x="0" y="10" width="500" height="40"/>
<textElement textAlignment="Center">
<font size="24"/>
</textElement>
<textFieldExpression class="java.lang.String">
<![CDATA[$P{reportTitle}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="0" y="40" width="500" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.String">
<![CDATA["Create by: " + $P{author}
+ " on " + $P{startDate}]]>
</textFieldExpression>
</textField>
</band>
</title>
<columnHeader>
<band height="30">
<rectangle>
<reportElement x="0" y="0" width="500" height="25"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement x="5" y="5" width="50" height="15"/>
<textElement/>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement x="55" y="5" width="150" height="15"/>
<text><![CDATA[Email]]></text>
</staticText>
<staticText>
<reportElement x="205" y="5" width="255" height="15"/>
<text><![CDATA[Password]]></text>
</staticText>
</band>
</columnHeader>
<detail>
<band height="20">
<textField>
<reportElement x="5" y="0" width="50" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.Integer">
<![CDATA[$F{id}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="55" y="0" width="150" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{email}]]>
</textFieldExpression>
</textField>
<textField>
<reportElement x="205" y="0" width="255" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String">
<![CDATA[$F{password}]]>
</textFieldExpression>
</textField>
</band>
</detail>
</jasperReport>
这个示例与HelloWorld的主要区别,在于黑体部分。
<queryString>
<![CDATA[SELECT * FROM user ORDER BY id]]>
</queryString>
这里定义了从user表中查询数据的SQL语句,user表中包含id, email和password三个字段;
<field name="id" class="java.lang.Integer"/>
用于定义user表中的字段;
<textFieldExpression class="java.lang.Integer">
<![CDATA[$F{id}]]>
使用这个模板的客户端核心代码:
try {
JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
// Make the driver class available.
Class.forName("com.mysql.jdbc.Driver");
// Create a connection to pass into the report.
java.sql.Connection conn =
DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","123456");
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, conn);
JRCsvExporter csvExporter = new JRCsvExporter();
csvExporter.setParameter(JRExporterParameter.JASPER_PRINT,jasperPrint);
csvExporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME,reportDest);
csvExporter.exportReport();
JasperViewer.viewReport(jasperPrint);
} catch (JRException e) {
e.printStackTrace();
}
catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
catch (SQLException ex) {
ex.printStackTrace();
}
}
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, conn);
这句将HelloWorld中空的JasperReports数据源替换成了一个叫做conn的数据库连接参数,这也是程序的重点所在!
这次,我们将报表导出成CSV格式。
<queryString>
<![CDATA[SELECT * FROM user ORDER BY id]]>
</queryString>
建立一个简单的Java类文件(POJOs),User.java:
public class User implements java.io.Serializable {
private Integer id;
private String email;
private String password;
public User() {
}
public User(String email, String password) {
this.email = email;
this.password = password;
}
public User(Integer id, String email, String password) {
this.id = id;
this.email = email;
this.password = password;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
JRXML文件
基本和JDBC数据源的一致,只是这里不再需要:
<queryString>
<![CDATA[SELECT * FROM user ORDER BY id]]>
</queryString>
重点看客户端核心代码:
try {
JasperReport jasperReport = JasperCompileManager.compileReport(reportSource);
ArrayList reportRows = new ArrayList();
reportRows.add(new User(1, "x.qi@cleversoft.com", "123456"));
reportRows.add(new User(1, "qixiang_nj@163.com", "000000"));
reportRows.add(new User(3, "qixiangnj@gmail.com", "abc123"));
reportRows.add(new User(3, "mail2qixiang@gmail.com", "987654321"));
JRDataSource dataSource = new JRBeanCollectionDataSource(reportRows);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport,
params, dataSource);
JasperExportManager.exportReportToPdfFile(jasperPrint, reportDest);
JasperViewer.viewReport(jasperPrint);
} catch (JRException e) {
e.printStackTrace();
}
}
JRDataSource dataSource = new JRBeanCollectionDataSource(reportRows);
这次,我们把使用POJOs的ArrayList作为了数据源。
我们将报表导出成pdf格式。