Logo Oracle Deutschland   Application Express Community
Eigene Berichts-Layouts mit Templates
Erscheinungsmonat APEX-Version Datenbankversion
September 2011 alle ab 9.2

Einer der Vorteile von Application Express ist die Möglichkeit, Berichte auf Tabellen sehr schnell zusammenzustellen. Für das Layout wird eine Vielzahl von fertigen Vorlagen (Berichts-Templates) mitgeliefert. Häufig stellt man als Entwickler jedoch fest, dass keine der mitgelieferten Vorlagen so richtig zufriedenstellt. In diesem Tipp lesen Sie daher, wie Sie ein vollständig eigenes Berichts-Layout erstellen und als Template hinterlegen können.

Wir starten mit einem einfachen Bericht. Damit ein eigenes Layout auch wirklich benötigt wird, nehmen wir nicht die bekannte Tabelle EMP, sondern statt dessen die Data Dictionary View USER_TABLES.

Ausgangssituation: Bericht auf die Tabelle EMP
Abb.1: Ausgangssituation: Bericht auf die Tabelle USER_TABLES

Wenn Sie eine Abfrage mit sehr vielen Spalten als Bericht darstellen möchten, stoßen Sie meist an die Grenzen der mitgelieferten Berichts-Templates. In diesem Beispiel bekommen Sie vom Browser eine horizontale Scroll-Leiste. Um die hinteren Spalten zu sehen, muss man nach rechts scrollen. Dies ist nicht besonders benutzerfreundlich - daher wird für diesen Bericht ein anderes Layout benötigt:

  1. Die Informationen sollen in vier Berichtsspalten dargestellt werden: Tabellenname, Storage-Details, Statistiken und weitere Merkmale.
  2. In den Spalten Storage-Details, Statistiken und weitere Merkmale müssen daher mehrere Informationen untergebracht werden.
  3. Detail-Informationen sollen ausgeblendet sein - wenn man mit der Maus darüberfährt, werden sie aktiviert (JavaScript).
  4. Wenn sich die Maus über einer Zeile befindet, soll diese hervorgehoben werden.

Application Express kennt zwei Typen von Berichts-Templates:

  • Generische Spalten-Templates passen auf jeden Bericht. Es nur ein Spalten-Layout definiert - bei Anwendung des Templates werden alle Spalten des Berichts auf diese Art und Weise dargestellt. Generische Spalten-Templates haben den Vorteil, dass sie - einmal definiert - auf eine Vielzahl von Berichten angewendet werden können. Auf der anderen Seite steht der Nachteil, dass man nicht auf Besonderheiten eines bestimmten Berichts eingehen kann.
  • Benannte Spalten (Zeilen-Templates) passen meist nur zu einem bestimmten Bericht. Hier wird das Layout für jede Spalte des Berichts explizit festgelegt. Die Spalten werden entweder mit ihrem Namen oder anhand der Reihenfolge in der SQL-Abfrage angesprochen. Somit bezieht sich ein Benannte Spalten (Zeilen-Template) exakt auf diesen Bericht und kann auf dessen Besonderheiten eingehen. Dem gegenüber steht der Nachteil, dass diese Templates meist  nicht für andere Berichte verwendet werden können.

Die mit Application Express ausgelieferten Berichts-Templates sind durchgehend Generische Spalten-Templates. Sie sollten diesen (wenn möglich) den Vorzug geben, da sie im Vergleich zu den Benannte Spalten-Templates  besser wiederverwendet werden können. 

Benannte Spalten-Templates sollten Sie dann verwenden, wenn die verschiedenen Spalten des Berichts unterschiedlich dargestellt werden sollen.  Von den oben genannten Anforderungen können 1,2 und 3 nur mit benannten Spalten realisiert werden, daher wird im folgenden ein solches beschrieben. Die Definition eines generischen Spalten-Templates funktioniert überigens genauso - der einzige Unterschied ist, dass nur ein Spaltenlayout definiert wird. Dieses wird dann einfach für alle Spalten verwendet.

Navigieren Sie zu den Gemeinsamen Komponenten, von dort zu den Templates und klicken dort auf Erstellen.

Neues Template erstellen: Auswahl des Typs
Abb.2: Neues Template erstellen: Auswahl des Typs

Wählen Sie als Template Typ Bericht aus. Klicken Sie dann auf Weiter.

