Manchmal, aber nur manchmal… ♫

hält SAP Überraschungen bereit, das glaubt man kaum…

Aber von vorne.

In einem Projekt haben wir uns gewundert, warum es in einer dynamisch generierten internen Tabelle einen CONVERSION OVERFLOW gab, obwohl das Feld vom Typ DEC ausreichend groß dimensioniert war. Die Lösung war offensichtlich. Hinterher…

2015-08-10_15-31-23

Erzeugung

Wir sind bei der Erzeugung der internen Tabelle wie folgt vorgegangen:

  • Definition des Feldkataloges
  • Erzeugung der internen Tabelle mit Hilfe von cl_alv_table_create=>create_dynamic_table

Beispielhaft kann die Erzeugung folgendermaßen veranschaulicht werden:

  FIELD-SYMBOLS <fcat>  TYPE lvc_s_fcat.
  DATA gt_table         TYPE lvc_t_fcat.

  APPEND INITIAL LINE TO gt_fcat ASSIGNING .
  <fcat>-fieldname = 'FELD1'.
  <fcat>-scrtext_l = 'Feld 1: CHAR'.
  <fcat>-inttype   = 'C'.
  <fcat>-intlen    = 20.
  <fcat>-datatype  = 'CHAR'.

  APPEND INITIAL LINE TO gt_fcat ASSIGNING .
  <fcat>-fieldname = 'FELD2'.
  <fcat>-scrtext_l = 'Feld 2: DEC'.
  <fcat>-inttype   = 'P'.
  <fcat>-intlen    = 16.
  <fcat>-datatype  = 'DEC'.
  <fcat>-decimals  = 2.

  CALL METHOD cl_alv_table_create=>create_dynamic_table
    EXPORTING
      it_fieldcatalog           = gt_fcat
      i_length_in_byte          = abap_true
    IMPORTING
      ep_table                  = gd_table
    EXCEPTIONS
      generate_subpool_dir_full = 9.

Das macht SAP

Im Debugger sieht man die erzeugte Datenstruktur im Detail.

2015-08-10_15-40-25

Hier ist auch erkennbar, dass die gepackte Zahl im internen Format nicht 16 Bytes groß ist, sondern nur 8. Dadurch passt nur eine vierzehnstellige Zahl (plus Vorzeichen) in das Feld. Im Coding wurde jedoch die maximale Größe von intern 16 Bytes verwendet.

Versteckte Parameter

Ich habe mir die Erzeugung der internen Tabelle durch cl_alv_table_create=>create_dynamic_table genauer angesehen und bin dann recht schnell auf den Parameter I_LENGTH_IN_BYTE gestoßen. Dieser Parameter ist in der Schnittstelle – wie so oft – sehr anschaulich und gut dokumentiert:

boolsche Variable (X=true, space=false)

Der Parameter ist optional und hat als Vorgabewert ABAP_FALSE.

Um es vorweg zu nehmen: Nachdem wir den Parameter auf ABAP_TRUE gesetzt haben, funktionierte alles, wie erwartet.

Beim Debuggen bin ich irgendwann auf folgende Stelle gestossen:

if ls_fieldcat-inttype eq 'P'.
  if r_length_in_byte eq abap_true.
    l_leng = ls_fieldcat-intlen.
  else.
    l_leng =  ( ls_fieldcat-intlen + 1 ) / 2.
  endif.
endif.

Meiner Meinung nach ist das Coding hier verkehrt, da gepackte Zahlen immer aus Halbbytes bestehen. An dieser Stelle darf nicht einfach die Länge halbiert werden. Warum genau diese “Halbierung” statt findet, habe ich auch nicht verstanden. Es hat wahrscheinlich mit Unicode zu tun.

Fazit

Die Erzeugung von internen Tabellen sollte meiner Meinung nach eh nicht mehr mit dem erwähnten Funktion erzeugt werden, da hier im Hintergrund Subroutine-Pools generiert werden. Die Verwendung ist nur eingeschränkt möglich (maximale Anzahl Aufrufe: 36). Inzwischen sind die Möglichkeiten mit CREATE DATA & RTTC deutlich eleganter und zukunftssicherer. Allerdings habe ich die Verwendung von CREATE_DYNMIC_TABLE auch schon mal als elegant bezeichnet…

Die Methode mit CREATE_DYNAMIC_TABLE hat auch einen großen Vorteil: Bei dem Aufbau der internen Tabelle kann ich gleich semantische Informationen mitgeben/ anreichern (Titel, Texte, Suchhilfen etc.), die nicht automatisch übernommen werden. Ich dann diesen Feldkatalog nicht nur zur Erzeugung der internen Tabelle verwenden, sondern auch für die Anzeige.

Bei der Variante über CREATE DATA und RTTC werden fast ausschließlich die technischen Informationen ausgewertet. Wenn ein verwendetes Datenelement korrekte Überschriften hat, ist es okay, aber wenn ich eigene Felder mit einem generischen Datenelement aufbaue (FELD1, FELD2) und diese im gleichen Zug benennen will, dann muss ich dies separat tun.

Enno Wulff