JasperReports - Crosstabs

Raporty tabeli krzyżowej (cross-tabulation) to raporty zawierające tabele, które porządkują dane w wierszach i kolumnach w formie tabelarycznej. Obiekt tabeli przestawnej służy do wstawiania raportu tabeli przestawnej w raporcie głównym. Tabel krzyżowych można używać z dowolnym poziomem danych (nominalnym, porządkowym, przedziałowym lub współczynnikiem) i zwykle wyświetlają podsumowane dane zawarte w zmiennych raportu w postaci tabeli dynamicznej. Zmienne służą do wyświetlania danych zbiorczych, takich jak sumy, liczebności, wartości średnie.

Właściwości tabeli krzyżowej

Element JRXML <crosstab> służy do wstawiania tabeli przestawnej do raportu.

Atrybut

Poniżej znajduje się lista atrybutów <crosstab> element -

  • isRepeatColumnHeaders- Wskazuje, czy nagłówki kolumn powinny zostać ponownie wydrukowane po podziale strony. Wartość domyślna to true .

  • isRepeatRowHeaders- Wskazuje, czy nagłówki wierszy powinny zostać ponownie wydrukowane po przerwaniu kolumny tabeli przestawnej. Wartość domyślna to true .

  • columnBreakOffset- Gdy nastąpi przerwanie kolumny, wskazuje wielkość odstępu w pionie, mierzoną w pikselach, przed umieszczeniem kolejnego elementu tabeli przestawnej poniżej poprzedniego na tej samej stronie. Wartość domyślna to 10.

  • runDirection- Wskazuje, czy dane tabeli przestawnej powinny być wypełniane od lewej do prawej (LTR), czy od prawej do lewej (RTL). Wartość domyślna to LTR.

  • ignoreWidth- Wskazuje, czy tabela przestawna będzie rozciągać się poza początkowy limit szerokości tabeli przestawnej i nie generuje podziałów kolumn. W przeciwnym razie zatrzyma renderowanie kolumn w ramach ograniczenia szerokości tabeli przestawnej i będzie kontynuował wyświetlanie pozostałych kolumn dopiero po rozpoczęciu renderowania wszystkich wierszy. Wartość domyślna to false .

Elementy podrzędne

Element <crosstab> ma następujące elementy podrzędne -

  • <reportElement>- Ten element definiuje pozycję, szerokość i wysokość tabeli przestawnej wewnątrz otaczającej go tabeli przestawnej. Atrybuty tego elementu obejmują wszystkie standardowe atrybuty <reportElement>.

  • <crosstabParameter>- Ten element służy do uzyskiwania dostępu do zmiennych raportu i parametrów z poziomu tabeli przestawnej. Atrybuty tego elementu obejmują -

    • name - określa nazwę parametru.

    • class - wskazuje klasę parametru.

  • <parametersMapExpression>- Ten element służy do przekazywania zmiennej raportu lub parametru zawierającego instancję java.util.Map jako zestaw parametrów tabeli przestawnej. Ten element nie zawiera atrybutów.

  • <crosstabDataset>- Ten element definiuje zbiór danych, który ma być użyty do wypełnienia tabeli przestawnej (szczegółowe wyjaśnienie znajduje się w następnej sekcji). Atrybuty tego elementu obejmują -

    • isDataPreSorted - wskazuje, czy dane w zestawie danych są wstępnie posortowane. Wartość domyślna to false .

  • <crosstabHeaderCell>- Ten element definiuje zawartość regionu znajdującego się w lewym górnym rogu tabeli przestawnej, gdzie spotykają się nagłówki kolumn i wierszy. Rozmiar tej komórki jest obliczany automatycznie na podstawie zdefiniowanych szerokości i wysokości wierszy i kolumn.

  • <rowGroup>- ten element definiuje grupę używaną do dzielenia danych na wiersze. Atrybuty tego elementu obejmują -

    • name - określa nazwę grupy wierszy.

    • szerokość - określa szerokość grupy wierszy.

    • headerPosition - określa pozycję zawartości nagłówka (góra, środek, dół, rozciągnięcie).

    • totalPosition - definiuje pozycję całej kolumny (początek, koniec, brak).

    Ten element zawiera następujące elementy podrzędne -

    • <bucket>

    • <crosstabRowHeader>

    • <crosstabTotalRowHeader>

  • <columnGroup>- ten element definiuje grupę używaną do podziału danych na kolumny. Atrybuty tego elementu obejmują -

    • name - określa nazwę grupy kolumn.

    • wysokość - określa wysokość nagłówka grupy kolumn.

    • headerPosition - definiuje pozycję zawartości nagłówka ( Right, Left, Center, Stretch ).

    • totalPosition - definiuje pozycję całej kolumny ( początek, koniec, brak ).

    Ten element zawiera następujące elementy podrzędne -

    • <bucket>

    • <crosstabColumnHeader>

    • <crosstabTotalColumnHeader>

  • <measure>- Ten element definiuje obliczenia, które mają być wykonywane w wierszach i kolumnach. Atrybuty tego elementu obejmują -

    • name - określa nazwę miary.

    • klasa - wskazuje klasę miary.

    • obliczenia - wskazuje obliczenia, które mają być wykonane między wartościami komórek tabeli przestawnej. Jego wartości mogą być dowolne z następujących: Nothing, Count, DistinctCount, Sum, Average, Lowest, Highest, StandardDeviation, Variance i First . Wartość domyślna toNothing.

  • <crosstabCell>- Ten element określa, w jaki sposób będą układane dane w komórkach niebędących nagłówkami. Atrybuty tego elementu obejmują -

    • columnTotalGroup - wskazuje grupę, która ma zostać użyta do obliczenia sumy kolumny.

    • wysokość - określa wysokość komórki.

    • rowTotalGroup - wskazuje grupę, która ma zostać użyta do obliczenia sumy wiersza.

    • szerokość - określa szerokość komórki.

  • <whenNoDataCell>- Ten element określa, co ma być wyświetlane w pustej komórce tabeli przestawnej. Ten element nie zawiera atrybutów.