Völlig neu oder auf Basis eines bereits existierenden Templates
Abb.3: Völlig neu oder auf Basis eines bereits existierenden Templates
Namen, Theme, Klasse und Typ auswählen
Abb.4: Namen, Theme, Klasse und Typ auswählen

Achten Sie beim Dialog in Abbildung 4 auf den Template-Typ. Wählen Sie dort Benannte Spalte (Zeilen Template) aus. Der Template-Typ kann später nicht mehr geändert werden. Anschließend navigieren Sie wieder zu den Gemeinsamen Komponenten und von dort zu den Templates. Suchen Sie dann Ihr neues Template aus und klicken Sie es an. Daraufhin sehen Sie den in Abbildung 5 dargestellten Dialog.


Template bearbeiten ...
Abb.5: Template bearbeiten ...

Bearbeiten Sie nun das Template in den einzelnen Abschnitten dieses Formulars:

  • Zeilen Template 1-4
    In diesen Bereichen können Sie 4 verschiedene Layouts für die Berichtszeilen hinterlegen. Welches Layout angezeigt wird, richtet sich nach der zu jedem Layout gleichzeitig hinterlegten Bedingung
  • Spaltenüberschrifts-Template
  • Text vor der ersten und nach der letzten Zeile
  • Seitennummerierung

Der Bericht auf die Data Dictionary View USER_TABLES selektiert  insgesamt 48 Spalten. Im folgenden werden nicht alle Spalten bearbeitet - zur Veranschaulichung genügt ein Teil davon. Beginnen wir mit den Spaltenüberschriften. Es soll nicht für jede Tabellenspalte eine Überschrift, sondern im gesamten nur vier Überschriften erzeugt werden (analog der oben genannten Anforderungen). Der Bereich Spaltenüberschrifts-Template würde für jede Berichtsspalte eine Überschrift erzeugen tragen Sie Ihre Überschriften daher im Bereich Vor Zeilen ein.

Berichts-Überschrift
Abb.6: Berichts-Überschrift

Anschließend hinterlegen Sie das Zeilen-Template 1. Lassen Sie zunächst nur den Tabellennamen, den Tablespace-Namen und einige Platzhalter anzeigen. Der Tabellenname kann entweder mit #TABLE_NAME# (dem Spaltennamen der View USER_TABLES) oder anhand der Reihenfolge in der SQL-Abfrage (#1#) angesprochen werden.

Zeilen-Template ... erste Version
Abb.7: Zeilen-Template ... erste Version

Speichern Sie Ihre Änderungen anschließend ab. Nun muss das Template dem Bericht zugewiesen werden. Navigieren Sie dazu zu den Berichtsattributen und weisen Sie das soeben erzeugte Template zu.

Template in den Berichtsattributen zuweisen
Abb.8: Template in den Berichtsattributen zuweisen 

Das erste Zwischenergebnis sieht dann wie folgt aus:

erstes Zwischenergebnis
Abb.9: erstes Zwischenergebnis

Exkurs: Bedingte Darstellung

Als Exkurs sollen nun alle Tabellen, die im Tablespace SYSTEM liegen, rot dargestellt werden. Nutzen Sie dazu eine PL/SQL-Bedingung:

Nutzung von PL/SQL-Bedingungen
Abb.10: Nutzung von PL/SQL-Bedingungen

Das Zeilen Template 1 definiert nun die Darstellung in rot und wird mit der PL/SQL-Bedingung '#TABLESPACE_NAME#' = 'SYSTEM' versehen. Achten Sie dabei auf die Hochkommata, welche das #TABLESPACE_NAME# umschließen. Generell gilt für die PL/SQL-Bedingung in einem Template: Achten Sie darauf, dass der Spaltenname wie eine Ersetzungszeichenfolge und nicht wie eine Bind-Variable angesprochen wird. Application Express-Elemente können jedoch durchaus als Bind-Variablen verwendet werden. Hinterlegen Sie als Bedingung also '#TABLESPACE_NAME#' = :P1_TS_NAME und nicht #TABLESPACE_NAME# = :P1_TS_NAME (Achten Sie auf die Hochkommata).

Das Zeilen-Template 2 definiert die normale Darstellung mit schwarzer Schrift und ist ohne Bedingung - es soll angewendet werden, wenn das erste nicht zum Zuge kommt.  Auf diese Art und Weise können Sie vier verschiedene Zeilen-Templates mitsamt Bedingungen hinterlegen.

