主报表中的多个子报表使用相同的数据源

时间:2015-04-29 12:14:49

标签: jasper-reports

我有一个包含2个子报告的主报告。我正在使用自定义数据源来获取报告内容。但是,在jasper studio中预览主报表时,只会显示一个子报表(无论哪个子报表首先出现)。

例如。只显示report1.jrxml。如果删除该子报告,则会显示report2.jrxml。

main.jrxml

<detail>
    <band height="250">
        <subreport runToBottom="true">
            <reportElement positionType="Float" x="0" y="130" width="1960" height="120" uuid="89a9f872-756e-4c82-922d-537cfde30cca"/>
            <dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></dataSourceExpression>
            <subreportExpression><![CDATA["report1.jrxml"]]></subreportExpression>
        </subreport>
    </band>
    <band height="250">
        <subreport runToBottom="true">
            <reportElement positionType="Float" x="0" y="90" width="1960" height="120" uuid="892c0849-9532-48cb-94c0-f2e87528232a"/>
            <dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></dataSourceExpression>
            <subreportExpression><![CDATA["report2.jrxml"]]></subreportExpression>
        </subreport>
    </band>
</detail>

我尝试了以下内容:

  1. 将子报表放在不同的详细信息区域中。
  2. 将“位置类型”设置为“浮动”。
  3. 将“Run To Bottom”属性设置为“True”。

2 个答案:

答案 0 :(得分:3)

问题在于尝试将 相同数据源 用于多个子报表。第一个子报告的数据源已耗尽,因此后续子报告没有可用的数据。

解决方案:

您必须使用 JRRewindableDataSource

来回放数据源

感谢lucianc Community answer

总结任务:

创建一个包装RewindableDSWrapper,它会倒回数据源并委托对它的所有调用。

package com.jasper.api;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import net.sf.jasperreports.engine.JRRewindableDataSource;

public class RewindableDSWrapper implements JRRewindableDataSource {

  private final JRRewindableDataSource ds;

  public RewindableDSWrapper(JRRewindableDataSource ds) {

    this.ds = ds;

    try {
        this.ds.moveFirst();
    } catch (JRException e) {
        e.printStackTrace();
    }

  }

  public boolean next() throws JRException {

    return ds.next();

  }

  public Object getFieldValue(JRField jrField) throws JRException {

    return ds.getFieldValue(jrField);

  }

  public void moveFirst() throws JRException {

    ds.moveFirst();

   }

 }

在自定义数据源类中实现JRRewindableDataSource接口。

public void moveFirst() throws JRException {
    // provide logic for rewinding datasource
}

在您的jrxml文件中,如果您的数据源是自定义的,那么

<dataSourceExpression><![CDATA[new com.jasper.api.RewindableDSWrapper((JRRewindableDataSource)$P{REPORT_DATA_SOURCE})]]></dataSourceExpression>

您将REPORT_DATA_SOURCE转换为JRRewindableDataSource,因为编译器会尝试将其转换为JRDataSource。

同时将包含RewindableDSWrapper类的jar文件添加到工作室的classpath中。

答案 1 :(得分:0)

我找到了不需要其他Java类的替代解决方案。如果您的数据源是JRBeanCollectionDataSource,则可以像下面这样在dataSourceExpression字段内调用方法cloneDataSource()

<dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}.cloneDataSource()]]></dataSourceExpression>

这将实例化一个新的迭代器,它与moveFirst()方法中发生的事情相同。

documentation