JasperReports 处理空值
最后修改日期:2024 年 2 月 12 日
在本文中,我们将展示如何在 JasperReports 中处理空值。
JasperReports 是一个开源报告库。它可以创建各种格式的报告,包括 PDF、HTML、XLS 或 CSV。JasperReports 创建面向页面、可直接打印的文档。
数据源经常包含空值。这些在我们的报告中看起来不美观;因此,我们将展示如何将它们替换为空字符串或更具描述性的消息,例如“N/A”。
<textField isBlankWhenNull="true">
为了处理空值,我们可以将 textField 的 isBlankWhenNull 属性设置为 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);
'''
该表在 occupation 和 salary 列中包含空值。
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} 值和用于替换潜在空值的可选字符串。
在本文中,我们演示了如何将空值替换为空字符串或更具描述性的消息。