Um eigene Toolbar-Funktionen erweiterte ALV

ajanzen.com
Um eigene Toolbar-Funktionen erweiterte
ALV-Anzeige
ajanzen.com
1 Einleitung
Der Fokus des vorliegenden Dokumentes liegt auf dem Vorgehen zum Einbinden einer
eigenen Toolbarfunktion bei ALV-Erzeugung unter Verwendung von Klasse
CL_SALV_TABLE. Im Rahmen dessen wird auch auf die Behandlung des Ereignisses
auslösen der eigenen Toolbarfunktion eingegangen. Zur besseren Strukturierung des
Codes ist die Ereignisbehandlung in ein eigenständiges INCLUDE ausgelagert.
Die im vorliegenden Beispiel ausgeprägte Funktion ist relativ einfach und visualisiert
ausschließlich die ausgewählten Zeilen in einem Pop-Up.
Das komplette Beispielcoding ist in Kapitel 3 enthalten. Nähere Informationen zum
Ablauf können Kapitel 2 entnommen werden.
1
ajanzen.com
2 Informationen zur Programmlogik
Im vorliegenden Beispiel werden vorbereitend die Informationen aus Tabelle SFLIGHT
in eine interne Tabelle selektiert und in Form eines ALVs visualisiert. Anschließend
wird gezeigt, wie die Toolbar der ALV-Anzeige um eigene Funktionen erweitert werden
kann. Das Ergebnis kann Abbildung 1 entnommen werden.
Aus Gründen der Übersichtlichkeit sind Hauptprogramm und das INCLUDE zur
Ereignisbehandlung in eigenständigen Kapiteln enthalten.
2.1 Hauptprogramm
In Kapitel 2.1 wird zwischen dem umgesetzten Vorgehen (siehe Unterkapitel 2.1.1)
und
einer
anderen
möglichen
Vorgehensweise
(siehe
Unterkapitel
2.1.2)
unterschieden.
2.1.1 Umgesetztes Vorgehen
Im ersten Schritt des ALV-Aufrufes wird über die FACTORY-Methode der Klasse
CL_SALV_TABLE eine Instanz derselben Klasse erzeugt. Dabei wird der FactoryMethode die Tabelle mit den anzuzeigenden Informationen direkt mitgegeben. Eine
zusätzliche Angabe eines Feldkataloges ist nicht notwendig, da sich die
CL_SALV_TABLE-Klasse die Dictionary-Informationen anhand der Tabellenfelder
ermittelt. Zu beachten ist, dass beim Aufruf der FACTORY-Methode der optionale
Parameter R_CONTAINER mit einem Default-Container belegt wird. Die Begründung
für den Container-Einsatz ist in Kapitel 2.1.2 enthalten.
Über eine Instanz von Klasse CL_SALV_COLUMNS_TABLE wird die Spaltenbreite an
den Inhalt angepasst (optimiert).
Zum besseren Auswählen der einzelnen Zeilen, erfolgt das Aktivieren des
Selektionsmodus. Für diese Aktivität wird zum ALV eine Instanz der Klasse
CL_SALV_SELECTIONS erzeugt und der Selektionsmodus durch Aufruf von Methode
SET_SELECTION_MODE( ) gesetzt.
Für das Erweitern der Toolbar um die gewünschte Funktion, ist eine Instanz der Klasse
CL_SALV_FUNCTIONS_LIST zum ALV notwendig. Vor dem Einfügen der eigenen
Funktion werden über Methode SET_ALL( ) der soeben erzeugten Instanz alle SAPStandard ALV-Funktionen aktiviert. In Abbildung 1 sind diese Funktionen links vom
roten Rahmen aufgeführt.
2
ajanzen.com
Das Hinzufügen der eigenen Funktion erfolgt über Methode ADD_FUNCTION( ) der
Klasse CL_SALV_FUNCTIONS_LIST. In dem vorliegenden Beispiel sind alle
Schnittstellenparameter der Methode belegt und die neue Funktion rechts neben den
Standard-Funktionen positioniert. Das Ergebnis des bisher beschriebenen Vorgehens
ist in Abbildung 1 visualisiert. Der rote Rahmen hebt die eigene Funktion hervor.
Abbildung 1: Um eine eigene Funktion erweiterte Toolbar
Wie bereits einleitend erwähnt, wird beim Klick auf die neu eingefügte Funktion ein
Ereignis ausgelöst. Die Ereignisbehandlung findet über eine eigenständige lokale
Klasse statt. Nähere Informationen zu der Klasse können Kapitel 2.2 entnommen
werden.
Damit das ALV weiß, wo das Klick-Ereignis behandelt wird, ist eine Verbindung
zwischen Ereignis und Ereignis-Behandler herzustellen, also das Ereignis zu
registrieren. Zum Registrieren wird eine Instanz der Klasse CL_SALV_EVENTS_
TABLE benötigt. Das Objekt der Klasse verwaltet die SALV-Ereignisse.
Da zur Ereignisbehandlung eine eigenständige Klasse zum Einsatz kommt, muss
diese ebenfalls instanziiert werden. Nach Instanziieren der lokalen Behandler-Klasse
wird diese über die Anweisung SET HANDLER der Instanz von CL_SALV_EVENTS_
TABLE
zugeordnet
und
damit
die
Verbindung
zwischen
Ereignis
und
Ereignisbehandlung hergestellt.
Hinweis: Bei dem ausgelösten Ereignis handelt es sich um ADDED_FUNCTION.
Dieses kann der Registerkarte Ereignisse der Klasse CL_SALV_EVENTS_TABLE
entnommen werden (siehe Abbildung 2). In der Behandler-Klasse kommt für die
Ereignisbehandlung Methode HANDLE_TOOLBAR_CLICK zum Einsatz.
3
ajanzen.com
Abbildung 2: Ereignis ADDED_FUNCTION der Klasse CL_SALV_EVENTS_TABLE
Das eigentliche Visualisieren erfolgt durch Methode DISPLAY( ) der ALV-Klasse. Da
der Factory-Methode ein Container mitgegeben wurde, ist auch eine Art „TrägerDynpro“ notwendig. Dieses ist erforderlich, damit sich der Container irgendwo
„andocken“ kann. In diesem Beispiel wird das Dynpro über die Anweisung WRITE
erzeugt.
2.1.2 Exkurs
Mir sind zwei Vorgehen bekannt, die beim Einsatz der CL_SALV_TABLE-Klasse das
Einbinden eigener Funktionen in die Toolbar ermöglichen. In Kapitel 2.1.1 ist eines der
Vorgehen beschrieben. Das zugehörige Coding kann Kapitel 3 entnommen werden.
Die zweite Möglichkeit basiert auf dem Einsatz des PF-STATUS. Der PF-Status mit
allen ALV-Standardfunktionen kann aus dem Demo-Report SALV_DEMO_TABLE_
FUNCTIONS kopiert werden und hat hier die Bezeichnung SALV_STANDARD. Nach
dem Kopieren lässt sich der PF-Status durch eigene Funktionen erweitern (sieh
Abbildung 3).
Abbildung 3: Um eigene Funktion erweiterter PF-Status
Das Bekanntmachen des PF-Status der SALV-Instanz erfolgt über folgende
Anweisung:
4
ajanzen.com
gr_salv->set_screen_status(
pfstatus
=
'SALV_STANDARD'
report
=
sy-repid
set_functions = gr_salv->c_functions_all ).
Auch eine über den PF-Status eingefügte Funktion erscheint in der Toolbar und das
Ausführen dieser Funktion erzeugt ein Ereignis. Die Ereignisbehandlung unterscheidet
sich nicht von der Ereignisbehandlung beim ersten Vorgehen und kann dem
vorliegenden Dokument entnommen werden.
Welches der beiden Vorgehen zum Erweitern der Toolbar eingesetzt werden kann,
hängt davon ab, ob der FACTORY-Methode der Klasse CL_SALV_TABLE ein
Container mitgegeben wird oder nicht. Wird auf das Mitgeben eines Containers
verzichtet, erfolgt im Rahmen der Ausführung der DISPLAY( ) Methode ein
Dynproaufruf. Bei diesem Vorgehen können eigene Funktionen nur über den PFStatus mitgeteilt werden.
Bei Angabe eines Containers, ist das Erweitern der Toolbar nur über die Methode
ADD_FUNCTION( ) möglich. Da in diesem Fall kein Dynpro-Aufruf in Methode
DISPLAY( ) erfolgt, ist der zusätzliche Aufruf eines „Träger-Dynpros“ im Programm
notwendig.
In diesem Beispiel habe ich mich für die Variante mit Container entschieden. Das hat
m.E. den Vorteil, dass der Beispielcode direkt kopiert und getestet werden kann. Statt
der WRITE-Anweisung für das Träger-Dynpro kann zum Aufruf eines Dynpros auch
die Anweisung CALL-Screen verwendet werden. Auch bei der Verwendung der
Container hat der Entwickler freie Hand. So kommen hier beispielsweise folgende
Container in Frage:
•
CL_GUI_DOCKING_CONTAINER
•
CL_GUI_DIALOGBOX_CONTAINER
•
CL_GUI_CUSTOM_CONTAINER
2.2 INCLUDE zur Ereignisbehandlung
Wie bereits im Vorfeld beschrieben, ist für die Behandlung des Ereignisses ButtonClick eine Behandler-Klasse notwendig. In dem vorliegenden Beispiel wurde die
Klasse in ein eigenständiges INCLUDE ausgelagert. Die ausgeprägte Logik ist in
Kapitel 2.2 beschrieben.
5
ajanzen.com
Die Behandler-Klasse besteht neben der Constructor-Methode ausschließlich aus
Methode HANDLE_TOOLBAR_CLICK. Letztere wurde als Event-handler für das
Ereignis ADDED_FUNCTION der CL_SALV_EVENTS_TABLE definiert.
Beim Instanziieren der Behandler-Klasse werden der Constructor-Methode eine
Instanz der SALV-Klasse und die Tabelle mit den Daten übergeben. Der Inhalt beider
Parameter wird in klassenglobalen Attributen abgelegt und damit für die
Weiterverarbeitung vorgehalten. Bei Ablage der Datentabelle ist zu beachten, dass
diese nicht über ein „=“ sondern über die Anweisung GET REFERENCE OF erfolgt.
Siehe nachfolgende Erklärung:
Bei Verwenden des „=“ für die Datenzuweisung wird der Inhalt der ImportparameterTabelle IT_SFLIGHT in das globale Klassenattribut kopiert. Dadurch existieren die
Informationen (Tabellen) doppelt (siehe Abbildung 4).
Globales Attribut
GT_SFLIGHT_CLASS
Importparameter
IT_SFLIGHT
Mandant
001
001
001
001
001
…
Carrier
AA
AA
AZ
AZ
AZ
…
Flug-Nr.
17
64
555
555
788
…
Flugdatum
15.10.2014
12.12.2014
15.10.2014
04.02.2015
23.06.2015
…
Flugpreis
422,94
422,94
185,00
185,00
1.030,00
…
Mandant
001
001
001
001
001
…
…
…
…
…
…
…
…
Carrier
AA
AA
AZ
AZ
AZ
…
Flug-Nr.
17
64
555
555
788
…
Flugdatum
15.10.2014
12.12.2014
15.10.2014
04.02.2015
23.06.2015
…
Flugpreis
422,94
422,94
185,00
185,00
1.030,00
…
…
…
…
…
…
…
…
Abbildung 4: Doppeln der Daten bei Zuweisung über „=“
Bei Verwendung der Anweisung GET REFERENCE OF wird ein Zeiger auf die
übergebenen Daten erzeugt. Dadurch sind die Informationen nur einmal vorhanden
und alle Änderungen (z.B. sortieren der Tabelle im ALV) sind ohne weiteren Aufwand
ersichtlich (siehe Abbildung 5).
Importparameter
IT_SFLIGHT
Mandant
001
001
001
001
001
…
Carrier
AA
AA
AZ
AZ
AZ
…
Flug-Nr.
17
64
555
555
788
…
Flugdatum
15.10.2014
12.12.2014
15.10.2014
04.02.2015
23.06.2015
…
Flugpreis
422,94
422,94
185,00
185,00
1.030,00
…
…
…
…
…
…
…
…
Globales Attribut
GT_SFLIGHT_CLASS
Abbildung 5: Zeiger auf Ursprungsdaten bei der Zuweisung GET REFERENCE OF
Hinweis: In der FACTORY( )-Methode der SALV-Klasse wird ebenfalls nur eine
Referenz auf die übergebenen Daten erzeugt.
6
ajanzen.com
Zu Beginn der Verarbeitung von Methode HANDLE_TOOLBAR_CLICK wird
abgefragt, um was für eine Funktion es sich handelt. Diese Information ist im EreignisParameter E_SALV_FUNCTION enthalten. Handelt es sich um die im Vorfeld erstellte
Toolbar-Funktion, werden die ausgewählten Zeilen ermittelt. Das erfolgt über eine
Instanz der Selektionsklasse CL_SALV_SELECTIONS zur, in der ConstructorMethode klassenglobal abgelegten, SALV-Instanz. Das eigentliche Bestimmen der
ausgewählten Zeilen findet über Methode GET_SELECTED_ROWS( ) der
Selektionsklasse statt. Unter Verwendung der Indizes werden die selektierten Zeilen
aus der klassenglobal vorliegende Tabellenreferenz auf die Daten bestimmt und in
einem Pop-Up angezeigt.
7
3 Coding
Wie aus der Überschrift ersichtlich ist, enthält Kapitel 3 das komplette Beispielcoding.
Genau wie beim Aufbau von Kapitel 2 sind Hauptprogramm und das INCLUDE zur
Ereignisbehandlung in eigenständigen Unterkapiteln enthalten.
3.1 Hauptprogramm
*--------------------------------------------------------------------*
* Das vorliegende Programm dient der Demonstration eines SALV im
* Selection-mode erweitert um eine eigene Toolbar-Funktion
*
* Date: 28.03.2015
*--------------------------------------------------------------------*
* Änderungen
*--------------------------------------------------------------------*
REPORT
zaj_sel_mode_own_funct_salv.
***************************************************************************
****
* Include zur Ereignisbehandlung
***************************************************************************
****
INCLUDE zaj_sel_mode_own_funct_salv_cl.
DATA: gr_salv
TYPE REF TO cl_salv_table.
DATA: gr_columns
TYPE REF TO cl_salv_columns_table.
DATA: gr_functions
TYPE REF TO cl_salv_functions_list.
DATA: gr_selections
TYPE REF TO cl_salv_selections.
DATA: gt_sflight
TYPE flighttab.
DATA: gr_err_salv
TYPE REF TO cx_salv_msg.
DATA: gr_err_salv_exist
TYPE REF TO cx_salv_existing.
DATA: gr_err_wrong_call
TYPE REF TO cx_salv_wrong_call.
DATA: gv_string
TYPE string.
DATA: gr_events
TYPE REF TO cl_salv_events_table.
DATA: gr_event_handler
TYPE REF TO gcl_event_handler.
START-OF-SELECTION.
***************************************************************************
****
* Selektion der anzuzeigenden Daten
***************************************************************************
****
SELECT *
FROM sflight
INTO CORRESPONDING FIELDS OF TABLE gt_sflight.
IF sy-subrc NE 0.
*
In diesem Fall wird eine leere Tabelle angezeigt
ENDIF.
***************************************************************************
****
* Daten anzeigen
***************************************************************************
****
TRY.
*
ALV-Instanz erzeugen
CALL METHOD cl_salv_table=>factory
EXPORTING
list_display = if_salv_c_bool_sap=>false
r_container
= cl_gui_custom_container=>default_screen
IMPORTING
r_salv_table = gr_salv
CHANGING
t_table
= gt_sflight.
CATCH cx_salv_msg INTO gr_err_salv.
*
Fehler anzeigen
gv_string = gr_err_salv->get_text( ).
MESSAGE gv_string TYPE 'E'.
ENDTRY.
* Instanz für Spalten holen
gr_columns = gr_salv->get_columns(
).
* Spaltenbreite optimieren
gr_columns->set_optimize( abap_true ). " nur ein 'X'
***************************************************************************
****
* Selection-Mode aktivieren
***************************************************************************
****
* Instanz des Selection-Objektes holen
gr_selections = gr_salv->get_selections( ).
* Selektionsmodus setzen
gr_selections->set_selection_mode( if_salv_c_selection_mode=>row_column
).
***************************************************************************
****
* Alle Standard-Funktionen auf aktiv setzen
***************************************************************************
****
* Instanz für Funktionen holen
gr_functions = gr_salv->get_functions( ).
* Alle Standardfunktionen aktivieren
gr_functions->set_all( abap_true ). " nur ein 'X'
***************************************************************************
****
* Toolbar um eigene Funktionen erweitern
***************************************************************************
****
TRY.
*
Neue Funktion für das ALV vorsehen
gr_functions->add_function(
name
= 'NFUNC'
icon
= '@L1@'
text
= 'Neue Funktion'
tooltip
= 'Hinzugefügte Funktion'
position
= if_salv_c_function_position=>right_of_salv_functions
" Irgendein ICON aus Tabelle ICON
).
CATCH cx_salv_existing INTO gr_err_salv_exist.
*
Fehler anzeigen
gv_string = gr_err_salv_exist->get_text( ).
MESSAGE gv_string TYPE 'E'.
CATCH cx_salv_wrong_call INTO gr_err_wrong_call.
*
Fehler anzeigen
gv_string = gr_err_wrong_call->get_text( ).
MESSAGE gv_string TYPE 'E'.
ENDTRY.
***************************************************************************
****
* Ereignis zum Behandeln des Button-Click registrieren
***************************************************************************
****
* Das Objekt für die möglichen ALV-Ereignisse holen
gr_events = gr_salv->get_event( ).
* Objekt für die Ereignisbehandlung erzeugen ...
CREATE OBJECT gr_event_handler
EXPORTING
cr_salv
= gr_salv
it_sflight = gt_sflight.
* ... und bei den ALV-Ereignissen registrieren
SET HANDLER gr_event_handler->handle_toolbar_click FOR gr_events.
***************************************************************************
****
* * ALV-Anzeige anstoßen
***************************************************************************
****
* ALV-Anzeige anstoßen
gr_salv->display( ).
* "Trägerbildschirm" für Container rufen
WRITE space.
3.2 INCLUDE zur Ereignisbehandlung
***************************************************************************
****
* Definition der Klasse
***************************************************************************
****
CLASS gcl_event_handler DEFINITION.
PUBLIC SECTION.
METHODS: constructor
IMPORTING cr_salv
TYPE REF TO cl_salv_table
it_sflight TYPE flighttab.
METHODS: handle_toolbar_click FOR EVENT added_function OF
cl_salv_events_table
IMPORTING e_salv_function.
PROTECTED SECTION.
DATA: gr_salv_class
TYPE REF TO cl_salv_table.
DATA: gt_sflight_class TYPE REF TO flighttab.
METHODS: display_popup
CHANGING ct_sflight_display TYPE flighttab.
ENDCLASS.
"gcl_event_handler DEFINITION
***************************************************************************
****
* Implementierung der Klasse
***************************************************************************
****
CLASS gcl_event_handler IMPLEMENTATION.
METHOD constructor.
*
Importparameter in globale Klassenattribute übernehmen
gr_salv_class
= cr_salv.
GET REFERENCE OF it_sflight INTO gt_sflight_class.
ENDMETHOD.
"constructor
METHOD handle_toolbar_click.
DATA: lr_selections
TYPE REF TO cl_salv_selections.
DATA: lt_sel_rows
TYPE salv_t_row.
DATA: lv_sel_row
TYPE int4.
DATA: ls_sflight
TYPE sflight.
DATA: lt_sflight_display
TYPE flighttab.
CASE e_salv_function.
WHEN 'NFUNC'.
***************************************************************************
****
*
Hier behandeln wir unsere Funktion
***************************************************************************
****
*
Instanz des Selection-Objektes holen
lr_selections = gr_salv_class->get_selections( ).
*
Indes der markierten Zeilen bestimmen
lt_sel_rows = lr_selections->get_selected_rows( ).
*
Die selektierten Datensätze ermitteln
LOOP AT lt_sel_rows INTO lv_sel_row.
*
selektierte Zeilen auslesen
READ TABLE gt_sflight_class->*
INTO ls_sflight INDEX lv_sel_row.
*
Datensatz für die Anzeige übernehmen
APPEND ls_sflight TO lt_sflight_display.
ENDLOOP.
*
Daten in einem separaten Pop-Up visualisieren
display_popup(
CHANGING
ct_sflight_display = lt_sflight_display ).
WHEN OTHERS.
***************************************************************************
****
*
Wenn sonst irgendwas passiert, soll keine Reaktion erfolgen
***************************************************************************
****
ENDCASE.
ENDMETHOD.
"handle_toolbar_click
METHOD display_popup.
DATA: lr_salv_popup
TYPE REF TO cl_salv_table.
DATA: lr_err_salv
TYPE REF TO cx_salv_msg.
DATA: lv_string
TYPE string.
TRY.
*
ALV-instanz erzeugen
CALL METHOD cl_salv_table=>factory
EXPORTING
list_display = if_salv_c_bool_sap=>false
IMPORTING
r_salv_table = lr_salv_popup
CHANGING
t_table
= ct_sflight_display.
CATCH cx_salv_msg INTO lr_err_salv.
*
Fehler anzeigen
lv_string = lr_err_salv->get_text( ).
MESSAGE lv_string TYPE 'E'.
ENDTRY.
*
Größe des Fensters setzen
lr_salv_popup->set_screen_popup(
start_column = 5
*
end_column
= 160
start_line
= 5
end_line
= 15 ).
Anzeige anstoßen
lr_salv_popup->display( ).
ENDMETHOD.
ENDCLASS.
"display_popup
"gcl_event_handler IMPLEMENTATION