簡體   English   中英

如何將主報表數據源傳遞給子報表(JasperReports)?

[英]How to pass main report data source to subreport (JasperReports)?

我正在使用 JasperReports,並為該報告填寫了JRDataSource 現在,我想將主要的REPORT_DATA_SOURCE傳遞給子報表。 我怎樣才能做到這一點?

據我所知REPORT_DATA_SOURCE是一個消耗對象,所以它只能使用一次,對嗎?。 我可以復制這個數據源並傳遞它嗎?

順便說一句:我使用 iReport 來創建布局。

您可以通過內置的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>

注:報表使用相同的(有主報告)數據源可以導致子報表失去了第一排的效果 您可以閱讀為什么我的子報表中缺少第一條記錄? 發布以了解如何避免此問題。

我們假設數據源參數是“dataSourceParam”,並且我們放置的java類中的數據源值(列表)是“dataSourceList”:

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>

“REPORT_DATA_SOURCE”是一個消耗品,你可以使用盡可能多的時間。

我已經將數據源測試為xml文件數據源,不會像ALEX所說的那樣出現。

“這不會丟失子報告中的第一行。”

我想可能是我用xpath來選擇,所以每次都不會丟失記錄。

如果您使用 JDBC 數據庫作為數據源,請將 sql 作為參數傳遞給子報表。

如果您使用 ResultSet 作為參數,則可能會在您在詳細信息帶中定義子報表時丟失一條記錄。

是的,您需要注意如何傳遞數據源。 使用 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; 
    } 
}

這是一個已經回答的老問題,但我可以將 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>

我遇到過在子報表中有一個表格的情況。 子報表只有一個標題帶和一個匯總帶,表在匯總中。 我也想對表使用子報表數據源,但無法在接受的答案中使用任何一種方法。 因此,這里作為在 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作為參數傳遞而不是作為數據源傳遞,例如:

<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"或類似內容,否則子報表將是空白的,因為它沒有數據。

只是為了完成 Alex K 的回答,真正讓它對我有用的是按如下方式克隆數據源

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM