web-dev-qa-db-fra.com

Comment passer de la source de données du rapport principal au sous-rapport (JasperReports)?

J'utilise JasperReports et je remplis la JRDataSource pour le rapport ..__ Maintenant, je veux passer le REPORT_DATA_SOURCE principal au sous-rapport. Comment puis-je faire ceci?

Autant que je sache, le REPORT_DATA_SOURCE est un objet consommable, il ne peut donc être utilisé qu'une seule fois, n'est-ce pas?. Puis-je copier cette source de données et la transmettre?

BTW: J'utilise iReport pour créer la mise en page.

31
adis

Vous pouvez transmettre source de données via le paramètre intégré REPORT_DATA_SOURCE.

L'exemple:

<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>

Vous pouvez créer une nouvelle instance de source de données en fonction d'une variable, d'un paramètre ou d'un champ.

L'échantillon:

<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>

Un autre échantillon:

<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>

Ou vous pouvez passer le source de données via le paramètre:

<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>

Remarque: Utiliser le même (avec le rapport principal) source de données dans sous-rapport peut provoquer le effet de perdre la première ligne dans lesous-rapport. Vous pouvez lire Pourquoi le premier enregistrement manque-t-il dans mon sous-rapport? post pour comprendre comment éviter ce problème.

34
Alex K

Oui, vous devez faire attention à la manière de transmettre une source de données. Avec une connexion SQL, vous pouvez simplement passer une expression de connexion telle que $P{REPORT_CONNECTION}. Ensuite, le sous-rapport a sa propre requête SQL.

Dans votre cas, vous voulez transmettre les données réelles. En fonction des détails, cela peut être aussi simple que de simplement définir une expression de mappage de paramètres telle que $P{REPORT_PARAMETERS_MAP}. C'est sur un onglet différent dans cette même fenêtre où vous définissez la connexion de sous-rapport dans iReport. Cela suffit souvent pour transmettre la source de données.

Mais vous aurez peut-être besoin d'un peu de code pour gérer les choses. Considérez cet exemple avec une source de données CSV réutilisée dans des sous-rapports. La raison pour laquelle vous ne pouvez pas simplement utiliser l'objet JRParameter.REPORT_DATA_SOURCE est que le pointeur de ligne d'index n'est jamais réinitialisé. Par conséquent, le fait de placer cet objet d'origine dans le sous-rapport entraîne la fermeture prématurée du jeu d'enregistrements. Nous avons résolu ce problème avec une classe d'assistance minimale:

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; 
    } 
}
1
mdahlman

J'ai eu une situation où j'ai eu une table dans un sous-rapport. Le sous-rapport comporte uniquement une bande de titre et une bande de résumé, avec le tableau dans le résumé. Je voulais aussi utiliser la source de données de sous-rapport pour la table, mais je ne pouvais utiliser aucune des approches de la réponse acceptée. Donc, voici une approche alternative qui fonctionne très bien dans la version 6.6.0:

Dans le rapport principal:

        <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>

La clé ici est que la List est passée en tant que paramètre etPASen tant que source de données comme:

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

Le sous-rapport comprend alors:

...
<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>
...

Notez que dans le sous-rapport, vous devez également inclure la propriété whenNoDataType="AllSectionsNoDetail" ou quelque chose du genre, sinon le sous-rapport sera vide car il ne contient aucune donnée.

0
Tim

"REPORT_DATA_SOURCE" est un objet consommable. Vous pouvez utiliser autant de temps que vous le souhaitez.

J'ai testé la source de données en tant que fichier XML DataSource, et ne sera pas présenté comme l'a dit ALEX.

"cela ne perdra pas la première ligne du sous-rapport."

Je pense que j’utilise peut-être le chemin xpath pour sélectionner, afin que chaque fois ne soit pas un enregistrement de perte.

Si vous utilisez la base de données JDBC comme source de données, pealse transmettra le sql en tant que paramètre du sous-rapport.

Si vous utilisez ResultSet en tant que paramètre, vous pouvez peut-être perdre un enregistrement lorsque vous définissez le sous-rapport dans des bandes de détail.

0
zg_spring

C'est une vieille question à laquelle on a déjà répondu, mais je peux passer le haricot trop volant au sous-rapport, en évitant la perte du premier enregistrement ou en passant tous les enregistrements au sous-rapport . Cette solution présente l'avantage de pouvoir utiliser le sous-rapport comme rapport principal. et passe "simplement" l'enregistrement réel comme source de données de sous-rapport (en utilisant groovy comme rapport lang):

<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>
0
jneira

nous supposons que le paramètre source de données est "dataSourceParam" et que la valeur de la source de données (liste) est "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);**

dans le modèle de rapport principal, nous avons mis dans la déclaration des paramètres:

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

puis dans la balise subreport nous mettons:

<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>
0
Shessuky