JasperReports 快速指南



JasperReports - 入门

什么是报表

报表是对信息进行有意义、明确定义和总结的呈现。通常,日常活动会被自动化,数据会被汇总成支持决策的“报表”。报表将通常杂乱无章的数据转换为图表、图形和其他形式的图形表示。

报表模板

通常,大多数商业报表生成工具都采用以下布局来生成报表。

标题
页眉
列标题
明细
列脚注
页脚注
汇总

以下是图表中每个元素的描述:

序号 元素和描述
1

标题

标题包含报表的“标题”。它仅在报表的开头出现一次,例如,“教程点报表”。

2

页眉

页眉可能包含日期和时间信息和/或组织名称。这出现在每一页的顶部。

3

列标题

列标题列出您希望在报表中显示的特定字段的名称,例如,“作者姓名”、“开始时间”、“结束时间”、“工作时长”、“日期”等。

4

明细

明细是显示特定字段(列出在列标题中)的条目部分,例如“Manisha”、“9:00”、“18:00”、“9”、“2013年2月10日”。

5

列脚注

列脚注可能显示任何字段的总和,例如,“总工作时长:180”。

6

页脚注

页脚注可能包含页码信息。它出现在每一页的底部,例如,“1/23”。

7

汇总

汇总包含从“明细”部分推断出的信息,例如,在列出每个作者的工作时长后,可以将每个作者的总工作时长放入饼图、图形等可视化图表中,以便更好地进行比较。

JasperReports

以下是报表开发过程中遇到的常见问题:

  • 核心更改 - 通常,反映业务更改或增强,需要更改报表的核心逻辑。

  • 结果导出 - 报表可以导出到各种格式,例如:HTML、文本、PDF、MS Excel、RTF、ODT、逗号分隔值、XML 或图像。

  • 复杂报表 - 子报表和交叉表报表是良好的示例。

  • 图表报表 - 可视化图表,例如,图形、饼图、XY 线、条形图、仪表和时间序列。

为了消除上述问题的开销并促进报表过程,引入了许多框架、工具、库和第三方应用程序。JasperReports 就是其中之一。

JasperReports 是一个开源的 Java 报表引擎。它是基于 Java 的,并且没有自己的表达式语法。JasperReports 能够将丰富的内容传递到屏幕、打印机或 PDF、HTML、XLS、RTF、ODT、CSV、TXT 和 XML 文件中。由于它不是一个独立的工具,因此无法单独安装。相反,它通过将它的库包含在应用程序的 CLASSPATH 中来嵌入到 Java 应用程序中。

JasperReports 是一个 Java 类库,并非面向最终用户,而是面向需要在其应用程序中添加报表功能的 Java 开发人员。

JasperReports 的功能

JasperReports 的一些重要功能包括:

  • 它具有灵活的报表布局。

  • 它可以以文本或图形方式呈现数据。

  • 开发人员可以通过多种方式提供数据。

  • 它可以接受来自多个数据源的数据。

  • 它可以生成水印(水印就像覆盖在主图像上的辅助图像)。

  • 它可以生成子报表。

  • 它能够以多种格式导出报表。

JasperReports - 环境设置

JasperReports 是一个纯 Java 库,而不是一个独立的应用程序。它不能单独运行,因此需要嵌入到另一个客户端或服务器端的 Java 应用程序中。由于它是基于 Java 的,因此它可以在任何支持 Java 的平台上运行(JDK 1.3 及更高版本)。所有 JasperReport 的功能都集中在一个 JAR 文件中,即 jasperreports-x.x.x.jar。此 JAR 以及所需的和可选的库(.ZIP 文件)可以从以下网站下载:JasperReport 库链接。从此链接下载最新版本。

ZIP 文件包含 JasperReports JAR 文件以及 JasperReports 源代码、依赖的 JAR 和许多演示 JasperReport 功能的示例。

JasperReport 环境

要开始创建报表,我们需要准备好环境。将下载的 JasperReport.ZIP 文件解压缩到任何位置(在本例中,我们将其解压缩到 C:\tools\jasperreports-5.0.1)。解压缩文件的目录结构与如下所示相同:

Jasper directory structure

以下是所有目录的详细信息:

  • build - 包含编译后的 JasperReport 类文件。

  • demo - 包含各种示例,演示 JasperReports 功能的各个方面。

  • dist - 包含 jasperreports-x.x.x.jar 文件。我们将此 JAR 文件添加到我们的 CLASSPATH 中以利用 JasperReports。

  • docs - 包含 JasperReports 文档的本地副本。

  • lib - 包含所有需要的 JAR,用于构建 JasperReports 并在我们的应用程序中使用它。

  • src - 包含 JasperReports 源代码。

  • build.xml - 一个 ANT 构建文件,用于构建 JasperReports 源代码。如果我们不打算修改 JasperReports,则不需要使用此文件,因为 JasperReports 以编译形式分发。

  • changes.txt - 一个文本文档,解释当前版本和先前版本的 JasperReports 类库之间的差异。

  • license.txt - 一个包含 LGPL(较少通用公共许可证)许可证全文的文本文档。

  • readme.txt - 一个文本文档,包含有关如何构建和执行提供的示例的说明。

基本上,我们仅使用dist 下的 jasperreports-x.x.x.jar 和lib 目录下的 JAR 来生成报表。由于 JasperReports 是一个开源工具,如果在 jasperreports-x.x.x.jar 中执行期间发现任何缺陷或错误,我们可以修复它并使用 build.xml 文件重新构建 JAR。

设置 CLASSPATH

要使用 JasperReport,我们需要将以下文件设置为我们的 CLASSPATH:

  • jasperreports-x.x.x.jar,其中 x.x.x 是 JasperReports 版本。(位于目录 C:\tools\jasperreports-x.x.x\dist 下)。

  • lib 子目录(C:\tools\jasperreports-x.x.x\lib)下的所有 JAR 文件。

在安装过程中,我们使用了 JasperReport 5.0.1 版本。右键单击“我的电脑”并选择“属性”,单击“高级”选项卡下的“环境变量”按钮。现在使用此C:\tools\jasperreports-5.0.1\dist\jasperreports-5.0.1.jar:C:\tools\jasperreports-5.0.1\lib更新“Path”变量。现在您已准备好创建报表。

在本教程中的所有示例中,我们都使用了 ANT 任务来生成报表。build 文件负责导入生成报表所需的所有必需的 JAR。因此,如上所述设置 CLASSPATH 仅适用于那些希望在不使用 ANT 的情况下生成报表的用户。

构建设置

本教程中的所有示例:

  • 使用简单的文本编辑器编写。

  • 保存在目录 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint 下。

  • 使用 Apache ANT 从命令提示符编译和执行。我们将使用一个baseBuild.xml文件,我们将在后续章节中将其导入 ANT build.xml文件中。将此文件保存到 C:\tools\jasperreports-5.0.1\test。以下是 baseBuild.xml 文件的内容:

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportExample" basedir = ".">
   <description>Previews our JasperReport XML Design</description>
   <property name = "file.name" value = "jasper_report_template" />
   
   <!-- Directory where the JasperReports project file was extracted
   needs to be changed to match the local environment -->
   <property name = "jasper.dir" value = "../" />
   <property name = "dist.dir" value = "${jasper.dir}/dist" />
   <property name = "lib.dir" value = "${jasper.dir}/lib" />
   <property name = "src.dir" value = "src" />
   <property name = "classes.dir" value = "classes" />
   <property name = "main-class" value = "com.tutorialspoint.HelpMe" />

   <path id = "classpath">
      <pathelement location = "./" />
      <pathelement location = "${classes.dir}" />
	  
      <fileset dir = "${lib.dir}">
         <include name = "**/*.jar" />
      </fileset>
	  
      <fileset dir = "${dist.dir}">
         <include name = "**/*.jar" />
      </fileset>
   </path>
   
   <target name = "compile" depends = "clean-sample">
      <mkdir dir = "${classes.dir}"/>
		
      <javac srcdir = "${src.dir}" destdir = "${classes.dir}" 
         classpathref = "classpath" />
   </target>
   
   <target name = "run" depends = "compile">
      <echo message = "Running class : ${main-class}"/>
	  
      <java fork = "true" classname = "${main-class}">
         <classpath>
            <path refid = "classpath" />
         </classpath>
      </java>
   </target>
   
   <target name = "clean-sample">
      <delete dir = "${classes.dir}" />
      <delete file = "./${file.name}.jasper" />
      <delete file = "./${file.name}.jrprint" />
   </target>
   
</project>

此文件包含所有必需的目标,例如清理目录、编译 Java 文件和执行类文件。

以下是 baseBuild.xml 中各个目录的详细信息。(假设当前目录为 C:\tools\jasperreports-5.0.1\test):

  • jasper.dir - 是 C:\tools\jasperreports-5.0.1 目录

  • lib.dir - 是 C:\tools\jasperreports-5.0.1\lib 目录

  • src.dir - 是 C:\tools\jasperreports-5.0.1\test\src

  • classes.dir - 是 C:\tools\jasperreports-5.0.1\test\classes

  • main-class - com.tutorialspoint.HelpMe。当没有从命令行传递类文件名时,此类是一个简单执行的类。将此文件保存到 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint。

package com.tutorialspoint;

public class HelpMe {
   public static void main(String[] args) {
      System.out.println("This is the default class executed."
         + "Please pass the fully qualified class" + " name to be executed as command line"
         + " parameter, for example," + " com.tutorialspoint.HelpMe ");
   }
}

Jasper 管理器类

有一些类将用于编译 JRXML 报表设计、填充报表、打印报表、导出到 PDF、HTML 和 XML 文件、查看生成的报表和报表设计。

Manager Classes

这些类的列表如下:

  • net.sf.jasperreports.engine.JasperCompileManager - 用于编译 JRXML 报表模板。

  • net.sf.jasperreports.engine.JasperFillManager - 用于使用数据源中的数据填充报表。

  • net.sf.jasperreports.engine.JasperPrintManager - 用于打印由 JasperReports 库生成的文档。

  • net.sf.jasperreports.engine.JasperExportManager - 用于获取报表填充过程生成的文档的 PDF、HTML 或 XML 内容。

  • net.sf.jasperreports.view.JasperViewer - 它表示一个简单的 Java Swing 应用程序,可以加载和显示报表。

  • net.sf.jasperreports.view.JasperDesignViewer - 在设计时用于预览报表模板。

设置 Apache ANT

我们将使用 Apache ANT 构建所有示例。因此,请查看ANT - 环境设置章节,在您的系统上设置 Apache ANT。

JasperReports - 生命周期

JasperReports 的主要目的是以简单灵活的方式创建面向页面、可打印的文档。以下流程图描述了创建报表时的典型工作流程。

Jasper Life Cycle

如图像所示,生命周期具有以下不同的阶段 -

  • 设计报表 - 在此步骤中,我们创建 JRXML 文件,它是一个 XML 文档,其中包含报表布局的定义。我们可以使用任何文本编辑器或iReportDesigner手动创建它。如果使用 iReportDesigner,则以可视化方式设计布局,因此可以忽略 JRXML 的实际结构。

  • 编译报表 - 在此步骤中,JRXML 编译成称为 Jasper 文件(*.jasper)的二进制对象。进行此编译是为了提高性能。为了运行报表,您需要将 Jasper 文件与应用程序一起发布。

  • 执行报表(填充数据到报表) - 在此步骤中,应用程序中的数据将填充到已编译的报表中。类 net.sf.jasperreports.engine.JasperFillManager 提供了填充报表数据所需的函数。将创建一个 Jasper 打印文件(*.jrprint),该文件可用于打印或导出报表。

  • 将报表导出到所需格式 - 在此步骤中,我们可以使用 JasperExportManager 将上一步中创建的 Jasper 打印文件导出到任何格式。由于 Jasper 提供了各种导出形式,因此使用相同的输入,我们可以创建数据的多种表示形式。

后续章节将详细概述上述每个步骤。

JasperReports - 设计

JasperReport 中的 JRXML 模板(或 JRXML 文件)是标准的 XML 文件,扩展名为 .jrxml。所有 JRXML 文件都包含标签 <jasperReport> 作为根元素。这反过来又包含许多子元素(所有这些都是可选的)。JasperReport 框架可以处理不同类型的数据源。在本教程中,我们将展示如何仅通过将 Java 数据对象(使用 Java Bean)的集合传递到 JasperReport 引擎来生成基本报表。最终报表将显示人员列表及其姓名和国家/地区等类别。

本章介绍以下步骤,以描述如何设计 JasperReport -

  • 创建 JRXML 报表模板和。
  • 预览 XML 报表模板。

创建 JRXML 报表模板

创建 JRXML 文件,即使用文本编辑器创建jasper_report_template.jrxml,并根据我们的环境设置将此文件保存在C:\tools\jasperreports-5.0.1\test中。

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">
  
   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
	
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
	
   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535" 
               height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
			
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
  
      </band>
   </columnHeader>
 
    <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" 
               height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
			
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>

      </band>
   </detail>
	
</jasperReport>

以下是上述报表模板中主要字段的详细信息 -

  • <queryString> - 此处为空(因为我们通过 Java Bean 传递数据)。通常包含检索报表结果的 SQL 语句。

  • <field name> - 此元素用于将数据从数据源或查询映射到报表模板。name在报表主体中重复使用,并且区分大小写。

  • <fieldDescription> - 此元素将字段名称与 XML 文件中的相应元素映射。

  • <staticText> - 这定义了不依赖于任何数据源、变量、参数或报表表达式的静态文本。

  • <textFieldExpression> - 这定义了结果字段的外观。

  • $F{country} - 这是一个变量,包含结果的值,即标签 <field name> 中预定义的字段。

  • <band> - 区域包含报表中显示的数据。

报表设计完成后,将其保存在 C:\ 目录中。

预览 XML 报表模板

JasperReports JAR 文件中提供了一个实用程序net.sf.jasperreports.view.JasperDesignViewer,它有助于预览报表设计,而无需编译或填充它。此实用程序是一个独立的 Java 应用程序,因此可以使用 ANT 执行。

让我们编写一个 ANT 目标viewDesignXML来查看 JRXML。因此,让我们创建并保存build.xml到 C:\tools\jasperreports-5.0.1\test 目录下(应放置在与 JRXML 相同的目录中)。以下是 build.xml 文件 -

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewDesignXML" basedir = ".">

   <import file = "baseBuild.xml" />
   <target name = "viewDesignXML" description = "Design viewer is 
      launched to preview the JXML report design.">
      
      <java classname = "net.sf.jasperreports.view.JasperDesignViewer" fork = "true">
         <arg value = "-XML" />
         <arg value = "-F${file.name}.jrxml" />
         <classpath refid = "classpath" />
      </java>
   </target>

</project>

接下来,让我们打开一个命令提示符并转到放置 build.xml 的目录。执行命令ant(因为 viewDesignXML 是默认目标)。输出如下 -

C:\tools\jasperreports-5.0.1\test>ant
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

viewDesignXML:
[java] log4j:WARN No appenders could be found for logger
(net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
[java] log4j:WARN Please initialize the log4j system properly.

可以忽略 Log4j 警告,并且作为上述执行的结果,将打开一个标记为“JasperDesignViewer”的窗口,显示我们的报表模板预览。

Jasper Design Viewer

正如我们所看到的,仅显示了获取数据的报表表达式,因为 JasperDesignViewer 无法访问实际的数据源或报表参数。通过关闭窗口或在命令行窗口中按 Ctrl-c 来终止 JasperDesignViewer。

JasperReports - 编译报表设计

我们在上一章中生成了 JasperReport 模板(JRXML 文件)。此文件不能直接用于生成报表。它必须编译成 JasperReport 的原生二进制格式,称为Jasper文件。在编译时,我们将 JasperDesign 对象转换为 JasperReport 对象 -

Jasper Report Compiling

接口net.sf.jasperreports.engine.design.JRCompiler在编译过程中起着核心作用。此接口有几个实现,具体取决于用于报表表达式的语言,报表表达式可以用 Java、Groovy、JavaScript 或任何其他脚本语言编写,只要编译器实现可以在运行时对其进行评估。

我们可以通过以下两种方式编译 JRXML 文件 -

  • 程序化编译。
  • 通过 ANT 任务编译。

JRXML 的程序化编译

JasperReports API 提供了一个外观类net.sf.jasperreports.engine.JasperCompileManager用于编译 JasperReport。此类包含用于编译报表模板的几个公共静态方法。模板的源可以是文件、输入流和/或内存对象。

JRXML 文件(jasper_report_template.jrxml)的内容如下。它保存在目录C:\tools\jasperreports-5.0.1\test中 -

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
   
   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>

            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>
   
   <detail>
      <band height = "16">
		
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535" height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

以下代码演示了上述jasper_report_template.jrxml文件的编译。

package com.tutorialspoint;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;

public class JasperReportCompile {

   public static void main(String[] args) {
      String sourceFileName = "C://tools/jasperreports-5.0.1/test" + 
         "/jasper_report_template.jrxml";

      System.out.println("Compiling Report Design ...");
      try {
          /**
          * Compile the report to a file name same as
          * the JRXML file name
          */
         JasperCompileManager.compileReportToFile(sourceFileName);
      } catch (JRException e) {
         e.printStackTrace();
      }
      System.out.println("Done compiling!!! ...");
   }
}

模板编译

下一步,让我们将上述内容保存在文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportCompile.java中,并在 build.xml 文件中按如下所示导入baseBuild.xml。baseBuild.xml 已经包含compilerun目标 -

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "run" basedir = ".">

   <import file = "baseBuild.xml"/>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class = com.tutorialspoint.JasperReportCompile如下 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class = com.tutorialspoint.JasperReportCompile
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml
compile:
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:27:
   warning: 'includeantruntime' was not set, defaulting to
   build.sysclasspath=last;set to false for repeatable builds
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportCompile
   [java] Compiling Report Design ...
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] Done compiling!!! ...

BUILD SUCCESSFUL
Total time: 8 seconds

作为上述编译的结果,您将看到模板文件jasper_report_template.jasper已在 C:\tools\jasperreports-5.0.1\test 目录中生成。

预览已编译的报表模板

net.sf.jasperreports.view.JasperDesignViewer可用于预览已编译的报表模板和 JRXML 模板。

为了进一步操作,让我们向上述 build.xml 文件添加一个新的目标viewDesign,这将允许我们预览已编译的报表。以下是修改后的 build.xml -

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewDesign" basedir = ".">

   <import file = "baseBuild.xml" />
   <target name = "viewDesign" description="Design viewer is launched 
      to preview the compiled report design.">
      
      <java classname = "net.sf.jasperreports.view.JasperDesignViewer" fork = "true">
         <arg value = "-F${file.name}.jasper" />
         <classpath refid = "classpath" />
      </java>
   </target>

</project>

让我们执行命令 - ant(viewDesign 是默认目标)在命令提示符下。JasperDesignViewer 窗口打开,显示 Jasper 文件,如下所示 -

Jasper Design Viewer

通过 ANT 任务编译

由于报表模板编译更像是一个设计时作业而不是运行时作业,因此 JasperReport 库有一个自定义 ANT 任务。对于某些情况下,当 JRXML 文件在运行时创建时,我们无法使用此 ANT 任务。自定义 ANT 任务称为 JRC,由类:net.sf.jasperreports.ant.JRAntCompileTask实现。其语法和行为与内置的<javac>ANT 任务非常相似。

模板编译