Grupowanie danych w tabeli krzyżowej

Silnik obliczeń tabeli przestawnej agreguje dane, wykonując iterację po powiązanych rekordach zestawu danych. Aby zagregować dane, należy je najpierw pogrupować. W tabeli przestawnej wiersze i kolumny są oparte na określonych elementach grupy, tzwbuckets. Definicja zasobnika powinna zawierać -

  • bucketExpression - wyrażenie, które ma zostać ocenione w celu uzyskania elementów grupy danych.

  • ComparatorExpression - potrzebny w przypadku, gdy naturalne uporządkowanie wartości nie jest najlepszym wyborem.

  • orderByExpression - wskazuje wartość używaną do sortowania danych.

Grupy wierszy i kolumn (zdefiniowane powyżej) w tabeli przestawnej zależą buckets.

Wbudowane zmienne całkowite tabeli krzyżowej

Poniżej znajduje się lista aktualnych wartości miary oraz sumy różnych poziomów odpowiadające komórce, do których można uzyskać dostęp poprzez zmienne nazwane zgodnie z poniższym schematem -

  • Bieżąca wartość obliczenia miary jest przechowywana w zmiennej o tej samej nazwie co miara.

  • <Measure> _ <Column Group> _ALL - Zwraca sumę wszystkich wpisów w grupie kolumn z tego samego wiersza.

  • <Measure> _ <Row Group> _ALL - Zwraca sumę wszystkich wpisów w grupie wierszy z tej samej kolumny.

  • <Measure> _ <Row Group> _ <Column Group> _ALL - Daje to połączoną sumę odpowiadającą wszystkim wpisom w grupach wierszy i kolumn.

Przykład

Aby zademonstrować tabele przestawne, napiszmy nowy szablon raportu (jasper_report_template.jrxml). Tutaj dodamy tabelę przestawną do sekcji podsumowania. Zapisz go w kataloguC:\tools\jasperreports-5.0.1\test. Zawartość pliku jest taka, jak podano poniżej -

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

Szczegóły powyższego pliku są następujące -

  • Crosstab jest definiowany przez element <crosstab>.

  • Element <rowGroup> definiuje grupę do podziału danych na wiersze. Tutaj w każdym wierszu będą wyświetlane dane dla innej nazwy.

  • Elementy <bucket> i <bucketExpression> definiują, które wyrażenie raportu ma być używane jako separator grupy dla <rowGroup>. Tutaj użyliśmy pola nazwy jako separatora, aby podzielić wiersze według nazwy.

  • Element <crosstabRowHeader> definiuje wyrażenie, które ma być używane jako nagłówek wiersza. Zawiera pojedynczy element podrzędny, a mianowicie <cellContents>, który działa jak wewnętrzna wstęga wewnątrz tabeli przestawnej. Zamiast definiować nazwę zmiennej dla pola tekstowego wewnątrz <crosstabRowHeader>, przypisaliśmy nazwę do <rowGroup> (poprzez jej atrybut name), dzięki czemu tworzy ona niejawną zmienną. Element <crosstabRowHeader> definiuje zawartość komórki nagłówka dla całego wiersza. Jako jedyny element podrzędny przyjmuje pojedynczy element <cellContents>.

  • Element <columnGroup>, jak również jego elementy podrzędne, są analogiczne do elementu <rowGroup>, z tą różnicą, że wpływa na kolumny zamiast na wiersze.

  • Element <measure> definiuje obliczenia, które mają być wykonywane w wierszach i kolumnach. Kalkulacja atrybut jest ustawiony na hrabiego .

  • Element <crosstabCell> definiuje sposób rozmieszczenia danych w komórkach niebędących nagłówkami. Ten element zawiera również pojedynczy element <crosstabCell> jako jedyny element podrzędny.

Kody java do wypełniania raportów pozostają niezmienione. Zawartość plikuC:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\JasperReportFill.java są jak podano poniżej -

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

Zawartość pliku POJO C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBean.java są następujące -

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

Zawartość pliku C:\tools\jasperreports-5.0.1\test\src\com\tutorialspoint\DataBeanList.java są następujące -

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

Generowanie raportów

Następnie skompilujmy i uruchommy powyższe pliki przy użyciu naszego zwykłego procesu kompilacji ANT. Zawartość pliku build.xml (zapisanego w katalogu C: \ tools \ jasperreports-5.0.1 \ test) jest taka, jak podano poniżej.

Plik importu - baseBuild.xml jest pobierany z rozdziału Konfiguracja środowiska i powinien być umieszczony w tym samym katalogu, co plik 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>

Następnie otwórzmy okno wiersza poleceń i przejdźmy do katalogu, w którym znajduje się plik build.xml. Na koniec wykonaj polecenieant -Dmain-class=com.tutorialspoint.JasperReportFill (viewFullReport jest domyślnym celem) w następujący sposób -

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

W wyniku powyższej kompilacji otworzy się okno JasperViewer, jak pokazano na poniższym ekranie -

Tutaj widzimy, że każdy kraj i nazwa są zestawione w tabeli.