ZetCode

JasperReports 处理空值

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

在本文中,我们将展示如何在 JasperReports 中处理空值。

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

数据源经常包含空值。这些在我们的报告中看起来不美观;因此,我们将展示如何将它们替换为空字符串或更具描述性的消息,例如“N/A”。

<textField isBlankWhenNull="true">

为了处理空值,我们可以将 textFieldisBlankWhenNull 属性设置为 true

$F{salary} != null ? $F{salary} : 'N/A'

另一个选择是在 textFieldExpression 中使用三元运算符。

class CleanData {

    static String removeNull(def oldval, def newval = '') {
        if (oldval == null) {
            newval
        } else {
            oldval
        }
    }
}

另一个选项是定义一个外部方法。

示例

在下一个示例中,我们将使用 isBlankWhenNull 属性和三元运算符。

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')
@Grab(group='com.h2database', module='h2', version='1.4.200')
@GrabConfig(systemClassLoader=true)

import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperFillManager
import net.sf.jasperreports.engine.JasperExportManager
import groovy.sql.Sql

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

def createTable = '''
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), occupation VARCHAR(255), salary INT);
INSERT INTO users(name, occupation, salary) VALUES('John Doe', 'gardener', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Roger Roe', 'driver', 940);
INSERT INTO users(name, occupation, salary) VALUES('Roman Novy', 'programmer', 1980);
INSERT INTO users(name, occupation, salary) VALUES('Lucia Biela', NULL, NULL);
INSERT INTO users(name, occupation, salary) VALUES('Tomas Gerber', 'soldier', 1250);
INSERT INTO users(name, occupation, salary) VALUES('Maria Smith', 'teacher', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Oleg Vasil', NULL, 2550);
INSERT INTO users(name, occupation, salary) VALUES('Martin Krajci', 'optician', 2050);
'''

def url = "jdbc:h2:mem:"
Sql.withInstance(url) { sql ->

    sql.execute(createTable)

    def params = [:]
    def jPrint = JasperFillManager.fillReport(jrReport, params, sql.connection)

    JasperExportManager.exportReportToPdfFile(jPrint, "report.pdf")
}

我们在内存中的 H2 数据库中定义了一个 users 表。

def createTable = '''
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), occupation VARCHAR(255), salary INT);
INSERT INTO users(name, occupation, salary) VALUES('John Doe', 'gardener', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Roger Roe', 'driver', 940);
INSERT INTO users(name, occupation, salary) VALUES('Roman Novy', 'programmer', 1980);
INSERT INTO users(name, occupation, salary) VALUES('Lucia Biela', NULL, NULL);
INSERT INTO users(name, occupation, salary) VALUES('Tomas Gerber', 'soldier', 1250);
INSERT INTO users(name, occupation, salary) VALUES('Maria Smith', 'teacher', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Oleg Vasil', NULL, 2550);
INSERT INTO users(name, occupation, salary) VALUES('Martin Krajci', 'optician', 2050);
'''

