JasperReports - Tablas cruzadas

Los informes de tabla cruzada (tabulación cruzada) son los informes que contienen tablas que organizan los datos en filas y columnas en forma tabular. El objeto de tabla de referencias cruzadas se utiliza para insertar un informe de tabla de referencias cruzadas dentro del informe principal. Las tablas de referencias cruzadas se pueden utilizar con cualquier nivel de datos (nominal, ordinal, intervalo o relación) y, por lo general, muestran los datos resumidos, contenidos en las variables del informe, en forma de tabla dinámica. Las variables se utilizan para mostrar datos agregados como sumas, recuentos, valores promedio.

Propiedades de la tabla de referencias cruzadas

Elemento JRXML <crosstab> se utiliza para insertar una tabla de referencias cruzadas en un informe.

Atributo

A continuación se muestra una lista de atributos de un <crosstab> elemento -

  • isRepeatColumnHeaders- Indica si los encabezados de las columnas deben reimprimirse después de un salto de página. El valor predeterminado es verdadero .

  • isRepeatRowHeaders: Indica si los encabezados de fila deben volver a imprimirse después de un salto de columna de tabla de referencias cruzadas. El valor predeterminado es verdadero .

  • columnBreakOffset- Cuando se produce un salto de columna, indica la cantidad de espacio vertical, medido en píxeles, antes de la siguiente pieza de la tabla de referencias cruzadas que se colocará debajo de la anterior en la misma página. El valor predeterminado es 10.

  • runDirection- Indica si los datos de la tabla de referencias cruzadas se deben completar de izquierda a derecha (LTR) o de derecha a izquierda (RTL). El valor predeterminado es LTR.

  • ignoreWidth- Indica si la tabla de referencias cruzadas se extenderá más allá del límite de ancho de la tabla de referencias cruzadas inicial y no generará saltos de columna. De lo contrario, dejará de representar columnas dentro del límite de ancho de la tabla de referencias cruzadas y continuará con las columnas restantes solo después de que todas las filas hayan comenzado a representarse. El valor predeterminado es falso .

Elementos secundarios

Un elemento <crosstab> tiene los siguientes subelementos:

  • <reportElement>- Este elemento define la posición, el ancho y la altura de la tabla de referencias cruzadas dentro de su recinto. Los atributos de este elemento incluyen todos los atributos <reportElement> estándar.

  • <crosstabParameter>- Este elemento se utiliza para acceder a variables y parámetros del informe desde la tabla de referencias cruzadas. Los atributos de este elemento incluyen:

    • nombre : esto define el nombre del parámetro.

    • clase : indica la clase de parámetro.

  • <parametersMapExpression>- Este elemento se utiliza para pasar una variable de informe o un parámetro que contiene una instancia de java.util.Map , como un conjunto de parámetros para la tabla de referencias cruzadas. Este elemento no contiene atributos.

  • <crosstabDataset>- Este elemento define el conjunto de datos que se utilizará para completar la tabla de referencias cruzadas (consulte la siguiente sección para obtener una explicación detallada). Los atributos de este elemento incluyen:

    • isDataPreSorted : esto indica si los datos en el conjunto de datos están preordenados. El valor predeterminado es falso .

  • <crosstabHeaderCell>- Este elemento define el contenido de la región que se encuentra en la esquina superior izquierda de la tabla de referencias cruzadas donde se encuentran los encabezados de columna y de fila. El tamaño de esta celda se calcula automáticamente en función de los anchos y alturas de filas y columnas definidas.

  • <rowGroup>- Este elemento define un grupo utilizado para dividir los datos en filas. Los atributos de este elemento incluyen:

    • nombre : define el nombre del grupo de filas.

    • ancho : esto define el ancho del grupo de filas.

    • headerPosition : esto define la posición del contenido del encabezado (Superior, Medio, Inferior, Estirado).

    • totalPosition : define la posición de toda la columna (Inicio, Fin, Ninguno).

    Este elemento contiene los siguientes subelementos:

    • <bucket>

    • <crosstabRowHeader>

    • <crosstabTotalRowHeader>

  • <columnGroup>- Este elemento define un grupo utilizado para dividir los datos en columnas. Los atributos de este elemento incluyen:

    • nombre : define el nombre del grupo de columnas.

    • altura : define la altura del encabezado del grupo de columnas.

    • headerPosition : define la posición del contenido del encabezado ( derecha, izquierda, centro, estiramiento ).

    • totalPosition : define la posición de toda la columna ( Inicio, Fin, Ninguno ).

    Este elemento contiene los siguientes subelementos:

    • <bucket>

    • <crosstabColumnHeader>

    • <crosstabTotalColumnHeader>

  • <measure>- Este elemento define el cálculo que se realizará en filas y columnas. Los atributos de este elemento incluyen:

    • nombre : define el nombre de la medida.

    • clase : indica la clase de medida.

    • cálculo : indica el cálculo que se realizará entre los valores de celda de la tabla de referencias cruzadas. Sus valores pueden ser cualquiera de estos: Nada, Recuento, DistinctCount, Suma, Promedio, Mínimo, Máximo, Desviación estándar, Varianza y Primero . El valor predeterminado esNothing.

  • <crosstabCell>- Este elemento define cómo se distribuirán los datos en las celdas sin encabezado. Los atributos de este elemento incluyen:

    • columnTotalGroup : indica el grupo que se utilizará para calcular el total de la columna.

    • altura : esto define la altura de la celda.

    • rowTotalGroup : indica el grupo que se utilizará para calcular el total de la fila.

    • ancho : esto define el ancho de la celda.

  • <whenNoDataCell>- Este elemento define qué mostrar en una celda de tabla cruzada vacía. Este elemento no contiene atributos.

