​Es kommt immer mal wieder vor, dass man während der Entwicklung noch nicht genau weiß, wie die Strukturen und internen Tabellen zur Laufzeit aussehen werden bzw. müssen. Zu der folgenden Lösung bin ich bei der Herausforderung inspiriert worden, dass eine Schnittstelle entwickelt werden sollte, bei der Felder aus HCM-Infotypen ausgelesen und in eine Datei geschrieben werden sollten. Die auszuwertenden Infotypen sollten aber von den Fachteams gepflegt werden können und somit gab es keine Struktur bzw. Informationen darüber, welche Infotypen gelesen werden mussten.

Da bei dieser Entwicklung große Teile dynamisch zur Laufzeit erfolgen mussten, habe ich mir eine Klasse mit unterschiedlichen Methoden zur Unterstützung dafür angelegt. Eine dieser Methoden zur dynamischen Erzeugung einer internen Tabelle möchte ich nun vorstellen.

Zuerst benötigen wir die Struktur ZEXX_S_FIELDS. Diese Struktur wird für die interne Tabelle zur Übergabe an meine Methode verwendet, um die Informationen über die Felder des dynamisch zur Laufzeit erzeugten Teils der internen Tabelle zu übergeben..

Aufbauend auf dieser Struktur wird der Tabellentyp ZEXX_TT_FIELDS angelegt, damit dieser als Parameter in einer Methode verwendet werden kann.

Nun ist es an der Zeit unsere Klasse ZCL_EXX_DYNAMIC mit der statischen Methode CREATE_INT_TABLE anzulegen.

Die Methode hat die in der folgenden Abbildung zu sehenden Parameter und eine Ausnahme. Neben dem dynamischen Teil der internen Tabelle gab es einen fixen Teil der immer als erste Spalten ausgegeben werden sollte. Dies waren die Spalten der Tabelle PLOGI. Um die Klasse aber für andere Anwendungen wiederverwenden zu können, wurde diese Tabelle (Struktur) an den Parameter IM_S_BASE_TABLE übergeben. Die dynamischen Felder sind als Aufzählung in der internen Tabelle IM_T_TABLES enthalten.

Der folgende Coding-Block enthält die Implementierung der Methode CREATE_INT_TABLE

  METHOD create_int_table.


    DATA: lr_datadescr    TYPE REF TO  cl_abap_datadescr,
          lr_structdescr  TYPE REF TO  cl_abap_structdescr,
          lt_components   TYPE         cl_abap_structdescr=>component_table,
          ls_component    LIKE LINE OF lt_components,
          lv_fieldname    TYPE         fieldname,
          gd_data         TYPE REF TO  data.

    FIELD-SYMBOLS: <ls_s_fields> TYPE zexx_s_fields.

*   wenn weder eine Tabelle noch eine Struktur übergeben wurde Ausnahme auslösen
    IF im_s_base_table IS INITIAL AND im_t_fields  IS INITIAL.
      RAISE no_fields.
    ENDIF.

    IF im_s_base_table IS NOT INITIAL.
*   Anfügen der Felder einer Tabelle oder Struktur
      lr_structdescr ?= cl_abap_typedescr=>describe_by_name( im_s_base_table ).
      ls_component-name = 'BASE_TABLE'.
      ls_component-type = lr_structdescr.
      ls_component-as_include = 'X'.
      APPEND ls_component TO lt_components.
    ENDIF.

    IF im_t_fields IS NOT INITIAL.
*   Anfügen der Felder aus der internen Tabelle die ggfls. übergeben wurde
      LOOP AT im_t_fields ASSIGNING <ls_s_fields>.
        ls_component-name = |Z_| && |{  <ls_s_fields>-fieldname }|.
        lv_fieldname = |{ <ls_s_fields>-tabname }| && |-| && |{ <ls_s_fields>-fieldname }|.
        lr_datadescr ?= cl_abap_datadescr=>describe_by_name( lv_fieldname ).
        ls_component-type = lr_datadescr.
        ls_component-as_include = ' '.
        APPEND ls_component TO lt_components.
      ENDLOOP.
    ENDIF.

    TRY.
        lr_structdescr = cl_abap_structdescr=>create( p_components = lt_components ).
      CATCH cx_sy_struct_creation.
    ENDTRY.

    TRY.
        re_r_table = cl_abap_tabledescr=>create( p_line_type = lr_structdescr ).
        CREATE DATA gd_data TYPE HANDLE re_r_table.
      CATCH cx_sy_table_creation.
    ENDTRY.

  ENDMETHOD. 

