报表工具jasperreports其实分为两个大块,IReport和Jasperreports,前者是一个报表定义和生成工具,后者在前者的工作基础上进行web架构的动态查询和输出。
今天我们主要说前者ireport。ireport是sourceforge的项目,下载地址http://jasperforge.org/index.php?q=project/ireport。
简单地说,ireport就是个用来画报表(样式上是what you see is what you get)的客户端工具,我们可以用它来进行可视化的报表样式编辑,并可连接数据库生成报表,导出为excel和pdf等文件格式,实际上它的主要作用是用来定义一个固定格式的后缀为.jrxml的xml文件,这个文件定义了报表的样式(如报表标题title、页头pageHeader、报表体detail、页尾pageFooter等,包括页宽、线条、字体等细节)和报表内容(pageHeader和detail中定义,前者定义报表的表头,后者定义报表中每一列要展现的数据是什么)。
至于ireport怎么安装使用的有关细节,网上已有许多资料,这里就不赘述了。这里我要做的是:用ireport设计一个通用的符合.jrxml文件格式的模板,在这个模板的基础上根据数据库里的报表配置生成单独的jrxml文件。
下面是我在ireport工具的辅助下得到的一个通用模板,用户在前台报表查询时,程序会读取数据库中相应报表的配置,在这个模板的基础上生成该报表对应的.jrxml文件。
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
<property name="ireport.zoom" value="1.2100000000000002"/>
<property name="ireport.x" value="0"/>
<property name="ireport.y" value="0"/>
<parameter name="ReportTitle" class="java.lang.String"/>
<parameter name="Reporter" class="java.lang.String"/>
<parameter name="ReportDate" class="java.lang.String"/>
<title>
<band height="68">
<line>
<reportElement x="0" y="0" width="515" height="1"/>
</line>
<textField isBlankWhenNull="true" bookmarkLevel="1">
<reportElement x="0" y="7" width="515" height="30"/>
<textElement textAlignment="Center">
<font fontName="宋体" size="22"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{ReportTitle}]]></textFieldExpression>
</textField>
<staticText>
<reportElement x="388" y="37" width="35" height="15"/>
<textElement>
<font fontName="宋体" size="10"/>
</textElement>
<text><![CDATA[制表人:]]></text>
</staticText>
<staticText>
<reportElement x="377" y="52" width="46" height="15"/>
<textElement>
<font fontName="宋体" size="10"/>
</textElement>
<text><![CDATA[制表时间:]]></text>
</staticText>
<textField>
<reportElement x="423" y="37" width="92" height="15"/>
<textElement>
<font fontName="宋体" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{Reporter}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="423" y="53" width="92" height="15"/>
<textElement>
<font fontName="宋体" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{ReportDate}]]></textFieldExpression>
</textField>
</band>
</title>
<pageHeader>
<band height="20">
</band>
</pageHeader>
<detail>
<band height="15">
</band>
</detail>
<pageFooter>
<band height="33">
<line>
<reportElement x="0" y="10" width="515" height="1"/>
</line>
<textField>
<reportElement x="205" y="14" width="65" height="15"/>
<textElement textAlignment="Right">
<font fontName="宋体" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["第" + String.valueOf($V{PAGE_NUMBER}) + "页,共"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="270" y="14" width="39" height="15"/>
<textElement>
<font fontName="宋体" size="10"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[String.valueOf($V{PAGE_NUMBER})+"页 "]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>
解释一下:
<parameter name="ReportTitle" class="java.lang.String"/>
<parameter name="Reporter" class="java.lang.String"/>
<parameter name="ReportDate" class="java.lang.String"/>
定义了填充报表时需要输入的三个参数,分表是报表标题,制表人和制表时间,这些参数将在程序填充报表时动态地获取(如来于后台数据库)并显示在报表中(注意title部分的红色字体)。
title部分是在组建具体的.jrxml文件时用来定义报表标题部分的,直接copy引用即可。
pageHeader部分是用来定义报表头的内容,它显示了具体地一个报表显示的列的列名,如:
<pageHeader>
<band height="20">
<staticText>
<reportElement mode="Opaque" x="0" y="5" width="50" height="15" forecolor="#FFFFFF" backcolor="#333333"/>
<textElement>
<font fontName="宋体" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<text><![CDATA[编号]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="50" y="5" width="200" height="15" forecolor="#FFFFFF" backcolor="#333333"/>
<textElement textAlignment="Left" verticalAlignment="Top" rotation="None" lineSpacing="Single" markup="none">
<font fontName="宋体" size="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<text><![CDATA[姓名]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="250" y="5" width="265" height="15" forecolor="#FFFFFF" backcolor="#333333"/>
<textElement textAlignment="Left" verticalAlignment="Top" rotation="None" lineSpacing="Single" markup="none">
<font fontName="宋体" size="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<text><![CDATA[街道]]></text>
</staticText>
</band>
</pageHeader>
detail部分定义了每一列的数据来源。如:
<detail>
<band height="15">
<textField isStretchWithOverflow="true">
<reportElement stretchType="RelativeToTallestObject" x="0" y="0" width="50" height="15"/>
<box leftPadding="10" rightPadding="10">
<leftPen lineWidth="0.5"/>
<bottomPen lineWidth="0.5"/>
</box>
<textElement verticalAlignment="Middle">
<font fontName="宋体" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" pattern="" isBlankWhenNull="false">
<reportElement positionType="Float" stretchType="RelativeToTallestObject" mode="Transparent" x="50" y="0" width="200" height="15" forecolor="#000000" backcolor="#FFFFFF"/>
<box leftPadding="10" rightPadding="10">
<leftPen lineWidth="0.5"/>
<bottomPen lineWidth="0.5"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle" rotation="None" lineSpacing="Single" markup="none">
<font fontName="宋体" size="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" pattern="" isBlankWhenNull="false">
<reportElement positionType="Float" stretchType="RelativeToTallestObject" mode="Transparent" x="250" y="0" width="265" height="15" forecolor="#000000" backcolor="#FFFFFF"/>
<box leftPadding="10" rightPadding="10">
<leftPen lineWidth="0.5"/>
<bottomPen lineWidth="0.5"/>
<rightPen lineWidth="0.5"/>
</box>
<textElement textAlignment="Left" verticalAlignment="Middle" rotation="None" lineSpacing="Single" markup="none">
<font fontName="宋体" size="10" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="STSong-Light" pdfEncoding="UniGB-UCS2-H" isPdfEmbedded="true"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{street}]]></textFieldExpression>
</textField>
</band>
</detail>
请注意红色字体的部分,它引用了通用模板中没有定义的Field(需要在程序生成具体模板的时候根据后台数据库的报表配置动态地添加定义):
<field name="id" class="java.lang.Integer"/>
<field name="name" class="java.lang.String"/>
<field name="street" class="java.lang.String"/>
请注意,jrxml文件对元素的定义顺序有严格要求,field的定义必须在parameter 后,否则jrxml文件无法编译通过,其他元素的定义顺序也必须一样如例所示。
最后是页尾pageFooter部分,它引用了jasperreport对象的一些固有属性,如总页码、当前页码等。在这里它也是通用的,生成具体报表的jrxml文件时直接copy引用即可。
好了,生成了报表的jrxml文件,接下来就要把它编译成.jasper文件,用符合要求的数据来填充报表,并输出为excel、pdf、html等格式的报表文件,如何在web上做到这些呢?请看下一篇