ALV-Grid, F4-Hilfe und Protokollanzeige

Bei einer Anforderung mit einem eingabebereiten ALV-Grid bin ich auf ein Problem bei der Verarbeitung von fehlerhaften Einträgen gestoßen. Aufgabe war, dass in einem bestimmten Feld nur bestimmte Werte zugelassen sind. Es sind zwar mehr Werte vorhanden, aber es dürfen nur bestimmte Werte eingetragen werden. Ähnlich wie bei einer Materialnummer: Es sind viele Materialnummern vorhanden, aber es dürfen nur Materialnummern mit bestimmten Eigenschaften verwendet werden.

Dafür gibt es das ALV-Grid Ereignis “DATA_CHANGED”. Hier werden die Eingaben geprüft und wenn die Eingabe nicht korrekt ist, kann man mit ER_DATA_CHANGED->ADD_PROTOCOL_ENTRY eine entsprechende Meldung ausgeben. Diesen Protokoll-Eintrag kann man für verschiedene Felder in verschiedenen Zeilen machen. Am Ende der Bearbeitung werden alle Fehler in einem Protokollfenster angezeigt.

Diese Prüfung hatte ich erfolgreich eingebaut. Das Feld hat jedoch auch eine F4-Hilfe in der ich in den Selektionsoptionen der Suchhilfe eine Einschränkung vorgegeben habe. Der Anwender bekommt also in der Suchhilfe nur valide Einträge angezeigt. Allerdings kann es sein, dass es zu der Einschränkung keine Einträge gibt und der Anwender einen anderen Wert auswählt. Dieser wird korrekt übertragen und in DATA_CHANGED geprüft, wie alle anderen Eingaben auch.

Aaaaaber: das Protokoll wurde nicht ausgegeben, wenn der per F4 gewählte Wert nicht korrekt war.

Nach einiger Recherche und Prüfungen, ob ich nicht etwas falsch programmiert hatte, bin ich auf eine Lösung gekommen, die gut funktioniert: Im Ereignis DATA_CHANGED gibt es den Parameter E_ONF4. Dieser hat den Wert “A”, wenn das Ereignis nach der Wertauswahl mittels Suchhilfe aufgerufen wurde. In diesem Fall muss man die Methode ER_DATA_CHANGED->DISPLAY_PROTOCOL manuell aufrufen. Dann wird der Fehler angezeigt.

Hier das komplette Beispiel-Coding, mit dem du das Verhalten nachstellen kannst:

Coding

Code bei Github: https://github.com/tricktresor/ALV_GRID_F4_PROT

Powered by abapGit

REPORT zt9r_alv_grid_f4_protocol.

PARAMETERS test.


CLASS appl DEFINITION.
  PUBLIC SECTION.
    METHODS start IMPORTING container TYPE REF TO cl_gui_container.
  PRIVATE SECTION.
    DATA grid TYPE REF TO cl_gui_alv_grid.
    TYPES: BEGIN OF ts_data,
             id TYPE c LENGTH 10,
           END OF ts_data,
           tt_data TYPE STANDARD TABLE OF ts_data WITH DEFAULT KEY.
    DATA data TYPE tt_data.
    METHODS get_fcat RETURNING VALUE(result) TYPE lvc_t_fcat.
    METHODS on_data_changed FOR EVENT data_changed OF cl_gui_alv_grid
      IMPORTING
        e_onf4
        e_onf4_after
        e_onf4_before
        e_ucomm
        er_data_changed.
    METHODS on_f4 FOR EVENT onf4 OF cl_gui_alv_grid
      IMPORTING
        e_display
        e_fieldname
        e_fieldvalue
        er_event_data
        es_row_no
        et_bad_cells.
ENDCLASS.

CLASS appl IMPLEMENTATION.
  METHOD start.

    grid = NEW #( i_parent = container ).
    DATA(lt_fcat) = get_fcat( ).
    data = VALUE #( ( ) ).
    grid->set_table_for_first_display(
      CHANGING
        it_outtab                     = data
        it_fieldcatalog               = lt_fcat
      EXCEPTIONS
        OTHERS                        = 1  ).
    grid->register_edit_event( cl_gui_alv_grid=>mc_evt_modified ).
    grid->set_ready_for_input( 1 ).
    grid->register_f4_for_fields( VALUE #( ( fieldname = 'ID' register = abap_true ) )  ).
    SET HANDLER on_data_changed FOR grid.
    SET HANDLER on_f4 FOR grid.

    cl_gui_container=>set_focus( grid ).

  ENDMETHOD.

  METHOD get_fcat.

    result = VALUE #(
      ( fieldname  = 'ID'
        inttype    = 'C'
        rollname   = 'CHAR10'
        edit       = abap_true
        f4availabl = abap_true
        datatype   = 'CHAR'
        reptext    = 'DEMO' ) ).

  ENDMETHOD.

  METHOD on_data_changed.
    LOOP AT er_data_changed->mt_good_cells ASSIGNING FIELD-SYMBOL(<cell>).
      CASE <cell>-fieldname.
        WHEN 'ID'.
          IF <cell>-value = 'WRONG'.
            er_data_changed->add_protocol_entry(
                i_msgid     = 'OO'
                i_msgty     = 'E'
                i_msgno     = '000'
                i_msgv1     = 'Input is wrong!'
                i_fieldname = <cell>-fieldname
                i_row_id    = <cell>-row_id
                i_tabix     = <cell>-tabix ).
            IF e_onf4 = 'A'.
              er_data_changed->display_protocol( ).
            ENDIF.
          ENDIF.
      ENDCASE.
    ENDLOOP.
  ENDMETHOD.

  METHOD on_f4.

    DATA answer TYPE c LENGTH 1.

    CALL FUNCTION 'POPUP_TO_DECIDE'
      EXPORTING
        defaultoption     = '1'          " Cursor position on first or second alternative
        textline1         = 'Please choose'
        text_option1      = 'OKAY'
        text_option2      = 'WRONG'
        icon_text_option1 = 'OKAY'
        icon_text_option2 = 'WRONG'
        titel             = 'Demo'
        start_column      = 25           " Start column of the dialog box
        start_row         = 6            " Start line of the dialog box
        cancel_display    = 'X'
      IMPORTING
        answer            = answer.
    IF answer = 'A'.
      RETURN.
    ENDIF.

    FIELD-SYMBOLS <mod_values> TYPE lvc_t_modi.
    ASSIGN er_event_data->m_data->* TO <mod_values>.
    <mod_values> = VALUE lvc_t_modi(
         ( row_id    = es_row_no-row_id
           fieldname = e_fieldname
           value     = SWITCH #( answer WHEN '1' THEN 'OKAY' ELSE 'WRONG' ) ) ).

    er_event_data->m_event_handled = abap_true.

  ENDMETHOD.
ENDCLASS.

INITIALIZATION.
  DATA(docker) = NEW cl_gui_docking_container( side = cl_gui_docking_container=>dock_at_bottom ratio = 90 ).
  NEW appl( )->start( docker ).

Enno Wulff