让我们向现有的 build.xml 添加新的目标compilereportdesing。在这里,源文件夹使用嵌套的 <src> 标签和文件集指定。嵌套的源标签允许编译散布在许多不同位置且未分组在单个根报表源文件夹下的报表模板。以下是修改后的 build.xml -

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "compilereportdesing" basedir = ".">
   
   <import file = "baseBuild.xml" />
   <target name = "viewDesign" description = "Design viewer is 
      launched to preview the compiled report design.">
      
      <java classname = "net.sf.jasperreports.view.JasperDesignViewer" fork = "true">
         <arg value = "-F${file.name}.jasper" />
         <classpath refid = "classpath" />
      </java>
		
   </target>

   <target name = "compilereportdesing" description = "Compiles the 
      JXML file and produces the .jasper file.">
		
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   </target>

</project>

接下来,让我们打开命令提示符并转到放置 build.xml 的目录。执行命令ant(compilereportdesing 是默认目标);输出如下 -

C:\tools\jasperreports-5.0.1\test>ant
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See
   https://logging.apache.org/log4j/1.2/faq.html#noconfig
   for more info.
   [jrc] File :
   C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

BUILD SUCCESSFUL
Total time: 5 seconds

文件jasper_report_template.jasper在文件系统中生成(在本例中为 C:\tools\jasperreports-5.0.1\test 目录)。此文件与通过调用 net.sf.jasperreports.engine.JasperCompileManager.compileReportToFile() 以编程方式生成的文件相同。我们可以预览此 jasper 文件,执行ant viewDesign

JasperReports - 填充报表

任何报表工具的主要目的是生成高质量的文档。报表填充过程通过操作数据集来帮助报表工具实现此目的。

报表填充过程所需的主要输入为 -

  • 报表模板 - 这是实际的 JasperReport 文件。

  • 报表参数 - 这些基本上是在报表填充时传递给引擎的命名值。我们将在报表参数章节中讨论它们。

  • 数据源 - 我们可以从各种数据源填充 Jasper 文件,例如 SQL 查询、XML 文件、csv 文件、HQL(Hibernate 查询语言)查询、Java Bean 集合等。这将在报表数据源章节中详细讨论。

此过程生成的输出是一个.jrprint文档,该文档已准备好查看、打印或导出到其他格式。外观类net.sf.jasperreports.engine.JasperFillManager通常用于使用数据填充报表模板。此类具有各种fillReportXXX()方法,用于填充报表模板(模板可以位于磁盘上、从输入流中获取或直接作为内存中的提供)。

此外观类中有两类 fillReportXXX() 方法 -

  • 第一种类型,接收 java.sql.Connection 对象作为第三个参数。大多数情况下,报表都是使用来自关系数据库的数据填充的。这可以通过 -

    • 通过 JDBC 连接到数据库。

    • 在报表模板中包含 SQL 查询。

    • JasperReports 引擎使用传递的连接并执行 SQL 查询。

    • 因此,将生成一个报表数据源以填充报表。

  • 第二种类型,接收 net.sf.jasperreports.engine.JRDataSource 对象,当需要填充的数据以其他形式提供时。

填充报表模板

让我们编写一个报表模板。JRXML 文件(C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml)的内容如下 -

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>

   <columnHeader>
      <band height = "23">
  
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
			
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>
   
   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535" height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

接下来,让我们将 Java 数据对象(Java Bean)的集合传递到 JasperReport 引擎,以填充此已编译的报表。

编写一个 POJO DataBean.java,它表示数据对象(Java Bean)。此类定义了两个 String 对象,即“name”和“country”。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint中。

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

编写一个类 DataBeanList.java,它具有生成 Java Bean 对象集合的业务逻辑。这将进一步传递到 JasperReports 引擎,以生成报表。在这里,我们在列表中添加了 4 个 DataBean 对象。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint中。

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

编写一个主类文件JasperReportFill.java,它从类(DataBeanList)获取 Java Bean 集合并将其传递到 JasperReports 引擎,以填充报表模板。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint中。

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "c://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);
      Map parameters = new HashMap();
      try {
         JasperFillManager.fillReportToFile( 
            sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

生成报表

我们现在将使用常规的 ANT 构建过程编译并执行这些文件。build.xml 文件如下所示 -

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "executereport" basedir = ".">
   <import file = "baseBuild.xml"/>

   <target name = "executereport" depends = "compile,compilereportdesing,run">
      <echo message = "Im here"/>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
         
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令 ant -Dmain-class = com.tutorialspoint.JasperReportFillexecutereport是默认目标)如下 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class = com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

compile:
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:27:
   warning: 'includeantruntime' was not set, defaulting to
   build.sysclasspath=last; set to false for repeatable builds
   [javac] Compiling 1 source file to
   C:\tools\jasperreports-5.0.1\test\classes

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 8 seconds

作为上述执行的结果,文件jasper_report_template.jrprint将在与.jasper文件相同的目录中生成(在本例中,它将在 C:\tools\jasperreports-5.0.1\test 中生成)。

Jasper 报表 - 查看和打印报表

报表填充过程的输出JasperPrint 对象可以使用内置的查看器组件进行查看,或者打印,或者导出到更流行的文档格式,如 PDF、HTML、RTF、XLS、ODT、CSV 或 XML。本章将讨论 Jasper 文档的查看和打印,下一章将讨论导出,即 '导出报表。'

查看报表

JasperReport 提供了一个内置的查看器,用于以其原始格式查看生成的报表。它是一个基于 Swing 的组件,其他 Java 应用程序可以集成此组件,而无需将文档导出到其他格式即可查看或打印。net.sf.jasperreports.view.JRViewer 类表示此可视组件。此类还可以根据应用程序需求进行自定义,方法是将其子类化。

JasperReports 还带有一个 Swing 应用程序,它使用可视组件来查看报表。此应用程序有助于以与 *.jrprint 生成的相同格式查看报表。此 Swing 应用程序在net.sf.jasperreports.view.JasperViewer 类中实现。要使用此类查看报表,我们需要将其包装到一个 ANT 目标中。

查看生成的报表

以下示例演示了如何使用 JasperViewer 类查看报表 -

让我们编写一个报表模板。JRXML 文件 (C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml) 的内容如下所示 -

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
   
   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>
   
   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535" height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

接下来,让我们将 Java 数据对象(Java Bean)的集合传递给 JasperReports 引擎,以填充此已编译的报表。

编写一个 POJO DataBean.java,它表示数据对象(Java Bean)。此类定义了两个 String 对象,即“name”和“country”。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

编写一个类 DataBeanList.java,它具有生成 Java Bean 对象集合的业务逻辑。这将进一步传递给 JasperReports 引擎,以生成报表。在这里,我们在列表中添加了 4 个 DataBean 对象。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

编写一个主类文件JasperReportFill.java,它从类(DataBeanList)获取 Java Bean 集合并将其传递到 JasperReports 引擎,以填充报表模板。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint中。

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "c://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      try {
         JasperFillManager.fillReportToFile( 
            sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

让我们编写一个目标viewFillReport到 build.xml 文件。build.xml 文件如下所示 -

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml"/>

   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer
      to preview the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc"
         classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFillReport 是默认目标)。结果,我们将看到如下屏幕所示的 JasperViewer 窗口 -

Jasper Report Viewer

打印报表

我们可以使用net.sf.jasperreports.engine.JasperPrintManager类打印由 JasperReports 库生成的文档(以其专有格式,即JasperPrint对象)。这是一个外观类,它依赖于 Java 2 打印 API。在将 JasperReport 文档导出到其他格式(如 HTML 或 PDF)后,我们也可以打印这些文档。

打印生成的报表

以下代码演示了如何打印报表。让我们更新现有的类 JasperReportFill。我们将使用JasperPrintManager.printReport()方法。此方法将源文件名(此处我们传递.jrprint文件,我们在上一步中使用方法 JasperFillManager.fillReportToFile() 生成)作为第一个参数。第二个参数是显示标准打印对话框的布尔值(我们在此处将其设置为true)。

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrintManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = "c://tools/jasperreports-5.0.1/" +
         "test/jasper_report_template.jasper";
      String printFileName = null;
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      try {
    	   printFileName = JasperFillManager.fillReportToFile( 
            sourceFileName, parameters, beanColDataSource);
         if(printFileName != null){
            JasperPrintManager.printReport( printFileName, true);
         }
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

现在,让我们将此文件保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint。我们将使用 ANT 编译并执行此文件。build.xml 的内容如下所示 -

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "executereport" basedir = ".">
   <import file = "baseBuild.xml"/>

   <target name = "executereport" depends = "compile,compilereportdesing,run">
      <echo message = "Im here"/>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc"
         classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>
	
</project>

接下来,让我们打开命令提示符并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportPrint。结果,将出现一个打印对话框。单击确定打印文档。

JasperReports - 导出报表

我们在上一章中看到了如何打印和查看 JasperReport 生成的文档。在这里,我们将看到如何将这些报表转换为或导出到其他格式,如 PDF、HTML 和 XLS。提供了外观类net.sf.jasperreports.engine.JasperExportManager来实现此功能。导出意味着将JasperPrint对象(.jrprint 文件)转换为不同的格式。

以下代码(JasperReportExport.java)演示了 JasperReport 文档的导出过程。JasperExportManager 提供了仅将报表导出到 PDF、HTML 和 XML 的方法。要导出到 XLS 格式,我们使用了net.sf.jasperreports.engine.export.JRXlsExporter类。此代码生成以下三个文件 -

  • sample_report.pdf
  • sample_report.html
  • sample_report.xls

导出到其他格式

让我们编写一个报表模板。JRXML 文件(C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml)的内容如下 -

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
   
   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535" height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
            <text><![CDATA[]]> </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

接下来,POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示 -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

编写一个主类文件JasperReportFill.java,它从类(DataBeanList)获取 Java Bean 集合并将其传递到 JasperReports 引擎,以填充报表模板。将其保存到目录C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint中。

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRXlsExporter;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = "c://tools/jasperreports-5.0.1/"
         + "test/jasper_report_template.jasper";
      String printFileName = null;
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();
      JRBeanCollectionDataSource beanColDataSource =
         new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      try {
         printFileName = JasperFillManager.fillReportToFile(sourceFileName,
            parameters, beanColDataSource);
         if (printFileName != null) {
            /**
             * 1- export to PDF
             */
            JasperExportManager.exportReportToPdfFile(printFileName,
               "C://sample_report.pdf");

            /**
             * 2- export to HTML
             */
            JasperExportManager.exportReportToHtmlFile(printFileName,
               "C://sample_report.html");

            /**
             * 3- export to Excel sheet
             */
            JRXlsExporter exporter = new JRXlsExporter();

            exporter.setParameter(JRExporterParameter.INPUT_FILE_NAME,
               printFileName);
            exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME,
               "C://sample_report.xls");

            exporter.exportReport();
         }
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

在这里,我们包含了将 jasper 打印文件导出到 pdf、html 和 xls 格式的逻辑。

生成报表

让我们使用我们常规的 ANT 构建过程编译并执行上述文件。build.xml 文件如下所示 -

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "executereport" basedir = ".">
   <import file = "baseBuild.xml"/>

   <target name = "executereport" depends = "compile,compilereportdesing,run">
      <echo message = "Im here"/>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc"
         classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

转到命令提示符,然后转到目录 C:\tools\jasperreports-5.0.1\test,其中放置了 build.xml。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill。输出如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting t
   [javac] Compiling 4 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

executereport:
   [echo] Im here

BUILD SUCCESSFUL
Total time: 32 seconds

上述执行的结果是,您将在 C:\ 目录中找到三个文件 sample_report.pdf、sample_report.html、sample_report.xls。

报表参数

填充报表的 主要输入是 - 报表模板、参数和数据源。本章将描述参数,下一章我们将讨论数据源。

参数是对象引用,它们在报表填充操作期间传递给报表引擎。无法通过数据源传递的数据可以通过参数传递。诸如作者姓名、报表标题等数据可以通过参数传递。JasperReports 模板或 JRXML 模板可以具有零个或多个参数元素。

参数声明

参数声明如下 -

<parameter name = "exampleParameter" class = "java.lang.String" />

名称属性

<parameter> 元素的name属性是必需的。它通过名称在报表表达式中引用参数。参数名称应为单个单词。它不应包含任何特殊字符,如点或逗号。

类属性

class属性也是必需的,它指定参数值的类名。其默认值为java.lang.String。这可以更改为运行时可用的任何类。无论报表参数的类型是什么,引擎都会在使用 $P{} 令牌的报表表达式中处理强制转换,因此无需进行手动强制转换。

报表参数值始终打包在 java.util.Map 对象中,该对象以参数名称作为其键。报表参数可以在报表的查询字符串中使用,以便进一步自定义从数据库检索的数据集。它们充当查询中的动态过滤器,为报表提供数据。

内置参数

以下是预定义的报表参数,可以在表达式中使用 -

序号 参数名称和描述
1

REPORT_PARAMETERS_MAP

包含一个包含所有用户定义和内置参数的映射。

2

REPORT_CONNECTION

这指向用户提供的类 java.sql.Connection,用于 JDBC 数据源。

3

REPORT_DATA_SOURCE

这是用户提供的 JRDataSource 实例,表示内置数据源类型之一或用户定义的数据源。

4

REPORT_MAX_COUNT

这是一个java.lang.Integer值,允许用户限制数据源中的记录。

5

REPORT_SCRIPTLET

这指向net.sf.jasperreports.engine.JRAbstractScriptlet,并包含用户提供的报表脚本的实例。

6

REPORT_LOCALE

这是一个java.util.Locale实例,包含所需的资源包区域设置。

7

REPORT_RESOURCE_BUNDLE

这指向java.util.ResourceBundle对象,并包含本地化消息。

8

REPORT_TIME_ZONE

这是一个java.util.TimeZone实例,用于日期格式化。

9

REPORT_VIRTUALIZER

这是net.sf.jasperreports.engine.JRVirtualizer对象的实例,用于页面虚拟化(优化内存消耗)。

10

REPORT_CLASS_LOADER

这是一个java.lang.ClassLoader实例,在报表填充过程中用于加载资源,例如图像、字体和子报表模板

11

IS_IGNORE_PAGINATION

如果设置为java.lang.Boolean.TRUE,则报表将在一个长页面上生成,并且不会发生分页。

示例

让我们将ReportTitleAuthor传递到报表(由 JasperReportFill.java 生成)。修改后的文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示 -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

让我们将参数<ReportTitle>和<Author>添加到我们现有的报表模板(章节报表设计)。报表标题和作者将显示在报表的开头。修改后的报表模板(jasper_report_template.jrxml)如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录 -

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50">
	
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>

   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
           
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
				
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

报表生成

我们将使用我们常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下。

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />

   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview
      the report stored in the .JRprint file.">
      
		
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: warning:
   'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig
   for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 seconds

上述编译的结果是,将打开一个 JasperViewer 窗口,如下面的屏幕所示 -

Jasper Report Parameter Example

在这里,我们看到报表标题“联系人列表”和作者“由 Manisha 准备”显示在报表的开头。

报表数据源

数据源是结构化数据容器。在生成报表时,JasperReports 引擎从数据源获取数据。可以从数据库、XML 文件、对象数组和对象集合中获取数据。我们在章节填充报表中看到了,fillReportXXX() 方法期望接收要填充的报表的 数据源,其形式为net.sf.jasperreports.engine.JRDataSource对象或java.sql.Connection(当报表数据位于关系数据库中时)。

JRDataSource 接口只有两个方法需要实现 -

  • public boolean next() throws JRException;

    • 在报表填充时,当报表引擎遍历数据时,将在数据源对象上调用此方法。

  • public Object getFieldValue(JRField jrField) throws JRException;

    • 此方法提供当前数据源记录中每个报表字段的值。

检索数据源中的数据的唯一方法是使用报表字段。根据获取数据源中记录的方式,JRDataSource 接口有几个默认实现。

数据源实现

下表总结了数据源及其实现类:

数据源 实现类
JDBC net.sf.jasperreports.engine.JRResultSetDataSource
JavaBean net.sf.jasperreports.engine.data.JRBeanCollectionDataSource, net.sf.jasperreports.engine.data.JRBeanArrayDataSource
基于 Map 的 net.sf.jasperreports.engine.data.JRMapArrayDataSource, net.sf.jasperreports.engine.data.JRMapCollectionDataSource
TableModel net.sf.jasperreports.engine.data.JRTableModelDataSource
XML net.sf.jasperreports.engine.data.JRXmlDataSource
CSV net.sf.jasperreports.engine.data.JRCsvDataSource
XLS net.sf.jasperreports.engine.data.JRXlsDataSource
net.sf.jasperreports.engine.JREmptyDataSource

JDBC 数据源

JRResultSetDataSource封装了一个java.sql.ResultSet对象。当报表数据从关系数据库中提取时,这是最常用的数据源实现。如果将java.sql.Connection传递给引擎,则引擎首先执行相关的查询并将返回的java.sql.ResultSet对象存储在 JRResultSetDataSource 实例中。

JavaBean 数据源

JRBeanArrayDataSourceJRBeanCollectionDataSource表示可以封装 JavaBean 对象的数组和集合的实现。数组或集合中的每个对象将在此类型的数据源中被视为一条记录。特定 JavaBean 属性与相应报表字段之间的映射是通过命名约定进行的。报表字段的名称必须与 JavaBean 规范中指定的 JavaBean 属性的名称相同。

在本教程的所有示例中,我们都使用了 JRBeanCollectionDataSource。

基于 Map 的数据源

如果父应用程序已经将报表数据存储在内存中作为java.util.Map 对象,则实现类JRMapArrayDataSourceJRMapCollectionDataSource很有用。封装的数组或集合中的每个 Map 对象都被视为数据源中的一个虚拟记录,并且每个报表字段的值都是使用报表字段(作为键的名称)从 map 中提取的。

TableModel 数据源

在许多客户端应用程序中,数据以表格格式显示。许多应用程序中的一个常见需求是允许用户将此表格格式打印为报表。实现类JRTableModelDataSource使从表格格式生成报表的任务对于 Swing 应用程序来说变得微不足道。此类封装了一个 javax.swing.table.TableModel 对象。可以按名称或按其基于 0 的索引访问封装的 TableModel 对象中的列。

XML 数据源

JRXmlDataSource是基于 DOM 的数据源实现,它使用 XPath 表达式从 XML 文档中选择数据。XML 数据源中的记录由通过 XPath 表达式选择的节点元素表示。使用字段描述(JRXML 中的<fieldDescription>元素)提供的 XPath 表达式从每个记录中检索字段值。

XPath 是一种用于遍历 XML 文档的属性和元素的语言。有关 XPath 的更多信息,请访问http://www.w3.org/TR/xpath.

CSV 数据源

JRCsvDataSource表示数据源的实现,这些数据源从结构化文本文件(通常是 CSV)中检索其数据。使用它们的列索引检索字段值。

XLS 数据源

JRXlsDataSource表示数据源的实现,这些数据源从 Excel 文档中检索其数据。此数据源实现的报表字段映射也基于字段列索引。

空数据源

JREmptyDataSource模拟一个具有给定数量的虚拟空记录的数据源。它由 UI 工具用于提供基本的报表预览功能,或在特殊的报表模板中,或用于测试和调试目的。

可回退数据源

net.sf.jasperreports.engine.JRRewindableDataSource扩展了基本JRDataSource接口。它仅向接口添加了一个名为 moveFirst() 的方法。此方法旨在将光标移动到数据源中的第一个元素。

当处理放置在不允许拆分的波段内的子报表时,可回退数据源很有用,因为 isSplitAllowed="false" 设置且当前页面上没有足够的空间来呈现子报表。

JRResultSetDataSource外,所有上述数据源实现都是可回退的,因为它不支持将记录指针移回。只有在手动使用此数据源包装 java.sql.ResultSet 然后将其传递给子报表时,这才会带来问题。如果 SQL 查询位于子报表模板中,则不会出现问题,因为引擎将在下一页面重新启动子报表时再次执行它。

数据源提供程序

JasperReports 库有一个接口net.sf.jasperreports.engine.JRDataSourceProvider。这有助于创建和处置数据源对象。使用 GUI 工具创建报表模板时,需要一个特殊的工具来自定义报表的 ​​数据源。JRDataSourceProvider 是将自定义数据源插入设计工具的标准方法。此接口的自定义实现应实现以下方法,这些方法允许创建和处置数据源对象,以及如果可能,列出数据源内可用报表字段的方法:

public boolean supportsGetFieldsOperation();

public JRField[] getFields(JasperReport report)
   throws JRException, UnsupportedOperationException;

public JRDataSource create(JasperReport report) throws JRException;

public void dispose(JRDataSource dataSource) throws JRException;

报表字段

报表字段是表示数据源和报表模板之间数据映射的元素。字段可以在报表表达式中组合以获得所需的输出。报表模板可以包含零个或多个<field>元素。声明报表字段时,数据源应提供与报表模板中定义的所有字段相对应的数据。

字段声明

字段声明如下所示:

<field name = "FieldName" class = "java.lang.String"/>

名称属性

<field>元素的name属性是必需的。它通过名称在报表表达式中引用字段。

类属性

class属性指定字段值的类名。其默认值为java.lang.String。这可以更改为运行时可用的任何类。无论报表字段的类型如何,引擎都会在使用 $F{} 令牌的报表表达式中处理转换,从而使手动转换变得不必要。

字段描述

<fieldDesciption>元素是一个可选元素。在实现自定义数据源时,这非常有用。例如,我们可以存储一个键或一些信息,通过这些信息,我们可以在运行时从自定义数据源中检索字段的值。通过使用<fieldDesciption>元素而不是字段名称,您可以轻松克服在从数据源检索字段值时对字段命名约定的限制。

以下是我们现有 JRXML 文件(第 报表设计 章)中的一段代码。在这里,我们可以看到nameclassfieldDescription元素的使用。

<field name = "country" class = "java.lang.String">
   <fieldDescription><![CDATA[country]]></fieldDescription>
</field>

<field name = "name" class = "java.lang.String">
   <fieldDescription><![CDATA[name]]></fieldDescription>
</field>

排序字段

在需要数据排序并且数据源实现不支持排序(例如 CSV 数据源)时,JasperReports 支持基于内存的字段数据源排序。可以使用报表模板中的一个或多个<sortField>元素进行排序。

如果指定了至少一个排序字段,则在报表填充过程中,数据源将传递给JRSortableDataSource实例。然后,它从数据源中获取所有记录,根据指定的字段在内存中执行排序,并替换原始数据源。

排序字段名称应与报表字段名称相同。用于排序的字段应具有实现 java.util.Comparable 的类型。对所有字段执行自然顺序排序,除了 java.lang.String 类型的字段(对于 String 类型,使用与报表填充区域设置相对应的校对器)。当指定多个排序字段时,将使用这些字段作为排序键按其在报表模板中出现的顺序执行排序。以下示例演示了排序功能。

排序报表示例

让我们将<sortField>元素添加到我们现有的报表模板中(第 报表设计 章)。让我们按降序对字段country进行排序。修改后的报表模板(jasper_report_template.jrxml)如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录下:

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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" 
   name = "jasper_report_template" pageWidth = "595" pageHeight = "842" 
   columnWidth = "515" leftMargin = "40" rightMargin = "40" 
   topMargin = "50" bottomMargin = "50">
	
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>
   
   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
  
   <sortField name = "country" order = "Descending"/>
   <sortField name = "name"/>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
            
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
            
         </textField>
      
      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>
  
   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>

</jasperReport>

报表填充的 Java 代码保持不变。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName =
      "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示:

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: warning:
   'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig
   for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Field Sort Example

在这里,我们可以看到国家/地区名称按字母顺序以降序排列。

报表表达式

报表表达式是 JasperReports 的强大功能,它允许我们在报表上显示计算数据。计算数据不是静态数据,也不是作为报表参数或数据源字段专门传递的数据。报表表达式是通过组合报表参数、字段和静态数据构建的。默认情况下,Java 语言用于编写报表表达式。JasperReports 编译器支持其他用于报表表达式的脚本语言,如 Groovy 脚本语言、JavaScript 或 BeanShell 脚本。

本章将向您解释:报表表达式是如何工作的,假设它们仅使用 Java 语言编写。在 JRXML 报表模板中,有几个元素定义了表达式,例如:

  • <variableExpression>
  • <initialValueExpression>
  • <groupExpression>
  • <printWhenExpression>
  • <imageExpression>
  • <textFieldExpression>

表达式声明

基本上,所有报表表达式都是 Java 表达式,它们可以引用报表字段、报表变量和报表参数。

表达式中的字段引用

要在表达式中使用报表字段引用,必须将字段的名称放在$F{}字符序列之间,如下所示:

<textfieldexpression>
   $F{Name}
</textfieldexpression>

以下是我们现有 JRXML 文件(第 报表设计 章)中的一段代码:

<textFieldExpression class = "java.lang.String">
   <![CDATA[$F{country}]]>
</textFieldExpression>

表达式中的变量引用

要在表达式中引用变量,必须将变量的名称放在$V{}之间,如下面的示例所示:

<textfieldexpression>
   "Total height : " + $V{SumOfHeight} + " ft."
</textfieldexpression>

表达式中的参数引用

要在表达式中引用参数,应将参数的名称放在$P{}之间,如下面的示例所示:

<textfieldexpression>
   "ReportTitle : " + $P{Title}
</textfieldexpression>

以下是我们现有 JRXML 文件中的一段代码,它演示了在表达式中引用参数的方法。(JRXML 来自章节 报表设计)−

<textField isBlankWhenNull = "true" bookmarkLevel = "1">
   <reportElement x = "0" y = "10" width = "515" height = "30"/>
   
   <textElement textAlignment = "Center">
      <font size = "22"/>
   </textElement>
   
   <textFieldExpression class = "java.lang.String">
      <![CDATA[$P{ReportTitle}]]>
   </textFieldExpression>
   
   <anchorNameExpression>
      <![CDATA["Title"]]>
   </anchorNameExpression>
</textField>

<textField isBlankWhenNull = "true">
   <reportElement  x = "0" y = "40" width = "515" height = "20"/>
   
   <textElement textAlignment = "Center">
      <font size = "10"/>
   </textElement>
   
   <textFieldExpression class = "java.lang.String">
      <![CDATA[$P{Author}]]>
   </textFieldExpression>
</textField>

如上所述,参数、字段和变量引用实际上是真正的 Java 对象。通过报表模板中参数、字段或变量声明中得知其类,我们甚至可以在表达式中调用这些对象引用的方法。

以下示例展示了如何从 java.lang.String 报表字段“Name”中提取并显示首字母−

<textFieldExpression>
   $F{Name}.substring(0, 1)
</textFieldExpression>

表达式中的资源包引用

要在表达式中引用资源,应将放在$R{}之间,如下面的示例所示−

<textfieldexpression>
   $R{report.title}
</textfieldexpression>

根据运行时提供的区域设置和report.title键,加载与报表模板关联的资源包。因此,报表标题通过从资源包中提取字符串值来显示。有关国际化的更多信息,请参阅章节 国际化

计算器

计算器是 JasperReports 中的一个实体,它在报表填充时计算表达式并递增变量或数据集。在编译过程中,编译器会生成信息并将其存储在编译后的报表中。此信息在报表填充时用于构建 net.sf.jasperreports.engine.fill.JRCalculator 类的实例。

Java 源文件由基于 Java 的报表编译器动态生成和编译。此生成的类是 JRCalculator 的子类,编译生成的字节码存储在 JasperReport 对象中。此字节码在报表填充时加载,并实例化生成的类以获得表达式计算所需的计算器对象。

条件表达式

JasperReports 在定义变量表达式时不支持 if-else 语句。相反,您可以使用三元运算符{cond} ? {statement 1} : {statement 2}。此运算符可以嵌套在 Java 表达式中,以根据多个条件获得所需的输出。

报表中条件表达式的示例

让我们修改现有的报表模板(章节 报表设计)并为字段 country 添加条件表达式。修改后的报表模板(jasper_report_template.jrxml)如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录下−

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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" 
   name = "jasper_report_template" pageWidth = "595" pageHeight = "842" 
   columnWidth = "515" leftMargin = "40" rightMargin = "40" 
   topMargin = "50" bottomMargin = "50">

   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>
   
   <queryString>
      <![CDATA[]]>
   </queryString>
   
   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>
   
   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
   
   <sortField name = "country" order = "Descending"/>
   <sortField name = "name"/>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
            
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>
   
   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}.isEmpty() ? "NO COUNTRY" : $F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
			
      </band>
   </detail>
	
</jasperReport>

报表填充的 Java 代码如下所示。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下−

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName =
      "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下−

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

我们将在 Java Bean 列表中添加一条新的记录,其中 country 字段为空。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下−

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));
      dataBeanList.add(produce("Tanmay", ""));
      
      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。build.xml 文件(保存在 C:\tools\jasperreports-5.0.1\test 目录下)的内容如下所示。

