“Seite X von Y” rechtsbündig ausrichten
Hinweis: Dieses Tutorial ist veraltet! Es gibt sinnvollere Varianten für die Problemlösung. Seit Jasperreports 6.x ist hier die Verwendung der Variablen MASTER_CURRENT_PAGE, MASTER_TOTAL_PAGES und der passenden “Evaluation Time” MASTER zu empfehlen.
Für Rückfragen stehe ich gerne unter “Kontakt” zur Verfügung.
Problemstellung
In iReport Elementpalette gibt es unter Werkzeuge/Tools das Element “Page X von Y”; tatsächlich handelt es sich beim Einfügen um zwei Textfelder, in denen die automatische Variable $V{PAGE_NUMBER} abgedruckt wird (In $V{PAGE_NUMBER} wird bei der Berichtgenerierung die Anzahl der Seiten gezählt). Die unterschiedlichen Werte (linkes Feld: “Seite {Aktuelle Seite} von”, rechtes Feld “{Gesamtseitenzahl}”) werden dabei dadurch erzielt, dass sich die Einstellungen “Evaluation Time” der Textfelder unterscheiden. Das linke Textfeld hat die Einstellung “Evaluation Time = Now” und wird damit jedesmal ausgewertet und abgedruckt, wenn eine neue Seite in den Bericht eingefügt wird. Das rechte Textfeld hat die Einstellung “Evaluation Time = Report”; dadurch wartet die Jasperreports Engine mit der Auswertung und Abdruck dieses Textfeldes, bis der Report vollständig generiert ist. Zu diesem Zeitpunkt enthält die Variable die Gesamtzahl der Seiten, und beim rückwirkenden Druck des Textfeldes steht somit auf jeder Seite im rechten Textfeld die Gesamtseitenzahl.
Der Haken an der Sache ist, dass hierfür zwei Textfelder benötigt werden, in denen der gesamte Fußtext verteilt ist. Eine rechtsbündige Ausrichtung des linken Textfeldes, sowie eine linksbündige Ausrichtung des rechten Textfeldes ist damit zwingend erforderlich, wenn man insgesamt einen zusammenhängenden Fußzeilentext haben möchte. Die Gesamtzahl der Seiten ist auch üblicherweise im Bericht variabel, sodass sich nur schwer eine exakt passende Breite des rechten Textfeldes festlegen lässt (Die Zahl kann nur eine Ziffer haben, oder auch fünf…). Möchte man Textumbrüche vermeiden (in einer Fußzeile ohnehin nicht ratsam!), muss also das reche Textfeld ausreichend groß gewählt werden. Durch die Linksausrichtung des Textes verbleibt also immer ein gewisser Abstand bis zum rechten Rand der Seite.
Lösung
Hinweis: Es gibt eine einfache Lösung mittels Zählvariablen, passendem Reset-Type und Evaluation time “Auto” im Textfeld, welche aber nur mit einigen Einschränkungen funktioniert: z.B. http://community.jaspersoft.com/questions/541043/page-x-y-footer-subreport
Prinzipielles Vorgehen: Einführen einer Listen-Variablen. Während der Berichtgenerierung wird jede aktuelle Seitenzahl an die Liste angehängt. Zum Schluß wird das einzige Textfeld mit dem kompletten Fußzeilentext von der ersten bis zur letzten Seite nachträglich in den Bericht generiert. Dabei wird immer wie auch oben die Variable $V{PAGE_NUMBER} für die Gesamtseitenzahl und bei jeder generierten Fußzeile das oberste Element aus der neuen Listen-Variablen verwendet (und danach entfernt). So lässt sich in der Fußzeile ein zusammenhängender Text anzeigen und eben auch rechts ausrichten.
Einzelschritte
- Definieren der Variablen “PageStack” (Name beliebig). Der Datentyp dieser Variablen (“Variable Class”) ist “java.util.LinkedList”. Das Bild rechts zeigt die sonstigen, wesentlichen Einstellungen: “Calculation” muss “Nothing” oder “System” sein, da der Variablenwert anderweitig, über den Ausdruck (“Variable Expression”) gesetzt wird. “Reset type” ist “Report”, damit die Variable einmal zu Beginn der Berichtsgenerierung mit dem Initialwert geladen wird (“Initial Value Expression”, hier wird mit dem Ausdruck “new java.util.LinkedList()” ein neues Listenobjekt angelegt und der Variablen zugewiesen). Die Einstellung für “Increment type” muss natürlich “Page” sein, damit der Inhalt der Variablen einmal für jede neue Seite des Berichts angepasst wird. Die vorzunehmende Anpassung ist nun das eigentlich spannende und steht in der Einstellung “Variable Expression”:
!$V{PageStack}.contains($V{PAGE_NUMBER}) && $V{PageStack}.add($V{PAGE_NUMBER}) ? $V{PageStack} : $V{PageStack}
Was passiert hier? Nun, in den ersten beiden Teilen des Ausdrucks vor dem Fragezeichen wird überprüft, ob sich die aktuelle Seitenzahl bereits in der Liste befindet (wenn ja, wird der zweite Teil des Ausdruck ausgelassn). Im zweiten Teil wird dann die aktuelle Seitenzahl zur Liste hinzugefügt. Das Ergebnis der beiden Ausdrücke ist ein Wahrheitswert (true/false), also nicht als Ergebnis für “Variable Expression” verwendbar. Deshalb wird das ganze in eine if-else-Konstrukt (<wenn / if> ? <dann / then> : <sonst / else>) eingebaut, in dem aber sowohl der true-Zweig als auch der false-Zweig lediglich die Variable selbst zurück geben. Das Ergebnis des gesamten Ausdruck ist also einzig und allein die aktualisierte Liste mit Seitenzahlen. - Fußzeilentext unter Verwendung der Variablen $V{PageStack} und $V{PAGE_NUMBER} in einem Textfeld mit Einstellung “Evaluation Time = Report” anlegen. Der Knackpunkt hierbei ist der Teilausdruck <code>$V{PageStack}.removeFirst()</code>; damit wird jedesmal, wenn am Ende der Berichtsgenerierung eines der Fußzeilentextfelder nachträglich in den Bericht generiert wird, das oberste Element der Liste “PageStack” dafür verwendet und gleichzeitg aus der Liste entfernt…
Musterlösungen
Laden Sie sich die ZIP-Datei mit einer vollständigen Musterlösung für diese Problemstellung herunter. Das Archiv enthält Beispieldaten im CSV-Format, eine Datenquellenbeschreibungsdatei zum Import in iReport und alle hier erläuterten Beispielberichte. In der Datei “Readme.txt” finden Sie Hinweise zur Installation des Beispiels und gegebenfalls Hinweise auf zusätzliche Beispiele.