Créer des sous-rapports

Les sous-rapports sont l'une des fonctionnalités intéressantes des JasperReports. Cette fonction permet d'incorporer un rapport dans un autre rapport, c'est-à-dire qu'un rapport peut être un sous-rapport d'un autre. Les sous-rapports nous aident à simplifier la conception des rapports, car nous pouvons créer de nombreux rapports simples et les encapsuler dans un rapport principal. Les sous-rapports sont compilés et remplis comme des rapports normaux. Tout modèle de rapport peut être utilisé comme sous-rapport lorsqu'il est incorporé dans un autre modèle de rapport, sans que rien ne change à l'intérieur (du modèle de rapport).

Les sous-rapports sont comme des modèles de rapport normaux. Il s'agit en fait d' objets net.sf.jasperreports.engine.JasperReport , qui sont obtenus après la compilation d'un objet net.sf.jasperreports.engine.design.JasperDesign .

Élément <subreport>

Un élément <subreport> est utilisé lors de l'introduction de sous-rapports dans les rapports maîtres. Voici la liste des sous-éléments de l'élément JRXML <subreport>.

  • <reportElement>

  • <parametersMapExpression> - Ceci est utilisé pour transmettre une carte contenant des paramètres de rapport au sous-rapport. La carte est généralement obtenue à partir d'un paramètre dans le rapport principal ou à l'aide du paramètre REPORTS_PARAMETERS_MAP intégré pour transmettre les paramètres du rapport parent au sous-rapport. Cette expression doit toujours renvoyer un objet java.util.Map dans lequel les clés sont les noms de paramètres.

  • <subreportParameter> - Cet élément est utilisé pour transmettre des paramètres au sous-rapport. Il a un nom d' attribut , qui est obligatoire.

  • <connectionExpression> - Ceci est utilisé pour passer un java.sql.Connection au sous-rapport. Il est utilisé uniquement lorsque le modèle de sous-rapport nécessite une connexion à la base de données pendant la phase de remplissage du rapport.

  • <dataSourceExpression> - Ceci est utilisé pour transmettre une source de données au sous-rapport. Cette source de données est généralement obtenue à partir d'un paramètre du rapport principal ou à l'aide du paramètre REPORT_DATA_SOURCE intégré pour transmettre la source de données du rapport parent au sous-rapport.

  • Les éléments ( connectionExpression et dataSourceExpression ) ne peuvent pas être présents en même temps dans une déclaration d'élément <subreport>. En effet, nous ne pouvons pas fournir à la fois une source de données et une connexion au sous-rapport. Nous devons choisir l'un d'entre eux et nous y tenir.

  • <returnValue> - Ceci est utilisé pour affecter la valeur de l'une des variables du sous-rapport à l'une des variables du rapport principal. Ce sous-élément a les attributs suivants -

    • subreportVariable - Cet attribut spécifie le nom de la variable de sous-rapport dont la valeur doit être renvoyée.

    • toVariable - Cet attribut spécifie le nom de la variable de rapport parent dont la valeur doit être copiée / incrémentée avec la valeur du sous-rapport.

    • calcul - Cet attribut peut prendre des valeurs: Nothing, Count, DistinctCount, Sum, Average, Minimum, Maximum, StandardDeviation, Variance. La valeur par défaut pour le calcul des attributs est "Rien".

    • incrementerFactoryClass - Cet attribut spécifie la classe de fabrique pour créer l'instance d'incrémentation.

  • <subreportExpression> - Ceci indique où trouver le modèle de rapport compilé pour le sous-rapport. Cet élément a unclassattribut. L' attribut class peut prendre l'une de ces valeurs: java.lang.String, java.io.File, java.net.URL, java.io.InputStream, net.sf.jasperreports.engine.JasperReport. La valeur par défaut est java.lang.String .

  • isUsingCache - Ceci est un attribut de l'élément <subreport>. Il s'agit d'une valeur booléenne. Lorsqu'elle est définie sur true , le moteur de création de rapports essaiera de reconnaître les objets de modèle de sous-rapport précédemment chargés, en utilisant leur source spécifiée. Cette fonctionnalité de mise en cache est disponible uniquement pour les éléments de sous-rapport qui ont des expressions renvoyant des objets java.lang.String comme source de modèle de sous-rapport, représentant des noms de fichier, des URL ou des ressources de chemin de classe.

Exemple

