12.8 Codebeispiel zu ITAB mit Kopfzeile
Das Codebeispiel aus Listing 12.2 könnte Ihnen in älteren Programmcodes begegnen.
1 *&---------------------------------------------*
2 *& Report Z_TEILNEHMERLISTE12_ITAB_KOPFZ *
3 *& *
4 *&---------------------------------------------*
5 *& *
6 *& *
7 *&---------------------------------------------*
8
9 REPORT z_teilnehmerliste12_itab_kopfz.
10
11 * Workarea deklarieren
12 DATA: wa_zteilnehmer02 TYPE zteilnehmer02.
13
14 * Felder deklarieren
15 DATA: zeilen_itab01 TYPE i.
16
17 * Interne Tabellen deklarieren,
Beispiele mit Kopfzeile
18 DATA: BEGIN OF itab01 OCCURS 0,
19 zzkurstitel TYPE
zteilnehmer02-zzkurstitel,
20 tkurspreis TYPE
zteilnehmer02-tkurspreis,
21 END OF itab01.
22
23 DATA BEGIN OF itab02 OCCURS 0.
24 INCLUDE STRUCTURE itab01.
25 DATA minteiln TYPE i.
26 DATA END OF itab02.
27
28 DATA: BEGIN OF itab03 OCCURS 0,
29 bezeichnung TYPE
zteilnehmer02-zzkurstitel,
30 preis TYPE zteilnehmer02-tkurspreis,
31 maxteil TYPE i VALUE 10,
32 END OF itab03.
33
34 DATA BEGIN OF itab04 OCCURS 0.
35 INCLUDE STRUCTURE zteilnehmer02.
36 DATA END OF itab04.
37
38 * Workarea deklarieren
39
40 * Selektionsbild deklarieren
41
42 *----------------------------------------------*
43 * initialization.
44
45 *----------------------------------------------*
46 * at selection-screen.
47
48 *----------------------------------------------*
49 START-OF-SELECTION.
50
51 * Datenbanktabelle lesen und itab01 füllen
über Kopfzeile
52 SELECT * FROM zteilnehmer02 INTO wa_zteilnehmer02.
53 MOVE-CORRESPONDING wa_zteilnehmer02 TO itab01.
54 APPEND itab01.
55 ENDSELECT.
56
57 * Datenbanktabelle lesen und itab02 füllen
über Array-Fetch
58 SELECT * FROM zteilnehmer02
59 INTO CORRESPONDING FIELDS OF TABLE itab02.
60
61 * Datenbanktabelle lesen und itab03 füllen über
Kopfzeile und Zuweisung
62 SELECT * FROM zteilnehmer02 INTO wa_zteilnehmer02.
63 itab03-bezeichnung =
wa_zteilnehmer02-zzkurstitel.
64 itab03-preis = wa_zteilnehmer02-tkurspreis.
65 APPEND itab03.
66 ENDSELECT.
67
68 * Datenbanktabelle lesen und itab04 füllen
über Array-Fetch
69 SELECT * FROM zteilnehmer02
70 INTO CORRESPONDING FIELDS OF TABLE itab04.
71
72 *----------------------------------------------*
73 END-OF-SELECTION.
74
75 * Anzahl der Rumpfzeileneinträge für itab01
lesen und ausgeben
76 DESCRIBE TABLE itab01 LINES zeilen_itab01.
77 SKIP.
78 WRITE: / 'Anzahl Zeilen itab01:',
zeilen_itab01.
79
80 * Kopfzeile initialisieren, füllen und neue
Zeile in itab01 anhängen
81 CLEAR itab01.
82 itab01-zzkurstitel = 'LINUX-GRUNDLAGEN'.
83 itab01-tkurspreis = '456.78'.
84 zeilen_itab01 = zeilen_itab01 + 1.
85 INSERT itab01 INDEX zeilen_itab01.
86
87 * itab01 in Liste ausgeben
88 SKIP.
89 WRITE: / 'sy-tabix, itab01-zzkurstitel,
itab01-tkurspreis'.
90 LOOP AT itab01.
91 WRITE: / sy-tabix, itab01-zzkurstitel,
itab01-tkurspreis.
92 ENDLOOP.
93
94 * itab02 verarbeiten und in Liste ausgeben
95 SKIP.
96 WRITE: / 'itab02-zzkurstitel,
itab02-tkurspreis, itab02-minteiln'.
97 LOOP AT itab02 WHERE zzkurstitel =
'PC-GRUNDLAGEN'.
98 itab02-minteiln = 2.
99 WRITE: / itab02-zzkurstitel,
itab02-tkurspreis, itab02-minteiln.
100 ENDLOOP.
101
102 * itab03 verarbeiten, ausgeben und Rumpf
modifizieren
103 SKIP.
104 WRITE: / 'itab03-bezeichnung, itab03-preis,
itab03-maxteil'.
105 LOOP AT itab03.
106 IF itab03-bezeichnung = 'PC-GRUNDLAGEN'.
107 itab03-preis = 567.
108 MODIFY itab03.
109 ENDIF.
110 WRITE: / itab03-bezeichnung, itab03-preis,
itab03-maxteil.
111 ENDLOOP.
112
113 * Einen Satz aus itab03 mit Index lesen und
ausgeben
114 READ TABLE itab03 INDEX 3.
115 SKIP.
116 * WRITE: / 'gelesen von itab03 Zeile',
sy-tabix,
117 WRITE: / 'gelesen von itab03',
sy-tabix NO-GAP, '.Zeile:',
118 itab03-bezeichnung, itab03-preis,
itab03-maxteil.
119
120 * Einen Satz aus itab04 mit Schlüssel lesen und
ausgeben
121 READ TABLE itab04 WITH KEY
mandant = sy-mandt tnummer = 5.
122 SKIP.
123 WRITE: / 'gelesen von itab04',
124 itab04-mandant, itab04-tnummer,
itab04-tname, itab04-tgeburt
sdatum, itab04-tgeschlecht.
125
126 * Einen Satz aus itab01 über Index lesen,
löschen, protokollieren
127 READ TABLE itab01 INDEX 3.
128 DELETE itab01 INDEX 3.
129 SKIP.
130 WRITE: / 'gelöscht von itab01',
sy-tabix NO-GAP, '.Zeile:',
131 itab01-zzkurstitel,
itab01-tkurspreis.
132
133 * Gezielt einzelnen Satz aus itab02 über
Schlüssel lesen, löschen, protokollieren
134 READ TABLE itab02 WITH KEY
zzkurstitel = 'SAP-Grundlagen'.
135 DELETE itab02 WHERE
zzkurstitel = 'SAP-Grundlagen'.
136 SKIP.
137 WRITE: / 'gelöscht von itab02',
sy-tabix NO-GAP, '.Zeile:',
itab02-zzkurstitel.
138
139 * Interne Tabellen sortieren
140 SORT itab04 BY zzkurstitel.
141 SKIP.
142 LOOP AT itab04.
143 WRITE: / itab04-zzkurstitel,
itab04-tkurspreis, itab04-tnummer,
itab04-tname.
144 ENDLOOP.
145
146 SORT itab04 AS TEXT BY zzkurstitel.
147 SKIP.
148 LOOP AT itab04.
149 WRITE: / itab04-zzkurstitel,
itab04-tkurspreis, itab04-tnummer,
itab04-tname.
150 ENDLOOP.
151
152 SORT itab04 AS TEXT BY zzkurstitel tname.
153 SKIP.
154 LOOP AT itab04.
155 WRITE: / itab04-zzkurstitel,
itab04-tkurspreis, itab04-tnummer,
itab04-tname.
156 ENDLOOP.
157
158 SORT itab04 DESCENDING AS TEXT
BY zzkurstitel tname.
159 SKIP.
160 LOOP AT itab04.
161 WRITE: / itab04-zzkurstitel,
itab04-tkurspreis, itab04-tnummer,
itab04-tname.
162 ENDLOOP.
163
164 BREAK-POINT.
165 * Wirkung von CLEAR, REFRESH und FREE
bei internen Tabellen mit Kopfzeile
166 CLEAR itab01. "initialisiert Kopfzeile
167 CLEAR itab01[]. "löscht Rumpfzeilen
168
169 CLEAR itab02. "initialisiert Kopfzeile
170 REFRESH itab02. "löscht Rumpfzeilen
171
172 CLEAR itab03. "initialisiert Kopfzeile
173 FREE itab03. "löscht Rumpfzeilen und
gibt Speicherplatz frei
174
175 SKIP.
Anmerkungen zum Quellcode
Sehen Sie sich die folgenden Zeilen im Quellcode genauer an.
Zeile 18 bis 21
Die interne Standardtabelle ITAB01 wird deklariert; die initiale Speicherplatzbelegung wird dem System überlassen. Die interne Tabelle hat zwei Felder, die hinsichtlich ihrer Deklarationen auf das ABAP Dictionary verweisen.
Zeile 23 bis 26
Die interne Tabelle ITAB02 wird deklariert. Sie soll die Struktur der Zeilen von ITAB01 und ein zusätzliches Feld enthalten – insgesamt hat eine Zeile demnach drei Felder.
Zeile 34 bis 36
In die Tabelle ITAB04 wird die Struktur der Datenbanktabelle eingebaut. Eine Zeile der internen Tabelle ist damit strukturgleich mit einer Zeile der Datenbanktabelle.
Zeile 52 bis 55
Die Datenbanktabelle wird satzweise in ihre Workarea gelesen. Von dort aus werden namensgleiche Felder in die Kopfzeile der internen Tabelle übertragen. Nach dem Übertragen wird der Inhalt der Kopfzeile als neue Zeile an den Tabellenrumpf angehängt. Der Inhalt der Kopfzeile bleibt dabei erhalten und wird in diesem Fall durch eine neue Zeile aus der Datenbanktabelle überschrieben. Der letzte Inhalt der Kopfzeile wird nicht mehr überschrieben.
Zeile 58 bis 59
Mit einem Array-Fetch wird der Inhalt der Datenbanktabelle blockweise in die namensgleichen Felder der internen Tabelle übertragen; nur namensgleiche Felder werden gefüllt. Der Arbeitsbereich der Datenbanktabelle und die Kopfzeile der internen Tabelle werden nicht beansprucht.
Zeile 76
Die Anzahl der Rumpfzeilen der internen Tabelle wird ermittelt und für die Weiterverarbeitung in eine Variable gestellt.
Zeile 81
Die Kopfzeile der internen Tabelle wird initialisiert. Dies ist immer dann sinnvoll, wenn man sicher sein möchte, dass von alten Inhalten der Kopfzeile keine Reste mehr übrig sind, denn sie würden unter Umständen die neu aufzubauende Zeile unbrauchbar machen.
Zeile 82 bis 85
Die neue Rumpfzeile wird in der Kopfzeile aufgebaut. Die Position wird bestimmt, vor der die neue Zeile eingefügt werden soll. Dann wird der Inhalt der Kopfzeile als neue Zeile an der berechneten Stelle in den Tabellenrumpf geschrieben.
Zeile 90 bis 92
In einer Schleife wird nacheinander jeder Satz der internen Tabelle in die Kopfzeile übertragen, um von dort aus weiterverarbeitet zu werden. Der Anweisungsblock für die Verarbeitung ist hier durch eine Listausgabe symbolisiert.
Zeile 97
Die Schleife soll nur die Zeilen der internen Tabelle in die Kopfzeile übertragen, die eine bestimmte Bedingung erfüllen. Nur die übertragenen Sätze können von der Kopfzeile aus weiterverarbeitet werden.
Zeile 105 bis 111
Die Schleife stellt alle Rumpfzeilen satzweise in die Kopfzeile. Dort findet eine Verarbeitung statt. Wenn für den aktuellen Satz eine bestimmte Bedingung erfüllt ist, wird der Inhalt der Kopfzeile verändert. Der Inhalt der veränderten Kopfzeile wird in die aktuelle Rumpfzeile übertragen. Alle anderen Rumpfzeilen, für die die Bedingung nicht erfüllt ist, werden nicht modifiziert.
Zeile 114
Die dritte Rumpfzeile wird in die Kopfzeile übertragen.
Zeile 121
Es wird eine Zeile aus der internen Tabelle gelesen. Der Schlüssel soll dabei das Risiko so weit einschränken, dass möglichst der richtige Satz gelesen wird. Bei Standardtabellen bleibt die Wahl der Schlüsselfelder dem Entwickler überlassen – er muss die Felder und Inhalte so geschickt wählen, dass die Beschreibung zum »richtigen« Satz führt.
[+] Schlüssel als WHERE-Bedingung vorstellen
Vielleicht hilft es Ihnen, wenn Sie sich den Schlüssel hier nicht in dem Sinn vorstellen, wie Sie ihn von Datenbanktabellen her kennen, sondern eher als WHERE-Bedingung. Eine READ-Anweisung mit einer WHERE-Bedingung gibt es in ABAP allerdings nicht.
Zeile 128
Die dritte Rumpfzeile der internen Tabelle wird gelöscht.
Zeile 135
Alle Rumpfzeilen werden gelöscht, für die diese Bedingung gilt.
Zeile 140
Die interne Tabelle wird aufsteigend nach dem Inhalt des Feldes ZZKURSTITEL binär sortiert.
Zeile 146
Die interne Tabelle wird aufsteigend nach dem Inhalt des Feldes ZZKURSTITEL gemäß den landesspezifischen Einstellungen lexikalisch sortiert.
Zeile 152
Die interne Tabelle wird nach den Feldern ZZKURSTITEL und TNAME sortiert. Erstes Sortierkriterium ist das Feld ZZKURSTITEL. Bei gleichem Feldinhalt von ZZKURSTITEL wird als zweites Sortierkriterium nach dem Inhalt des Feldes TNAME sortiert.
Zeile 158
Die Sortierreihenfolge ist absteigend, sodass danach der lexikalisch höchste Wert in der ersten Zeile der internen Tabelle steht.
Zeile 166
Die Kopfzeile der internen Tabelle wird initialisiert. Mit anderen Worten: Jedes Feld erhält seinen typgerechten Initialwert. Auch wenn die Felder beispielsweise in der DATA-Anweisung durch VALUE mit einem Wert vorbelegt wurden, erhält das Feld nicht den Vorbelegungswert, sondern seinen typgerechten Initialwert; bei Feldern vom Typ c wäre dies beispielsweise ein Leerzeichen (» «).
Zeile 167
Alle Rumpfzeilen der internen Tabelle werden gelöscht. Beachten Sie dabei den Unterschied zwischen Löschen und Initialisieren.
Zeile 170
Die Anweisung hat die gleiche Wirkung wie die CLEAR-Anweisung in Zeile 167.
Zeile 173
Auch mit dieser Anweisung werden die Rumpfzeilen gelöscht. Zusätzlich wird der initiale Speicherplatz für die interne Tabelle freigegeben. Wenn man die interne Tabelle erneut füllen möchte, ist die Anweisung FREE ungünstiger, da sie nicht so performant wie die Anweisung REFRESH ist.
Ausgabe des Quellcodes im ABAP Debugger verfolgen
Im Tabellenmodus des ABAP Debuggers können Sie Schritt für Schritt genau verfolgen, wie eine Zeile aus der Datenbanktabelle in die Kopfzeile der internen Tabelle übertragen wird, und von dort aus in den Tabellenrumpf. Wie oben bereits erwähnt, ist die Kopfzeile der internen Tabelle durch einen Hut gekennzeichnet (, siehe Abbildung 12.6): Fehlt der Hut, wie in Abbildung 12.4, muss es sich um eine interne Tabelle ohne Kopfzeile handeln. Klicken Sie auf das Hutsymbol in der Tabellenansicht, um den Inhalt der Kopfzeile zu prüfen.
Sie können das Zusammenspiel von Tabellenrumpf und Kopfzeile besonders gut beobachten, wenn Sie abwechselnd auf das Hutsymbol und auf das Tabellensymbol () klicken. Sie können auch, wie in Abbildung 12.6 dargestellt, die beiden Debugger-Werkzeuge Tabelleninhalt und Feldliste parallel darstellen, um zugleich die Kopfzeile und den Tabellenrumpf zu beobachten.
Wieder verwenden Sie den Debugger, um den Ablauf des Programms mitzuverfolgen. Der Debugger steht vor dem blockweisen Füllen der internen Tabelle, erkennbar am gelben Pfeil vor der Anweisung (siehe Abbildung 12.7).
Alle Zeilen der Datenbanktabelle wurden mit einem einzigen Kommando in die Rumpfzeilen übertragen. Die Kopfzeile ist nach wie vor initial (siehe Abbildung 12.8). Sie können den Inhalt der Kopfzeile mit einem Klick auf das Hutsymbol prüfen.
Mit der READ-Anweisung wurde eine Zeile eindeutig identifiziert und in die Kopfzeile übertragen (siehe Abbildung 12.9).
Im Literal der Bedingung 'SAP-Grundlagen' stehen auch Kleinbuchstaben. In der internen Tabelle kann im Beispiel der Inhalt des Literals nicht gefunden werden, weil im Feld ZZKURSTITEL nur Großbuchstaben stehen – die Anweisung löscht in diesem Beispiel daher keine einzige Rumpfzeile (siehe Abbildung 12.10).
Da die DELETE-Anweisung keine Zeile löschen konnte, liefert sie den Returncode 4 und stellt ihn in das Feld SY-SUBRC (siehe Abbildung 12.11).
[»] Fehler auffangen
Soll dieser Fehler aufgefangen werden, muss unmittelbar nach der DELETE-Anweisung mit einer IF- oder CASE-Struktur der Inhalt von SY-SUBRC abgefragt werden und ein entsprechender Anweisungsblock folgen.
Nach der SORT-Anweisung liegt die interne Tabelle binär, nach der zugrunde liegenden Codetabelle aufsteigend sortiert vor (siehe Abbildung 12.12).
Wie in Abbildung 12.13 zu sehen ist, wurde mit der ersten CLEAR-Anweisung bereits die Kopfzeile initialisiert. Deutlich sehen Sie den Unterschied des Initialwertes für ZZKURSTITEL und TKURSPREIS. Das erste Feld ist vom Typ c, das zweite Feld vom Typ p. Mit der zweiten CLEAR-Anweisung soll als Nächstes der Tabellenrumpf gelöscht werden.
Die zuletzt ausgeführte Anweisung CLEAR itab01[] hat alle Rumpfzeilen gelöscht (siehe Abbildung 12.14). Weder die Zeilennummer bzw. der Index noch die Initialwerte sind erhalten geblieben.