Smart Filter

Vor einiger Zeit habe ich euch den Magic Filter vorgestellt. Hier habe ich den aktuellen Filter eines Grids auf mehrere Objekte angewendet.

Heute möchte ich euch eine weitere Möglichkeit der Filterung vorstellen: Die Filterung anhand einer Mehrfachselektion. Damit es ins Konzept passt und weil jedes Kind einen Namen braucht, habe ich es Smart Filter genannt.

Smart Filter: Anwendung

Am Anfang war das Grid (oder genauer: Der SALV-Table). Als Beispieldaten dienen die Länderbezeichnungen.

Das Grid besitzt eine selbst definierte Funktion “Filter”:

filter_sel1

Um diese Funktion zu verwenden, müssen mindestens eine Zeile und mindestens eine Spalte markiert werden (STRG gedrückt halten für Mehrfachselektion!):

filter_sel2

Mit einem Klick auf “Filter” wird dann die “Schnittmenge” gefiltert:

filter_sel3

Die Anwendungsmöglichkeiten sind sicherlich beschränkt, aber bei größeren Listen, die anhand bestimmter Felder und Feldwerte kontrolliert werden müssen, sicherlich sehr hilfreich.

Anmerkungen zum Code

Da der zusätzliche Button in dieser Variante nicht im Fullscreen-Grid funktioniert, muss die Darstellung in einem Docking-Container erfolgen.

Um dies einfach zu tun, habe ich den PARAMETER dummy verwendet, damit ein Selektionsbild angezeigt wird.

Mit Druck auf die Enter-Taste wird das Grid angezeigt.

Um den Zusatzbutton anzuzeigen, wird Command Chaining verwendet:

mr_salv->get_functions( )->add_function( ... )

Code

REPORT.

PARAMETERS dummy.

*----------------------------------------------------------------------*
* CLASS lcl_grid DEFINITION
*----------------------------------------------------------------------*
CLASS lcl_grid DEFINITION.
 PUBLIC SECTION.
 CLASS-METHODS start.
 PROTECTED SECTION.
 CLASS-DATA mt_data TYPE STANDARD TABLE OF t005t.
 CLASS-DATA mr_salv TYPE REF TO cl_salv_table.
 CLASS-METHODS add_filter_value
 IMPORTING
 structure TYPE any
 fieldname TYPE fieldname
 CHANGING
 filter TYPE lvc_t_filt.
 CLASS-METHODS add_filter_selection.
 CLASS-METHODS set_filter
 IMPORTING
 filter TYPE lvc_t_filt.
 CLASS-METHODS add_function.
 CLASS-METHODS on_function FOR EVENT added_function
 OF cl_salv_events_table
 IMPORTING e_salv_function.


ENDCLASS. "lcl_grid DEFINITION

*----------------------------------------------------------------------*
* CLASS lcl_grid IMPLEMENTATION
*----------------------------------------------------------------------*
CLASS lcl_grid IMPLEMENTATION.
 METHOD start.

*== Daten lesen
 SELECT * FROM t005t INTO TABLE mt_data.

*== Docker erzeugen
 DATA lr_docker TYPE REF TO cl_gui_docking_container.
 CREATE OBJECT lr_docker
 EXPORTING
 side = cl_gui_docking_container=>dock_at_bottom
 ratio = 80.

*== SALV-Table erzeugen
 CALL METHOD cl_salv_table=>factory
 EXPORTING
 r_container = lr_docker
 IMPORTING
 r_salv_table = mr_salv
 CHANGING
 t_table = mt_data.

*== alle Funktionen einblenden, um Filter löschen zu können
 DATA lr_funcs TYPE REF TO cl_salv_functions_list.
 lr_funcs = mr_salv->get_functions( ).
 lr_funcs->set_all( ).
*== Eigene Funktion einblenden
 add_function( ).

*== ON_Usercommand registrieren
 DATA lr_events TYPE REF TO cl_salv_events_table.
 lr_events = mr_salv->get_event( ).
 SET HANDLER on_function FOR lr_events.

*== Anzeige
 mr_salv->display( ).

 ENDMETHOD. "start

 METHOD add_function.