Nutzung von PL/SQL-Bedingungen: Ergebnis
Abb.11: Nutzung von PL/SQL-Bedingungen: Ergebnis

Zurück zu den ursprünglichen Anforderungen: Die zweite Berichtsspalte soll etwas erweitert werden.Entfernen Sie das Zeilen-Template 2 und die Bedingung für das Zeilen-Template 1 wieder und ersetzen Sie ...

<td valign="top">#TABLESPACE_NAME#</td>

... durch ...

  <td valign="top" 
onMouseOver="javascript:document.getElementById('Storage_#ROWNUM#').style.visibility='visible';"
onMouseOut="javascript:document.getElementById('Storage_#ROWNUM#').style.visibility='hidden';">
<div style="position: relative">
<div id="Storage_#ROWNUM#"
style="position: absolute; left: 100px; top: 0px;
visibility: hidden;
background-color: yellow;
border-style: solid;
border-color: black">
<table cellpadding="0" cellspacing="0" style="padding: 2px">
<tr><td colspan="2" valign="top"><b>Extents:</b><td></tr>
<tr><td>Initial </td><td align="right">#INITIAL_EXTENT#</td></tr>
<tr><td>Nächstes</td><td align="right">#NEXT_EXTENT#</td></tr>
<tr><td>Minimum </td><td align="right">#MIN_EXTENTS#</td></tr>
<tr><td>Maximum </td><td align="right">#MAX_EXTENTS#</td></tr>
</table>
</div>
</div>
Tablespace #TABLESPACE_NAME#
</td>

Neben dem Tablespace-Namen wird noch ein sog. DIV-Container (dunkelblau) hinzugefügt. Inhalt sind die Angaben zur Storage als geschachtelte HTML-Tabelle (hellblau). Das Besondere an diesem DIV-Container ist, dass er durch das CSS-Attribut position: absolute frei im Dokument positioniert wird. Das Attribut left: 100px besagt, dass es stets 100 Pixel links des Elternelements positioniert wird. Die zwei ineinander geschachtelten DIV-Container sind in diesem Zusammenhang wichtig - der äußere muss das Attribut position: relative enthalten. 

Mit den Attributen onMouseOver und onMouseOut (rot) wird der DIV-Container eingeblendet, sobald man mit der Maus über den Text TABLESPACE #TABLESPACE_NAME# fährt. Verläßt man diesen Bereich, wird der Container wieder ausgeblendet. Um den DIV-Container mit einem JavaScript-Kommando ansprechen zu können, wird als ID Storage_#ROWNUM# verwendet. Zu #ROWNUM# finden Sie weiter unten noch weitere Informationen.

Storage-Details per MouseOver einblenden ...
Abb.12: Storage-Details per MouseOver einblenden ...

Analog lässt sich der Bericht nun mit Angaben zu den Tabellen-Statistiken erweitern - im gleichen Schritt werden die zusätzlichen Merkmale zu den Tabellen direkt in die letzte Spalte eingetragen. 

 <td valign="top" align="left">
Kompression: #COMPRESSION#<br>
Row Movement: #ROW_MOVEMENT#<br>
Monitoring: #MONITORING#
</td>

Das Ergebnis sieht wie folgt aus:

Statistik-Details per MouseOver einblenden ...
Abb.13: Statistik-Details per MouseOver einblenden ...

Schön ware jetzt noch, wenn die Tabellenzeile, über der sich die Maus gerade befindet, hervorgehoben würde. Damit wäre auch besser zu erkennen, zu welcher Tabelle die eingeblendeten Details zu Storage oder Statistiken gehören. Auch dies ist einfach zu realisieren: Gehen Sie zum Anfang des Zeilentemplates zum Tag <tr>:

<tr id="ZEILE_#ROWNUM#" 
onMouseOver="javascript:document.getElementById('ZEILE_#ROWNUM#').style.backgroundColor='#dddddd';
document.getElementById('ZEILE_#ROWNUM#').style.fontWeight='bold';"
onMouseOut="javascript:document.getElementById('ZEILE_#ROWNUM#').style.backgroundColor='white';
document.getElementById('ZEILE_#ROWNUM#').style.fontWeight='normal';">