Agrupación de datos en tabla cruzada

El motor de cálculo de tabla cruzada agrega datos iterando a través de los registros del conjunto de datos asociados. Para agregar datos, es necesario agruparlos primero. En una tabla de referencias cruzadas, las filas y columnas se basan en elementos de grupo específicos, denominadosbuckets. Una definición de depósito debe contener:

  • bucketExpression : la expresión que se evaluará para obtener elementos del grupo de datos.

  • comparatorExpression : necesario en el caso de que el orden natural de los valores no sea la mejor opción.

  • orderByExpression : indica el valor utilizado para ordenar los datos.

Los grupos de filas y columnas (definidos anteriormente) en una tabla de referencias cruzadas se basan en buckets.

Variables totales de tabla cruzada incorporadas

A continuación se muestra una lista del valor actual de la medida y se puede acceder a los totales de los diferentes niveles correspondientes a la celda a través de variables nombradas de acuerdo con el siguiente esquema:

  • El valor actual de un cálculo de medida se almacena en una variable que tiene el mismo nombre que la medida.

  • <Medida> _ <Grupo de columnas> _TODOS : esto produce el total de todas las entradas en el grupo de columnas de la misma fila.

  • <Medida> _ <Grupo de filas> _TODOS : esto da el total de todas las entradas en el grupo de filas de la misma columna.

  • <Medida> _ <Grupo de filas> _ <Grupo de columnas> _TODOS : esto produce el total combinado correspondiente a todas las entradas en los grupos de filas y columnas.

Ejemplo

Para demostrar las tablas de referencias cruzadas, escriba una nueva plantilla de informe (jasper_report_template.jrxml). Aquí, agregaremos la tabla de referencias cruzadas a la sección de resumen. Guárdelo en el directorioC:\tools\jasperreports-5.0.1\test. El contenido del archivo es el que se indica a continuación:

<?xml version = "1.0" encoding = "UTF-8"?>

<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN"
   "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
	
