www.alexander-merz.com | Alexander Merz

JasperReports-Einführung Teil 2 – Abschnitte und Größenangaben

Ein Bericht besteht aus mehr als nur Kolonnen von blanken Zahlen und Daten. Im zweiten Artikel nehmen wir die Abschnitte unter die Lupe, in die JasperReports einen Bericht aufteilt und wie Elementgrößen angegeben werden.

Die Quelltexte der Java-Klassen, der XML-Dateien und der SQL-Skripte finden sich unter www.alexander-merz.com/jr-examples.zip.

Im ersten Artikel haben wir bereits einen dieser Abschnitte kennen gelernt: den <detail>- Block. Er nimmt die Daten des Reports auf. Es existieren aber noch 7 weitere:

Der <title>-Block

(Titel)

Dieser Block wird nur auf der ersten Seite des Berichtes ausgegeben. Beziehungsweise kann über ein Attribute festgelegt werden, dass er als eigenständige Seite erscheint.

Der <pageheader>-Block

(Seitenkopf)

Der Block für den Seitenkopf wird auf jeder Ausgabeseite wiederholt. Auf der ersten Seite steht er unterhalb des <title>-Blocks.

Der <columnHeader>-Block

(Spaltenkopf)

Die Daten im <detail>-Block werden meist als Tabelle wiedergegeben. Im Spaltenkopf- Abschnitt können die Überschriften für die einzelnen Spalten der Tabelle angegeben werden. Der Spaltenkopf-Abschnitt befindet sich auf jeder Ausgabeseite, die auch einen <detail>- Block enthält.

Der <columnFooter>-Block

(Spaltenfuß)

Als Gegenstück zum <columnHeader> erscheint dieser Abschnitt immer am Ende <detail>- Blocks einer Ausgabeseite.

Der <summary>-Block

(Zusammenfassung)

Die Zusammenfassung erscheint am Ende des <detail>-Blocks, auch bei mehrseitigen Berichten. Er wird nicht auf jeder Ausgabeseite wiederholt. Ein Beispiel für den Einsatz des Blocks stellt eine Rechnung dar: Im <detail>-Block werden die einzelnen Posten aufgelistet, der <summary>-Block enthält den aufsummierten Rechnungsbetrag. Über ein Attribut kann dieser Block auch selbstständig auf einer eigenen Seite erscheinen.

Der <pageFooter>-Block

(Seitenfuß)

Dieser Block wird am Ende einer jeden Ausgabenseite ausgegeben. Die Ausgabe erfolgt nicht, wenn der <title>-Block oder der <lastPageFooter>-Block die Ausgabeseite vollständig einnehmen. Hier kann z.B. die Seitenzahl platziert werden.

Der <lastPageFooter>-Block

(Letzte Seite)

Wie der Name schon andeutet, wird dieser Block als letzter Abschnitt auf der letzten Ausgabeseite ausgegeben. Er erscheint auf der letzten Seite anstatt des <pageFooter>- Bereiches. Das hat zur Folge, dass ein eventuell vorhandener <pageFooter> nicht ausgegeben wird, wenn der Bericht nur eine Ausgabeseite umfasst.

Abschnitte einbinden

Innerhalb der Abschnitte müssen wir genauso ein <band> definieren, dass die Größe des Abschnittes festlegt. Zur Ausgabe von statischen und dynamischen Text benutzen wir die bereits bekannten <staticText> bzw. <textField>-Tags.

Ein rudimentäres Beispiel (vollständig zu finden in Example3.jrxml):

<title>
  <band>
   <staticText>
    <text><![CDATA[Titel-Seite]]></text>
   </staticText>
  </band>
 </title>

 <pageHeader>
  <band>
   <staticText>
    <text><![CDATA[Seitenkopf-Block]]></text>
   </staticText>
  </band>
 </pageHeader>

 <columnHeader>
  <band>
   <staticText>
    <text><![CDATA[Spaltenkopf-Block]]></text>
   </staticText>
  </band>
 </columnHeader>

 <detail>
  <band>
   <staticText>
    <text><![CDATA[Detail-Block]]></text>
   </staticText>
  </band>
 </detail>

 <columnFooter>
  <band>
   <staticText>
    <text><![CDATA[Spaltenfuß-Block]]></text>
   </staticText>
  </band>
 </columnFooter>

 <pageFooter>
  <band>
   <staticText>
    <text><![CDATA[Seitenfuß-Block]]></text>
   </staticText>
  </band>
 </pageFooter>

 <lastPageFooter>
  <band>
   <staticText>
    <text><![CDATA[Letzte-Seite-Block]]></text>
   </staticText>
  </band>
 </lastPageFooter>

 <summary>
  <band>
   <staticText>
    <text><![CDATA[Zusammenfassungsblock]]></text>
   </staticText>
  </band>
 </summary>

Wird dieses Beispiel kompiliert, dann wird eine einzelne Ausgabeseite erzeugt. Sie enthält alle Elemente bis auf den <pageFooter>-Abschnitt. Der Grund dafür ist, dass auf der letzten Seite immer der <lastPageFooter>-Abschnitt statt des <pageFooter>-Abschnitts ausgegeben wird. Und in diesem Fall ist die einzelne Seite zugleich die letzte Seite.

Die hier gezeigte Reihenfolge der einzelnen Abschnitte in der XML-Datei muss unbedingt eingehalten werden.