该表在 occupationsalary 列中包含空值。

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"
              language="groovy"
              name="report" topMargin="20" bottomMargin="20">

    <queryString language="SQL">
        <![CDATA[ SELECT id, name, occupation, salary from users ]]>
    </queryString>

    <field name="id" class="java.lang.Integer"/>
    <field name="name"/>
    <field name="occupation"/>
    <field name="salary" class="java.lang.Integer" />

    <title>
        <band height="60">
            <staticText>
                <reportElement x="0" y="0" width="595" height="35"/>
                <textElement textAlignment="Center"/>
                <text><![CDATA[Users]]></text>
            </staticText>
        </band>
    </title>

    <detail>
        <band height="30">

            <textField>
                <reportElement x="0" y="0" width="25" height="25"/>
                <textFieldExpression class="java.lang.Integer">
                    <![CDATA[$F{id}]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="30" y="0" width="100" height="25"/>
                <textFieldExpression>
                    <![CDATA[$F{name}]]>
                </textFieldExpression>
            </textField>

            <textField isBlankWhenNull="true">
                <reportElement x="140" y="0" width="70" height="25"/>
                <textFieldExpression>
                    <![CDATA[ $F{occupation} ]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="220" y="0" width="70" height="25"/>
                <textElement textAlignment="Right"/>
                <textFieldExpression class="java.lang.Integer">
                    <![CDATA[ $F{salary} != null ? $F{salary} : 'N/A'  ]]>
                </textFieldExpression>
            </textField>

        </band>
    </detail>

</jasperReport>

这是报告模板。

<textField isBlankWhenNull="true">
    <reportElement x="140" y="0" width="70" height="25"/>
    <textFieldExpression>
        <![CDATA[ $F{occupation} ]]>
    </textFieldExpression>
</textField>

我们将 occupation 字段的 isBlankWhenNull 设置为 true。具有空值的单元格将为空。

<textField>
    <reportElement x="220" y="0" width="70" height="25"/>
    <textElement textAlignment="Right"/>
    <textFieldExpression class="java.lang.Integer">
        <![CDATA[ $F{salary} != null ? $F{salary} : 'N/A'  ]]>
    </textFieldExpression>
</textField>

对于 salary 字段,我们使用三元运算符。空值将被替换为 N/A 字符串。


在下一个示例中,我们定义了一个处理空值的外部方法。

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')
@Grab(group='net.sf.jasperreports', module='jasperreports-fonts', version='6.21.0')
@Grab(group='com.h2database', module='h2', version='1.4.200')
@GrabConfig(systemClassLoader=true)

import net.sf.jasperreports.engine.JasperCompileManager
import net.sf.jasperreports.engine.JasperFillManager
import net.sf.jasperreports.engine.JasperExportManager
import groovy.sql.Sql

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

def createTable = '''
CREATE TABLE users(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), occupation VARCHAR(255), salary INT);
INSERT INTO users(name, occupation, salary) VALUES('John Doe', 'gardener', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Roger Roe', 'driver', 940);
INSERT INTO users(name, occupation, salary) VALUES('Roman Novy', 'programmer', 1980);
INSERT INTO users(name, occupation, salary) VALUES('Lucia Biela', NULL, NULL);
INSERT INTO users(name, occupation, salary) VALUES('Tomas Gerber', 'soldier', 1250);
INSERT INTO users(name, occupation, salary) VALUES('Maria Smith', 'teacher', NULL);
INSERT INTO users(name, occupation, salary) VALUES('Oleg Vasil', NULL, 2550);
INSERT INTO users(name, occupation, salary) VALUES('Martin Krajci', 'optician', 2050);
'''

def url = "jdbc:h2:mem:"
Sql.withInstance(url) { sql ->

    sql.execute(createTable)

    def params = [:]
    def jPrint = JasperFillManager.fillReport(jrReport, params, sql.connection)

    JasperExportManager.exportReportToPdfFile(jPrint, "report.pdf")
}

class CleanData {

    static String removeNull(def oldval, def newval = '') {
        if (oldval == null) {
            newval
        } else {
            oldval
        }
    }
}

在 Groovy 代码中,我们定义了 CleanData 及其 removeNull 方法。它允许我们选择一个特定的消息来代替空值。

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"
              language="groovy"
              name="report" topMargin="20" bottomMargin="20">

    <import value="com.zetcode.CleanData"/>

    <queryString language="SQL">
        <![CDATA[ SELECT id, name, occupation, salary from users ]]>
    </queryString>

    <field name="id" class="java.lang.Integer"/>
    <field name="name"/>
    <field name="occupation"/>
    <field name="salary" class="java.lang.Integer" />

    <variable name="sumsal" class="java.lang.Integer" calculation="Sum">
        <variableExpression><![CDATA[$F{salary}]]></variableExpression>
    </variable>

    <title>
        <band height="60">
            <staticText>
                <reportElement x="0" y="0" width="595" height="35"/>
                <textElement textAlignment="Center"/>
                <text><![CDATA[Users]]></text>
            </staticText>
        </band>
    </title>

    <detail>
        <band height="30">

            <textField>
                <reportElement x="0" y="0" width="25" height="25"/>
                <textFieldExpression class="java.lang.Integer">
                    <![CDATA[$F{id}]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="30" y="0" width="100" height="25"/>
                <textFieldExpression>
                    <![CDATA[$F{name}]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="140" y="0" width="70" height="25"/>
                <textFieldExpression>
                    <![CDATA[ CleanData.removeNull($F{occupation}, 'N/A') ]]>
                </textFieldExpression>
            </textField>

            <textField>
                <reportElement x="220" y="0" width="70" height="25"/>
                <textElement textAlignment="Right"/>
                <textFieldExpression>
                    <![CDATA[ CleanData.removeNull($F{salary}, 'N/A') ]]>
                </textFieldExpression>
            </textField>

        </band>
    </detail>

    <summary>
        <band height="25">
            <textField>
                <reportElement x="220" y="0" width="70" height="25"/>
                <textElement textAlignment="Right">
                    <font isBold = "true"/>
                </textElement>
                <textFieldExpression><![CDATA[$V{sumsal}]]></textFieldExpression>
            </textField>
        </band>
    </summary>

</jasperReport>

在此报告中,我们使用外部 CleanData.removeNull 方法。

<import value="com.zetcode.CleanData"/>

我们将类导入到报告中。

<textField>
    <reportElement x="140" y="0" width="70" height="25"/>
    <textFieldExpression>
        <![CDATA[ CleanData.removeNull($F{occupation}, 'N/A') ]]>
    </textFieldExpression>
</textField>

我们将 CleanData.removeNull 传递 $F{occupation} 值和用于替换潜在空值的可选字符串。

在本文中,我们演示了如何将空值替换为空字符串或更具描述性的消息。

作者

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

列出 所有 JasperReports 教程