ZetCode

JasperReports Scriptlet

最后修改日期:2024 年 2 月 12 日

在本文中,我们将介绍 JasperReport scriptlet。

JasperReports 是一个开源报告库。它可以创建各种格式的报告,包括 PDF、HTML、XLS 或 CSV。JasperReports 以简单灵活的方式创建面向页面、可打印的文档。

Scriptlet 是 Java 类,它们为 JasperReports 提供额外的功能。当报表表达式无法执行更复杂的操作时,我们可以使用 scriptlet。Scriptlet 在每次报表事件发生时执行。Scriptlet 可以影响报表变量的值。

计算几何平均数

下面的应用程序计算利率的几何平均数。几何平均数定义为 n 个数的乘积的 n 次根。它用于增长率,例如人口增长或利率,其中简单的算术平均数不能给出准确的结果。

report.xml
<?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="report" topMargin="20" bottomMargin="20">

    <scriptlet name="MyScriptlet" class="com.zetcode.MyScriptlet"/>

    <parameter name="vals" class="java.util.List"/>
    <variable name="gmean" class="java.lang.Double"/>

    <summary>
        <band height="30">

            <staticText>
                <reportElement x="0" y="0" width="90" height="15"/>
                <textElement/>
                <text><![CDATA[Geometric mean: ]]></text>
            </staticText>

            <textField>
                <reportElement x="100" y="0" width="200" height="15"/>
                <textElement/>
                <textFieldExpression class="java.lang.Double">
                    <![CDATA[$V{gmean}]]>
                </textFieldExpression>
            </textField>
        </band>
    </summary>

</jasperReport>

这是报表模板文件。模板包含摘要段,其中有一个变量:gmean

<scriptlet name="MyScriptlet" class="com.zetcode.MyScriptlet"/>

Scriptlet 使用 scriptlet 标签引用。它是一个包含几何平均数计算的类。

<parameter name="rets" class="java.util.List"/>
<variable name="gmean" class="java.lang.Double"/>

我们有一个参数和一个变量。参数是利率值列表。变量是计算出的几何平均数。

<textFieldExpression class="java.lang.Double">
    <![CDATA[$V{gmean}]]>
</textFieldExpression>

textFieldExpression 标签中,我们输出几何平均数。

report.gvy
package com.zetcode

@Grab(group='net.sf.jasperreports', module='jasperreports', version='6.21.0')
@Grab(group='org.apache.commons', module='commons-math3', version='3.6.1')
@Grab(group='com.github.librepdf', module='openpdf', version='1.3.39')

import java.util.List
import net.sf.jasperreports.engine.JRDefaultScriptlet
import net.sf.jasperreports.engine.JREmptyDataSource
import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperFillManager
import net.sf.jasperreports.renderers.JCommonDrawableRendererImpl

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics

// Report generation

def xmlFile = "report.xml"
def jrReport = JasperCompileManager.compileReport(xmlFile)

def vals = [1.2, 1.8, -1.2, 0.9, 1.1, 3.5, -2.7]

def params = [:]
params.put("vals", vals)

def jrPrint = JasperFillManager.fillReport(jrReport,
        params, new JREmptyDataSource())

JasperExportManager.exportReportToPdfFile(jrPrint, "report.pdf")

// Scriptlet class

class MyScriptlet extends JRDefaultScriptlet {

    private DescriptiveStatistics stats

    void afterReportInit() {

        def vals = getParameterValue("vals")
        stats = new DescriptiveStatistics()

        vals.forEach((val) -> stats.addValue(val))
    }

    void afterDetailEval() {
        setVariableValue("gmean", stats.getMean())
    }
}

Groovy 脚本生成报表。

def vals = [1.2, 1.8, -1.2, 0.9, 1.1, 3.5, -2.7]

这些值是我们的利率。

params.put("vals", vals)

该列表被放入参数中。该列表映射到报表中创建的 <parameter name="vals" class="java.util.List"/> 元素。

class MyScriptlet extends JRDefaultScriptlet {

Scriptlet 继承自 JRDefaultScriptlet。它为 scriptlet 事件提供了默认的空实现。

private DescriptiveStatistics stats

void afterReportInit() {

    def vals = getParameterValue("vals")
    stats = new DescriptiveStatistics()

    vals.forEach((val) -> stats.addValue(val))
}

在报表初始化后,我们获取包含利率值的 vals 参数,并将其插入 DescriptiveStatistics

void afterDetailEval() {
    setVariableValue("gmean", stats.getMean())
}

afterDetailEval 事件之后,计算几何平均数并将其设置为 gmean 变量。

图表 Scriptlet

下面的应用程序创建一个饼图。它使用了 JFreeChart 库。

report.xml
<?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="report" pageWidth="595" pageHeight="842"
              columnWidth="555" leftMargin="20" rightMargin="20"
              topMargin="20" bottomMargin="20">