导入文件 - baseBuild.xml 从章节 环境设置中获取,应放置在与 build.xml 相同的目录下。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class = com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下−

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 3 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See
   https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
    [java] log4j:WARN No appenders could be found for logger
    (net.sf.jasperreports.extensions.ExtensionsEnvironment).
    [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 5 minutes 5 seconds

C:\tools\jasperreports-5.0.1\test>

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Expression Example

在这里,我们可以看到,对于最后一条记录,我们没有为 country 字段传递任何数据,“NO COUNTRY”正在打印。

报表变量

报表变量是在报表表达式之上构建的特殊对象。

报表变量简化了以下任务−

  • 报表表达式在整个报表模板中大量使用。这些表达式可以通过使用报表变量仅声明一次。

  • 报表变量可以根据相应的表达式值执行各种计算,例如计数、求和、平均值、最小值、最大值、方差等。

如果在报表设计中定义了变量,则表达式中的新变量可以引用这些变量。因此,在报表设计中声明变量的顺序很重要。

变量声明

变量声明如下−

<variable name = "CityNumber" class = "java.lang.Integer" incrementType = "Group"
   incrementGroup = "CityGroup" calculation = "Count">
   <variableExpression>
      <![CDATA[Boolean.TRUE]]>
   </variableExpression>
</variable>

如上所示,<variable> 元素包含多个属性。这些属性总结如下−

名称属性

参数字段类似,</variable> 元素的name属性是必需的。它允许在报表表达式中通过其声明名称引用变量。

类属性

class属性也是必需的,它指定变量值的类名。其默认值为java.lang.String。这可以更改为类路径中可用的任何类,在报表编译时和报表填充时均可。引擎负责在使用 $V{} 令牌的报表表达式中进行类型转换,因此不需要手动类型转换。

计算

此属性确定在填充报表时对变量执行什么计算。以下小节描述了 <variable> 元素的 calculation 属性的所有可能值。

  • Average − 变量值是变量表达式每个非空值的平均值。仅对数字变量有效。

  • Count − 变量值是变量表达式非空实例的计数。

  • First − 变量值是变量表达式的第一个实例的值。后续值将被忽略。

  • Highest − 变量值是变量表达式的最高值。

  • Lowest − 变量值是报表中变量表达式的最低值。

  • Nothing − 对变量不执行任何计算。

  • StandardDeviation − 变量值是与报表表达式匹配的所有非空值的标准差。仅对数字变量有效。

  • Sum − 变量值是报表表达式返回的所有非空值的总和。

  • System − 变量值是自定义计算(使用 JasperReports 的脚本程序功能自己计算该变量的值)。

  • Variance − 变量值是报表变量表达式求值返回的所有非空值的方差。

Incrementer FactoryClass

此属性确定在填充报表上的当前记录时用于计算变量值的类。默认值为实现net.sf.jasperreports.engine.fill.JRIncrementerFactory的任何类。工厂类将由引擎在运行时根据为变量设置的calculation属性实例化递增器对象。

IncrementType

这决定何时重新计算变量的值。此属性使用以下值−

  • Column − 在每列结束时重新计算变量值。

  • Group − 当由 incrementGroup 指定的组发生更改时重新计算变量值。

  • None − 每次记录都重新计算变量值。

  • Page − 在每页结束时重新计算变量值。

  • Report − 仅在报表结束时重新计算变量值一次。

IncrementGroup

incrementTypeGroup时,这确定重新计算变量值的组的名称。这采用 JRXML 报表模板中声明的任何组的名称。

ResetType

这决定何时重置变量的值。此属性使用以下值−

  • Column − 在每列开始时重置变量值。

  • Group − 当由 incrementGroup 指定的组发生更改时重置变量值。

  • None − 从不重置变量值。

  • Page − 在每页开始时重置变量值。

  • Report − 仅在报表开始时重置变量值一次。

ResetGroup

resetTypeGroup时,这确定重置变量值的组的名称。此属性的值将是 JRXML 报表模板中声明的任何组的名称。

内置报表变量

有一些内置系统变量,可以在表达式中直接使用,如下所示−

序号 变量名称和描述
1

PAGE_NUMBER

此变量的值是其当前页码。它可以用来显示当前页码和总页码,使用 JasperReports 文本字段元素的一个特殊功能,即evaluationTime属性。

2

COLUMN_NUMBER

此变量包含当前列号。

3

REPORT_COUNT

此报表变量包含已处理的记录总数。

4

PAGE_COUNT

此变量包含生成当前页面时已处理的记录数。

5

COLUMN_COUNT

此变量包含生成当前列时已处理的记录数。

6

GroupName_COUNT

此变量的名称派生自其对应的组的名称,后缀为_COUNT序列。此变量包含当前组中的记录数。

示例

让我们向现有的报表模板(章节 报表设计)添加一个变量(countNumber)。我们将为每条记录添加前缀计数。修改后的报表模板(jasper_report_template.jrxml)如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录下−

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50">
	
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[country]]>
      </fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[name]]>
      </fieldDescription>
   </field>
   
   <variable name = "countNumber" class = "java.lang.Integer" calculation = "Count">
      <variableExpression>
         <![CDATA[Boolean.TRUE]]>
      </variableExpression>
   </variable>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
			
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535"	height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA["  " + String.valueOf($V{countNumber}) +"."+$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>

</jasperReport>

报表填充的 Java 代码保持不变。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName =
      "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示:

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   
   <import file = "baseBuild.xml" />
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc"
         classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下−

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: warning:
   'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig
   for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 seconds

上述编译的结果是,一个 JasperViewer 窗口打开,如下面的屏幕所示−

Jasper Report Variable Example

在这里,我们看到每条记录都添加了前缀计数。

报表节

我们在章节 入门中讨论了简单报表模板的结构。类似地,JasperReports 将报表模板结构化为多个节。节是报表的一部分,具有指定的的高度,并且可以包含报表对象,例如线条、矩形、图像或文本字段。

在报表填充时,报表引擎会遍历提供的报表数据源的虚拟记录。根据每个节的定义行为,引擎会在适当的时候渲染每个报表节。例如,详细信息节为数据源中的每条记录渲染。当发生分页符时,页面页眉和页面页脚节会根据需要渲染。

在 JasperReports 中,术语和报表章节也被称为 **报表段(report bands)**。章节由一个或多个报表段组成。这些章节在报表生成时重复填充,并最终生成报表文档。

主要章节

JasperReports 中的报表模板包含以下主要章节:

<title></title>

<pageheader></pageheader>

<columnheader></columnheader>

<groupheader></groupheader>

<detail></detail>

<groupfooter></groupfooter>

<columnfooter></columnfooter>

<pagefooter></pagefooter>

<lastpagefooter></lastpagefooter>

<summary></summary>

<nodata></nodata>

<background></background>

下表总结了每个章节:

序号 章节及描述
1

标题(Title)

此章节仅在报表开头出现一次。

2

页面页眉(Page Header)

此章节出现在生成文档的每个页面开头。

3

列页眉(Column Header)

此章节出现在生成文档的每一列开头。如果报表仅定义了一列,则列页眉和页脚章节将被忽略。

4

组页眉(Group Header)

此章节由报表组引入(章节 )。每当分组表达式值发生变化时,组页眉章节就会打印在明细章节上方。如果定义了多个组,则组页眉按组定义的顺序打印。

5

明细(Detail)

此章节针对报表数据源提供的每一行数据重复出现。明细章节可以由多个报表段组成。

6

组页脚(Group Footer)

此章节由报表组引入(章节 )。组页脚章节打印在明细章节下方,并在分组表达式的值发生变化之前打印。组页脚始终打印数据源中的最后一行数据。如果定义了多个组,则组页脚按组定义的逆序打印。

7

列页脚(Column Footer)

此章节出现在每一列底部。如果报表的列数为 1,则列页眉和页脚章节将被忽略。

8

页面页脚(Page Footer)

此章节出现在每个页面底部。

9

最后一页页脚(Last Page Footer)

此章节替换报表最后一页上的常规页面页脚。如果也存在汇总章节,则此章节可能不是文档的最后一页。当需要在最后一页底部显示汇总信息时,此章节有时很有用。

10

汇总(Summary)

此章节仅在报表末尾出现一次。

11

无数据(No Data)

当“无数据时打印报表”属性设置为“无数据”章节时,将打印此章节。如果在报表模板中定义了 <noData> 章节,并且数据源为空,则在填充时仅考虑 <noData> 章节,其内容将生成报表输出。

12

背景(Background)

背景章节显示在每个页面上,并且不能溢出到下一页。此章节中的元素在页面初始化时进行评估,并在背景中显示。所有其他页面对象都显示在背景对象之上。此章节可用于创建页面水印。

章节、元素和属性关系

下图显示了报表章节中的元素和属性关系。

Report Sections

章节元素

上面提到的所有报表章节都是可选的。但是任何报表模板都至少包含一个这样的章节。这些章节中的每一个都包含一个 <band> 元素作为其唯一的子元素。<band> 可以包含零个或多个以下子元素:

<line>、<rectangle>、<ellipse>、<image>、<staticText>、<textField>、<subReport> 或 <elementGroup>

这些元素中的每一个都必须包含一个 <reportElement> 作为其第一个元素(elementGroup 除外)。<reportElement> 确定如何为该特定元素布局数据。与变量和参数不同,报表元素不需要名称,因为通常不需要在报表模板中获取任何单个元素。

下表总结了 <reportElement> 的属性:

属性 描述 有效值
x 指定报表段元素的 x 坐标。 表示元素 x 坐标(以像素为单位)的整数。此属性是必需的。
y 指定报表段元素的 y 坐标。 表示元素 y 坐标(以像素为单位)的整数。此属性是必需的。
width 指定报表段元素的宽度。 表示元素宽度(以像素为单位)的整数。此属性是必需的。
height 指定报表段元素的高度。 表示元素高度(以像素为单位)的整数。此属性是必需的。
key 报表段元素的唯一标识符。 唯一的字符串值。
stretchType 指定包含报表段拉伸时元素如何拉伸

