JasperReports报表Detail不显示数据?排查与解决
2025-03-10 11:00:07
JasperReports 报表 Detail Band 不显示数据问题排查与解决
在使用 JasperReports 生成报表时, 咱们可能会遇到这样一个问题:用 JRBeanCollectionDataSource 传递动态获取的数据到报表模板,数据提取没问题(调试确认过),但报表的 Detail Band 就是不显示数据,一片空白。
问题原因分析
这种情况,多半是以下几个原因造成的:
- JRXML 模板配置错误: 模板可能没有正确绑定数据源,或者字段映射有问题。
- 数据源传递问题: Java 代码中创建的 JRBeanCollectionDataSource 对象没有正确传递给报表引擎。
- 字段名称不匹配: JRXML 模板中定义的字段名 (field name) 和 Java Bean 中的属性名不一致。
- 数据类型不匹配: JRXML 模板中定义的字段类型和 Java Bean 中对应属性的类型不一致。
- 数据源使用方式错误: 使用
JRBeanCollectionDataSource
时, 第二个参数设置可能有误。
解决方案
下面,针对这些可能的原因,一步步排查和解决问题。
1. 检查 JRXML 模板配置
首先看看 JRXML 模板文件,确保正确定义了 parameter 和 field。
检查点:
-
parameter 定义: 确保定义了名为
TEST_DATA_SOURCE
的 parameter,且其class
属性设置为net.sf.jasperreports.engine.JRDataSource
。<parameter name="TEST_DATA_SOURCE" class="net.sf.jasperreports.engine.JRDataSource"/>
-
field 定义: 确保定义了与 Java Bean 属性对应的 field,并且
name
属性与 Bean 中的属性名一致,class
属性与属性的类型一致。<field name="TEST1" class="java.lang.String"/> <field name="TEST2" class="java.lang.String"/> <field name="TEST3" class="java.lang.String"/> <field name="TEST4" class="java.lang.String"/> <field name="TEST5" class="java.lang.String"/>
-
TEST1
定义了java.lang.String
, 而在fillParameters()
里使用了parseInt
。请保证类型匹配, 或使用相同的类型。例如都用java.lang.String
// ...
var extractedRow = {
TEST1: row.getFieldAsString("TEST1") || "0", // 将 TEST1 保持为字符串
// ...其他字段
};
```xml
<field name="TEST1" class="java.lang.String"/>
```
-
Detail Band 绑定: 在 Detail Band 中,使用
<textFieldExpression>![CDATA[$F{fieldName}]]</textFieldExpression>
来绑定字段。确保fieldName
与上面定义的 field 的name
属性一致。<detail> <band height="30"> <textField> <reportElement x="0" y="0" width="172" height="30"/> <textFieldExpression><![CDATA[$F{TEST1}]]></textFieldExpression> </textField> </band> </detail>
2. 检查数据源传递
在 Java 代码 (这里是 JavaScript) 中,要确保创建了 JRBeanCollectionDataSource
对象,并将其正确地放入 parameterMap
。
检查点:
-
正确创建 JRBeanCollectionDataSource: 使用
Java.type
获取JRBeanCollectionDataSource
类,然后用你的数据列表创建实例。第二个参数应设为false
,这表示传入的集合不是嵌套的数据源。var JRBeanCollectionDataSource = Java.type("net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"); var jrDataSource = new JRBeanCollectionDataSource(extractedData, false);
-
正确放入 parameterMap: 使用
parameterMap.put("TEST_DATA_SOURCE", jrDataSource);
将数据源放入参数映射中。确保 key 与 JRXML 中定义的 parameter 的 name 一致。
3. 字段名称和类型匹配
仔细对比 JRXML 中的 field 定义和 Java Bean 中的属性,确保名称和类型完全一致。
- 大小写敏感: Java 和 JRXML 中的字段名都是大小写敏感的。
TEST1
和test1
是不同的。 - 类型一致:
java.lang.String
和java.lang.Integer
是不同的类型。
4. JRBeanCollectionDataSource
的第二个参数
JRBeanCollectionDataSource
的构造函数有两个参数:
- 第一个参数是你的数据集合(List、Array 等)。
- 第二个参数是一个布尔值,用来指示 JasperReports 是否使用 bean 属性的名称作为字段名。
当传入false
时,意味着集合本身就是数据行,不需要进一步分解。应当确保您将此设置为false
,因为它指示 JasperReports 不要查找TEST1
,TEST2
等属性在extractedData
集合上, 而是在该集合的每一个项目里查找。
修改 fillParameters()
函数如下:
function fillParameters() {
try {
var rawData = datasourceHelper.get("testDataSource").getRows();
if (!rawData || rawData.length === 0) {
throwError("No data retrieved from 'testDataSource'.");
return; //明确表示在没取到数据时不进行操作。
}
var extractedData = [];
for (var i = 0; i < rawData.length; i++) {
var row = rawData[i];
var extractedRow = {
TEST1: row.getFieldAsString("TEST1") || "0",
TEST2: row.getFieldAsString("TEST2") || "",
TEST3: row.getFieldAsString("TEST3") || "",
TEST4: row.getFieldAsString("TEST4") || "",
TEST5: row.getFieldAsString("TEST5") || ""
};
extractedData.push(extractedRow);
}
var JRBeanCollectionDataSource = Java.type("net.sf.jasperreports.engine.data.JRBeanCollectionDataSource");
var jrDataSource = new JRBeanCollectionDataSource(extractedData, false); // 重点:第二个参数设为 false
parameterMap.put("TEST_DATA_SOURCE", jrDataSource);
} catch (e) {
throwError("ERROR: " + e.message);
}
}
5. 使用 Jaspersoft Studio 调试 (进阶技巧)
如果上述步骤都检查过了,还是不行,可以用 Jaspersoft Studio 来调试报表。
-
在 Jaspersoft Studio 中打开 JRXML 文件。
-
配置数据源:
- 在 "Data" 选项卡中,点击 "Add" -> "Dataset and Query".
- 选择 "JavaBean datasource"。
- 输入你的 JavaBean 类的完整类名(即使是在JavaScript中使用的模拟结构, 在测试时这里提供一个形式)。
- "Factory class": 可以填写一个空的工厂类,这个工厂类只需要一个静态方法,用于返回测试的list, 这个方法甚至可以返回空的List. 比如
public class TestBeanFactory { public static List<TestBean> getTestData() { // 即使是空list, 也是用来给Jaspersoft Studio识别字段类型的。 return Collections.emptyList(); // 或 List.of(new TestBean(...)); //使用真实的测试数据. } } public class TestBean{ private String TEST1; private String TEST2; private String TEST3; private String TEST4; private String TEST5; public TestBean(String TEST1, String TEST2, String TEST3, String TEST4, String TEST5) { this.TEST1 = TEST1; this.TEST2 = TEST2; this.TEST3 = TEST3; this.TEST4 = TEST4; this.TEST5 = TEST5; } //Getter Setter... }
- 然后 "Read attributes", Jaspersoft Studio应该可以发现这些定义的fields。
-
预览报表: 点击 "Preview" 按钮。如果数据源配置正确,应该能看到数据。即使实际运行环境没有这个
TestBeanFactory
, 但是这里能提供设计时需要的字段结构, 不妨碍Jaspersoft Studio中预览和设计。
通过 Jaspersoft Studio 的调试,可以快速定位是 JRXML 模板的问题还是 Java 代码的问题。
通过以上几个方面的排查和修改, 一般就能解决 JasperReports Detail Band 不显示数据的问题。细心是关键! Good Luck!