Wiederverwendbarer modaler Auswahldialog in ABAP mit CL_SALV_TABLE

In einer typischen ABAP Dynproanwendung benötigt man irgendwann die Funktionalität, Daten dem Benutzer in einem Popup zu präsentieren und die  Auswahl zu prüfen. Häufig wird so ein Dialog manuell implementiert, obwohl es funktional immer das Gleiche ist. Was ist CL_SALV_TABLE?

Mit dem Funktionsbaustein REUSE_ALV_GRID_DISPLAY gibt es eine Standardfunktionalität zur Implementierung eines Dialogs als auch zur Anzeige von Daten im Fullscreen. Nachteil ist, dass der Funktionsbaustein  REUSE_ALV_GRID_DISPLAY nicht gut zur heute üblichen objektorientierten Programmierung passt, da er als Callback FORM-Routinen in einem Programm erwartet.

Die Klasse CL_SALV_TABLE ist eine objektorientierte Verschalung des Funktionsbausteins REUSE_ALV_GRID_DISPLAY. Ein Beispiel zur Implementierung eines spezifischen Dialogs findet sich in Programm SALV_DEMO_TABLE_POPUP.

Aus dieser Ausgangssituation heraus implementieren wir in diesem Blog einen modalen Auswahldialog mit folgenden Eigenschaften.

  • Einfache objektorientierte Schnittstelle aufsetzend auf Klasse CL_SALV_TABLE
  • Automatische Größenanpassung abhängig von der Anzahl der übergeben Datensätze
  • Optionale Anpassung der Gridspalten über den Feldkatalog
  • Optionale Überprüfung der Auswahl durch eigene Logik

Das Coding besteht aus den folgenden Teilen:

Im Folgenden beschreibe ich die Benutzung der Klasse ZCL_RL_DIALOG_MODAL ausgehend von den Unittests.

Unittest Einfachaufruf

Der folgende Code zeigt den Einfachaufruf des Dialogs. Die anzuzeigenden Daten kommen aus der SalesorderHeader-Tabelle SNWD_SO im Enterprise Procurement Model.  Die durch den Benutzer ausgewählten Datensätze werden im Exportparameter et_data_sel zurückgegeben.

  METHOD simple_call.
    TYPES:
      BEGIN OF ts_dlg_epm_so,
        so_id            TYPE snwd_so_id,
        net_amount       TYPE snwd_ttl_net_amount,
        tax_amount       TYPE snwd_ttl_tax_amount,
        currency_code    TYPE snwd_curr_code,
        lifecycle_status TYPE snwd_so_lc_status_code,
      END OF ts_dlg_epm_so.

    DATA lt_dlg_epm_so TYPE TABLE OF ts_dlg_epm_so.
    DATA lt_dlg_epm_so_sel TYPE TABLE OF ts_dlg_epm_so ##NEEDED.

    SELECT * FROM snwd_so INTO CORRESPONDING FIELDS OF TABLE lt_dlg_epm_so UP TO 20 ROWS.

    mr_dialog_modal->open(
      EXPORTING
        it_data = lt_dlg_epm_so
        iv_title = 'Testdialog'
        iv_width = 40
      IMPORTING
        et_data_sel = lt_dlg_epm_so_sel ).

  ENDMETHOD.

Die open-Methode der Klasse ZCL_RL_DIALOG_MODAL ist generisch als STANDARD TABLE typisiert. Die Logik analysiert die übergebene Datenstruktur und erzeugt daraus die Spaltenköpfe des ALV Grids. Die Breite (Parameter iv_width) übergibt der Aufrufer. Die Höhe des Dialogs berechnet die Logik der open-Methode abhängig von der Anzahl der übergebenen Datenzeilen selbst.

Unittest Anpassung Feldkatalog

Das folgende Beispiel zeigt den Aufruf des Dialogs mit Anpassung des Feldkatalogs, um z.B. nicht benötigte Spalten auszublenden.

METHOD fieldcatalog.
    DATA lt_dlg_epm_so TYPE TABLE OF snwd_so.
    DATA lt_dlg_epm_so_sel TYPE TABLE OF snwd_so ##NEEDED.
    DATA lt_fcat TYPE lvc_t_fcat.
    FIELD-SYMBOLS  TYPE lvc_s_fcat.

    SELECT * FROM snwd_so INTO TABLE lt_dlg_epm_so UP TO 4 ROWS.

    lt_fcat = mr_dialog_modal->get_fieldcatalog( lt_dlg_epm_so ).

    LOOP AT lt_fcat ASSIGNING .
      CASE -fieldname.
        WHEN 'SO_ID'.
          -key = abap_true.
        WHEN 'NET_AMOUNT' OR 'TAX_AMOUNT' OR 'LIFECYCLE_STATUS' OR 'BILLING_STATUS' OR 'DELIVERY_STATUS'.
        WHEN OTHERS.
          -no_out = abap_true.
      ENDCASE.
    ENDLOOP.

    mr_dialog_modal->open(
      EXPORTING
        it_data = lt_dlg_epm_so
        iv_title = 'Testdialog'
        iv_width = 62
        it_fcat = lt_fcat
      IMPORTING
        et_data_sel = lt_dlg_epm_so_sel ).
  ENDMETHOD.

Unittest Prüfung Eingaben