NoStretch(默认) - 元素不会拉伸。

RelativeToTallestObject - 元素将拉伸以适应其组中最高的元素。

RelativeToBand - 元素将拉伸以适应报表段的高度。

positionType 指定报表段拉伸时元素的位置。

Float - 元素将根据周围元素的大小移动。

FixRelativeToTop(默认) - 元素将相对于报表段的顶部保持固定位置。

FixRelativeToBottom - 元素将相对于报表段的底部保持固定位置。

isPrintRepeatedValues 指定是否打印重复值。

true(默认) - 将打印重复值。

false - 不会打印重复值。

mode 指定元素的背景模式 Opaque, Transparent
isRemoveLineWhenBlank 指定当元素为空并且同一水平空间中没有其他元素时是否应移除元素。 true, false
isPrintInFirstWholeBand 指定元素是否必须打印在完整报表段中,即未在报表页面或列之间分割的报表段。 true, false
isPrintWhenDetailOverFlows 指定当报表段溢出到新页面或列时是否打印元素。 true, false
printWhenGroupChanges 指定在指定的组发生变化时打印元素。 字符串值。
forecolor 指定元素的前景色。 十六进制 RGB 值(以 # 字符开头),或以下预定义值之一:black、blue、cyan、darkGray、gray、green、lightGray、magenta、orange、pink、red、yellow、white。
backcolor 指定元素的背景色。 forecolor的有效值相同

章节属性

以下是报表章节的属性:

高度(Height)

章节的高度指定该特定章节的高度(以像素为单位),在整个报表设计中非常重要。

打印时表达式(Print When Expression)

确定是否应打印章节的布尔表达式。

允许分割(Split Allowed)

指示是否允许在章节不适合当前页面时进行分割的标志。如果为 true,则章节将转移到下一页。请注意,如果章节不适合下一页,则无论标志的值如何,都会分割章节。splitType可以取以下值:

  • splitType="Stretch:" 分割拉伸内容。如果章节在当前页面上拉伸(如果可用空间小于声明的高度),则添加到原始高度的区域将允许分割到下一页。

  • splitType="Prevent:" 阻止第一次尝试分割。如果章节不适合下一页,则会正常分割,因为报表段分割阻止仅在第一次尝试分割时有效。

  • splitType="Immediate:" 立即分割。报表段允许在除其最顶部元素上方以外的任何位置分割。

示例

为了演示每个章节,让我们编写报表模板 (jasper_report_template.jrxml)。将此文件保存到 C:\tools\jasperreports-5.0.1\test 目录。在此文件中,我们将显示每个章节中的文本(我们上面讨论过)。文件内容如下所示:

<?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"
   name = "jasper_report_template" pageWidth = "300" pageHeight = "300" 
   columnWidth = "300" leftMargin = "0" rightMargin = "0" 
   topMargin = "0" bottomMargin = "0" >

   <title>
      <band height = "50">
         
         <textField>
            <reportElement x = "100" y = "16" width = "100" height = "20"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Title"]]>
            </textFieldExpression>
        
         </textField>
      
      </band>
   </title>
   
   <pageHeader>
      <band height = "40">
         
         <textField>
            <reportElement  mode = "Opaque" x = "100" y = "10" 
               width = "90" height = "20"/>
            
            <textElement>
               <font isBold = "true"/>
            </textElement>
            
            <textFieldExpression>
               <![CDATA["Page Header"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </pageHeader>
   
   <columnHeader>
      <band height = "40">
            
         <textField>
            <reportElement  x = "100" y = "10" width = "90" height = "20"/>
            
            <textElement>
               <font isItalic = "true"/>
            </textElement>
            
            <textFieldExpression>
               <![CDATA["Column Header"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </columnHeader>
   
   <detail>
      <band height ="40">
         
         <textField>
            <reportElement mode = "Opaque" x = "100" y = "10" 
               width = "90" height = "20" backcolor = "#99CCFF"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Report Details"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <columnFooter>
      <band height = "40">
         
         <textField>
            <reportElement  x = "100" y = "10" width = "90" height = "20"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Column Footer"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </columnFooter>
   
   <pageFooter>
      <band height = "40">
         
         <textField>
            <reportElement  x = "100" y = "10" width = "90" height = "20"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Page Footer"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </pageFooter>
   
   <lastPageFooter>
      <band height = "40">
         
         <textField>
            <reportElement  x = "100" y = "10" width = "90" height = "20"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Last Page Footer"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </lastPageFooter>
   
   <summary>
      <band height = "40">
         
         <textField>
            <reportElement  x = "100" y = "10" width = "90" height = "20"/>
            <textElement/>
            
            <textFieldExpression>
               <![CDATA["Summary"]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </summary>
	
</jasperReport>

填充并生成报表的 Java 代码如下所示。让我们将此文件 JasperReportFill.java 保存到 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint 目录。

package com.tutorialspoint;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperReportFill {
   public static void main(String[] args) {
      String sourceFileName = "C://tools/jasperreports-5.0.1/test/" + 
         "jasper_report_template.jasper";

      try {
         JasperFillManager.fillReportToFile(sourceFileName, null,
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

在这里,我们在填充报表时使用 JREmptyDataSource 的实例来模拟一个包含一个记录的数据源,但此单个记录中的所有字段都为空。

报表生成

我们将使用我们常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   
   <import file = "baseBuild.xml" />
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview 
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
		
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc"
         classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defau
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFac
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnviro
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnviro
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 minutes 22 seconds

上述编译的结果是,一个 JasperViewer 窗口打开,如下面的屏幕所示−

Jasper Report Section Example

在这里,我们可以看到在每个章节中都打印了一段文本。需要注意的是,由于 JRXML 包含 <lastPageFooter> 元素,因此它将显示在报表的最后一页,而不是显示 <pageFooter> 元素。<columnHeader> 和 <columnFooter> 元素仅在报表包含多列时才会显示。

报表组

JasperReports 中的组有助于以逻辑方式组织报表上的数据。报表组表示数据源中连续记录的序列,这些记录具有某些共同点,例如某个报表字段的值。报表组由 <group> 元素定义。报表可以包含任意数量的组。声明后,可以在整个报表中引用组。

报表组包含三个元素:

  • 组表达式 - 指示必须更改以启动新数据组的数据。

  • 组页眉章节 - 帮助在分组数据的开头放置标签。

  • 组页脚章节 - 帮助在分组数据的末尾放置标签。

在报表填充时遍历数据源的过程中,如果组表达式的值发生变化,则会发生组中断,并且相应的 <groupFooter> 和 <groupHeader> 章节将插入到生成的文档中。

报表组机制不会对数据源提供的数据执行任何排序。仅当数据源中的记录已根据报表中使用的组表达式排序时,数据分组才能按预期工作。

组属性

<group> 元素包含允许我们控制分组数据布局方式的属性。下表总结了这些属性:

序号 属性及描述
1

name

这是必须的。它通过名称在报表表达式中引用组。它遵循我们为报表参数、字段和报表变量提到的相同命名约定。当您想引用特定报表组时,可以在其他 JRXML 属性中使用它。

2

isStartNewColumn

设置为 true 时,每个数据组都将在新列中开始。默认值为 false

3

isStartNewPage

设置为true时,每个数据组将从新的一页开始。默认值为false

4

isResetPageNumber

设置为true时,每次新组开始时,报表页码将重置。默认值为false

5

isReprintHeaderOnEachPage

设置为true时,组标题将打印在每一页上。默认值为false
6

minHeightToStartNewPage

定义列底部需要保留的最小垂直空间,以便将组标题放置在当前列中。该空间以报表单位指定。

7

footerPosition

呈现组页脚在页面上的位置,以及它与后续报表部分的关系。其值可以是:NormalStackAtBottomForceAtBottomCollateAtBottom。默认值为Normal

8

keepTogether

设置为true时,可防止组在其第一次断开尝试时被分割。

示例

让我们向现有的报表模板(第 报表设计 章)添加一个组(CountryGroup)。计算每个国家/地区的出现次数,并将计数显示为组页脚。在组标题中,每个记录的计数都带有前缀。修改后的报表模板 (jasper_report_template.jrxml) 如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录中 -

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50">

   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>
   
   <sortField name = "country" order = "Descending"/>
   <sortField name = "name"/>
   
   <variable name = "CountryNumber" class = "java.lang.Integer"
      incrementType = "Group" incrementGroup = "CountryGroup"
      calculation = "Count">
      <variableExpression><![CDATA[Boolean.TRUE]]></variableExpression>
   </variable>
   
   <group name = "CountryGroup" minHeightToStartNewPage = "60">
      <groupExpression><![CDATA[$F{country}]]></groupExpression>
      
      <groupHeader>
         <band height = "20">
            
            <textField evaluationTime = "Group" evaluationGroup = "CountryGroup"
               bookmarkLevel = "1">
               <reportElement mode = "Opaque" x = "0" y = "5" width = "515"
                  height = "15" backcolor = "#C0C0C0"/>
               
               <box leftPadding = "10">
                  <bottomPen lineWidth = "1.0"/>
               </box>
               <textElement/>
               
               <textFieldExpression class = "java.lang.String">
                  <![CDATA["  " + String.valueOf($V{CountryNumber}) + ". "
                  + String.valueOf($F{country})]]>
               </textFieldExpression>
               
               <anchorNameExpression>
                  <![CDATA[String.valueOf($F{country})]]>
               </anchorNameExpression>
            </textField>
         
         </band>
      </groupHeader>
      
      <groupFooter>
         <band height = "20">
            
            <staticText>
               <reportElement x = "400" y = "1" width = "60" height = "15"/>
               <textElement textAlignment = "Right"/>
               <text><![CDATA[Count :]]></text>
            </staticText>
            
            <textField>
               <reportElement x = "460" y = "1" width = "30" height = "15"/>
               <textElement textAlignment = "Right"/>
               
               <textFieldExpression class = "java.lang.Integer">
                  <![CDATA[$V{CountryGroup_COUNT}]]>
               </textFieldExpression>
            </textField>
         
         </band>
      </groupFooter>
   
   </group>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
            
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
               <text><![CDATA[]]>
            </text>
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" width = "535" height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>  
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "414" y = "0" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
	
</jasperReport>

报表填充的 Java 代码保持不变。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName =
      "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示 -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用我们常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下。

导入文件 - baseBuild.xml 从第 环境设置 章中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview 
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下−

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: warning:
   'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig
   for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 seconds

上述编译的结果是,一个 JasperViewer 窗口打开,如下面的屏幕所示−

Jasper Report Groups Example

在这里,我们看到每个国家/地区都被分组,并且每个国家/地区的出现次数都显示在每个组的页脚中。

报表字体

报表包含文本元素,并且每个元素都可以具有自己的字体设置。可以使用 <font> 标签(在 <textElement> 标签中可用)来指定这些设置。报表可以定义多个字体。定义后,它们可以用作整个报表中其他字体定义的默认或基本字体设置。

报表字体

报表字体是字体设置的集合,在报表级别声明。在设置文本元素的字体属性时,可以在整个报表模板中重复使用报表字体。

报表字体现已弃用。不要使用文档本身中声明的 <reportFont/> 元素。请改用 <style/> 元素。

字体属性

下表总结了 <font> 元素的主要属性 -

序号 属性及描述
1

fontName

字体名称,可以是物理字体的名称、逻辑字体的名称或注册的 JasperReports 字体扩展中的字体系列的名称。

2

size

以磅为单位测量的字体大小。默认为 10。

3

isBold

指定是否需要粗体字体的标志。默认为 false。

4

isItalic

指定是否需要斜体字体的标志。默认为 false。

5

isUnderline

指定是否需要下划线文本修饰的标志。默认为 false。

6

isStrikeThrough

指定是否需要删除线文本修饰的标志。默认为 false。

7

pdfFontName

将文档导出为 PDF 格式时,iText 库所需的等效 PDF 字体名称。

8

pdfEncoding

等效的 PDF 字符编码,iText 库也需要它。

9

isPdfEmbedded

指定字体是否应嵌入文档本身的标志。默认为 false。如果设置为 true,则有助于在没有任何问题的情况下查看 PDF 文档。

字体类型

在 JasperReports 中,字体可以分类为 -

  • 逻辑字体 - 自版本 1.0 以来,Java 平台已识别五种字体类型,称为逻辑字体。它们是 - Serif、SansSerif、Monospaced、Dialog 和 DialogInput。这些逻辑字体不是安装在系统任何位置的实际字体库。它们仅仅是 Java 运行时识别的字体类型名称。这些必须映射到安装在系统上的某些物理字体。

  • 物理字体 - 这些字体是实际的字体库,例如 TrueType 或 PostScript Type 1 字体。物理字体可以是 Arial、Time、Helvetica、Courier 或许多其他字体,包括国际字体。

  • 字体扩展 - JasperReports 库可以通过其对字体扩展的内置支持,在运行时利用动态注册的字体。可以使用字体扩展使字体系列列表可用于 JasperReports。它们由外观相似的字体面组成,并支持特定的语言环境。

如上表所述,我们需要在fontName属性中指定物理字体的名称、逻辑字体的名称或注册的 JasperReports 字体扩展中的字体系列的名称。

PDF 字体名称

JasperReports 库在将报表导出到 PDF(便携式文档格式)时使用 iText 库。PDF 文件可以在各种平台上查看,并且始终看起来相同。部分原因在于,在此格式中,有一种特殊的处理字体的方式。导出到 PDF 时,fontName属性无效。pdfFontName属性存在于我们需要指定字体设置的地方。

iText 库知道如何处理内置字体和 TTF 文件,并识别以下内置字体名称 -

  • Courier
  • Courier-Bold
  • Courier-BoldOblique
  • Courier-Oblique
  • Helvetica
  • Helvetica-Bold
  • Helvetica-BoldOblique
  • Helvetica-Oblique
  • Symbol
  • Times-Roman
  • Times-Bold
  • Times-BoldItalic
  • Times-Italic
  • ZapfDingbats

根据 iText 库的先决条件,要使用字体,我们需要指定以下内容之一作为字体名称 -

  • 上述列表中的内置字体名称。

  • TTF(True Type Font)文件的名称,它可以在磁盘上找到。

  • 字体的真实名称,前提是包含该字体的 TTF 文件已在之前向 iText 注册或在注册字体时已定义别名。

基于上述先决条件,pdfFontName属性可以包含以下值之一 -

  • 上述列表中内置 PDF 字体的名称。

  • 导出到 PDF 时,可以在运行时位于磁盘上的 TTF 文件的名称。

  • 已注册字体的真实名称。

  • 作为字体文件向 iText 注册的字体的键的后缀(net.sf.jasperreports.export.pdf.font之后的部分)。

默认字体和继承

每个文本元素都继承其父元素的字体和样式属性,而父元素又从其父元素继承这些属性。如果未为元素定义任何样式和/或字体,则将应用在 <jasperReport/> 根元素中声明的默认样式(和/或字体 - 但现在已弃用)。

在 JasperReports 中定义默认样式或字体不是强制性的。如果未为给定元素定义字体,则引擎将查找继承的字体属性,或者,如果未在此方式找到任何属性,则它将在/src/default.jasperreports.properties文件中查找net.sf.jasperreports.default.font.name属性。其值定义了当未为文本元素显式定义字体属性或从其父元素继承时要使用的字体系列的名称。

下表列出了/src/default.jasperreports.properties文件中定义的主要默认字体属性及其值 -

属性 描述
net.sf.jasperreports.default.font.name=SansSerif 默认字体名称。
net.sf.jasperreports.default.font.size=10 默认字体大小。
net.sf.jasperreports.default.pdf.font.name=Helvetica 默认 PDF 字体。
net.sf.jasperreports.default.pdf.encoding=Cp1252 默认 PDF 字符编码。
net.sf.jasperreports.default.pdf.embedded=false 默认情况下,PDF 字体不嵌入。

示例

为了演示使用字体和字体属性以获得特定的文本外观,让我们编写新的报表模板 (jasper_report_template.jrxml)。JRXML 的内容如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录中。在这里,我们将以各种字体格式显示报表标题中的文本。

<?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"
   name = "jasper_report_template" pageWidth = "595" pageHeight = "842"
   columnWidth = "555" leftMargin = "20" rightMargin = "20" topMargin = "30"
   bottomMargin = "30">

   <title>
      <band height = "682">
      
      <staticText>
         <reportElement x = "0" y = "50" width = "150" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[Welcome to TutorialsPoint!]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "50" width = "390" height = "40"/>
         <textElement/>
         
         <text>
           <![CDATA[<staticText>
           <reportElement x = "0" y = "50" width = "150" height = "40"/>
           <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "100" width = "150" height = "40"/>
         
         <textElement>
            <font size = "12"/>
         </textElement>
         
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "100" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "100" width = "150" height = "40"/>
            
            <textElement>
               <font size = "14"/>
            </textElement>
				
            <text> Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "150" width = "150" height = "40"/>
         
         <textElement>
            <font fontName = "DejaVu Serif" size = "12" isBold = "false"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "150" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "250" width = "150" height = "40"/>
            
            <textElement>
               <font fontName = "DejaVu Serif" size = "12" isBold = "false"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "200" width = "150" height = "40"/>
         
         <textElement>
            <font fontName = "DejaVu Serif" size = "12" isBold = "true"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "200" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "300" width = "150" height = "40"/>
            
            <textElement>
               <font fontName = "DejaVu Serif" size = "12" isBold = "true"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "250" width = "150" height = "40"/>
         
         <textElement>
            <font fontName = "Monospaced" size = "12" isItalic = "true" 
               isUnderline = "true" pdfFontName = "Courier-Oblique"/>
         </textElement>
         
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "250" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "350" width = "150" height = "40"/>
            
            <textElement>
               <font fontName = "Monospaced" size = "12" isItalic = "true"
                  isUnderline = "true" pdfFontName = "Courier-Oblique"/>
            </textElement>
            
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "300" width = "150" height = "40"/>
         
         <textElement>
            <font fontName = "Monospaced" size = "12" isBold = "true"
               isStrikeThrough = "true" pdfFontName = "Courier-Bold"/>
         </textElement>
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "300" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "400" width = "150" height = "40"/>
            
            <textElement>
               <font fontName = "Monospaced" size = "12" isBold = "true"
                  isStrikeThrough = "true" pdfFontName = "Courier-Bold"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "350" width = "150" height = "40" 
            forecolor = "#FF0000"/>
         
         <textElement>
            <font size = "14"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "350" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "450" width = "150" height = "40"
               forecolor = "red"/>
            
            <textElement><font size = "14"/></textElement>
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "400" width = "150" height = "40" mode = "Opaque"
            forecolor = "#00FF00" backcolor = "#FFFF00"/>
         
         <textElement>
            <font fontName = "Serif" size = "12" isBold = "true" 
               pdfFontName = "Times-Bold"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "400" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "500" width = "150" height = "40"
               forecolor = "green" backcolor = "#FFFF00" mode = "Opaque"/>
            
            <textElement>
               <font fontName = "Serif" size = "12" isBold = "true"
                  pdfFontName = "Times-Bold"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement x = "0" y = "450" width = "150" height = "40" mode = "Opaque"
            forecolor = "#0000FF" backcolor = "#FFDD99"/>
         
         <textElement textAlignment = "Center" verticalAlignment = "Middle">
            <font fontName = "SansSerif" size = "12" isBold = "false"
            isItalic = "true" pdfFontName = "Sans.Slanted" isPdfEmbedded = "true"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "450" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "550" width = "150" height = "90"
               forecolor = "blue" backcolor = "#FFDD99" mode = "Opaque"/>
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font fontName = "SansSerif" size = "12" isBold = "false"
                  pdfFontName = "Sans.Slanted" isPdfEmbedded = "true"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      </staticText>
      
      <staticText>
         <reportElement mode = "Opaque" x = "0" y = "500" width = "150" height = "40"
            forecolor = "#FF0000" backcolor = "#99DDFF"/>
         
         <textElement textAlignment = "Right" verticalAlignment = "Bottom">
            <font fontName = "SansSerif" size = "12" isBold = "true"
               pdfFontName = "DejaVu Sans Bold" isPdfEmbedded = "true"/>
         </textElement>
			
         <text><![CDATA[Welcome to TutorialsPoint!]]></text>
      </staticText>
      
      <staticText>
         <reportElement x = "160" y = "500" width = "390" height = "40"/>
         <textElement/>
         
         <text>
            <![CDATA[<staticText>
            <reportElement x = "0" y = "650" width = "150" height = "90"    forecolor = "red"
               backcolor = "#99DDFF" mode = "Opaque"/>
            
            <textElement textAlignment = "Right" verticalAlignment = "Bottom">
               <font fontName = "SansSerif" size = "12" isBold = "true"
                  pdfFontName = "DejaVu Sans Bold" isPdfEmbedded = "true"/>
            </textElement>
				
            <text>Welcome to TutorialsPoint!</text></staticText>]]>
         </text>
      
      </staticText>
   
   </band>
</title>

</jasperReport>

填充和生成报表的 Java 代码如下所示。让我们将此文件JasperFontsReportFill.java保存到 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint 目录中。

package com.tutorialspoint;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperFontsReportFill {
   public static void main(String[] args) {
      String sourceFileName = "C://tools/jasperreports-5.0.1/test/" + 
         "jasper_report_template.jasper";

      try {
         JasperFillManager.fillReportToFile(sourceFileName, null,
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

在这里,我们在填充报表时使用JREmptyDataSource的实例来模拟其中包含一条记录的数据源,但所有字段均为null

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the report 
      stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
		
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperFontsReportFill(viewFullReport 是默认目标)如下 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperFontsReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to build.
   [javac] Compiling 5 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperFontsReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 45 minutes 3 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Fonts Example

在这里,我们可以看到文本“Welcome to TutorialsPoint”以不同的字体格式显示。

Unicode 支持

在 JasperReports 中,处理文本需要一些专门的工具来处理字符表示和文本格式属性。任何文本都可以被视为具有特定表示结构的字符序列。文本外观包括布局(和段落)以及字体设置。但在大多数情况下,文本布局保持不变,字体设置在不同语言环境中运行报表时可能会发生变化。

我们知道不同的语言需要不同的字符集来表示特定的字符。因此,处理文本意味着处理字体。但是,有关如何在 JasperReports 中使用字体的详细讨论可在第 报表字体 章中找到。

关于给定报表中文本内容的主要功能之一是将其国际化。这意味着,我们可以在不同的本地化环境中运行报表,使用不同的语言和其他本地化设置,而无需任何硬编码修改。当报表旨在进行国际化时,字符编码是一个重要的功能。

字符编码

字符是最小的书写单位,传达有意义的信息。它是一个抽象的概念,字符没有视觉外观。“大写拉丁字母 A”与“小写拉丁字母 a”以及“大写西里尔字母 A”和“大写希腊字母 Alpha”是不同的字符。

字符的视觉表示称为字形。特定的一组字形称为字体。“大写拉丁字母 A”、“大写西里尔字母 A”和“大写希腊字母 Alpha”可能具有相同的字形,但它们是不同的字符。同时,Times New Roman、Gill Sans 和 Poetica chancery italic 中“大写拉丁字母 A”的字形可能看起来非常不同,但它们仍然表示相同的字符。

可用字符的集合称为字符集。给定字符在字符集中的位置(索引)称为其代码位置或代码点。在给定字符集中以数字方式表示代码点的方法称为字符编码

编码通常以八位字节表示。八位字节是一组八个二进制数字,即八个 1 和 0。八位字节可以表示介于 0 和 255 之间或介于 0x00 和 0xFF 之间的数字范围,以使用十六进制表示法。

Unicode

Unicode 是一种字符集,包含了世界上大多数语言使用的字符。它可以容纳数百万个字符,并且已经包含了数十万个。Unicode 分为 64K 个字符的“平面”。在大多数情况下,只使用第一个平面,称为基本多语言平面或 BMP。

UTF-8 是推荐的编码方式。它使用可变数量的字节来表示不同的字符。

在 JRXML 文件中,编码属性在头部指定。它在报表编译时用于解码 XML 内容。例如,如果报表只包含法语单词和 ç、é、â 等字符,则 ISO-8859-1(也称为 Latin-1)编码就足够了。

<?xml version = "1.0" encoding = "ISO-8859-1"?>

如上所示,理想情况下,我们可以选择适合最小字符集的编码,该字符集可以正确表示文档中的所有字符。但在多语言文档(即包含多种语言拼写单词的文档)的情况下,应选择适合最小字符集的编码,即使这些字符属于不同的语言,也能够正确表示文档中的所有字符。能够处理多语言文档的字符编码之一是 **UTF-8**,它被 JasperReports 用作默认编码值。

在国际化过程中,文本通常保存在资源包文件中,而不是保存在文档中。因此,在某些情况下,JRXML 本身看起来完全兼容 ASCII,但在运行时生成的报表确实包含了无法用 ASCII 读取的文本。因此,对于某种类型的文档导出格式(例如 CSV、HTML、XHTML、XML 和文本),也必须知道生成文档的编码。不同的语言由不同的字符编码支持。因此,每次都需要在本地化环境中运行报表。此外,我们必须知道,生成文档语言的最合适的字符编码是什么。在这种情况下,JRXML 文件本身中定义的编码属性可能不再有用。

为了解决此类问题,我们可以使用一个名为 net.sf.jasperreports.export.character.encoding 的导出自定义属性。此导出自定义属性默认为 UTF-8,并且存在于 JasperReports 中。

此默认值设置在 default.jasperreports.properties 文件中。对于导出时的更具体选项,CHARACTER_ENCODING 导出参数也可用。

示例

为了演示如何在 Jasperreports 中使用 Unicode 支持,让我们编写新的报表模板 (jasper_report_template.jrxml)。**将其保存到 C:\tools\jasperreports-5.0.1\test** 目录。在这里,我们将使用 Unicode 字符 (\uXXXX) 显示不同语言的文本。任何使用 UTF-8 编码的字符都可以仅使用其 4 位十六进制代码来表示。例如,希腊字母 Γ 可以写成 \u0393。当遇到此类表示法时,引擎会调用字符集中相应的字符表示,并且只会打印出该特定字符。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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <parameter name = "GreekText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u0394\u03B5\u03BD "+
         "\u03BA\u03B1\u03C4\u03B1\u03BB\u03B1\u03B2\u03B1\u03AF"+
         "\u03BD\u03C9 \u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"]]>
      </defaultValueExpression>
   </parameter>
   
   <parameter name = "CyrillicText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u042F \u043D\u0435 "+
         "\u043C\u043E\u0433\u0443 \u043F\u043E\u043D\u044F\u0442\u044C "+
         "\u0433\u0440\u0435\u0447\u0435\u0441\u043A\u0438\u0439"]]>
      </defaultValueExpression>
   </parameter>

   <parameter name = "ArabicText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u0627\u0646\u0646\u0649 \u0644\u0627 "+
         "\u0627\u0641\u0647\u0645 \u0627\u0644\u0644\u063A\u0629 "+
         "\u0627\u0644\u0639\u0631\u0628\u064A\u0629"]]>
      </defaultValueExpression>
   </parameter>
   
   <parameter name = "HebrewText" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression><![CDATA["\u05D0\u05E0\u05D9 \u05DC\u05D0 "+
         "\u05DE\u05D1\u05D9\u05DF \u05E2\u05D1\u05E8\u05D9\u05EA"]]>
      </defaultValueExpression>
   </parameter>
   
   <title>
      <band height = "782">
         
         <textField>
            <reportElement x = "0" y = "50" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "50" width = "340" height = "60"/>
            <textElement/>
            
            <text>
               <![CDATA["GreekText and CyrillicText"]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "120" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isBold = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "120" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "190" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isItalic = "true" 
                  isUnderline = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "190" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "0" y = "260" width = "200" height = "60"/>
            
            <textElement>
               <font fontName = "DejaVu Sans" size = "14" isBold = "true" 
                  isItalic = "true" isUnderline = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{GreekText} + "\n" + $P{CyrillicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <staticText>
            <reportElement x = "210" y = "260" width = "340" height = "60"/>
            <textElement/>
            <text><![CDATA["GreekText and CyrillicText"]]></text>
         </staticText>

         <textField>
            <reportElement x = "0" y = "330" width = "200" height = "60"/>
            
            <textElement textAlignment = "Right">
               <font fontName="DejaVu Sans" size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ArabicText}]]>
            </textFieldExpression>
				
         </textField>
         
         <textField>
            <reportElement x = "210" y = "330" width = "340" height = "60"/>
            
            <textElement textAlignment = "Right">
               <font fontName = "DejaVu Sans" size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{HebrewText}]]>
            </textFieldExpression>
				
         </textField>
      
      </band>
   </title>
	
</jasperReport>

在上面的文件中,我们可以看到 UTF-8 编码的存在。此外,本地化的 Unicode 文本片段存储在文档参数中。

填充和生成报表的 Java 代码如下所示。让我们将此文件 **JasperUnicodeReportFill.java** 保存到 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint 目录。

package com.tutorialspoint;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperUnicodeReportFill {
   public static void main(String[] args) {
      String sourceFileName ="C://tools/jasperreports-5.0.1/test/" + 
         "jasper_report_template.jasper";

      try {
         JasperFillManager.fillReportToFile(sourceFileName, null, 
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

在填充报表时,我们使用 JREmptyDataSource 的实例来模拟其中包含一条记录的数据源,但此单条记录中的所有字段均为 null

报表生成

我们将使用我们常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下。

导入文件 - baseBuild.xml 从章节环境设置中获取,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the report 
      stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
		
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>

   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令 **ant -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill**(viewFullReport 是默认目标)如下所示:

C:\tools\jasperreports-5.0.1\test>ant  -Dmain-class=com.tutorialspoint.JasperUnicodeReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting t
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperUnicodeReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 4 minutes 1 second

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Unicode Example

在这里,我们可以看到显示的文本使用不同的语言。我们还看到这些语言在同一页面上组合在一起,并且混合在同一个文本元素中。

报表样式

JasperReports 具有一个 <style> 功能,有助于控制报表模板中的文本属性。此元素是在报表级别声明的一组样式设置。<style> 元素控制诸如前景颜色、背景颜色、字体是否为粗体、斜体或普通、字体大小、字体的边框以及许多其他属性。样式可以扩展其他样式,并添加或覆盖父样式的属性。

样式属性

一个 <style> 元素具有许多属性。以下表格列出了一些最常用的属性:

序号 属性及描述
1

name

是必须的。它必须是唯一的,因为它在整个报表中引用相应的报表样式。

2

isDefault

指示此样式是否为文档的默认样式。

3

style

是对父样式的引用。

4

mode

指定元素的透明度。可能的值为 OpaqueTransparent

5

forecolor

是对象的 foreground color 前景色。

6

backcolor

是对象的 background color 背景色。

7

fill

确定用于填充对象的填充图案。目前,允许的唯一值为 Solid

6

radius

指定矩形角弧的半径。

7

scaleImage

仅为图像指定缩放比例。可能的值:Clip, FillFrame, RetainShape, RealHeight,RealSize

8

hAlign

指定水平对齐方式。可能的值:Left, Center, Right,Justified

9

vAlign

指定垂直对齐方式。可能的值:Top, Middle,Bottom

10

rotation

指定元素的旋转。可能的值:None, Left, Right,UpsideDown

11

lineSpacing

指定文本行之间的行距。可能的值:Single, 1_1_2, Double

12

markup

指定格式化文本的标记样式。

13

fontName

指定字体名称。

14

fontSize

指定字体大小。

15

isBold

指示字体样式是否为粗体。

16

isItalic

指示字体样式是否为斜体。

17

isUnderline

指示字体样式是否为下划线。

18

isStrikeThrough

指示字体样式是否为删除线。

19

pdfFontName

指定相关的 PDF 字体名称。

20

pdfEncoding

指定 PDF 输出格式的字符编码。

22

isPdfEmbedded

指示 PDF 字体是否嵌入。

23

pattern

指定格式化文本的格式模式。

24

isBlankWhenNull

指示如果表达式计算结果为 null,是否应显示空字符串(空格)。

条件样式

在某些情况下,只有在满足特定条件时才应应用样式(例如,在报表详细信息部分交替显示相邻行的颜色)。这可以通过使用条件样式来实现。

条件样式有两个元素:

  • 布尔条件表达式
  • 样式

只有当条件计算结果为 true 时,才会使用该样式。

将样式应用于报表元素

任何类型的报表元素都可以使用 style 属性引用报表样式定义。因此,样式定义中声明的所有适用于当前元素的样式属性都将被继承。要覆盖继承的值,可以使用报表元素级别指定的样式属性。

样式模板

我们可以通过在公共位置定义样式来创建一组具有相同外观的报表。然后,报表模板可以引用此公共样式模板。样式模板是一个 XML 文件,其中包含一个或多个样式定义。样式模板文件按照惯例使用 ***.jrtx** 扩展名,但这并非强制性要求。

样式模板包含以下元素:

  • <jasperTemplate> - 这是样式模板文件的根元素。

  • <template> - 此元素用于包含对其他模板文件的引用。此元素的内容被解释为所引用模板文件的位置。

  • <style> - 此元素与报表设计模板(JRXML 文件)中同名元素相同,区别在于样式模板中的样式不能包含条件样式。此限制是由条件样式涉及报表表达式,并且表达式只能在单个报表定义的上下文中解释这一事实造成的。

对样式模板的引用在 JRXML 报表中包含为 <template> 元素。样式模板在报表填充时加载,并且样式名称引用在所有模板加载后解析。在加载样式模板并将样式名称解析为样式时,会创建一个样式模板树/图,树的顶部是在报表中定义的一组样式。在此树上,样式名称引用解析为在深度优先遍历中与名称匹配的最后一个样式。

示例

让我们尝试一下条件样式和样式模板。让我们将 <style> 元素 alternateStyle 添加到我们现有的报表模板中(第 报表设计 章)。根据条件,偶数计数的字体颜色变为蓝色。我们还包含了一个样式模板 "styles.jrtx"。修改后的报表模板 (jasper_report_template.jrxml) 如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录:

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50">
	
   <template>"styles.jrtx"</template>
   
   <style name = "alternateStyle" fontName = "Arial" forecolor = "red">
      <conditionalStyle>
         <conditionExpression>
            <![CDATA[new Boolean($V{countNumber}.intValue() % 2 == 0)]]>
         </conditionExpression>
			
         <style forecolor = "blue" isBold = "true"/>
      </conditionalStyle>
   </style>
   
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription><![CDATA[country]]></fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription><![CDATA[name]]></fieldDescription>
   </field>

   <variable name = "countNumber" class = "java.lang.Integer" calculation = "Count">
      <variableExpression><![CDATA[Boolean.TRUE]]></variableExpression>
   </variable>

   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
				
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression><![CDATA["Title"]]></anchorNameExpression>
         </textField>

         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
				
         </textField>
      
      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15" backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
				
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535" height = "14" backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
            
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
				
         </staticText>
         
         <textField>
            <reportElement style = "alternateStyle" x = "414" y = "0" 
               width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" 
               style = "Strong"/>
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>

</jasperReport>

样式模板 styles.jrtx 的内容如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录。

<?xml version = "1.0"?>

<!DOCTYPE jasperTemplate PUBLIC "-//JasperReports//DTD Template//EN"
  "http://jasperreports.sourceforge.net/dtds/jaspertemplate.dtd">

<jasperTemplate>
   <style name = "Strong" isBold = "true" pdfFontName = "Helvetica-Bold" 
      backcolor = "lightGray forecolor = "green"/>
</jasperTemplate>

报表填充的 Java 代码保持不变。文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java 的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示 -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java 的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the 
      report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
		
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下−

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: warning:
   'includeantruntime' was not set, defaulting to build.sysclasspath=last;
   set to false for repeatable builds
   [javac] Compiling 3 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See
   https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Style Example

在这里,我们可以看到偶数计数(在国家列中)的字体颜色已更改为蓝色。在名称列中,字体颜色已更改为绿色(此样式是从样式模板中引用的)。

报表脚本

在我们之前的章节中,我们已经看到报表上显示的数据通常是从报表参数和报表字段中获取的。可以使用报表变量及其表达式来处理此数据。在某些情况下,使用报表表达式或变量无法轻松实现复杂的功能。例如,复杂的字符串操作、在内存中构建映射或对象列表或使用第三方 Java API 操作日期。对于此类情况,JasperReports 为我们提供了一种简单而强大的方法来使用 **脚本**。

脚本是在报表事件发生时每次执行的 Java 代码序列。可以通过脚本影响报表变量的值。

脚本声明

我们可以通过两种方式声明脚本:

  • 使用 <scriptlet> 元素。此元素具有 name 属性和 class 属性。class 属性应指定类的名称,该类扩展 JRAbstractScriptlet 类。该类必须在报表填充时的类路径中可用,并且必须具有一个空构造函数,以便引擎可以动态地实例化它。

  • 使用报表模板 (JRXML) 中 <jasperReport> 元素的 scriptletClass 属性。通过使用脚本的完全限定名称(包括整个包名称)设置此属性,我们表明我们要使用脚本。使用此属性创建的脚本实例充当脚本列表中的第一个脚本,并具有预定义的名称 REPORT。

脚本类

脚本程序(Scriptlet)是一个 Java 类,它必须继承以下类之一:

  • net.sf.jasperreports.engine.JRAbstractScriptlet − 此类包含许多抽象方法,每个实现都必须重写这些方法。JasperReports 会在适当的时候自动调用这些方法。开发人员必须实现所有抽象方法。

  • net.sf.jasperreports.engine.JRDefaultScriptlet − 此类包含 JRAbstractScriptlet 中每个方法的默认空实现。开发人员只需要实现其项目所需的那些方法。

下表列出了上述类中的方法。在报表填充阶段,报表引擎会在适当的时间调用这些方法。

序号 方法及描述
1

public void beforeReportInit()

报表初始化之前调用。

2

public void afterReportInit()

报表初始化之后调用。

3

public void beforePageInit()

每个页面初始化之前调用。

4

public void afterPageInit()

每个页面初始化之后调用。

5

public void beforeColumnInit()

每个列初始化之前调用。

6

public void afterColumnInit()

每个列初始化之后调用。

7

public void beforeGroupInit(String groupName)

在参数中指定的组初始化之前调用。

8

public void afterGroupInit(String groupName)

在参数中指定的组初始化之后调用。

9

public void beforeDetailEval()

在评估报表详细信息部分中的每个记录之前调用。

10

public void afterDetailEval()

在评估报表详细信息部分中的每个记录之后调用。

每个报表可以指定任意数量的脚本程序。如果未为报表指定脚本程序,引擎仍然会创建一个唯一的 JRDefaultScriptlet 实例并将其注册到内置的 REPORT_SCRIPTLET 参数中。

我们可以向脚本程序添加任何需要的其他方法。报表可以通过使用内置参数 REPORT_SCRIPTLET 调用这些方法。

全局脚本程序

我们可以通过另一种方式将脚本程序与报表关联,即通过全局声明脚本程序。这使得脚本程序适用于在给定的 JasperReports 部署中填充的所有报表。由于可以将脚本程序作为扩展添加到 JasperReports 中,因此这变得很容易。脚本程序扩展点由 net.sf.jasperreports.engine.scriptlets.ScriptletFactory 接口表示。JasperReports 会在运行时加载通过扩展提供的全部脚本程序工厂。然后,它会询问每个工厂它们想要应用于当前正在运行的报表的脚本程序实例列表。在请求脚本程序实例列表时,引擎会提供一些上下文信息,工厂可以使用这些信息来确定哪些脚本程序实际上适用于当前报表。

报表监管器

监管器只是全局脚本程序的扩展,使我们能够解决报表引擎在运行时生成报表时进入无限循环的问题。无效的报表模板无法在设计时检测到,因为大多数情况下,进入无限循环的条件取决于在运行时馈送到引擎的实际数据。报表监管器有助于确定某个报表是否已进入无限循环,并且可以停止它。这可以防止运行报表的机器资源耗尽。

JasperReports 有两个简单的报表监管器,它们将根据指定的最大页面数或指定的超时间隔停止报表执行。它们是:

  • net.sf.jasperreports.governors.MaxPagesGovernor − 这是一个全局脚本程序,它查找两个配置属性以确定它是否适用于当前正在运行的报表。配置属性为:

    • net.sf.jasperreports.governor.max.pages.enabled=[true|false]

    • net.sf.jasperreports.governor.max.pages=[整数]

  • net.sf.jasperreports.governors.TimeoutGovernor− 这也是一个全局脚本程序,它查找以下两个配置属性以确定它是否适用。

    配置属性为:

    • net.sf.jasperreports.governor.timeout.enabled=[true|false]

    • net.sf.jasperreports.governor.timeout=[毫秒]

这两个监管器的属性可以在 jasperreports.properties 文件中全局设置,或者在报表级别作为自定义报表属性设置。这很有用,因为不同的报表可以有不同的估计大小或超时限制,而且因为您可能希望为所有报表启用监管器,同时为某些报表关闭它,反之亦然。

示例

让我们编写一个脚本程序类(MyScriptlet)。文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\MyScriptlet.java 的内容如下:

package com.tutorialspoint;

import net.sf.jasperreports.engine.JRDefaultScriptlet;
import net.sf.jasperreports.engine.JRScriptletException;


public class MyScriptlet extends JRDefaultScriptlet {

   public void afterReportInit() throws JRScriptletException{
      System.out.println("call afterReportInit()");
      // this.setVariableValue("AllCountries", sbuffer.toString());
      this.setVariableValue("someVar", new String("This variable value 
         was modified by the scriptlet."));
   }

   public String hello() throws JRScriptletException {
      return "Hello! I'm the report's scriptlet object.";
   }

}

上述脚本程序类的详细信息如下:

  • afterReportInit 方法中,我们将一个值设置为变量 "someVar" this.setVariableValue("someVar", new String("This variable value was modified by the scriptlet.")).

  • 在类的末尾,定义了一个名为 'hello' 的额外方法。这是一个示例,说明可以添加到脚本程序中的方法,该方法实际上返回一个值,而不是设置变量。

接下来,我们将脚本程序类引用添加到我们现有的报表模板中(章节 报表设计)。修改后的报表模板(jasper_report_template.jrxml)如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录:

<?xml version = "1.0"?>
<!DOCTYPE jasperReport PUBLIC
   "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" pageWidth = "595"
   pageHeight = "842" columnWidth = "515"
   leftMargin = "40" rightMargin = "40" topMargin = "50" bottomMargin = "50"
   scriptletClass = "com.tutorialspoint.MyScriptlet">
	
   <style name = "alternateStyle" fontName = "Arial" forecolor = "red">
      
      <conditionalStyle>
         <conditionExpression>
            <![CDATA[new Boolean($V{countNumber}.intValue() % 2 == 0)]]>
         </conditionExpression>
			
         <style forecolor = "blue" isBold = "true"/>
      </conditionalStyle>
   </style>
   
   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>

   <queryString>
      <![CDATA[]]>
   </queryString>

   <field name = "country" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[country]]>
      </fieldDescription>
   </field>

   <field name = "name" class = "java.lang.String">
      <fieldDescription>
         <![CDATA[name]]>
      </fieldDescription>
   </field>

   <variable name = "countNumber" class = "java.lang.Integer" 
      calculation = "Count">
      <variableExpression><
         ![CDATA[Boolean.TRUE]]>
      </variableExpression>
   </variable>

   <variable name = "someVar" class = "java.lang.String">
      <initialValueExpression>
        <![CDATA["This is the initial variable value."]]>
      </initialValueExpression>
   </variable>

   <title>
      <band height = "100">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
              <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
              <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
				
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
        
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "50" width = "515" 
               height = "30" forecolor = "#993300"/>
             
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$V{someVar}]]>
            </textFieldExpression>
				
         </textField>

      </band>
   </title>

   <columnHeader>
      <band height = "23">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "3" 
               width = "535" height = "15"
               backcolor = "#70A9A9" />
            
            <box>
               <bottomPen lineWidth = "1.0" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
				
         </staticText>
         
         <staticText>
            <reportElement x = "414" y = "3" width = "121" height = "15" />
                
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
            
            <text><![CDATA[Country]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "3" width = "136" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font isBold = "true" />
            </textElement>
				
            <text><![CDATA[Name]]></text>
         </staticText>
      
      </band>
   </columnHeader>

   <detail>
      <band height = "16">
         
         <staticText>
            <reportElement mode = "Opaque" x = "0" y = "0" 
               width = "535"	height = "14"
               backcolor = "#E5ECF9" />
            
            <box>
               <bottomPen lineWidth = "0.25" lineColor = "#CCCCCC" />
            </box>
				
            <textElement />
				
            <text>
               <![CDATA[]]>
            </text>
         </staticText>
         
         <textField>
            <reportElement style = "alternateStyle" x="414" y = "0" 
               width = "121" height = "15" />
            
            <textElement textAlignment = "Center" verticalAlignment = "Middle">
               <font size = "9" />
            </textElement>
            
				
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "0" y = "0" width = "136" height = "15" />
            <textElement textAlignment = "Center" verticalAlignment = "Middle" />
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <summary>
      <band height = "45">
            
         <textField isStretchWithOverflow = "true">
            <reportElement x = "0" y = "10" width = "515" height = "15" />
            <textElement textAlignment = "Center"/>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA["There are " + String.valueOf($V{REPORT_COUNT}) +
                  " records on this report."]]>
            </textFieldExpression>
         </textField>
         
         <textField isStretchWithOverflow = "true">
            <reportElement positionType = "Float" x = "0" y = "30" width = "515"
               height = "15" forecolor = "# 993300" />
               
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
               
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{REPORT_SCRIPTLET}.hello()]]>
            </textFieldExpression>
            
         </textField>
         
      </band>
   </summary>
	
</jasperReport>

修改后的报表模板的详细信息如下:

  • 我们在 <jasperReport> 元素的 scriptletClass 属性中引用了 MyScriptlet 类。

  • 脚本程序只能访问报表字段和参数,但不能修改它们。但是,脚本程序可以修改报表变量值。这可以通过调用 setVariableValue() 方法来实现。此方法在 JRAbstractScriptlet 类中定义,该类始终是任何脚本程序的父类。在这里,我们定义了一个变量 someVar,它将被 MyScriptlet 修改为具有值 This value was modified by the scriptlet

  • 上面的报表模板在摘要部分有一个方法调用,说明了如何编写新方法(在脚本程序中)并在报表模板中使用它们。($P{REPORT_SCRIPTLET}.hello()

报表填充的 Java 代码保持不变。文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java 的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO 文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下所示:

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下所示 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview 
      the report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下−

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to bu
   [javac] Compiling 4 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] call afterReportInit()
   [java] call afterReportInit()

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 18 minutes 49 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Scriplet Example

在这里,我们看到从 MyScriptlet 类显示了两个消息:

  • 在标题部分:This variable value was modified by the scriptlet
  • 在底部:Hello! I'm the report's scriptlet object.

创建子报表

子报表是 JasperReports 的一项不错的功能。此功能允许在一个报表中合并另一个报表,即一个报表可以是另一个报表的子报表。子报表有助于我们保持报表设计的简单性,因为我们可以创建许多简单的报表并将它们封装到主报表中。子报表的编译和填充方式与普通报表相同。任何报表模板在合并到另一个报表模板中时都可以用作子报表,而无需在报表模板内部进行任何更改。

子报表就像普通报表模板。它们实际上是 net.sf.jasperreports.engine.JasperReport 对象,这些对象在编译 net.sf.jasperreports.engine.design.JasperDesign 对象 后获得。

<subreport> 元素

<subreport> 元素用于将子报表引入主报表。以下是 <subreport> JRXML 元素中的子元素列表。

  • <reportElement>

  • <parametersMapExpression> − 用于传递包含报表参数的映射到子报表。该映射通常从主报表中的参数获得,或者通过使用内置的 REPORTS_PARAMETERS_MAP 参数将父报表的参数传递到子报表。此表达式应始终返回一个 java.util.Map 对象,其中键是参数名称。

  • <subreportParameter> − 此元素用于将参数传递到子报表。它有一个属性 name,这是必需的。

  • <connectionExpression > − 用于将 java.sql.Connection 传递到子报表。仅当子报表模板在报表填充阶段需要数据库连接时才使用它。

  • <dataSourceExpression> − 用于将数据源传递到子报表。此数据源通常从主报表中的参数获得,或者通过使用内置的 REPORT_DATA_SOURCE 参数将父报表的数据库连接传递到子报表。

  • 元素(connectionExpression 和 dataSourceExpression)不能同时出现在 <subreport> 元素声明中。这是因为我们不能同时向子报表提供数据源和数据库连接。我们必须选择其中之一并坚持使用它。

  • <returnValue> − 用于将子报表变量之一的值分配给主报表变量之一。此子元素具有以下属性:

    • subreportVariable − 此属性指定要返回其值的子报表变量的名称。

    • toVariable − 此属性指定要复制/递增其值的父报表变量的名称。

    • calculation − 此属性可以取以下值:Nothing、Count、DistinctCount、Sum、Average、Lowest、Highest、StandardDeviation、Variance。属性 calculation 的默认值为“Nothing”。

    • incrementerFactoryClass − 此属性指定用于创建递增器实例的工厂类。

  • <subreportExpression> − 指示在何处查找子报表的编译报表模板。此元素具有一个 class 属性。class 属性可以取以下任何值:java.lang.String、java.io.File、java.net.URL、java.io.InputStream、net.sf.jasperreports.engine.JasperReport。默认值为 java.lang.String

  • isUsingCache − 这是 <subreport> 元素的一个属性。这是一个布尔值,当设置为 true 时,报表引擎将尝试使用指定的源识别先前加载的子报表模板对象。此缓存功能仅适用于表达式返回 java.lang.String 对象作为子报表模板源的子报表元素,这些对象表示文件名、URL 或类路径资源。

示例

让我们举一个简单的例子来演示使用 JRDataSource 创建子报表。首先,让我们编写两个新的报表模板,一个作为子报表,另一个作为主报表。子报表(address_report_template.jrxml)模板的内容如下所示。将其保存到 C:\tools\jasperreports-5.0.1\test 目录。

<?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"
   name = "address_report_template" pageWidth = "175" pageHeight = "842" 
   columnWidth = "175" leftMargin = "0" rightMargin = "0" 
   topMargin = "0" bottomMargin = "0">

   <field name = "city" class = "java.lang.String"/>
   <field name = "street" class = "java.lang.String"/>
   
   <background>
      <band splitType = "Stretch"/>
   </background>
   
   <title>
      <band height = "20" splitType = "Stretch">
         
         <staticText>
            <reportElement x = "0" y = "0" width = "100" height = "20"/>
            
            <textElement>
               <font size = "14" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Addresses]]></text>
         </staticText>
      
      </band>
   </title>
   
   <pageHeader>
      <band height = "12" splitType = "Stretch"/>
   </pageHeader>
   
   <columnHeader>
      <band height = "12" splitType = "Stretch"/>
   </columnHeader>
   
   <detail>
      <band height = "27" splitType = "Stretch">
         
         <textField>
            <reportElement x = "0" y = "0" width = "120" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{city}+" Address:"]]>
            </textFieldExpression>
         </textField>
         
         <textField isStretchWithOverflow = "true">
            <reportElement x = "120" y = "0" width = "435" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{street}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <columnFooter>
      <band height = "8" splitType = "Stretch"/>
   </columnFooter>
  
   <pageFooter>
      <band height = "11" splitType = "Stretch"/>
   </pageFooter>
   
   <summary>
      <band height = "9" splitType = "Stretch"/>
   </summary>

</jasperReport>

由于我们使用数据源,因此我们需要编写一个对应的 POJO 文件 SubReportBean.java,如下所示。将其保存到目录 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint

package com.tutorialspoint;

public class SubReportBean {
   private String city;
   private String street;

   public String getCity() {
      return city;
   }

   public void setCity(String city) {
      this.city = city;
   }

   public String getStreet() {
      return street;
   }

   public void setStreet(String street) {
      this.street = street;
   }
}

在这里,我们声明了两个字段 'city''street',并定义了相应的 getter 和 setter 方法。

现在,让我们更新我们现有的 DataBean 文件。我们将添加一个新的字段 subReportBeanList,它是一个 java.util.List。此字段将保存 SubReportBean 对象的列表。DataBean 文件的内容如下所示。将其保存到目录 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint。

package com.tutorialspoint;

import java.util.List;

public class DataBean {
   private String name;
   private String country;
   private List<SubReportBean> subReportBeanList;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }

   public List<SubReportBean> getSubReportBeanList() {
      return subReportBeanList;
   }

   public void setSubReportBeanList(List<SubReportBean> subReportBeanList) {
      this.subReportBeanList = subReportBeanList;
   }
}

现在,让我们更新文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java。此文件的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {

      // Create sub report data
      SubReportBean subBean1 = new SubReportBean();
      subBean1.setCity("Mumbai");
      subBean1.setStreet("M.G.Road");
      SubReportBean subBean2 = new SubReportBean();
      subBean2.setCity("New York");
      subBean2.setStreet("Park Street");
      SubReportBean subBean3 = new SubReportBean();
      subBean3.setCity("San Fransisco");
      subBean3.setStreet("King Street");

      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      // Create master report data
      dataBeanList.add(produce("Manisha", "India",
         Arrays.asList(subBean1)));
      dataBeanList.add(produce("Dennis Ritchie", "USA",
         Arrays.asList(subBean2)));
      dataBeanList.add(produce("V.Anand", "India",
         Arrays.asList(subBean1)));
      dataBeanList.add(produce("Shrinath", "California",
         Arrays.asList(subBean3)));

      return dataBeanList;
   }

   /*
    * This method returns a DataBean object,
    * with name, country and sub report
    * bean data set in it.
    */
   private DataBean produce(String name, String country,
      List<SubReportBean> subBean) {
      DataBean dataBean = new DataBean();

      dataBean.setName(name);
      dataBean.setCountry(country);
      dataBean.setSubReportBeanList(subBean);

      return dataBean;
   }
}

在上述文件中的 produce() 方法中,我们正在设置 SubReportBean 列表。

现在,让我们编写一个新的主报表模板(jasper_report_template.jrxml)。将此文件保存到目录 C:\tools\jasperreports-5.0.1\test。此文件的内容如下所示:

<?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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth ="555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <parameter name = "SUBREPORT_DIR" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression>
         <![CDATA["C:\\tools\\jasperreports-5.0.1\\test\\"]]>
      </defaultValueExpression>
   </parameter>
   
   <field name = "country" class = "java.lang.String"/>
   <field name = "name" class = "java.lang.String"/>
   <field name = "subReportBeanList" class = "java.util.List"/>
   
   <background>
      <band splitType = "Stretch"/>
   </background>
   
   <title>
      <band height = "35" splitType = "Stretch">
         
         <staticText>
            <reportElement x = "0" y = "0" width = "204" height = "34"/>
            
            <textElement>
               <font size = "26" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Contact Report]]></text>
         </staticText>
      
      </band>
   </title>
   
   <pageHeader>
      <band height = "17" splitType = "Stretch"/>
   </pageHeader>
   
   <columnHeader>
      <band height = "21" splitType = "Stretch"/>
   </columnHeader>
   
   <detail>
      <band height = "112" splitType = "Stretch">
            
         <staticText>
            <reportElement x = "0" y = "0" width = "100" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Name:]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "20" width = "100" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Country:]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "104" y = "0" width = "277" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "104" y = "20" width = "277" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <subreport>
            <reportElement positionType = "Float" x = "335" y = "25" width = "175"
               height = "20" isRemoveLineWhenBlank = "true" backcolor = "#99ccff"/>

            <dataSourceExpression>
               new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
                  ($F{subReportBeanList})
            </dataSourceExpression>
            
            <subreportExpression class = "java.lang.String">
               <![CDATA[$P{SUBREPORT_DIR} + "address_report_template.jasper"]]>
            </subreportExpression>
         </subreport>
         
         <line>
            <reportElement x = "0" y = "50" width = "550" height = "1"/>
         </line>
      
      </band>
   </detail>
   
   <columnFooter>
      <band height = "19" splitType = "Stretch"/>
   </columnFooter>
   
   <pageFooter>
      <band height = "18" splitType = "Stretch"/>
   </pageFooter>
   
   <summary>
      <band height = "14" splitType = "Stretch"/>
   </summary>

