Hatten Sie schon einmal die Aufgabe dynamisch Reports mit APEX zu erzeugen? Es kann erst zur Laufzeit festgestellt werden wie viele Reporte pro Region dargestellt werden müssen.
In diesem Tipp erfahren Sie anhand der Tabellen des User Scott, unter Verwendung des htp Packages, wie sich mehrere Reports innerhalb einer Region aufbauen lassen.
Es wird ein Report pro Abteilung der DEPT-Tabelle erzeugt. Jeder Report enthält den Abteilungsnamen, den Standort und die Anzahl der Mitarbeiter in der Kopfzeile. Als Inhalt werden die Mitarbeiternummer, Name und Job der Mitarbeiter der jeweiligen Abteilung ausgegeben.
Um die Reports zu befüllen müssen im Datenbankschema des Users Objekt Typen, Nested Tables und eine Funktion angelegt werden.
CREATE OR REPLACE TYPE SCOTT.OT_EMP AS OBJECT
( empno number,
ename varchar2(20),
job varchar2(20))
/
CREATE OR REPLACE TYPE SCOTT.OTT_EMP AS TABLE OF OT_EMP
/
CREATE OR REPLACE TYPE SCOTT.OT_DEPT AS OBJECT
°( dname varchar2(20),
loc varchar2(20),
COUNT_EMPS NUMBER,
EMPS OTT_EMP)
/
CREATE OR REPLACE TYPE SCOTT.OTT_DEPT AS TABLE OF OT_DEPT
/
CREATE OR REPLACE FUNCTION get_Departments RETURN ott_dept IS
TYPE v_department_name IS TABLE OF dept.dname%TYPE;
TYPE v_department_loc IS TABLE OF dept.loc%TYPE;
TYPE v_department_no IS TABLE OF dept.deptno%TYPE;
TYPE v_employee_empno IS TABLE OF emp.empno%TYPE;
TYPE v_employee_ename IS TABLE OF emp.ename%TYPE;
TYPE v_employee_job IS TABLE OF emp.job%TYPE;
v_deptno v_department_no;
v_dname v_department_name;
v_loc v_department_loc;
v_empno v_employee_empno;
v_ename v_employee_ename;
v_job v_employee_job;
v_ot_dept ot_dept;
v_ot_emp ot_emp;
v_ott_dept ott_dept := ott_dept();
v_ott_emp ott_emp := ott_emp();
BEGIN
-- Der Select für die Collection vom Typ OTT_DEPT
SELECT deptno, dname, loc BULK COLLECT
INTO v_deptno, v_dname, v_loc
FROM dept;
-- Objekte werden einmal initialisiert
v_ot_dept := ot_dept(NULL, NULL, NULL, NULL);
v_ot_emp := ot_emp(NULL, NULL, NULL);
FOR i IN 1 .. v_deptno.COUNT LOOP
-- Der Objekttyp wird befüllt
v_ot_dept.dname := v_dname(i);
v_ot_dept.loc := v_loc(i);
-- Der Select für den Typ OTT_EMP
SELECT empno, ename, job BULK COLLECT
INTO v_empno, v_ename, v_job
FROM emp
WHERE deptno = v_deptno(i);
FOR x IN 1 .. v_empno.COUNT LOOP
-- Das Subset wird befüllt
v_ot_Emp.empno := v_empno(x);
v_ot_emp.ename := v_ename(x);
v_ot_emp.job := v_job(x);
v_ot_dept.count_emps := x;
-- Die Collection (Subset) wird erweitert und geschrieben
v_ott_emp.EXTEND();
v_ott_emp(x) := v_ot_emp;
END LOOP;
v_ot_dept.EMPS := v_ott_emp;
-- Die Collection wird erweitert und geschrieben
v_ott_dept.EXTEND();
v_ott_dept(i) := v_ot_dept;
v_ot_dept.COUNT_EMPS := 0;
END LOOP;
RETURN v_ott_dept;
END get_Departments;
/
Die Nested Table vom Typ OT_EMP enthält die Mitarbeiter der jeweiligen Abteilung. Die Nested Table vom Typ OT_DEPT enthält pro Datensatz die Überschriften je eines Reports und das Subset OTT_EMP.
Innerhalb der Funktion wird die Nested Table OTT_DEPT befüllt. Das geschieht über zwei Schleifen. Die äußere Schleife füllt OTT_DEPT. Für jeden Eintrag in der Collection wird eine innere Schleife gestartet, welche das Subset OTT_EMP befüllt.
Zur Darstellung des Reports wählen wir eine Seite mit einer Region vom Typ "PL/SQL Dynamic Content". Auf dieser Seite wird folgender Code eingebunden.
DECLARE
v_ott_emp ott_emp;
v_ott_dept ott_dept;
v_dat_style varchar2(100):='class="t12data"';
v_tab_style varchar2(100):='class="t12standardalternatingrowcolors"';
v_thead_style varchar2(100):='class="t12header"';
BEGIN
v_ott_dept := get_Departments;
IF v_ott_dept.COUNT > 0 THEN
FOR i IN v_ott_dept.FIRST .. v_ott_dept.LAST LOOP
htp.tableOpen(0,'top',0,0,v_tab_style);
htp.tableRowOpen;
htp.tableHeader(v_ott_dept(i).dname, 'top', 0, 0, 0, 0,v_thead_style);
htp.tableHeader(v_ott_dept(i).loc, 'top', 0, 0, 0, 0,v_thead_style);
htp.tableHeader(v_ott_dept(i).COUNT_EMPS ||' Mitarbeiter', 'top', 0, 0, 0, 0,v_thead_style);
htp.tableRowClose;
v_ott_emp := v_ott_dept(i).emps;
v_dat_style := 'class="t12data"';
IF v_ott_emp.COUNT > 0 THEN
FOR j IN v_ott_emp.FIRST .. v_ott_emp.LAST LOOP
htp.tableRowOpen;
htp.tableData(v_ott_emp(j).empno, 0, 0, 0, 0, 0, v_dat_style);
htp.tableData(v_ott_emp(j).ename, 0, 0, 0, 0, 0, v_dat_style);
htp.tableData(v_ott_emp(j).job, 0, 0, 0, 0, 0, v_dat_style);
htp.tableRowClose;
-- Wechselnde Farben des Reports einstellen
if v_dat_style = 'class="t12data"' then
v_dat_style := 'class="t12dataalt"';
else
v_dat_style := 'class="t12data"';
end if;
END LOOP;
END IF;
htp.tableClose;
htp.br;
END LOOP;
END IF;
END;
Es wird das CSS, des für die Applikation gewählten Themes, verwendet. In diesem Beispiel das Theme 12 Version 2.0. Beim Aufruf des htp Packages, wird analog zu in APEX erzeugten Reports, die jeweilige Klasse des CSS mit angegeben, damit sich die Reports nicht voneinander unterscheiden.
Es wird wie beim Befüllen der Collections, mit zwei Schleifen gearbeitet. Die äußere Schleife legt zuerst die Tabelle an und trägt die Überschriften in die Tabelle ein. Die innere Schleife füllt die Zeilen des Reports. Am Ende der inneren Schleife wird auch das Erscheinungsbild der Zeilen umgestellt.
Das Ergebnis ist eine Region auf der so viele Reports erscheinen, wie es Abteilungen innerhalb der Tabellen gibt.
In unserer Know-How Datenbank finden Sie mehr als 300 ausführliche Beiträge zu den
Oracle-Themen wie DBA, SQL, PL/SQL, APEX und vielem mehr.
Hier erhalten Sie Antworten auf Ihre Fragen.