【问题标题】:How to pass main report data source to subreport (JasperReports)?如何将主报表数据源传递给子报表(JasperReports)?
【发布时间】:2012-01-19 09:44:39
【问题描述】:

我正在使用 JasperReports 并填写 JRDataSource 以获取报告。 现在,我想将主 REPORT_DATA_SOURCE 传递给子报表。我该怎么做?

据我所知REPORT_DATA_SOURCE 是一个消耗品,所以只能使用一次,对吧?我可以复制这个数据源并传递它吗?

顺便说一句:我使用 iReport 创建布局。

【问题讨论】:

    标签: jasper-reports datasource report ireport subreport


    【解决方案1】:

    是的,您需要注意如何传递数据源。使用 SQL 连接,您只需传递像 $P{REPORT_CONNECTION} 这样的连接表达式。然后子报表就有了自己的 SQL 查询。

    在您的情况下,您想传递实际数据。根据细节,它可能就像定义一个参数映射表达式一样简单,如$P{REPORT_PARAMETERS_MAP}。它位于您在 iReport 中设置子报表连接的同一窗口中的不同选项卡上。通常这足以传递数据源。

    但是您可能需要一些代码来处理事情。考虑这个在子报表中重复使用的 CSV 数据源的示例。您不能只使用 JRParameter.REPORT_DATA_SOURCE 对象的原因是因为索引行指针永远不会重置,因此将原始对象传递到子报表中会使记录集过早关闭。我们用一个最小的帮助类解决了这个问题:

    package com.jaspersoft.untested_unsupported; 
    
    import java.io.File; 
    import java.io.FileNotFoundException; 
    import net.sf.jasperreports.engine.JRDataSource; 
    import net.sf.jasperreports.engine.data.JRCsvDataSource; 
    
    public class CsvDataSourceFactory { 
        public static JRDataSource getDataSource(String fileName, boolean firstRowHeaders) throws FileNotFoundException { 
            JRCsvDataSource csvDs = new JRCsvDataSource(new File(fileName)); 
            csvDs.setUseFirstRowAsHeader(firstRowHeaders); 
            return csvDs; 
        } 
    }
    

    【讨论】:

      【解决方案2】:

      您可以通过内置的REPORT_DATA_SOURCE参数传递数据源

      例子:

      <subreport>
          <reportElement x="261" y="25" width="200" height="100"/>
          <dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></dataSourceExpression>
          <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "subreport.jasper"]]></subreportExpression>
      </subreport>
      

      您可以根据变量、参数或字段创建新的数据源实例。

      样本:

      <variable name="HeadingsCollection" class="java.util.Collection" calculation="System">
          <initialValueExpression><![CDATA[new java.util.ArrayList()]]></initialValueExpression>
      </variable>
      ...
      <subreport>
          <reportElement x="0" y="0" width="515" height="20"/>
          <subreportParameter name="ReportTitle">
              <subreportParameterExpression><![CDATA[$P{ReportTitle}]]></subreportParameterExpression>
          </subreportParameter>
          <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($V{HeadingsCollection})]]></dataSourceExpression>
          <subreportExpression class="java.lang.String"><![CDATA["HeadingsReport.jasper"]]></subreportExpression>
      </subreport>
      

      另一个示例:

      <field name="cast" class="java.util.Collection"/>
      ...
      <subreport>
          <reportElement positionType="Float" x="15" y="25" width="245" height="20" isRemoveLineWhenBlank="true" backcolor="#99CCFF"/>
          <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{cast})]]></dataSourceExpression>
          <subreportExpression class="java.lang.String"><![CDATA["JRMDbCastSubreport.jasper"]]></subreportExpression>
      </subreport>
      

      或者你可以通过参数传递数据源

      <parameter name="SubreportDataSource" class="net.sf.jasperreports.engine.JRDataSource"/>
      ...
      <subreport>
          <reportElement positionType="Float" x="15" y="25" width="245" height="20" isRemoveLineWhenBlank="true"/>
          <dataSourceExpression>$P{SubreportDataSource}</dataSourceExpression>
          <subreportExpression class="java.lang.String"><![CDATA["Subreport.jasper"]]></subreportExpression>
      </subreport>
      

      注意:subreport 中使用相同的(与主报告)datasource 会导致 subreport 中丢失第一行的效果 >。您可以阅读Why is the first record missing from my subreport? 帖子以了解如何避免此问题。

      【讨论】:

      【解决方案3】:

      我们假设数据源参数为“dataSourceParam”,数据源值(列表)为“dataSourceList” 在我们放的java类中:

      final Map<String, Object> params = new HashMap<String, Object>();
      JRDataSource dataSource = new ListOfArrayDataSource( dataSourceList, 
                                new String[] {"date", "age", "adress", "email"});
      params.put("dataSourceParam",dataSourceList);**
      

      在主报告模板中我们放入参数声明:

      <parameter name="dataSourceParam" class="net.sf.jasperreports.engine.JRDataSource"/>
      

      然后在子报表标签中我们放置:

      <subreport isUsingCache="true">
          <reportElement key="subreport-1" stretchType="RelativeToTallestObject" isPrintRepeatedValues="false" x="112" y="45" width="338" height="29"/>
          <subreportParameter name="otherParameter">
              <subreportParameterExpression><![CDATA[$P{sumM1}]]></subreportParameterExpression>
          </subreportParameter>
          <dataSourceExpression><![CDATA[$P{dataSourceParam}]]></dataSourceExpression>
          <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{subReportFile}]]></subreportExpression>
      </subreport>
      

      【讨论】:

        【解决方案4】:

        “REPORT_DATA_SOURCE”是一个消耗品,你可以随意使用。

        我已经将数据源测试为xml文件数据源,不会像ALEX所说的那样出现。

        “这不会丢失子报表中的第一行。”

        我想可能是我使用xpath来选择,所以每次都不会丢失记录。

        如果您使用 JDBC 数据库作为数据源,请将 sql 作为参数传递给子报表。

        如果您使用 ResultSet 作为参数,可能会在您定义详细波段的子报表时丢失一条记录。

        【讨论】:

          【解决方案5】:

          这是一个已经回答的老问题,但我可以将 undelying bean 传递给子报表,避免丢失第一条记录或将所有记录传递给子报表。 该解决方案的优点是子报表可以用作主报表,并且“简单”地将实际记录作为子报表数据源传递(使用 groovy 作为报表语言):

          <subreport>
              <reportElement x="261" y="25" width="200" height="100"/>
              <dataSourceExpression><![CDATA[new JRBeanCollectionDataSource(
                 $P{REPORT_DATA_SOURCE}.data.toList().subList($V{REPORT_COUNT}-1,$V{REPORT_COUNT})]]></dataSourceExpression>
              <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "subreport.jasper"]]></subreportExpression>
          </subreport>
          

          【讨论】:

          • 在我使用 Java 的旧版本中,至少,.data 不是可见字段。
          • 是的,groovy允许你访问私有字段,不知道有没有办法用java读取它
          【解决方案6】:

          我有一种情况,我在子报表中有一个表格。子报表只有一个标题栏和一个摘要栏,表格在摘要中。我也想为表使用子报表数据源,但无法使接受的答案中的任何一种方法起作用。所以这里作为一种在 6.6.0 版中效果很好的替代方法:

          在主报告中:

                  <subreport>
                      <reportElement x="0" y="0" width="468" height="0" uuid="c057b890-3889-43dd-8634-bbf2e857cc0d"/>
                      <subreportParameter name="partsList">
                          <subreportParameterExpression><![CDATA[$F{drawingRevision}.getPartsList()]]></subreportParameterExpression>
                      </subreportParameter>
                      <subreportExpression><![CDATA["static/engineering/drawings/subreports/DrawingPartsList.jasper"]]></subreportExpression>
                  </subreport>
          

          这里的关键是 List 作为参数传递,而 NOT 作为数据源传递,例如:

          <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{drawingRevision}.getPartsList())]]></dataSourceExpression>
          

          然后子报告包括:

          ...
          <parameter name="partsList" class="java.util.List" isForPrompting="false"/>
          ...
          <summary>
              <band height="60" splitType="Stretch">
                  <componentElement>
                      <reportElement key="table" style="table" x="0" y="0" width="468" height="60" uuid="09499b35-b122-4fe4-a2b3-d91d6a19b2ab"/>
                      <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" whenNoDataType="AllSectionsNoDetail">
                          <datasetRun subDataset="PartList" uuid="87fcbcc9-f0f0-4397-87f2-237201fc1857">
                              <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{partsList})]]></dataSourceExpression>
                          </datasetRun>
          ...
          

          请注意,在子报表中您还需要包含属性whenNoDataType="AllSectionsNoDetail" 或类似的东西,否则子报表将是空白的,因为它没有数据。

          【讨论】:

            【解决方案7】:

            只是为了完成 Alex K 的answer,真正让我工作的是clone the data source,如下所示:

            <dataSourceExpression><![CDATA[((net.sf.jasperreports.engine.data.JRBeanCollectionDataSource) $P{REPORT_DATA_SOURCE}).cloneDataSource()]]></dataSourceExpression>
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-10-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多