</jasperReport>

在上面的模板中,我们定义了一个新的参数“SUBREPORT_DIR”,它定义了子报表的路径。我们定义了一个类型为 java.util.List 的字段 subReportBeanList,它对应于 DataBean 文件中的属性。元素 <subreport> 具有子元素 <dataSourceExpression>。我们将列表 subReportBeanList 放入 JRBeanCollectionDataSource 的实例中。在子元素 <subreportExpression/> 中,我们给出了子报表名称(AddressReport.jasper)。

现在,让我们编写一个新类 CreateReport 来编译和执行我们的报表模板。文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\CreateReport.java 的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class CreateReport {

   public static void main(String[] args) {
      String masterReportFileName = "C://tools/jasperreports-5.0.1/test"
         + "/jasper_report_template.jrxml";
      String subReportFileName = "C://tools/jasperreports-5.0.1/test"
         + "/AddressReport.jrxml";
      String destFileName = "C://tools/jasperreports-5.0.1/test"
         + "/jasper_report_template.JRprint";
			
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();
      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      try {
         /* Compile the master and sub report */
         JasperReport jasperMasterReport = JasperCompileManager
            .compileReport(masterReportFileName);
         JasperReport jasperSubReport = JasperCompileManager
            .compileReport(subReportFileName);

         Map<String, Object> parameters = new HashMap<String, Object>();
         parameters.put("subreportParameter", jasperSubReport);
         JasperFillManager.fillReportToFile(jasperMasterReport, 
            destFileName, parameters, beanColDataSource);

      } catch (JRException e) {

         e.printStackTrace();
      }
      System.out.println("Done filling!!! ...");
   }
}