Ein weiteres Beispiel (Example4.jrxml) zeigt, welche Elemente wiederholt werden, wenn eine mehrseitige Ausgabe erfolgt. Im Beispiel werden die beiden Datensätze aus der Datenbank geholt und jeder Datensatz auf einer eigenen Seite ausgegeben. Zu diesem Zweck wurde hier einfach die Höhe des <detail>-Abschnitts soweit erhöht, dass nur ein Datensatz auf einer Seite Platz hat.


Größenangaben

Bislang haben wir uns um die Attribute der XML-Tags nicht gekümmert. Real müssen wir aber die Höhe der einzelnen Abschnitte auf einer Ausgabenseite festlegen. Dies geschieht mit dem height-Attribute des <band>-Tags. Die Abschnitt-Tags selber besitzen keine weiteren Attribute, sondern dienen der reinen Unterteilung des Berichtes.

Alle Größenangaben müssen in Pixeln erfolgen; für die Gestaltung des Berichtes ist es wichtig zu wissen, dass JasperReports intern mit 72 Pixel pro Inch bzw. ca. 28 Pixel pro Zentimeter rechnet.

Sie sind nicht auf bestimmte Papiergrößen o.ä. festgelegt. Im <jasperReport>-Tag können Sie die Größe einer Ausgabeseite mit Hilfe der Attribute pageHeight und pageWeight festlegen. Erfolgt keine Größenangabe, geht JasperReports von 842x595 Pixel aus (A4- Format).

Daneben können Sie den druckbaren Bereich eingrenzen über die Attribute leftMargin (linker Einzug), rightMargin (rechter Einzug), topMargin (Abstand von oben) und bottomMargin (Abstand von unten).

Bei der Festlegung der Höhe der Abschnitte müssen Sie darauf achten, dass diese nicht zu hoch werden, ansonsten wirft JasperReports eine Fehlermeldung. Die Berechnung ist relativ simpel: Ausgehend von der Höhe der Gesamtseite ziehen Sie den topMargin- und bottomMargin- Wert ab, die verbleibende Höhe steht Ihnen für die einzelnen Abschnitte zur Verfügung. Eine Besonderheit gilt für den <detail>-Block, den dieser wird für jeden Datensatz wiederholt. Geben wir also eine bestimmte Höhe an, gilt diese pro Datensatz, nicht etwa für alle!

Dieses Verhalten sollte berücksichtigt werden, insbesondere wenn man den <title>-Block nutzt. Nehmen wir an, die uns zur Verfügung stehende Höhe beträgt 400 Pixel (z.B. bei Einsatz eines Querformates). Davon benutzen wir jeweils 30 Pixel für den Seitenkopf, den Spaltenkopf, den Spaltenfuß und den Seitenfuß (4x30 = 120). Damit verbleiben noch 280 Pixel. Ein Datensatz soll eine Höhe von 50 Pixel einnehmen. Ohne den <title>-Block passen genau 5 Datensätze auf diese Seite (und verschwenden 30 Pixel). Wenn ein <title> definiert wurde, der 190 Pixel groß ist, dann passiert folgendes: Der Titel wird platziert, danach die Seiten- und Spalten-Abschnitte, der verbleibende Rest der Höhe wird mit Datensätzen aufgefüllt. 280 Pixel minus 190 für den Titel lässt für die Datensätze aber nur noch 90 Pixel übrig. Da ein Datensatz aber 50 Pixel hoch ist, wird gerade mal noch einer platziert! Abgesehen davon, dass jetzt 40 Pixel verschwendet werden, wirkt ein einzelner Datensatz auf der ersten Seiten recht verloren.

In diesem Fall ist es sinnvoll den Titel-Abschnitt als eigenständige Seite zu erzeugen. Dies geschieht mit dem isTitleNewPage-Attribut im <jasperReport>-Tag. Der Summary-Abschnitt bei dem ähnliche optische Probleme auftreten können, kann mit dem isSummaryNewPage- Attribut gleichfalls auf eine eigene Abschlussseite verschoben werden.

Im Beispiel Example5.jrxml sind die Größenangabe für die Seite explizit vorgegeben und wir bestimmen, dass der Titel-Abschnitt und die Zusammenfassung jeweils auf eigenen Seiten platziert werden sollen.

<jasperReport
    name="Example5"
    pageWidth="595"
    pageHeight="842"
    leftMargin="20"
    rightMargin="20"
    topMargin="64"
    bottomMargin="64"
    isTitleNewPage="true"
    isSummaryNewPage="true">
Im Gegensatz zu den bisherigen Beispielen wurde die Höhe dieser beiden Abschnitte auf 560 Pixel festgelegt.
<title>
  <band height="560">
  ...

<summary>
  <band height="560">
  ...

Ohne die beiden auf true gesetzten Attribute isTitleNewPage und isSummaryNewPage im <jasperReport>-Tag würde beim Kompilieren aber ein Fehler auftreten und die Meldung erscheinen, dass diese Abschnitte zu groß sind. Da diese aber auf eigene Seiten platziert werden, ohne Seiten bzw. Spalten-Abschnitte, ist der Platz ausreichend.

Im nächsten Artikel werden wir uns die Formatierungsmöglichkeiten für Texte näher anschauen.

JasperReports-Einführung Teil 1
JasperReports-Einführung Teil 2 – Abschnitte und Größenangaben
JasperReports-Einführung Teil 3 - Texte und Schriften
JasperReports Einführung Teil 4 - Die Datenquellen