Das folgende Beispiel zeigt den Aufruf des Dialogs mit einer Prüfung der Eingaben. Die Prüfung der Eingaben erfolgt durch Übergabe eines Objekts, welches das Interface ZIF_RL_DIALOG_MODAL_CHECK implementiert. In diesem Fall ist dies die lokale Klasse lcl_dialog_modal_check. Die Prüfung in diesem Beispiel stellt sicher, dass der Benutzer beim Klicken des Ok-Button mindestens 1 Zeile ausgewählt hat.

  METHOD check_selection.
    TYPES:
      BEGIN OF ts_dlg_epm_so,
        so_id            TYPE snwd_so_id,
        net_amount       TYPE snwd_ttl_net_amount,
        tax_amount       TYPE snwd_ttl_tax_amount,
        currency_code    TYPE snwd_curr_code,
        lifecycle_status TYPE snwd_so_lc_status_code,
      END OF ts_dlg_epm_so.

    DATA lt_dlg_epm_so TYPE TABLE OF ts_dlg_epm_so.
    DATA lt_dlg_epm_so_sel TYPE TABLE OF ts_dlg_epm_so ##NEEDED.
    DATA lr_dialog_modal_check TYPE REF TO lcl_dialog_modal_check.

    SELECT * FROM snwd_so INTO CORRESPONDING FIELDS OF TABLE lt_dlg_epm_so UP TO 20 ROWS.

    CREATE OBJECT lr_dialog_modal_check.

    mr_dialog_modal->open(
      EXPORTING
        it_data = lt_dlg_epm_so
        iv_title = 'Testdialog'
        iv_width = 40
        ir_dialog_modal_check = lr_dialog_modal_check
      IMPORTING
        et_data_sel = lt_dlg_epm_so_sel ).

  ENDMETHOD.

CLASS lcl_dialog_modal_check DEFINITION FINAL.
  PUBLIC SECTION.
    INTERFACES zif_rl_dialog_modal_check.

  PRIVATE SECTION.
    METHODS conv_sy_to_bapiret2
      RETURNING VALUE(rs_return) TYPE bapiret2.
ENDCLASS.

CLASS lcl_dialog_modal_check IMPLEMENTATION.
  METHOD zif_rl_dialog_modal_check~check.
    IF lines( it_data_sel ) = 0.
      MESSAGE e499(sy) WITH 'Mindestens 1 Zeile auswählen'(001) INTO DATA(lv_msg) ##needed.
      rs_return = conv_sy_to_bapiret2( ).
    ENDIF.
  ENDMETHOD.

  METHOD conv_sy_to_bapiret2.

    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      INTO rs_return-message
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    rs_return-type = sy-msgty.
    rs_return-id = sy-msgid.
    rs_return-number = sy-msgno.
    rs_return-message_v1 = sy-msgv1.
    rs_return-message_v2 = sy-msgv2.
    rs_return-message_v3 = sy-msgv3.
    rs_return-message_v4 = sy-msgv4.
  ENDMETHOD.
ENDCLASS.

CLASS lcl_dialog_modal_check DEFINITION FINAL.
  PUBLIC SECTION.
    INTERFACES zif_rl_dialog_modal_check.

  PRIVATE SECTION.
    METHODS conv_sy_to_bapiret2
      RETURNING VALUE(rs_return) TYPE bapiret2.


ENDCLASS.

Implementierung in Deinem SAP-System

Die folgende Abbildung zeigt den Aufbau der Klasse ZCL_RL_DIALOG_MODAL. Die  Methoden OPEN und GET_FIELDCATALOG haben wir schon im Rahmen der Unittests gesehen. Die private Methode ON_USER_COMMAND wird als Eventhandler für das Drücken der Button registriert.

Die im Screenshot sichtbare lokalen Klasse LCL_TEST implementiert den Unittest. Die lokale LCL_DIALOG_MODAL_CHECK implementiert das Interface ZIF_RL_DIALOG_MODAL_CHECK und dient der Eingabeüberprüfung beim Unittest check_selection.

Um die Funktionalität in Deinem SAP-System zu implementieren, lege das Interface ZIF_RL_DIALOG_MODAL_CHECK und die Klasse ZCL_RL_DIALOG_MODAL über den Class Builder (Transaktion SE24) an, wechsle danach in die Quelltextansicht  und kopiere den Interface-Code und den Klassen-Code hinein. Generiere danach in Klasse ZCL_RL_DIALOG_MODAL das Testklasseninclude und füge den Unittest-Code ein.

Der letzte Schritt ist ein bisschen fummelig. Der Dialog benötigt einen GUI-Status, damit das Dynpro die Buttons für Ok, Abbrechen, Filtern usw. anzeigt. In dem Beispielcode heißt der GUI-Status SALV_TABLE_POPUP und liegt in Programm ZRL_TEST. Du brauchst irgendein Programm oder Funktionsgruppe, wo Du den GUI-Status anlegen kannst. Der Screenshot zeigt den GUI-Status. Die Buttons CONT und CANC müssen genau so benannt werden, da die Logik in Methode ON_USER_COMAND darauf aufsetzt. Buttons, die vom OkCode her mit & beginnen, werden durch das ALV-Grid selber verarbeitet.

Die manuelle Anlage des GUI-Status ist fehleranfällig. Deshalb ist der einfachste Weg, wenn Du den Standard GUI-Status des ALV-Grids kopierst und danach die Buttons anpasst. Der Standard GUI-Status heißt SALV_TABLE_STDPOPUP in Programm SAPLSALV_METADATA_STATUS.

Hast du noch Fragen zur CL_SALV_TABLE  oder anderen Themen?

Nutze gerne unsere Kommentarfunktion oder schreib mir direkt eine eMail

 

Du programmierst, bist ABAP-interessiert und hast Lust coole Projekte mit uns zu machen? Wir suchen dich! Schau doch mal in unserer Stellenbeschreibung vorbei.

Veröffentlicht in ABAP

Über den Autor

Rüdiger Lühr

Kommentar verfassen