在这里,我们看到我们正在编译主报表和子报表模板,并为报表填充传递主报表(.jasper)文件。

报表生成

现在,我们所有的文件都已准备就绪,让我们使用常规的 ANT 构建过程来编译和执行它们。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the 
      report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令 ant -Dmain-class=com.tutorialspoint.CreateReport(viewFullReport 是默认目标)如下所示:

Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: 
      warning: 'includeantruntime' was not set, defaulting to
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig 
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\
      jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.CreateReport
   [java] Compiling Report Design ...
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] Done filling!!! ...

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 72 minutes 13 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper SubReport Example

这里,我们可以看到显示了 Name、Country 和 Address 属性。

创建图表

以前,人们不得不依赖脚本程序来收集图表数据,并在报表模板中使用图像元素呈现图表。JasperReports 现在简化了这一过程,因为它使用新的图表组件内置支持图表。

使用新的图表组件,用户只需要应用视觉设置并定义表达式来帮助构建图表数据集。JasperReports 使用 JFreeChart 作为底层图表库。在配置新的图表组件时,涉及以下三个组件:

  • 整体图表组件。

  • 图表数据集(它对图表数据相关的设置进行分组)。

  • 图表绘图(它对与图表项呈现方式相关的视觉设置进行分组)。

JasperReports 目前支持以下类型的图表:饼图、3D 饼图、条形图、3D 条形图、XY 条形图、堆叠条形图、3D 堆叠条形图、折线图、XY 折线图、面积图、XY 面积图、堆叠面积图、散点图、气泡图、时间序列图、高低开收图、K 线图、多轴图、仪表盘、温度计和甘特图。