Prenons un exemple simple pour illustrer la création de sous-rapports à l'aide de JRDataSource. Commençons par écrire deux nouveaux modèles de rapport, l'un étant le sous-rapport et l'autre le rapport principal. Le contenu du modèle de sous-rapport (address_report_template.jrxml) est indiqué ci-dessous. Enregistrez-le dans le répertoire C: \ tools \ jasperreports-5.0.1 \ test.

<?xml version = "1.0" encoding = "UTF-8"?>
<jasperReport
   xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "address_report_template" pageWidth = "175" pageHeight = "842" 
   columnWidth = "175" leftMargin = "0" rightMargin = "0" 
   topMargin = "0" bottomMargin = "0">

   <field name = "city" class = "java.lang.String"/>
   <field name = "street" class = "java.lang.String"/>
   
   <background>
      <band splitType = "Stretch"/>
   </background>
   
   <title>
      <band height = "20" splitType = "Stretch">
         
         <staticText>
            <reportElement x = "0" y = "0" width = "100" height = "20"/>
            
            <textElement>
               <font size = "14" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Addresses]]></text>
         </staticText>
      
      </band>
   </title>
   
   <pageHeader>
      <band height = "12" splitType = "Stretch"/>
   </pageHeader>
   
   <columnHeader>
      <band height = "12" splitType = "Stretch"/>
   </columnHeader>
   
   <detail>
      <band height = "27" splitType = "Stretch">
         
         <textField>
            <reportElement x = "0" y = "0" width = "120" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{city}+" Address:"]]>
            </textFieldExpression>
         </textField>
         
         <textField isStretchWithOverflow = "true">
            <reportElement x = "120" y = "0" width = "435" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{street}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </detail>
   
   <columnFooter>
      <band height = "8" splitType = "Stretch"/>
   </columnFooter>
  
   <pageFooter>
      <band height = "11" splitType = "Stretch"/>
   </pageFooter>
   
   <summary>
      <band height = "9" splitType = "Stretch"/>
   </summary>

</jasperReport>

Comme nous utilisons une source de données, nous devons écrire un fichier POJO correspondant SubReportBean.java comme indiqué ci-dessous. Enregistrez-le dans le répertoire C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint -

package com.tutorialspoint;

public class SubReportBean {
   private String city;
   private String street;

   public String getCity() {
      return city;
   }

   public void setCity(String city) {
      this.city = city;
   }

   public String getStreet() {
      return street;
   }

   public void setStreet(String street) {
      this.street = street;
   }
}

Ici, nous avons déclaré deux champs 'city' et 'street' et les méthodes getter et setter respectives sont définies.

Maintenant, mettons à jour notre existant DataBeanfichier. Nous allons ajouter un nouveau champ subReportBeanList , qui est un java.util.List. Ce champ contiendra la liste des objets SubReportBean. Le contenu du fichier DataBean est comme ci-dessous. Enregistrez-le dans le répertoire C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint.

package com.tutorialspoint;

import java.util.List;

public class DataBean {
   private String name;
   private String country;
   private List<SubReportBean> subReportBeanList;

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }

   public List<SubReportBean> getSubReportBeanList() {
      return subReportBeanList;
   }

   public void setSubReportBeanList(List<SubReportBean> subReportBeanList) {
      this.subReportBeanList = subReportBeanList;
   }
}

Mettons maintenant à jour le fichier C: \ tools \ jasperreports-5.0.1 \ test \ src \ com \ tutorialspoint \DataBeanList.java. Le contenu de ce fichier est comme -

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {

      // Create sub report data
      SubReportBean subBean1 = new SubReportBean();
      subBean1.setCity("Mumbai");
      subBean1.setStreet("M.G.Road");
      SubReportBean subBean2 = new SubReportBean();
      subBean2.setCity("New York");
      subBean2.setStreet("Park Street");
      SubReportBean subBean3 = new SubReportBean();
      subBean3.setCity("San Fransisco");
      subBean3.setStreet("King Street");

      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      // Create master report data
      dataBeanList.add(produce("Manisha", "India",
         Arrays.asList(subBean1)));
      dataBeanList.add(produce("Dennis Ritchie", "USA",
         Arrays.asList(subBean2)));
      dataBeanList.add(produce("V.Anand", "India",
         Arrays.asList(subBean1)));
      dataBeanList.add(produce("Shrinath", "California",
         Arrays.asList(subBean3)));

      return dataBeanList;
   }

   /*
    * This method returns a DataBean object,
    * with name, country and sub report
    * bean data set in it.
    */
   private DataBean produce(String name, String country,
      List<SubReportBean> subBean) {
      DataBean dataBean = new DataBean();

      dataBean.setName(name);
      dataBean.setCountry(country);
      dataBean.setSubReportBeanList(subBean);

      return dataBean;
   }
}