<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 = "ReportTitle" class = "java.lang.String"/>
   <parameter name = "Author" class = "java.lang.String"/>
   
   <field name = "name" class = "java.lang.String"/>
   <field name = "country" class = "java.lang.String"/>
   
   <title>
      <band height = "70">
         
         <line>
            <reportElement x = "0" y = "0" width = "515" height = "1"/>
         </line>
         
         <textField isBlankWhenNull = "true" bookmarkLevel = "1">
            <reportElement x = "0" y = "10" width = "515" height = "30"/>
            
            <textElement textAlignment = "Center">
               <font size = "22"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{ReportTitle}]]>
            </textFieldExpression>
            
            <anchorNameExpression>
               <![CDATA["Title"]]>
            </anchorNameExpression>
         </textField>
         
         <textField isBlankWhenNull = "true">
            <reportElement  x = "0" y = "40" width = "515" height = "20"/>
            
            <textElement textAlignment = "Center">
               <font size = "10"/>
            </textElement>
            
            <textFieldExpression class = "java.lang.String">
               <![CDATA[$P{Author}]]>
            </textFieldExpression>
         </textField>
      
      </band>
   </title>
   
   <summary>
      <band height = "60">
      
      <crosstab>
         <reportElement width = "782" y = "0" x = "0" height = "60"/>
          
         <rowGroup name = "nameGroup" width = "100">
         
            <bucket>
               <bucketExpression class = "java.lang.String">
                  <![CDATA[$F{name}]]>
               </bucketExpression>
            </bucket>
            
            <crosstabRowHeader>
            
               <cellContents>
                  <box border = "Thin" borderColor = "black"/>
                  
                  <textField>
                     <reportElement width = "100" y = "0" x = "0" height = "20"/>
                     <textElement textAlignment = "Right" 
                        verticalAlignment = "Middle"/>
                     
                     <textFieldExpression>
                        <![CDATA[$V{nameGroup}]]>
                     </textFieldExpression>
                  </textField>
            
               </cellContents>
         
            </crosstabRowHeader>

         </rowGroup>
         
         <columnGroup name = "countryGroup" height = "20">
            <bucket>
               
               <bucketExpression class = "java.lang.String">
                  $F{country}
               </bucketExpression>
            </bucket>
            
            <crosstabColumnHeader>
               <cellContents>
                  <box border = "Thin" borderColor = "black"/>
                  <textField isStretchWithOverflow = "true">
                     <reportElement width = "60" y = "0" x = "0" height = "20"/>
                     <textElement verticalAlignment = "Bottom"/>
                     <textFieldExpression>
                        <![CDATA[$V{countryGroup}]]>
                     </textFieldExpression>
                  </textField>
               </cellContents>
            </crosstabColumnHeader>

         </columnGroup>
         
         <measure name = "tailNumCount" class = "java.lang.Integer"  
            calculation = "Count">
            <measureExpression>$F{country}</measureExpression>
         </measure>
         
         <crosstabCell height = "20" width = "60">
            <cellContents backcolor = "#FFFFFF">
               <box borderColor = "black" border = "Thin"/>
               <textField>
                  <reportElement x = "5" y = "0" width = "55" height = "20"/>
                  <textElement textAlignment = "Left" 
                     verticalAlignment = "Bottom"/>
                  <textFieldExpression class = "java.lang.Integer">
                      $V{tailNumCount}
                  </textFieldExpression>
               </textField>
            </cellContents>
         </crosstabCell>
      
      </crosstab>
      
      </band>
   </summary>
	
</jasperReport>