*== Eigene Funktion einfügen
 mr_salv->get_functions( )->add_function(
 name = 'ZFilterSel'
 icon = |{ icon_filter }|
 text = |Filter|
 tooltip = |Filter anhand Selektion|
 position = if_salv_c_function_position=>right_of_salv_functions ).

 ENDMETHOD. "add_function

 METHOD on_function.

 CASE e_salv_function.
 WHEN 'ZFilterSel'.
*== Filter anhand Selektion setzen
 add_filter_selection( ).
 ENDCASE.

 ENDMETHOD. "on_function

 METHOD add_filter_value.

 DATA ls_filter TYPE lvc_s_filt.
 FIELD-SYMBOLS <value> TYPE any.

*== Filterzeile hinzufügen
 ls_filter-fieldname = fieldname.
 ls_filter-sign = 'I'.
 ls_filter-option = 'EQ'.
 ASSIGN COMPONENT fieldname OF STRUCTURE structure TO <value>.
 IF sy-subrc = 0.
 ls_filter-low = <value>.
 SHIFT ls_filter-low LEFT DELETING LEADING space.
 READ TABLE filter WITH KEY fieldname = ls_filter-fieldname
 sign = ls_filter-sign
 option = ls_filter-option
 low = ls_filter-low
 TRANSPORTING NO FIELDS.
 IF sy-subrc > 0.
 APPEND ls_filter TO filter.
 ENDIF.
 ENDIF.

 ENDMETHOD. "add_filter_field

 METHOD add_filter_selection.

*== Lokale Daten
 DATA lt_filter TYPE lvc_t_filt.

 DATA lt_rows TYPE salv_t_row.
 FIELD-SYMBOLS <row> LIKE LINE OF lt_rows..
 DATA lt_cols TYPE salv_t_column.
 FIELD-SYMBOLS <col> LIKE LINE OF lt_cols.
 DATA lr_selection TYPE REF TO cl_salv_selections.

 FIELD-SYMBOLS <table_line> TYPE any.


*== Selektierte Spalten und Zeilen ermitteln
 lr_selection = mr_salv->get_selections( ).
 lt_rows = lr_selection->get_selected_rows( ).
 lt_cols = lr_selection->get_selected_columns( ).

*== Filter anhand der aktuellen Selektion setzen
 LOOP AT lt_rows ASSIGNING <row>.
 IF sy-subrc = 0.
 READ TABLE mt_data ASSIGNING <table_line> INDEX <row>.
 IF sy-subrc = 0.
 LOOP AT lt_cols ASSIGNING <col>.
 add_filter_value( EXPORTING structure = <table_line> fieldname = <col>
 CHANGING filter = lt_filter ).

 ENDLOOP.
 ENDIF.
 ENDIF.
 ENDLOOP.

*== Filter setzen
 set_filter( filter = lt_filter ).

 ENDMETHOD. "add_filter_selection

 METHOD set_filter.

*== Filter auf SAL-Table anwenden
 DATA lv_index TYPE i.
 DATA lr_display TYPE REF TO cl_salv_display_settings.
 DATA lv_title TYPE lvc_title.
 FIELD-SYMBOLS <filter> TYPE lvc_s_filt.

 cl_salv_controller_metadata=>set_lvc_filter( t_filter = filter
 r_filters = mr_salv->get_filters( ) ).
 lr_display = mr_salv->get_display_settings( ).

 LOOP AT filter ASSIGNING <filter>.
 IF lv_title IS INITIAL.
 lv_title = <filter>-fieldname.
 ELSE.
 CONCATENATE '/' <filter>-fieldname INTO lv_title.
 ENDIF.
 ENDLOOP.

 CONCATENATE 'Filter ist aktiv (' lv_title ')' INTO lv_title .

 lr_display->set_list_header( lv_title ).

 mr_salv->refresh( ).
 ENDMETHOD. "set_filter

ENDCLASS. "lcl_grid IMPLEMENTATION

AT SELECTION-SCREEN.

 lcl_grid=>start( ).

 

Enno Wulff