    <scriptlet name="MyScriptlet" class="com.zetcode.MyScriptlet"/>

    <parameter name="langs" class="java.util.Map"/>
    <variable name="Chart" class="net.sf.jasperreports.renderers.JCommonDrawableRendererImpl"
              calculation="System"/>

    <detail>
        <band height="430">
            <image scaleImage="Clip" hAlign="Center">
                <reportElement x="0" y="0" width="515" height="300"/>
                <imageExpression>
                    <![CDATA[ $V{Chart} ]]>
                </imageExpression>
            </image>

        </band>
    </detail>

</jasperReport>

在报表模板文件中,我们有一个详细信息段,其中有一个 <image> 元素,用于显示图表。

<scriptlet name="MyScriptlet" class="com.zetcode.MyScriptlet" />

Scriptlet 是一个创建图表对象的 Groovy 类。

<parameter name="langs" class="java.util.Map"/>
<variable name="Chart" class="net.sf.jasperreports.renderers.JCommonDrawableRendererImpl"
            calculation="System"/>

我们有一个参数和一个变量。参数是要在图表中显示的值的映射。变量包含图表对象。

report.gvy
package com.zetcode

@Grab(group='net.sf.jasperreports', module='jasperreports', version='6.21.0')
@Grab(group='com.github.librepdf', module='openpdf', version='1.3.39')

import net.sf.jasperreports.engine.JREmptyDataSource
import net.sf.jasperreports.engine.JRException
import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperExportManager
import net.sf.jasperreports.engine.JasperFillManager
import net.sf.jasperreports.engine.JRDefaultScriptlet
import net.sf.jasperreports.renderers.JCommonDrawableRendererImpl

import org.jfree.chart.ChartFactory
import org.jfree.data.general.DefaultPieDataset
import org.jfree.util.Rotation

// Report generation

def xmlFile = "report.xml"
def jrReport = JasperCompileManager.compileReport(xmlFile)

def langs = [ "Python": 30.2, "C#": 10.0, "Java": 17.5,
    "PHP": 8.5, "Clojure": 1.1]

def params = ["langs": langs]

def jrPrint = JasperFillManager.fillReport(jrReport,
        params, new JREmptyDataSource())

JasperExportManager.exportReportToPdfFile(jrPrint, "report.pdf")

// Scriptlet class

class MyScriptlet extends JRDefaultScriptlet {

    void afterReportInit() {

        def langs = getParameterValue("langs")
        def dataset = new DefaultPieDataset()

        langs.forEach(dataset::setValue)

        def chart = ChartFactory.createPieChart3D(
                "Computer languages",
                dataset,
                true,
                true,
                false
        )

        def plot = chart.getPlot()

        plot.setStartAngle(290)
        plot.setDirection(Rotation.CLOCKWISE)
        plot.setForegroundAlpha(0.5f)
        plot.setNoDataMessage("No data to display")

        this.setVariableValue("Chart", new JCommonDrawableRendererImpl(chart))
    }
}

脚本编译报表模板并创建一个 PDF 文件。

def langs = [ "Python": 30.2, "C#": 10.0, "Java": 17.5,
    "PHP": 8.5, "Clojure": 1.1]

此映射中的值将显示在饼图中。

def params = ["langs": langs]

数据作为 langs 参数传递。

class MyScriptlet extends JRDefaultScriptlet {

此 scriptlet 从 langs 参数检索数据并生成饼图。图表被设置为报表模板变量。

def langs = getParameterValue("langs")

在报表初始化后,我们获取包含图表数据的 langs 参数。

def dataset = new DefaultPieDataset()

langs.forEach(dataset::setValue)

数据被设置为 DefaultPieDataset

def chart = ChartFactory.createPieChart3D(
    "Computer languages",
    dataset,
    true,
    true,
    false
)

def plot = chart.getPlot()

plot.setStartAngle(290)
plot.setDirection(Rotation.CLOCKWISE)
plot.setForegroundAlpha(0.5f)
plot.setNoDataMessage("No data to display")

生成了一个 3D 饼图。

this.setVariableValue("Chart", new JCommonDrawableRendererImpl(chart))

生成的图表被设置为 Chart 报表模板变量。

在本文中,我们学习了 scriptlet;我们计算了利率的几何平均数并生成了一个 3D 饼图。

作者

我叫 Jan Bodnar,我是一名充满激情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 JasperReports 教程