Los detalles del archivo anterior son los siguientes:

  • La tabla de referencias cruzadas se define mediante el elemento <crosstab>.

  • El elemento <rowGroup> define un grupo para dividir los datos en filas. Aquí, cada fila mostrará datos con un nombre diferente.

  • Los elementos <bucket> y <bucketExpression> definen qué expresión de informe usar como delimitador de grupo para <rowGroup>. Aquí, usamos el campo de nombre como delimitador para dividir las filas por nombre.

  • El elemento <crosstabRowHeader> define la expresión que se utilizará como encabezado de fila. Contiene un único subelemento, llamado <cellContents>, que actúa como una banda interior dentro de la tabla de referencias cruzadas. En lugar de definir el nombre de la variable para el campo de texto dentro de <crosstabRowHeader>, hemos asignado el nombre a <rowGroup> (a través de su atributo de nombre), por lo tanto, crea una variable implícita. El elemento <crosstabRowHeader> define el contenido de la celda del encabezado para toda la fila. Toma un solo elemento <cellContents> como su único subelemento.

  • El elemento <columnGroup> así como sus subelementos son análogos al elemento <rowGroup>, excepto que influye en las columnas en lugar de en las filas.

  • El elemento <measure> define el cálculo que se realizará en filas y columnas. El atributo de cálculo se establece en Recuento .

  • El elemento <crosstabCell> define cómo se distribuirán los datos en las celdas sin encabezado. Este elemento también contiene un único elemento <crosstabCell> como único subelemento.

Los códigos Java para el llenado de informes no se modifican. El contenido del archivoC:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java son los que se indican a continuación:

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.JasperFillManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;

public class JasperReportFill {
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      String sourceFileName = 
         "C://tools/jasperreports-5.0.1/test/jasper_report_template.jasper";

      DataBeanList DataBeanList = new DataBeanList();
      ArrayList<DataBean> dataList = DataBeanList.getDataBeanList();

      JRBeanCollectionDataSource beanColDataSource =
      new JRBeanCollectionDataSource(dataList);

      Map parameters = new HashMap();
      /**
       * Passing ReportTitle and Author as parameters
       */
      parameters.put("ReportTitle", "List of Contacts");
      parameters.put("Author", "Prepared By Manisha");

      try {
         JasperFillManager.fillReportToFile(
         sourceFileName, parameters, beanColDataSource);
      } catch (JRException e) {
         e.printStackTrace();
      }
   }
}

El contenido del archivo POJO C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java son los siguientes:

package com.tutorialspoint;

public class DataBean {
   private String name;
   private String country;

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

El contenido del archivo C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java son los siguientes:

package com.tutorialspoint;

import java.util.ArrayList;

public class DataBeanList {
   public ArrayList<DataBean> getDataBeanList() {
      ArrayList<DataBean> dataBeanList = new ArrayList<DataBean>();

      dataBeanList.add(produce("Manisha", "India"));
      dataBeanList.add(produce("Dennis Ritchie", "USA"));
      dataBeanList.add(produce("V.Anand", "India"));
      dataBeanList.add(produce("Shrinath", "California"));

      return dataBeanList;
   }

   /**
    * This method returns a DataBean object,
    * with name and country set in it.
    */
   private DataBean produce(String name, String country) {
      DataBean dataBean = new DataBean();
      dataBean.setName(name);
      dataBean.setCountry(country);
      
      return dataBean;
   }
}

La generación del informe

A continuación, compilemos y ejecutemos los archivos anteriores utilizando nuestro proceso de compilación ANT habitual. El contenido del archivo build.xml (guardado en el directorio C: \ tools \ jasperreports-5.0.1 \ test) es como se indica a continuación.

El archivo de importación, baseBuild.xml, se obtiene del capítulo Configuración del entorno y debe colocarse en el mismo directorio que 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>

A continuación, abramos la ventana de la línea de comandos y vayamos al directorio donde se coloca build.xml. Finalmente, ejecute el comandoant -Dmain-class=com.tutorialspoint.JasperReportFill (viewFullReport es el destino predeterminado) de la siguiente manera:

C:\tools\jasperreports-5.0.1\test>ant -Dmain-class=com.tutorialspoint.JasperReportFill
Buildfile: C:\tools\jasperreports-5.0.1\test\build.xml

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

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 3 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.JasperReportFill
   [java] log4j:WARN No appenders could be found for logger
   (net.sf.jasperreports.extensions.ExtensionsEnvironment).
   [java] log4j:WARN Please initialize the log4j system properly.

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: 20 minutes 53 seconds

Como resultado de la compilación anterior, se abre una ventana de JasperViewer como se muestra en la pantalla que se muestra a continuación:

Aquí vemos que cada país y nombre están tabulados.