Dans la méthode produire () dans le fichier ci-dessus, nous définissons la liste de SubReportBean.

Maintenant, écrivons un nouveau modèle de rapport principal (jasper_report_template.jrxml). Enregistrez ce fichier dans le répertoireC:\tools\jasperreports-5.0.1\test. Le contenu de ce fichier est comme ci-dessous -

<?xml version = "1.0" encoding = "UTF-8"?>
<jasperReport xmlns = "http://jasperreports.sourceforge.net/jasperreports"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://jasperreports.sourceforge.net/jasperreports
   http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
   name = "jasper_report_template" language = "groovy" pageWidth = "595"
   pageHeight = "842" columnWidth ="555" leftMargin = "20" rightMargin = "20"
   topMargin = "20" bottomMargin = "20">

   <parameter name = "SUBREPORT_DIR" class = "java.lang.String" isForPrompting = "false">
      <defaultValueExpression>
         <![CDATA["C:\\tools\\jasperreports-5.0.1\\test\\"]]>
      </defaultValueExpression>
   </parameter>
   
   <field name = "country" class = "java.lang.String"/>
   <field name = "name" class = "java.lang.String"/>
   <field name = "subReportBeanList" class = "java.util.List"/>
   
   <background>
      <band splitType = "Stretch"/>
   </background>
   
   <title>
      <band height = "35" splitType = "Stretch">
         
         <staticText>
            <reportElement x = "0" y = "0" width = "204" height = "34"/>
            
            <textElement>
               <font size = "26" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Contact Report]]></text>
         </staticText>
      
      </band>
   </title>
   
   <pageHeader>
      <band height = "17" splitType = "Stretch"/>
   </pageHeader>
   
   <columnHeader>
      <band height = "21" splitType = "Stretch"/>
   </columnHeader>
   
   <detail>
      <band height = "112" splitType = "Stretch">
            
         <staticText>
            <reportElement x = "0" y = "0" width = "100" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Name:]]></text>
         </staticText>
         
         <staticText>
            <reportElement x = "0" y = "20" width = "100" height = "20"/>
            
            <textElement>
               <font size = "12" isBold = "true"/>
            </textElement>
				
            <text><![CDATA[Country:]]></text>
         </staticText>
         
         <textField>
            <reportElement x = "104" y = "0" width = "277" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{name}]]>
            </textFieldExpression>
         </textField>
         
         <textField>
            <reportElement x = "104" y = "20" width = "277" height = "20"/>
            
            <textElement>
               <font size = "12"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$F{country}]]>
            </textFieldExpression>
         </textField>
         
         <subreport>
            <reportElement positionType = "Float" x = "335" y = "25" width = "175"
               height = "20" isRemoveLineWhenBlank = "true" backcolor = "#99ccff"/>

            <dataSourceExpression>
               new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
                  ($F{subReportBeanList})
            </dataSourceExpression>
            
            <subreportExpression class = "java.lang.String">
               <![CDATA[$P{SUBREPORT_DIR} + "address_report_template.jasper"]]>
            </subreportExpression>
         </subreport>
         
         <line>
            <reportElement x = "0" y = "50" width = "550" height = "1"/>
         </line>
      
      </band>
   </detail>
   
   <columnFooter>
      <band height = "19" splitType = "Stretch"/>
   </columnFooter>
   
   <pageFooter>
      <band height = "18" splitType = "Stretch"/>
   </pageFooter>
   
   <summary>
      <band height = "14" splitType = "Stretch"/>
   </summary>

</jasperReport>

Dans le modèle ci-dessus, nous avons défini un nouveau paramètre "SUBREPORT_DIR", qui définit le chemin du sous-rapport. Nous avons défini un champ subReportBeanList de type java.util.List, qui correspond à property dans le fichier DataBean. L'élément <subreport> a un sous-élément <dataSourceExpression>. Nous avons mis la liste subReportBeanList dans une instance de JRBeanCollectionDataSource. Dans le sous-élément <subreportExpression />, nous avons donné le nom du sous-rapport (AddressReport.jasper).

Maintenant, écrivons une nouvelle classe CreateReportpour compiler et exécuter notre modèle de rapport. Le contenu du fichierC:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\CreateReport.java sont comme indiqué ci-dessous -