图表属性

图表是普通的报表元素,因此它们与所有其他报表元素共享一些属性。有一个名为 <chart> 的 JRXML 元素用于创建所有类型的图表。此元素对适用于所有类型图表的特殊图表特定设置进行分组。

图表子元素

<chart> 元素的子元素如下:

  • <reportElement> - 这些是可以显示的对象,例如静态文本、文本字段、图像、线条和矩形,您可以将它们放在报表模板部分中。

  • <Box> - 此元素用于用边框围绕图表,边框可以在每一侧自定义。

  • <chartTitle> - 此元素用于放置图表的标题。position 属性决定图表在报表中的标题位置。此元素具有属性 - Position(值可以是 TopBottomLeftRight。默认值为 Top)、color。<chartTitle> 以fonttitleExpression 作为子元素。

  • <chartSubtitle> - 此元素用于放置图表的副标题。此元素具有属性 - color。<chartSubtitle> 以fontsubtitleExpression 作为子元素。

  • <chartLegend> - 使用此元素可以控制与字体相关的属性以及图表图例的文本颜色和背景颜色。此元素具有属性 - textColorbackgroundColor

  • <anchorNameExpression> - 此元素创建锚点的目标。

  • <hyperlinkReferenceExpression> - 此元素包含一个报表表达式,指示外部资源(通常是 URL)的名称。

  • <hyperlinkAnchorExpression> - 超链接指向外部资源中的锚点。

  • <hyperlinkPageExpression> - 超链接指向当前报表中的页面。

  • <hyperlinkTooltipExpression> - 此元素控制超链接的工具提示。表达式的类型应为 java.lang.String

  • <hyperlinkParameter> - 此元素存在时,会根据参数值生成最终的超链接。

图表属性

<chart> 元素中可用于所有图表类型的属性如下:

  • isShowLegend - 此属性用于确定是否在报表上显示图表图例。值可以是 truefalse。默认值为 true

  • evaluationTime - 确定何时评估图表的表达式。值可以是 NowReportPageColumnGroupBand。默认值为 Now

  • evaluationGroup - 此属性确定用于评估图表表达式的组的名称。此属性的值必须与我们希望用作图表评估组的组的名称匹配。

  • hyperlinkType - 此属性可以保存任何文本值。默认值为 None。这意味着,即使存在特殊的超链接表达式,文本字段和图像也不表示超链接。

  • hyperlinkTarget - 此属性有助于在查看器中单击指定链接时自定义其行为。值可以是 SelfBlank。默认值为 Self

  • bookmarkLevel - 将此属性设置为正整数时,将在导出到 PDF 的报表中生成书签。默认值为 0

  • customizerClass - 这是类的名称(可选),可用于自定义图表。此元素的值必须是包含自定义类名称的字符串。

图表自定义

如上所述,JasperReports 使用 JFreeChart 作为底层图表库。JFreeChart 包含 JasperReports 不直接支持的功能。我们可以通过在 <chart> 元素中提供自定义类来利用这些功能。自定义类只不过是 net.sf.jasperreports.engine.JRChartCustomizer 接口的实现。实现此接口的最简单方法是扩展 net.sf.jasperreports.engine.JRAbstractChartCustomizer 类,从而访问参数、字段和变量,以便基于报表数据更灵活地自定义图表。

图表数据集

所有图表类型的一个共同属性是 <dataset> 元素。图表数据集有助于映射报表数据并在运行时检索图表数据。每种图表类型包含不同的子元素来定义图表的表达式。这些表达式定义用于生成图表的数据。所有这些子元素都包含一个 <dataset> 元素,该元素定义何时评估和重置图表的表达式。

JasperReports 中提供了多种类型的图表数据集,因为每种类型的图表都使用某些数据集:饼图、分类图、XY 图、时间序列图、时间段图、XYZ 图和高低图。这些数据集类型中的每一个都实现了 net.sf.jasperreports.engine.JRChartDataset 接口,该接口定义图表数据集。所有图表数据集都以相同的方式初始化和递增;但是,它们仅在它们映射的数据类型或数据系列方面有所不同。

数据集属性

下表总结了 <dataset> 元素的属性:

属性 描述
resetType 此属性确定何时重置图表表达式的值。 None、Report、Page、Column、Group。默认值为 Report
resetGroup 此属性确定重置图表表达式值的组的名称。 此属性的值必须与 JRXML 报表模板中声明的任何组的名称匹配。
incrementType 此属性确定何时重新计算图表表达式的值。 None、Report、Page、Column、Group。默认值为 "None"
incrementGroup 此属性确定重新计算图表表达式的组的名称。 此属性的值必须与 JRXML 报表模板中声明的组的名称匹配。

下表总结了 <dataset> 元素的子元素:

子元素 描述
<incrementWhenExpression> 可以通过使用此子元素过滤掉不需要的数据来自定义图表数据集的递增方式。
<datasetRun> 这包含实例化报表子数据集所需的信息。

数据集类型

下面解释特定的数据集类型:

饼图数据集

饼图数据集以以下表达式为特征:

  • <keyExpression> - 表示构成饼图中扇区的类别。此表达式可以返回任何 java.lang.Comparable 对象。

  • <valueExpression> - 生成与数据集中每个类别/键相对应的值。值始终是 java.lang.Number 对象。

  • <labelExpression> - 如果此表达式缺失,图表将为饼图中的每个扇区显示默认标签。使用此表达式(返回 java.lang.String 值)自定义饼图的项目标签。

  • <sectionHyperlink> - 设置与饼图扇区关联的超链接。

分类数据集

分类数据集以 <categorySeries> 元素为特征,该元素包含:

  • <seriesExpression> - 指示系列的名称。此表达式可以返回任何 java.lang.Comparable 对象。

  • <categoryExpression> - 返回系列表达式指定的系列中每个值的类别名称。类别是 java.lang.Comparable 对象。

  • <valueExpression> - 生成与数据集中每个类别相对应的值。值始终是 java.lang.Number 对象。

  • <labelExpression> - 如果此表达式缺失,图表将为图表中的每个项目显示默认标签。使用此表达式(返回 java.lang.String 值)自定义图表的项目标签。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

XY 数据集

XY 数据集以 <xySeries> 元素为特征,该元素包含:

  • <seriesExpression> - 指示系列的名称。此表达式可以返回任何 java.lang.Comparable 对象。

  • <xValueExpression> - 返回表示将添加到当前数据系列的 (x, y) 对中的 X 值的 java.lang.Number 值。

  • <yValueExpression> - 返回表示将添加到当前数据系列的 (x, y) 对中的 Y 值的 java.lang.Number 值。

  • <labelExpression> - 如果此表达式缺失,图表将为图表中的每个项目显示默认标签。使用此表达式(返回 java.lang.String 值)自定义图表的项目标签。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

XYZ 数据集

XYZ 数据集以 <xyzSeries> 元素为特征,该元素包含:

  • <seriesExpression> - 指示系列的名称。此表达式可以返回任何 java.lang.Comparable 对象。

  • <xValueExpression> - 返回表示将添加到当前数据系列的 (x, y, z) 项目中的 X 值的 java.lang.Number 值。

  • <yValueExpression> - 返回表示将添加到当前数据系列的 (x, y, z) 项目中的 Y 值的 java.lang.Number 值。

  • <zValueExpression> - 返回表示将添加到当前数据系列的 (x, y, z) 项目中的 Z 值的 java.lang.Number 值。

  • <labelExpression> - 如果此表达式缺失,图表将为图表中的每个项目显示默认标签。使用此表达式(返回 java.lang.String 值)自定义图表的项目标签。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

时间序列数据集

时间序列数据集以 timePeriod 属性和 <timeSeries> 元素为特征。timePeriod 属性指定数据集中数据系列的类型。时间序列可以包含与天、月、年或其他预定义时间段关联的数值。可能的值为:Year、Quarter、Month、Week、Day - 这是默认值、Hour、Minute、Second、Millisecond。

<timeSeries> 元素包含:

  • <seriesExpression> - 指示系列的名称。此表达式可以返回任何 java.lang.Comparable 对象。

  • <timePeriodExpression> − 返回一个 java.util.Date 值,引擎将根据上面提到的 timePeriod 属性的值从中提取相应的时间段。

  • <valueExpression> − 返回 java.lang.Number 值,在递增数据集的当前系列时,将其与相应的时间段值关联。

  • <labelExpression> - 如果此表达式缺失,图表将为图表中的每个项目显示默认标签。使用此表达式(返回 java.lang.String 值)自定义图表的项目标签。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

时间段数据集

时间段数据集以 <timePeriodSeries> 元素为特征,其中包含 -

  • <seriesExpression> - 指示系列的名称。此表达式可以返回任何 java.lang.Comparable 对象。

  • <startDateExpression> − 指定日期间隔的开始,当数值添加到时间段系列时,将与其关联。

  • <endDateExpression> − 指定日期间隔的结束,当数值添加到时间段系列时,将与其关联。

  • <valueExpression> − 返回 java.lang.Number 值,将其与由开始日期和结束日期表达式指定当前日期间隔关联。

  • <labelExpression> - 如果此表达式缺失,图表将为图表中的每个项目显示默认标签。使用此表达式(返回 java.lang.String 值)自定义图表的项目标签。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

高低数据集

高低数据集以以下表达式为特征 -

  • <seriesExpression> − 目前,高低或烛台图表中仅支持一个系列。但是,此单个系列必须由此表达式返回的 java.lang.Comparable 值标识,并且还必须用作图表图例中的系列名称。

  • <dateExpression> − 返回当前(高、低、开、收、量)项目所指的日期。

  • <highExpression> − 返回一个 java.lang.Number 值,当数据集递增时,它将成为添加到系列中的数据项的一部分。

  • <lowExpression> − 返回一个 java.lang.Number 值,当数据集递增时,它将成为添加到系列中的数据项的一部分。

  • <openExpression> − 返回一个 java.lang.Number 值,当数据集递增时,它将成为添加到系列中的数据项的一部分。

  • <closeExpression> − 返回一个 java.lang.Number 值,当数据集递增时,它将成为添加到系列中的数据项的一部分。

  • <volumeExpression> − 一个数字表达式,返回要用于当前数据项的成交量值。仅用于烛台图表。

  • <itemHyperlink> - 设置与图表项目关联的超链接。

值数据集

这是一种特殊图表数据集实现,包含单个值,用于渲染仪表和温度计图表。该值使用 <valueExpression> 表达式收集。

图表绘图

所有图表类型中另一个常见的 JRXML 元素是 <plot> 元素。这使我们能够定义图表的几个特性,例如方向和背景颜色。绘图根据图表类型而有所不同。

绘图属性

下表总结了 <plot> 元素的属性 -

属性 描述
backcolor 此属性定义图表的背景颜色。 任何六位十六进制值都是此属性的有效值。十六进制值必须以 # 开头。
方向 此属性定义图表的方位。 水平、垂直 默认值为“垂直”
backgroundAlpha 此属性定义图表的背景颜色的透明度。 此属性的有效值包括 0 到 1(包括)之间的任何十进制数。数字越高,背景越不透明。默认值为“1”。
foregroundAlpha 此属性定义图表的前景颜色的透明度。 此属性的有效值包括 0 到 1(包括)之间的任何十进制数。数字越高,背景越不透明。默认值为“1”。
labelRotation 此属性允许旋转 x 轴上的文本标签以顺时针或逆时针旋转。此属性仅适用于 x 轴不是数字或不显示日期的图表。 默认值为“0.0”。

<plot> 元素有一个子元素 <seriesColor>,其属性为:seriesOrdercolor。此元素自定义系列的颜色及其在颜色序列中的位置。

图表绘图的特定设置

  • piePlot − 它没有特定设置

  • pie3DPlot − 包含 depthFactor 属性,这是一个介于 0 到 1 之间的数值,表示饼图的深度占绘图区域高度的百分比。

  • barPlot − 可以显示或隐藏刻度标签、刻度标记或项目标签,并提供两个轴的设置。

  • bar3DPlot − 提供与 barPlot 相同的设置,并使用 xOffset 和 yOffset 属性生成 3D 效果。

  • linePlot − 可以显示或隐藏连接项目点的线,可以显示或隐藏与项目点关联的形状,并提供两个轴的设置。

  • scatterPlot − 与 linePlot 类似,它可以显示或隐藏连接项目点的线,可以显示或隐藏与项目点关联的形状,并提供两个轴的设置。

  • areaPlot − 提供两个轴的设置。

  • bubblePlot − 可以通过设置 scaleType 属性来设置气泡尺寸,并提供两个轴的设置。

  • timeSeriesPlot − 可以显示或隐藏连接项目点的线,可以显示或隐藏与项目点关联的形状,并提供两个轴的设置。

  • highLowPlot − 可以显示或隐藏开盘刻度,可以显示或隐藏收盘刻度,并提供两个轴的设置。

  • candlestickPlot − 可以显示或隐藏成交量,并提供两个轴的设置。

  • meterPlot − 包含刻度盘形状、刻度角、计量单位、刻度间隔、刻度盘颜色、指针颜色、刻度颜色、值显示字体、颜色和格式模式、数据范围以及仪表间隔的特定设置。

  • thermometerPlot − 包含值位置、水银颜色、显示/隐藏值线、值显示字体、颜色和格式模式、数据范围、低范围、中范围和高范围的特定设置。

  • multiAxisChart − 包含绘图中包含的轴的特定设置。

图表类型

JasperReports 提供对多种图表类型的内置支持。它们列出如下 -

  • pieChart − 饼图数据集和饼图绘图的组合。

  • pie3DChart − 将饼图数据集和 3D 饼图绘图组合在一起。

  • barChart − 分类数据集和条形图绘图的基本组合。

  • bar3DChart − 包含分类数据集和 3D 条形图绘图。

  • xyBarChart − 支持时间段数据集、时间序列数据集和 XY 数据集,并使用条形图绘图渲染轴和项目。

  • stackedBarChart − 使用来自分类数据集的数据,并使用条形图绘图渲染其内容。

  • stackedBar3DChart − 使用来自分类数据集的数据,并使用 3D 条形图绘图渲染其内容。

  • lineChart − 将分类数据集和折线图绘图组合在一起。

  • xyLineChart − 将 XY 数据集和折线图绘图组合在一起。

  • areaChart − 分类数据集中的项目使用面积图绘图进行渲染。

  • stackedAreaChart − 分类数据集中的项目使用面积图绘图进行渲染。

  • xyAreaChart − 使用来自 XY 数据集的数据,并通过面积图绘图进行渲染。

  • scatterChart − 将 XY 数据集与散点图绘图组合在一起。

  • bubbleChart − 将 XYZ 数据集与气泡图绘图组合在一起。

  • timeSeriesChart − 将时间序列数据集和时间序列绘图组合在一起。

  • highLowChart − 高低数据集和高低绘图的组合。

  • candlestickChart − 使用来自高低数据集的数据,但使用特殊的烛台绘图。

  • meterChart − 使用仪表绘图中的渲染选项,在刻度盘上显示来自值数据集的单个值。

  • thermometerChart − 使用温度计绘图中的渲染选项显示值数据集中的单个值。

  • multiAxisChart − 包含多个范围轴,所有这些轴共享一个公共域轴。

示例

为了演示图表,让我们编写一个新的报表模板 (jasper_report_template.jrxml)。在这里,我们将 <barChart> 元素添加到 <pageHeader> 部分,并将 <pieChart> 添加到 <summary> 部分。我们将在图表中显示每门课程获得的分数。将其保存到目录 C:\tools\jasperreports-5.0.1\test。文件内容如下 -

<?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"
   name = "jasper_report_template" pageWidth = "595" pageHeight = "860"
   columnWidth = "515" leftMargin = "40" rightMargin = "40"
   topMargin = "50" bottomMargin = "50">

   <field name = "subjectName" class = "java.lang.String"/>
   <field name = "marks" class = "java.lang.Integer"/>
   
   <variable name = "countNumber" class = "java.lang.Integer" calculation = "Count">
      <variableExpression>
         <![CDATA[Boolean.TRUE]]>
      </variableExpression>
   </variable>
   
   <background>
      <band splitType = "Stretch"/>
   </background>
   
   <title>
      <band height = "79" splitType = "Stretch"/>
   </title>
   
   <pageHeader>
      <band height = "200">
    
         <barChart>
            <chart evaluationTime = "Report">
               <reportElement x = "0" y = "0" width = "555" height = "200"/>
            
               <chartTitle>
                  <titleExpression>
                     <![CDATA["My First JR Bar Chart"]]>
                  </titleExpression>
               </chartTitle>
            </chart>
      
            <categoryDataset>
               <dataset incrementType = "None"/>
            
               <categorySeries>
                  <seriesExpression>
                     <![CDATA[$F{subjectName}]]>
                  </seriesExpression>
            
                  <categoryExpression>
                     <![CDATA[$F{subjectName}]]>
                  </categoryExpression>
            
                  <valueExpression>
                     <![CDATA[$F{marks}]]>
                  </valueExpression>

               </categorySeries>
            </categoryDataset>
      
            <barPlot isShowTickMarks = "false">
               <plot/>
            </barPlot>
         </barChart>
      
      </band>
   </pageHeader>
   
   <columnHeader>
      <band height = "20" splitType = "Stretch"/>
   </columnHeader>
   
   <detail>
      <band height = "20" splitType = "Stretch"/>
   </detail>
   
   <columnFooter>
      <band height = "20" splitType = "Stretch"/>
   </columnFooter>
   
   <pageFooter>
      <band height = "20" splitType = "Stretch"/>
   </pageFooter>
   
   <summary>
      <band height = "400" splitType = "Stretch">
      
         <pieChart>
            <chart evaluationTime = "Report">
               <reportElement x = "135" y = "0" width = "270" height = "300"/>
            
               <chartTitle>
                  <titleExpression>
                     <![CDATA["My First JR Pie Chart"]]>
                  </titleExpression>
               </chartTitle>
            </chart>
         
            <pieDataset>
               <dataset incrementType = "None"/>
               
               <keyExpression>
                  <![CDATA[$F{subjectName}]]>
               </keyExpression>
            
               <valueExpression>
                  <![CDATA[$F{marks}]]>
               </valueExpression>
            </pieDataset>
            
            <piePlot>
               <plot/>
               <itemLabel/>
            </piePlot>
         </pieChart>
      
      </band>
   </summary>
	