#ROWNUM# gibt die aktuelle Zeilennummer zurück. ZEILE_#ROWNUM# markiert damit als ID jede Zeile einer Berichtsseite eindeutig (ZEILE_1, ZEILE_2, ...). Mit Storage_#ROWNUM# wurde übrigens bereits oben der DIV-Container mit den Details zur Storage eindeutig markiert. Mit onMouseOver() werden, sobald mit der Maus über eine Zeile gefahren wird, deren Attribute backgroundColor auf Grau (#DDDDDD) und fontWeight (Schriftstärke) auf Fett gesetzt. Damit das JavaScript-Kommando die richtigen Attribute ändert, wird die ID ZEILE_#ROWNUM# verwendet. Verlässt man die Zeile mit der Maus, werden die Attribute wieder auf den Normalwert zurückgesetzt.

Tabellenzeile per MouseOver hervorheben ...
Abb.14: Tabellenzeile per MouseOver hervorheben ...

Zusammenfassend lässt sich sagen,  dass mit Berichts-Templates sehr ausgefeilte Layouts möglich sind. Nimmt man JavaScript und CSS-Attribute hinzu, so kann man den Bericht sogar aktiv gestalten - in diesem Beispiel durch das dynamische Ein- und Ausblenden von Details. Natürlich gehen die Möglichkeiten noch wesentlich weiter - Der Phantasie sind keine Grenzen gesetzt.

Zurück zur Community-Seite

Im folgenden finden Sie nochmals das gesamte Zeilen-Template 1 für den Bericht auf die Data Dictionary View USER_TABLES:

<tr id="ZEILE_#ROWNUM#" 
onMouseOver="javascript:document.getElementById('ZEILE_#ROWNUM#').style.backgroundColor='lightgray';
document.getElementById('ZEILE_#ROWNUM#').style.fontWeight='bold';"
onMouseOut="javascript:document.getElementById('ZEILE_#ROWNUM#').style.backgroundColor='white';
document.getElementById('ZEILE_#ROWNUM#').style.fontWeight='normal';">
<td valign="top">#TABLE_NAME#</td>
<td valign="top"
onMouseOver="javascript:document.getElementById('Storage_#ROWNUM#').style.visibility='visible';"
onMouseOut="javascript:document.getElementById('Storage_#ROWNUM#').style.visibility='hidden';">
<div style="position: relative">
<div id="Storage_#ROWNUM#"
style="position: absolute; left: 100px; top: 10px;
visibility: hidden;
background-color: yellow;
border-style: solid;
border-color: black">
<table cellspacing="0" cellpadding="0" style="padding: 2px">
<tr><td colspan="2" valign="top">Extents:<td></tr>
<tr><td>Initial</td><td align="right">#INITIAL_EXTENT#</td></tr>
<tr><td>Nächstes</td><td align="right">#NEXT_EXTENT#</td></tr>
<tr><td>Minimum</td><td align="right">#MIN_EXTENTS#</td></tr>
<tr><td>Maximum</td><td align="right">#MAX_EXTENTS#</td></tr>
</table>
</div>
</div>
Tablespace #TABLESPACE_NAME#
</td>
<td valign="top" align="center"
onMouseOver="javascript:document.getElementById('Stat_#ROWNUM#').style.visibility='visible';"
onMouseOut="javascript:document.getElementById('Stat_#ROWNUM#').style.visibility='hidden';">
<div style="position: relative">
<div id="Stat_#ROWNUM#"
style="position: absolute; left: 80px; top: 10px;
visibility: hidden;
background-color: orange;
border-style: solid;
border-color: black">
<table cellspacing="0" cellpadding="0" style="padding: 2px; white-space: nowrap">
<tr><td colspan="2" valign="top"><b>Statistiken:</b><td></tr>
<tr><td>Anzahl Zeilen</td><td align="right">#NUM_ROWS#</td></tr>
<tr><td>Allokierte Blöcke</td><td align="right">#BLOCKS#</td></tr>
<tr><td>Leere Blöcke</td><td align="right">#EMPTY_BLOCKS#</td></tr>
<tr><td>DS-Zeilenlänge</td><td align="right">#AVG_ROW_LEN#</td></tr>
</table>
</div>
</div>
#LAST_ANALYZED#
</td>
<td valign="top" align="left">
Kompression: #COMPRESSION#<br>
Row Movement: #ROW_MOVEMENT#<br>
Monitoring: #MONITORING#
</td>
</tr>