package com.tutorialspoint;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class CreateReport {

   public static void main(String[] args) {
      String masterReportFileName = "C://tools/jasperreports-5.0.1/test"
         + "/jasper_report_template.jrxml";
      String subReportFileName = "C://tools/jasperreports-5.0.1/test"
         + "/AddressReport.jrxml";
      String destFileName = "C://tools/jasperreports-5.0.1/test"
         + "/jasper_report_template.JRprint";
			
      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();
      JRBeanCollectionDataSource beanColDataSource = new 
         JRBeanCollectionDataSource(dataList);

      try {
         /* Compile the master and sub report */
         JasperReport jasperMasterReport = JasperCompileManager
            .compileReport(masterReportFileName);
         JasperReport jasperSubReport = JasperCompileManager
            .compileReport(subReportFileName);

         Map<String, Object> parameters = new HashMap<String, Object>();
         parameters.put("subreportParameter", jasperSubReport);
         JasperFillManager.fillReportToFile(jasperMasterReport, 
            destFileName, parameters, beanColDataSource);

      } catch (JRException e) {

         e.printStackTrace();
      }
      System.out.println("Done filling!!! ...");
   }
}

Ici, nous voyons que nous compilons les modèles de rapport principal et secondaire et transmettons le fichier de rapport principal (.jasper) pour le remplissage du rapport.

Génération de rapports

Maintenant, tous nos fichiers sont prêts, compilons-les et exécutons-les en utilisant notre processus de construction ANT normal. Le contenu du fichier build.xml (enregistré sous le répertoire C: \ tools \ jasperreports-5.0.1 \ test) est indiqué ci-dessous.

Le fichier d'importation - baseBuild.xml est extrait du chapitre Configuration de l'environnement et doit être placé dans le même répertoire que le build.xml.

<?xml version = "1.0" encoding = "UTF-8"?>
<project name = "JasperReportTest" default = "viewFillReport" basedir = ".">
   <import file = "baseBuild.xml" />
   
   <target name = "viewFillReport" depends = "compile,compilereportdesing,run"
      description = "Launches the report viewer to preview the 
      report stored in the .JRprint file.">
      
      <java classname = "net.sf.jasperreports.view.JasperViewer" fork = "true">
         <arg value = "-F${file.name}.JRprint" />
         <classpath refid = "classpath" />
      </java>
   </target>
   
   <target name = "compilereportdesing" description = "Compiles the JXML file and
      produces the .jasper file.">
      
      <taskdef name = "jrc" classname = "net.sf.jasperreports.ant.JRAntCompileTask">
         <classpath refid = "classpath" />
      </taskdef>
      
      <jrc destdir = ".">
         <src>
            <fileset dir = ".">
               <include name = "*.jrxml" />
            </fileset>
         </src>
         <classpath refid = "classpath" />
      </jrc>
		
   </target>

</project>

Ensuite, ouvrons la fenêtre de ligne de commande et allons dans le répertoire où build.xml est placé. Enfin, exécutez la commandeant -Dmain-class=com.tutorialspoint.CreateReport (viewFullReport est la cible par défaut) comme suit -

Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

clean-sample:
   [delete] Deleting directory C:\tools\jasperreports-5.0.1\test\classes

compile:
   [mkdir] Created dir: C:\tools\jasperreports-5.0.1\test\classes
   [javac] C:\tools\jasperreports-5.0.1\test\baseBuild.xml:28: 
      warning: 'includeantruntime' was not set, defaulting to
   [javac] Compiling 7 source files to C:\tools\jasperreports-5.0.1\test\classes

compilereportdesing:
   [jrc] Compiling 1 report design files.
   [jrc] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [jrc] log4j:WARN Please initialize the log4j system properly.
   [jrc] log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig 
      for more info.
   [jrc] File : C:\tools\jasperreports-5.0.1\test\
      jasper_report_template.jrxml ... OK.

run:
   [echo] Runnin class : com.tutorialspoint.CreateReport
   [java] Compiling Report Design ...
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.engine.xml.JRXmlDigesterFactory).
   [java] log4j:WARN Please initialize the log4j system properly.
   [java] Done filling!!! ...

viewFillReport:
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL
Total time: 72 minutes 13 seconds

À la suite de la compilation ci-dessus, une fenêtre JasperViewer s'ouvre comme indiqué dans l'écran ci-dessous -

Ici, nous pouvons voir que les attributs Nom, Pays et Adresse sont affichés.