JasperReports 创建统计图表
之前,人们不得不依靠脚本来收集图表数据并使用报表模板中的图像元素呈现图表。JasperReports 现在使它变得简单,因为它使用新的图表组件内置了对图表的支持。
使用新的图表组件,用户只需应用可视化设置并定义有助于构建图表数据集的表达式。JasperReports 使用 JFreeChart 作为底层图表库。配置新图表组件时,涉及以下三个组件 :
-
整体图表组件。
-
图表数据集(对图表数据相关设置进行分组)。
-
图表图(对与图表项目呈现方式相关的视觉设置进行分组)。
JasperReports 目前支持以下类型的图表:Pie, Pie 3D, Bar, Bar 3D, XY Bar, Stacked Bar, Stacked Bar 3D, Line, XY Line, Area, XY Area, Stacked Area, Scatter, Bubble, Time Series, High-Low-Open-Close、Candlestick、Multiple Axis、Meter、Thermometer和Gantt。
<chart>元素
图表是普通的报表元素,因此它们与所有其他报表元素共享其某些属性。有一个名为 <chart>的 JRXML 元素,用于创建所有类型的图表。此元素对适用于所有类型图表的特殊图表特定设置进行分组。
<chart>子元素
<chart> 元素的子元素是 :
-
<reportElement> : 这些是可显示的对象,如您放入报告模板部分的静态文本、文本字段、图像、线条和矩形。
-
<Box> : 此元素用于通过可在每一侧自定义的边框围绕图表。
-
<chartTitle> : 此元素用于放置图表的标题。该位置属性决定在报告中的图表的标题位置。此元素具有属性 -位置(值可以是Top、Bottom、Left、Right。默认值为Top)、color。<chartTitle> 将font和titleExpression作为子元素。
-
<chartSubtitle> : 此元素用于放置图表的副标题。此元素具有属性颜色。<chartSubtitle> 将font和subtitleExpression作为子元素。
-
<chartLegend> : 该元素可以使用此元素控制与字体相关的属性以及图表图例的文本颜色和背景颜色。该元素具有属性 - textColor和backgroundColor。
-
<anchorNameExpression> : 此元素为锚点创建目标。
-
<hyperlinkReferenceExpression> : 此元素包含一个报告表达式,指示外部资源的名称(通常是一个 URL)。
-
<hyperlinkAnchorExpression> : 超链接指向外部资源中的锚点。
-
<hyperlinkPageExpression> : 超链接指向当前报表中的页面。
-
<hyperlinkTooltipExpression> : 此元素控制超链接的工具提示。表达式的类型应该是java.lang.String。
-
<hyperlinkParameter> : 此元素存在时会根据参数值生成最终超链接。
<chart>属性
<chart> 元素中的属性是 :
-
isShowLegend : 此属性用于确定图表图例是否将显示在报表上。值可以是true或false。默认值为true。
-
evaluationTime : 确定何时评估图表的表达式。值可以是Now、Report、Page、Column、Group、Band。默认值为Now。
-
evaluationGroup : 此属性确定用于评估图表表达式的组的名称。此属性的值必须与组的名称匹配,我们希望用作图表的评估组。
-
hyperlinkType : 此属性可以保存任何文本值。默认值为None。这意味着,即使存在特殊的超链接表达式,文本字段和图像都不代表超链接。
-
hyperlinkTarget : 此属性有助于自定义在查看器中单击时指定链接的行为。值可以是Self或Blank。默认值为Self。
-
bookmarkLevel : 此属性设置为正整数时,在导出为 PDF 的报告中生成书签。默认值为0。
-
customrClass : 这是可用于自定义图表的类(可选)的名称。此元素的值必须是包含定制程序类名称的字符串。
图表定制
如上所述,JasperReports 使用JFreeChart作为底层图表库。JFreeChart包含 JasperReports 不直接支持的功能。我们可以通过<chart> 元素中的customrClass属性提供定制器类来利用这些功能。定制器类只是net.sf.jasperreports.engine.JRChartCustomizer接口的实现。实现此接口的最简单方法是扩展net.sf.jasperreports.engine.JRAbstractChartCustomizer类,从而可以访问参数、字段和变量,以便根据报表数据进行更灵活的图表定制。
图表数据集
所有图表类型的通用属性之一是 <dataset> 元素。图表数据集有助于在运行时映射报告数据和检索图表数据。每种图表类型都包含不同的子元素来定义图表的表达式。这些表达式定义用于生成图表的数据。所有这些子元素都包含一个 <dataset> 元素,该元素定义了图表表达式的评估和重置时间。
JasperReports 中提供了多种类型的图表数据集,因为每种类型的图表都适用于特定的数据集:Pie、Category、XY、Time Series、Time Period、XYZ 和 High-Low。这些数据集类型中的每一种都实现了定义图表数据集的net.sf.jasperreports.engine.JRChartDataset接口。所有图表数据集以相同的方式初始化和递增;但是,它们的区别仅在于它们映射的数据类型或数据系列。
数据集属性
下表总结了元素 <dataset> 的属性:
属性 | 描述 | 值 |
---|---|---|
resetType | 此属性确定何时重置图表表达式的值。 | 无、报告、页面、列、组。默认值为报告。 |
resetGroup | 此属性确定重置图表表达式值的组的名称。 | 此属性的值必须与 JRXML 报告模板中声明的任何组的名称相匹配。 |
incrementType | 此属性确定何时重新计算图表表达式的值。 | 无、报告、页面、列、组。默认值为"None"。 |
incrementGroup | 此属性确定重新计算图表表达式的组的名称。 | 此属性的值必须与 JRXML 报告模板中声明的组的名称相匹配。 |
下表总结了元素 <dataset> 的子元素 :
子元素 | 描述 |
---|---|
<incrementWhenExpression> | 可以通过使用此子元素过滤掉不需要的数据来自定义图表数据集的递增方式。 |
<datasetRun> | 这包含实例化报告子数据集所需的信息。 |
JasperReports 图表的示例
pom.xml文件
<dependencies>
<!-- https://mvnrepository.com/artifact/net.sf.jasperreports/jasperreports -->
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.17.0</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
</dependencies>
DataBean实体类:
package cn.xnip;
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;
}
}
DataBeanList类:
package cn.xnip;
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;
}
}
jasper_report_template.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" 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>
先编译报表文件:
package cn.xnip;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.view.JasperViewer;
public class JasperReportFill {
public static void main(String[] args) {
String filePath = "D:/idea_codes/jasper_reports/jasper_report_template.jrxml";
try {
JasperCompileManager.compileReportToFile(filePath,"d:/jasper_report_template.jasper");
System.out.println("编译成功");
} catch (JRException e) {
e.printStackTrace();
}
}
}
编译后在D:/盘根目录下生成jasper_report_template.jasper文件,然后再填充数据:
package cn.xnip;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class JasperReportFill {
public static void main(String[] args) {
String sourceFileName = "d:/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();
}
}
}
填充数据完毕后,在D:/盘根目录下生成jasper_report_template.jrprint文件,最后使用预览程序预览:
package cn.xnip;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.view.JasperViewer;
public class JasperReportFill {
public static void main(String[] args) {
String filePath = "D:/jasper_report_template.jrprint";
try {
JasperViewer.viewReport(filePath,false);
} catch (JRException e) {
e.printStackTrace();
}
}
}
最后输出结果如下:
在这里,我们看到条形图是在页眉中创建的,饼图是在摘要部分中创建的。