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:
- Globale ABAP-Klasse ZCL_RL_DIALOG_MODAL
- Globales ABAP-Interfaces ZIF_RL_DIALOG_MODAL_CHECK, welches implementiert werden kann, um die durch den Benutzer durchgeführte Auswahl zu prüfen
- Unittests zu ABAP-Klasse ZCL_RL_DIALOG_MODAL, welche die Benutzung der Funktionalität zeigen
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.