【问题标题】:Multiple Subreports in Main Report using same datasource使用相同数据源的主报表中的多个子报表
【发布时间】:2015-07-08 17:21:45
【问题描述】:

我有一个包含 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”。

【问题讨论】:

    标签: jasper-reports


    【解决方案1】:

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

    解决方案:

    您必须使用 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 文件添加到工作室的类路径中。

    【讨论】:

    • 另见这种类似的方法:community.jaspersoft.com/wiki/… 它稍微复杂一些,但它会缓存数据,这对于许多子报表或数据集来说可能很方便。
    【解决方案2】:

    我找到了一个不需要额外 java 类的替代解决方案。如果您的数据源是 JRBeanCollectionDataSource,您可以在 dataSourceExpression 字段中调用 cloneDataSource() 方法,如下所示:

    &lt;dataSourceExpression&gt;&lt;![CDATA[$P{REPORT_DATA_SOURCE}.cloneDataSource()]]&gt;&lt;/dataSourceExpression&gt;

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

    documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      相关资源
      最近更新 更多