Click here to load reader
Upload
dohanh
View
214
Download
0
Embed Size (px)
ajanzen.com
Generisches Erzeugen einer internen
Tabelle zur Laufzeit
ajanzen.com
1
1 Einleitung
In dem vorliegenden Dokument möchte ich auf die Möglichkeiten der generischen
Tabellenerzeugung zur Laufzeit eingehen. Dieses Vorgehen kann beispielsweise
verwendet werden, um interne Tabellen anhand vom Customizing zu erstellen oder
um Zusatzfelder zu erweitern.
Der Schwerpunkt des Dokumentes liegt nicht auf komplexen Erklärungen sondern auf
der Vorgehensbeschreibung anhand eines Beispiels. Das Beispiel ist so aufgebaut,
dass eine bestehende Struktur um zusätzliche Felder erweitert wird.
Das Beispielcoding aus Kapitel 3 liefert eine Datenausgabe in Form eines ALV. Die
Wirkung der einzelnen Anweisungen kann im Debugger gut nachverfolgt werden.
Das komplette Beispielcoding ist in Kapitel 3 enthalten. Nähere Informationen zum
Ablauf können Kapitel 2 entnommen werden.
ajanzen.com
2
2 Informationen zur Programmlogik
Im Rahmen des Beispielprogrammes wird die bestehende Tabelle SPFLI unter
Verwendung der CL_ABAP_* DESCR-Klassen zur Laufzeit um zwei zusätzliche
Felder erweitert. Anschließen erfolgt ein lesender Datenbankzugriff und die neuen
Felder mit Werten belegt. Abschließend wird die Anzeige der erweiterten Tabelle
angestoßen.
Leider kann die Struktur GS_SPFLI nicht direkt um die benötigten neuen Felder
erweitert werden (bzw. ist mir das entsprechende Vorgehen nicht bekannt). Aus
diesem Grund wird ein Umweg über ein DATA-Objekt (GR_TABLE_DATA)
genommen.
Zu Beginn der Programmverarbeitung werden die Komponenten der zu erweiternden
Struktur GS_SPFLI bestimmt. Für diese Aktivität kommen Methoden der Klassen
CL_ABAP_TYPEDESCR und CL_ABAP_STRUCTDESCR zum Einsatz. Das
Ergebnis der Beschreibung ist eine Tabelle mit den Strukturkomponenten. Für die
Typbeschreibung der einzelnen Komponenten werden Instanzen der Klasse
CL_ABAP_ELEMDESCR verwendet.
Abbildung 1: Auszug der Komponentenbeschreibung der Tabelle SPFLI
Im nächsten Schritt wird die Komponententabelle über ein einfaches APPEND um zwei
zusätzliche Felder erweitert. Durch die Klassen CL_ABAP_STRUCTDESCR und
CL_ABAP_TABLEDESCR werden zuerst eine Struktur- und anschließend eine
Tabellenbeschreibung instanziiert. Anschließend wird das DATA-Objekt unter
Verwendung der Tabellenbeschreibungsinstanz erzeugt.
Im Nachfolgenden Coding wird das DATA-Objekt mit Informationen gefüllt. Im letzten
Schritt erfolgt die Datenanzeige unter Verwendung eines ALV.
ajanzen.com
3
Hinweis: Der Typ des DATA-Objektes ist zu Beginn der Programmverarbeitung nicht
vorgegeben/bekannt, sondern wird zur Laufzeit erzeugt. Aus diesem Grund ist eine
direkte Verwendung der DATA-Tabelle im SELECT in der Art von GR_TABLE_DATA-
>* nicht möglich.
3 Coding
*-------------------------------------------------- ------------------*
* Das vorliegende Programm enthält Beispiele für dy namische Erzeugen
* einer internen Tabelle zur Laufzeit.
*
* Date: 22.03.2015
*-------------------------------------------------- ------------------*
* Änderungen
*-------------------------------------------------- ------------------*
REPORT zaj_gen_create_data .
DATA: gs_spfli TYPE spfli .
DATA: gt_orig_comp TYPE cl_abap_structdescr =>component_table .
DATA: gs_comp TYPE cl_abap_structdescr =>component .
DATA: gr_table_data TYPE REF TO data .
DATA: gt_new_comp TYPE cl_abap_structdescr =>component_table .
DATA: gr_struct_dscr TYPE REF TO cl_abap_structdescr .
DATA: gr_table_dscr TYPE REF TO cl_abap_tabledescr .
DATA: gr_salv TYPE REF TO cl_salv_table .
DATA: gr_columns TYPE REF TO cl_salv_columns_table .
DATA: gr_err_table TYPE REF TO cx_sy_table_creation .
DATA: gr_err_struct TYPE REF TO cx_sy_struct_creation .
DATA: gr_err_salv TYPE REF TO cx_salv_msg .
DATA: gv_err_message TYPE string .
FIELD-SYMBOLS: <gt_data> TYPE ANY TABLE.
FIELD-SYMBOLS: <gs_data> TYPE any .
FIELD-SYMBOLS: <gv_data> TYPE any .
START-OF-SELECTION.
*************************************************** *******************
* Komponenten der vorhandenen Struktur bestimmen
*************************************************** *******************
gr_struct_dscr ?= cl_abap_typedescr =>describe_by_data ( gs_spfli ).
gt_orig_comp = gr_struct_dscr -> get_components ( ).
*************************************************** *******************
* Erstellen der erweiterten Struktur
*************************************************** *******************
* Komponenten der vorhandenen Struktur für die Besc hreibung der
* aufnehmen neuen Struktur aufnehmen
LOOP AT gt_orig_comp INTO gs_comp .
APPEND gs_comp TO gt_new_comp .
ENDLOOP.
* Neue Struktur um zusätzliche Felder erweitern
gs_comp - name = 'COUNTER'.
* Der Typ ist hier eine Instanz der Klasse CL_ABAP_ ELEMDESCR
gs_comp - type ?= cl_abap_datadescr =>describe_by_name ( 'NUM10' ).
APPEND gs_comp TO gt_new_comp .
gs_comp - name = 'USER' .
gs_comp - type ?= cl_abap_datadescr =>describe_by_name ( 'SY-UNAME' ).
APPEND gs_comp TO gt_new_comp .
TRY.
* Strukturobjekt unter Verwendung der Komponent entabelle erstellen
gr_struct_dscr = cl_abap_structdescr =>create ( gt_new_comp ).
* Über das Strukturobjekt ein Tabellenobjekt er stellen
gr_table_dscr = cl_abap_tabledescr =>create ( gr_struct_dscr ).
CATCH cx_sy_struct_creation INTO gr_err_struct .
gv_err_message = gr_err_struct -> get_text ( ).
MESSAGE gv_err_message TYPE 'E' .
CATCH cx_sy_table_creation INTO gr_err_table .
gv_err_message = gr_err_table -> get_text ( ).
MESSAGE gv_err_message TYPE 'E' .
ENDTRY.
* DATA-Objekt aus der Beschreibung erzeugen
CREATE DATA gr_table_data TYPE HANDLE gr_table_dscr .
* Da es sich hierbei um eine generische Datenrefere nz handelt
* ist keine direkte Verwendung im SELECT möglich .. . deshalb der
* Umweg über das Feldsymbol
ASSIGN gr_table_data -> * TO <gt_data> .
* Datenselektion
SELECT *
FROM spfli
INTO CORRESPONDING FIELDS OF TABLE <gt_data> .
IF sy - subrc NE 0.
* Hier bei Bedarf einen Fehler ausgeben
ENDIF.
LOOP AT <gt_data> ASSIGNING <gs_data> .
* Über ein ASSIGN können hier wiederum die einzelne n Felder
* angesprochen werden
ASSIGN COMPONENT 'COUNTER' OF STRUCTURE <gs_data>
TO <gv_data> .
CHECK sy - subrc EQ 0.
* Schleifenindes übernehmen
MOVE sy - tabix TO <gv_data> .
ASSIGN COMPONENT 'USER' OF STRUCTURE <gs_data>
TO <gv_data> .
CHECK sy - subrc EQ 0.
* Ausführenden User übernehmen
MOVE sy - uname TO <gv_data> .
ENDLOOP.
*************************************************** ************************
****
* Daten anzeigen
*************************************************** ************************
****
TRY.
CALL METHOD cl_salv_table =>factory
EXPORTING
list_display = if_salv_c_bool_sap =>false
IMPORTING
r_salv_table = gr_salv
CHANGING
t_table = <gt_data> .
CATCH cx_salv_msg INTO gr_err_salv .
* Fehler anzeigen
gv_err_message = gr_err_salv -> get_text ( ).
MESSAGE gv_err_message TYPE 'E' .
ENDTRY.
* Spaltenbreite optimieren
gr_columns = gr_salv -> get_columns ( ).
gr_columns -> set_optimize ( abap_true ). " nur ein 'X'
* Die eigentliche Anzeige
gr_salv -> display ( ).