​Nachdem nun unsere Klasse erstellt ist, soll diese mit dem folgenden Beispiel-Report getestet werden. 

Im Coding wird zuerst die interne Tabelle mit den dynamischen Feldern (diese wurden bei der echten Entwicklung aus dem Customizing gelesen) gefüllt und zusammen mit der Angabe meiner Basis-Tabelle an die Methode CREATE_INT_TABLE übergeben.

*&---------------------------------------------------------------------*
*& Report  ZEXX_DEMO_DYN_TABLE
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT zexx_demo_dyn_table.


TYPES: BEGIN OF ty_used_attr,
        tablename TYPE infty,
        fieldname TYPE field,
        infty     TYPE infty,
        field     TYPE name_feld,
       END OF ty_used_attr.

DATA: lt_used_attr    TYPE STANDARD TABLE OF ty_used_attr,
      lr_datadescr    TYPE REF TO cl_abap_datadescr,
      gd_data TYPE REF TO data,
      lt_fields TYPE zexx_tt_fields,
      ls_fields TYPE zexx_s_fields.

FIELD-SYMBOLS: <attr_value> TYPE string,
               <used_attr>  TYPE ty_used_attr,
               <t_data>     TYPE STANDARD TABLE,
               <s_data>     TYPE any,
               <field>      TYPE any.


ls_fields-tabname = 'PA0001'.
ls_fields-fieldname = 'PERNR'.
APPEND ls_fields TO lt_fields.

ls_fields-tabname = 'PA0002'.
ls_fields-fieldname = 'NACHN'.
APPEND ls_fields TO lt_fields.

ls_fields-tabname = 'PA0002'.
ls_fields-fieldname = 'VORNA'.
APPEND ls_fields TO lt_fields.


CALL METHOD zcl_exx_dynamic=>create_int_table
  EXPORTING
    im_t_fields     = lt_fields
    im_s_base_table = 'PLOGI'
  RECEIVING
    re_r_table      = lr_datadescr
  EXCEPTIONS
    no_fields       = 1
    OTHERS          = 2.
IF sy-subrc <> 0.
*                 MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
*                            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.

CREATE DATA gd_data TYPE HANDLE lr_datadescr.
ASSIGN gd_data->* TO <t_data>.

APPEND INITIAL LINE TO <t_data> ASSIGNING <s_data>.

ASSIGN COMPONENT 2 OF STRUCTURE <s_data> TO <field>.
<field> = '01'.

ASSIGN COMPONENT 3 OF STRUCTURE <s_data> TO <field>.
<field> = 'P'.

ASSIGN COMPONENT 4 OF STRUCTURE <s_data> TO <field>.
<field> = '12345678'. 

​Wenn wir nun im Debugger anhalten, sehen wir das in der Zeile 60 dynamische die interne Tabelle mit unseren Feldern aus der Grundstruktur und den dynamisch zur Laufzeit übergebenen Feldern erzeugt wurde. Die folgenden Coding-Zeilen zeigen dann noch wie Sie auf die einzelnen Spalten einer neuen Zeile der internen Tabelle zugreifen können.

Auf diese Art und Weise konnten auch dynamisch typgerechte interne Tabellen erzeugt werden, die z.B. für die Zugriffe per Standard-Funktionsbausteine von Infotypen benötigt werden.

Die Entwicklungsobjekte stehen im folgenden Nugget als SAPlink Download zur Verfügung.

zip
Dateiname: NUGG_Z_DYN_TABLE.nugg.zip
Dateigröße: 3 kb
Datei herunterladen