</jasperReport>

上述文件的详细信息如下 -

  • 用于创建条形图的 JRXML 元素是 </barChart>,位于 <pageHeader> 中。它包含一个 </chart> 子元素,该元素包含一个 <reportElement> 子元素,用于定义图表的尺寸和位置。

  • 条形图中的 <dataset> 元素必须包含在 <categoryDataset> 和 </categoryDataset> JRXML 元素之间。

  • <categoryDataset> 必须包含 <categorySeries> 元素。此元素定义条形将表示什么数据元素(在本例中为科目名称)。

  • <categoryDataset> 还必须包含一个元素,该元素定义如何将数据分成类别以进行比较。在这里,数据按科目名称分开。

  • <valueExpression> 元素定义使用什么表达式来确定图表中每个条形的值。在这里,我们使用“marks”。

  • 对于饼图,我们在 <summary> 部分使用了元素 <pieChart>。它包含一个 </chart> 子元素。

  • 子元素包含一个报表表达式,指示在图表中使用什么作为键。在这里,我们使用了 subjectName。

  • 子元素包含一个用于计算键值的表达式。在这里,我们使用了 marks。

报表填充的 Java 代码保持不变。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();

      try {
         JasperFillManager.fillReportToFile( sourceFileName,
            parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

由于我们将显示每门科目获得的分数,因此需要更改 POJO。文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java 内容如下 -

package com.tutorialspoint;

public class DataBean {
   private String subjectName;
   private Integer marks;

   public String getSubjectName() {
      return subjectName;
   }

   public void setSubjectName(String subjectName) {
      this.subjectName = subjectName;
   }

   public Integer getMarks() {
      return marks;
   }

   public void setMarks(Integer marks) {
      this.marks = marks;
   }

}

文件 C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java 的内容也需要更新如下 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("English", 58));
      dataBeanList.add(produce("SocialStudies", 68));
      dataBeanList.add(produce("Maths", 38));
      dataBeanList.add(produce("Hindi", 88));
      dataBeanList.add(produce("Scince", 78));
      
      return dataBeanList;
   }

   /*
    * This method returns a DataBean object, with subjectName ,
    * and marks set in it.
    */
   private DataBean produce(String subjectName, Integer marks) {
      DataBean dataBean = new DataBean();

      dataBean.setSubjectName(subjectName);
      dataBean.setMarks(marks);

      return dataBean;
   }
}

报表生成

接下来,让我们使用我们常规的 ANT 构建过程编译和执行上述文件。build.xml 文件(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the 
      report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
		
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
			
         <classpath refid = "classpath" />
      </jrc>
   </target>

</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to bu
   [javac] Compiling 3 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig 
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 19 minutes 45 seconds

上述编译的结果是,一个 JasperViewer 窗口打开,如下面的屏幕所示−

Jasper Bar  Chart Example

Jasper Pie Chart Example

在这里,我们看到条形图是在 pageheader 中创建的,饼图是在 summary 部分创建的。

JasperReports - 交叉表

交叉表(交叉制表)报表是包含表格的报表,这些表格以表格形式跨行和列排列数据。交叉表对象用于在主报表中插入交叉表报表。交叉表可用于任何级别的数据(名义、有序、区间或比率),并且通常以动态表格的形式显示报表变量中包含的汇总数据。变量用于显示汇总数据,例如总和、计数、平均值。

交叉表属性

JRXML 元素 <crosstab> 用于将交叉表插入报表。

属性

以下是 <crosstab> 元素的属性列表 -

  • isRepeatColumnHeaders − 指示是否应在分页符后重新打印列标题。默认值为 true

  • isRepeatRowHeaders − 指示是否应在交叉表列中断后重新打印行标题。默认值为 true

  • columnBreakOffset − 当发生列中断时,指示在后续交叉表部分放置在同一页面上之前一个部分下方之前,以像素为单位测量的垂直空间量。默认值为 10。

  • runDirection − 指示是否应从左到右 (LTR) 或从右到左 (RTL) 填充交叉表数据。默认值为 LTR。

  • ignoreWidth − 指示交叉表是否会超出初始交叉表宽度限制并且不生成列中断。否则,它将在交叉表宽度限制内停止渲染列,并在所有行开始渲染后才继续渲染剩余的列。默认值为 false

子元素

<crosstab> 元素具有以下子元素 -

  • <reportElement> − 此元素定义交叉表在其包含元素中的位置、宽度和高度。此元素的属性包括所有标准 <reportElement> 属性。

  • <crosstabParameter> − 此元素用于从交叉表内部访问报表变量和参数。此元素的属性包括 -

    • name − 这定义了参数名称。

    • class − 表示参数类。

  • <parametersMapExpression> − 此元素用于传递一个报表变量或参数,该变量或参数包含 java.util.Map 的实例,作为交叉表的参数集。此元素不包含任何属性。

  • <crosstabDataset> − 此元素定义用于填充交叉表的数据集(有关详细说明,请参见下一节)。此元素的属性包括 -

    • isDataPreSorted − 指示数据集中的数据是否已预排序。默认值为 false

  • <crosstabHeaderCell> − 此元素定义交叉表左上角区域的内容,该区域是列标题和行标题的交汇处。此单元格的大小根据定义的行和列的宽度和高度自动计算。

  • <rowGroup> − 此元素定义用于将数据拆分为行的组。此元素的属性包括 -

    • name − 定义行组的名称。

    • width − 定义行组的宽度。

    • headerPosition − 定义标题内容的位置(顶部、中间、底部、拉伸)。

    • totalPosition − 定义整个列的位置(开始、结束、无)。

    此元素包含以下子元素 -

    • <bucket>

    • <crosstabRowHeader>

    • <crosstabTotalRowHeader>

  • <columnGroup> − 此元素定义用于将数据拆分为列的组。此元素的属性包括 -

    • name − 定义列组名称。

    • height − 定义列组标题的高度。

    • headerPosition − 定义标题内容的位置(右、左、中心、拉伸)。

    • totalPosition − 定义整个列的位置(开始、结束、无)。

    此元素包含以下子元素 -

    • <bucket>

    • <crosstabColumnHeader>

    • <crosstabTotalColumnHeader>

  • <measure> − 此元素定义要跨行和列执行的计算。此元素的属性包括 -

    • name − 定义度量的名称。

    • class − 指示度量类。

    • calculation − 指示要在交叉表单元格值之间执行的计算。其值可以是以下任何一个 - 无、计数、唯一计数、总和、平均值、最低值、最高值、标准差、方差第一个。默认值为

  • <crosstabCell> − 此元素定义非标题单元格中的数据如何布局。此元素的属性包括 -

    • columnTotalGroup − 指示用于计算列总计的组。

    • height − 定义单元格的高度。

    • rowTotalGroup − 指示用于计算行总计的组。

    • width − 定义单元格的宽度。

  • <whenNoDataCell> − 此元素定义在空交叉表单元格中显示的内容。此元素不包含任何属性。

交叉表中的数据分组

交叉表计算引擎通过迭代关联的数据集记录来聚合数据。为了聚合数据,需要先对其进行分组。在交叉表中,行和列基于特定的分组项,称为。桶定义应包含 -

  • bucketExpression − 要评估的表达式,以便获取数据分组项。

  • comparatorExpression − 在值的自然排序不是最佳选择的情况下需要。

  • orderByExpression − 指示用于排序数据的的值。

交叉表中的行和列组(如上所述)依赖于

内置交叉表总计变量

下面列出了度量的当前值以及对应于单元格的不同级别的总计,可以通过根据以下方案命名的变量访问 -

  • 度量计算的当前值存储在一个与度量名称相同的变量中。

  • <Measure>_<Column Group>_ALL − 这会产生同一行中列组中所有条目的总计。

  • <Measure>_<Row Group>_ALL − 这会产生同一列中行组中所有条目的总计。

  • <Measure>_<Row Group>_<Column Group>_ALL − 这会产生对应于行和列组中所有条目的组合总计。

示例

为了演示交叉表,让我们编写一个新的报表模板 (jasper_report_template.jrxml)。在这里,我们将交叉表添加到摘要部分。将其保存到目录C:\tools\jasperreports-5.0.1\test中。文件内容如下所示 -

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
	
<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <parameter name = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>
   
   <field name = "name" class = "java.lang.String"/>
   <field name = "country" class = "java.lang.String"/>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>
   
   <summary>
      <band height = "60">
      
      <crosstab>
         <reportElement width = "782" y = "0" x = "0" height = "60"/>
          
         <rowGroup name = "nameGroup" width = "100">
         
            <bucket>
               <bucketExpression class = "java.lang.String">
                  <![CDATA[$F{name}]]>
               </bucketExpression>
            </bucket>
            
            <crosstabRowHeader>
            
               <cellContents>
                  <box border = "Thin" borderColor = "black"/>
                  
                  <textField>
                     <reportElement width = "100" y = "0" x = "0" height = "20"/>
                     <textElement textAlignment = "Right" 
                        verticalAlignment = "Middle"/>
                     
                     <textFieldExpression>
                        <![CDATA[$V{nameGroup}]]>
                     </textFieldExpression>
                  </textField>
            
               </cellContents>
         
            </crosstabRowHeader>

         </rowGroup>
         
         <columnGroup name = "countryGroup" height = "20">
            <bucket>
               
               <bucketExpression class = "java.lang.String">
                  $F{country}
               </bucketExpression>
            </bucket>
            
            <crosstabColumnHeader>
               <cellContents>
                  <box border = "Thin" borderColor = "black"/>
                  <textField isStretchWithOverflow = "true">
                     <reportElement width = "60" y = "0" x = "0" height = "20"/>
                     <textElement verticalAlignment = "Bottom"/>
                     <textFieldExpression>
                        <![CDATA[$V{countryGroup}]]>
                     </textFieldExpression>
                  </textField>
               </cellContents>
            </crosstabColumnHeader>

         </columnGroup>
         
         <measure name = "tailNumCount" class = "java.lang.Integer"  
            calculation = "Count">
            <measureExpression>$F{country}</measureExpression>
         </measure>
         
         <crosstabCell height = "20" width = "60">
            <cellContents backcolor = "#FFFFFF">
               <box borderColor = "black" border = "Thin"/>
               <textField>
                  <reportElement x = "5" y = "0" width = "55" height = "20"/>
                  <textElement textAlignment = "Left" 
                     verticalAlignment = "Bottom"/>
                  <textFieldExpression class = "java.lang.Integer">
                      $V{tailNumCount}
                  </textFieldExpression>
               </textField>
            </cellContents>
         </crosstabCell>
      
      </crosstab>
      
      </band>
   </summary>
	
</jasperReport>

上述文件的详细信息如下 -

  • 交叉表由<crosstab>元素定义。

  • <rowGroup>元素定义一个组,用于将数据拆分为行。在这里,每一行将显示不同名称的数据。

  • <bucket>和<bucketExpression>元素定义要使用哪个报表表达式作为<rowGroup>的分组分隔符。在这里,我们使用name字段作为分隔符,以便按名称拆分行。

  • <crosstabRowHeader>元素定义要用作行标题的表达式。它包含一个子元素,即<cellContents>,它在交叉表内充当内部频段。与其在<crosstabRowHeader>内为文本字段定义变量名,不如将名称分配给<rowGroup>(通过其name属性),因此它会创建一个隐式变量。<crosstabRowHeader>元素定义整行的标题单元格的内容。它将单个<cellContents>元素作为其唯一的子元素。

  • <columnGroup>元素及其子元素类似于<rowGroup>元素,只是它影响列而不是行。

  • <measure>元素定义要跨行和列执行的计算。calculation属性设置为Count

  • <crosstabCell>元素定义非标题单元格中的数据如何布局。此元素还包含一个<crosstabCell>元素作为其唯一的子元素。

报表填充的 Java 代码保持不变。文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java的内容如下所示:

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

POJO文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java的内容如下 -

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }
}

文件C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java的内容如下 -

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

报表生成

接下来,让我们使用我们常规的 ANT 构建过程编译和执行上述文件。build.xml 文件(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the 
      report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>
	
</project>

接下来,让我们打开命令行窗口并转到放置 build.xml 的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFill(viewFullReport 是默认目标)如下所示 -

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to
   [javac] Compiling 3 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig 
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger (
   net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 20 minutes 53 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Crosstab Example

在这里,我们看到每个国家和名称都进行了制表。

JasperReports - 国际化

有时,我们需要不同语言的报表。为每种不同的语言编写相同的报表意味着很多冗余工作。只有文本片段因语言而异才应分别编写,并在运行时根据区域设置加载到文本元素中。这是报表国际化的目的。国际化报表一旦编写,即可在任何地方运行。

在以下步骤中,我们列出了如何生成不同语言的报表以及报表国际化的其他一些功能 -

  • 将资源包java.util.ResourceBundle与报表模板关联。有两种方法可以将java.util.ResourceBundle对象与报表模板关联。

    • 在设计时,通过将报表模板对象的resourceBundle属性设置为目标资源包的基本名称。

    • 可以在报表填充时通过提供java.util.ResourceBundle对象作为REPORT_RESOURCE_BUNDLE参数的值来进行动态/运行时关联。

    • 如果报表需要在与当前区域设置不同的区域设置中生成,则可以使用内置的REPORT_LOCALE参数在填充报表时指定运行时区域设置。

  • 为了方便报表国际化,在报表表达式内部可以使用特殊的语法$R{}来引用放置在与报表关联的java.util.ResourceBundle对象内的java.lang.String资源。$R{}字符语法从资源包中提取特定于区域设置的资源,具体取决于必须放在括号之间的键 -

<textFieldExpression>
   $R{report.title}
</textFieldExpression>

上述文本字段通过从与报表模板关联的资源包中提取字符串值来显示报表的标题,具体取决于运行时提供的区域设置和report.title键。

  • 根据报表区域设置以不同语言格式化消息,报表中有一个内置方法net.sf.jasperreports.engine.fill.JRCalculator。此方法提供的功能类似于java.text.MessageFormat类。此方法msg()具有三个方便的签名,允许您在消息中使用最多三个消息参数。

  • 一个内置的str()方法(等效于报表表达式中的$R{}语法),它根据报表区域设置访问资源包内容。

  • 对于日期和时间格式,可以使用内置的REPORT_TIME_ZONE参数来确保正确的时区转换。

  • 在生成的输出中,库会保留有关文本运行方向的信息,以便可以正确呈现以从右到左书写语言(如阿拉伯语和希伯来语)生成的文档。

  • 如果应用程序依赖于内置的Swing查看器来显示生成的报表,则需要通过调整按钮工具提示或显示的其他文本对其进行国际化。这很容易做到,因为查看器依赖于预定义的资源包来提取特定于区域设置的信息。此资源包的基本名称为net.sf.jasperreports.view.viewer.

示例

为了演示国际化,让我们编写新的报表模板 (jasper_report_template.jrxml)。JRXML的内容如下所示。将其保存到C:\tools\jasperreports-5.0.1\test目录中。

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">

<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"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth = "555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20" resourceBundle = "localizationdemo">
   
   <title>
      <band height = "552">
         
         <textField>
            <reportElement positionType = "Float" x = "150" y = "20" 
               width = "400" height = "50"/>
            
            <textElement>
               <font size = "24"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{REPORT_LOCALE}.getDisplayName ($P{REPORT_LOCALE})]]>
            </textFieldExpression>
         </textField>

         <textField isStretchWithOverflow = "true" isBlankWhenNull = "true">
            <reportElement positionType = "Float" x = "20" y = "125" 
               width = "530" height = "20"/>
            
            <textElement textAlignment = "Justified">
               <font size = "14"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$R{localization.text1}]]>
            </textFieldExpression>
         
         </textField>
      
      </band>
   </title>

</jasperReport>

在上述文件中,<jasperReport>元素的resourceBundle属性告诉JasperReports从哪里获取要用于报表的本地化字符串。我们需要创建一个属性文件,其根名称与属性的值匹配。填充报表时,此文件必须存在于类路径中的任何位置。在此示例中,属性文件localizationdemo.properties保存在目录C:\tools\jasperreports-5.0.1\test下。此文件的内容如下 -

localization.text1 = This is English text.

要使用不同的区域设置,文件名称必须为localizationdemo[locale].properties。在这里,我们将为西班牙语区域设置编写一个文件。将此文件保存为 - C:\tools\jasperreports-5.0.1\test\localizationdemo_es.properties。此文件的内容如下 -

localization.text1 = Este texto es en Español.

获取resourceBundle属性值的语法为$R{key}。

要让JasperReports知道我们希望使用哪个区域设置,我们需要为内置参数分配一个值。此参数的名称定义为一个名为REPORT_LOCALE的常量,此常量在net.sf.jasperreports.engine.JRParameter类中定义。常量的值必须是java.util.Locale的实例。此逻辑已纳入Java代码中,以填充和生成报表。让我们将此文件JasperReportFillI18.java保存到C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint目录中。文件内容如下 -

package com.tutorialspoint;

import java.util.HashMap;
import java.util.Locale;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;

public class JasperReportFillI18 {

   public static void main(String[] args) {
      String sourceFileName = "C://tools/jasperreports-5.0.1/test/"
         + "jasper_report_template.jasper";
      HashMap parameterMap = new HashMap();
      if (args.length > 0) {
         parameterMap.put(JRParameter.REPORT_LOCALE, new Locale(args[0]));
      }
      try {
         JasperFillManager.fillReportToFile(sourceFileName, null, 
            new JREmptyDataSource());
      } catch (JRException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }
}

报表生成

我们将使用常规的 ANT 构建过程编译并执行上述文件。文件 build.xml(保存在目录 C:\tools\jasperreports-5.0.1\test 下)的内容如下所示。

导入文件 - baseBuild.xml 来自章节 环境设置,应放置在与 build.xml 相同的目录中。

<?xml version = "1.0" encoding = "UTF-8"?>

<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the report stored 
      in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid="classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
   
   </target>
	
</project>

接下来,让我们打开命令行窗口并进入放置 build.xml 文件的目录。最后,执行命令ant -Dmain-class=com.tutorialspoint.JasperReportFillI18(viewFullReport 是默认目标)如下所示:

C:\tools\jasperreports-5.0.1\test>ant  -Dmain-class=com.tutorialspoint.JasperReportFillI18
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jasper
   [delete] Deleting: C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrprint

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28:
   warning: 'includeantruntime' was not set, defaulting to
   [javac] Compiling 1 source file to C:\tools\jasperreports-5.0.1\test\classes
   [javac] Note: C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\
      JasperReportFillI18.java
   uses unchecked or u
   [javac] Note: Recompile with -Xlint:unchecked for details.

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See https://logging.apache.org/log4j/1.2/faq.html#noconfig 
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.JasperReportFillI18
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 3 minutes 28 seconds

作为上述编译的结果,将打开一个 JasperViewer 窗口,如下面的屏幕截图所示:

Jasper Report Example
广告

© . All rights reserved.