Skip to Content

When editing an ALV-Grid you can send some messages to the user saying that he entered wrong data. Normally and mostly you will get a popup that displays the errors or warnings.

This looks quite ugly.

Therefore I like to use the possibility to define an extra message container for the grids messages. You can do this by passing a container reference with parameter I_APPLOGPARENT when creating the ALV grid.

    CREATE OBJECT mo_alv
        i_parent       = io_container_grid
        i_applogparent = io_container_prot
        i_appl_events  = 'X'
        OTHERS         = 5.

That looks much nicer:

But then I also wanted to display other messages in this message box that come from other functions but they are important for that grid.

Like: “Please mark a row for executing this function”

First I was struggling because the protocol object used within the ALV grid is PRIVATE *sigh*. So you cannot inherit the CL_GUI_ALV_GRID-class and write a method to access the protcol object MR_DATA_CHANGED.

Then I found two solutions. Both are not perfect but they work:

  1. Use the friends concept for accessing protected and private methods (IF_ALV_RM_GRID_FRIEND) see ABAPblog or Tricktresor (example Autosum)
  2. Create and destroy a separate instance of class CL_ALV_CHANGED_DATA_PROTOCOL

I will show you the second variation which works pretty well.

Before passing a message you will have to create an instance of CL_ALV_CHANGED_DATA_PROTOCOL and passing the container where the protocol should be shown to the object:

mo_prot = NEW #( i_calling_alv = mo_alv i_container = mo_message_container ).

The ALV-grid protocol container and the extra container cannot be shown simultanously. Before using one you will have to destroy the other.

Demo report

The report shows a selection screen and two docking container.

You can enter data in both. But when entering data in the parameter P_TEST you will get an error message in the alv-grid message container.

If you enter values in the KEY field that do not contain A, B or C, you will get an error message created the normal way in grid event DATA_CHANGED:

The disadvantage is that you cannot use both message senders at once. If there are any errors in the grid then the extra messages will not be shown. If you put the checks in a separate method where to pass the protocol object then you could call this method and add your extra messages to the standard alv grid.

The Code

Here is the complete coding (also at github):

REPORT ztrcktrsr_alv_edit_protocol.


      IMPORTING io_container_grid TYPE REF TO cl_gui_container
                io_container_prot TYPE REF TO cl_gui_container.
    CLASS-METHODS set_message
      IMPORTING i_message TYPE clike.

    TYPES: BEGIN OF ts_data,
             key   TYPE char10,
             value TYPE text40,
           END OF ts_data,
           tt_data TYPE STANDARD TABLE OF ts_data WITH DEFAULT KEY.
    CLASS-DATA mo_alv  TYPE REF TO cl_gui_alv_grid.
    CLASS-DATA mo_message_container TYPE REF TO cl_gui_container.
    CLASS-DATA mo_prot TYPE REF TO cl_alv_changed_data_protocol.
    CLASS-DATA mt_data TYPE tt_data.
    CLASS-METHODS handle_data_changed
                  FOR EVENT data_changed  OF  cl_gui_alv_grid
      IMPORTING er_data_changed sender.

ENDCLASS.                    "lcl_events DEFINITION


  METHOD go.

    DATA lt_fcat  TYPE lvc_t_fcat.

    "Make sure alv will be started only once
    CHECK mo_alv IS INITIAL.

    "Remember given container for protocol
    mo_message_container = io_container_prot.

    "create alv-grid
    CREATE OBJECT mo_alv
        i_parent       = io_container_grid
        i_applogparent = io_container_prot
        i_appl_events  = 'X'
        OTHERS         = 5.

    "Register edit event
    mo_alv->register_edit_event( cl_gui_alv_grid=>mc_evt_enter ).

    "enable edit mode
    mo_alv->set_ready_for_input( 1 ).

    "set handler for changing data
    SET HANDLER handle_data_changed FOR mo_alv.

    "Build simple field catalog
    APPEND LINES OF VALUE lvc_t_fcat(
                  ( fieldname = 'KEY'
                    tabname   = 'XX'
                    reptext   = 'Key'
                    datatype  = 'CHAR'
                    inttype   = 'C'
                    outputlen = 10
                    edit      = abap_true )
                  ( fieldname = 'VALUE'
                    tabname   = 'XX'
                    reptext   = 'Value'
                    datatype  = 'CHAR'
                    inttype   = 'C'
                    outputlen = 40
                    lowercase = abap_true
                    edit      = abap_true )
                            ) TO lt_fcat.

    "Make sure user can enter data
    DO 5 TIMES.

    " First Display
        it_fieldcatalog = lt_fcat
        it_outtab       = mt_data
        OTHERS          = 4 ).

    "Set focus on grid so user can immediately enter data in grid
    cl_gui_alv_grid=>set_focus( mo_alv ).


  METHOD set_message.

    IF mo_prot IS INITIAL.
      "create extra protocol
      mo_prot = NEW #( i_calling_alv = mo_alv i_container = mo_message_container ).
      "clear older protocol entries
      mo_prot->refresh_protocol( ).
    "add user message
    mo_prot->add_protocol_entry( i_msgty = 'E'
                                 i_msgno = '000'
                                 i_msgid = 'OO'
                                 i_msgv1 = i_message
                                 i_fieldname = space ).
    "and display
    mo_prot->display_protocol( ).


  METHOD handle_data_changed.

    DATA: ls_good                TYPE lvc_s_modi.

    IF mo_prot IS BOUND.
      "clear extra protocol
      mo_prot->refresh_protocol( ).
      mo_prot->free( ).
      CLEAR mo_prot.

    "Loop at all changed fields
    LOOP AT er_data_changed->mt_good_cells INTO ls_good.
      "Read data table
      READ TABLE mt_data ASSIGNING FIELD-SYMBOL(<data>) INDEX ls_good-row_id.
      IF sy-subrc = 0.
        IF ls_good-fieldname = 'KEY' AND ls_good-value CN 'ABC '.
          "Field does not contain A, B or C - That's bad!
          er_data_changed->add_protocol_entry( i_msgty     = 'E'
                                               i_msgno     = '000'
                                               i_msgid     = 'OO'
                                               i_msgv1     = 'Must be ABC!'
                                               i_fieldname = 'KEY'
                                               i_row_id    = ls_good-row_id ).

        "Change field
        ASSIGN COMPONENT ls_good-fieldname OF STRUCTURE <data> TO FIELD-SYMBOL(<field>).
        IF sy-subrc = 0.
          <field> = ls_good-value.

    "Set focus
    cl_gui_control=>set_focus( mo_alv ).

  ENDMETHOD.                    "handle_data_changed

ENDCLASS.                    "lcl_events IMPLEMENTATION


  DATA(docker_prot) = NEW cl_gui_docking_container( ratio = 20 side = cl_gui_docking_container=>dock_at_bottom ).
  DATA(docker_grid) = NEW cl_gui_docking_container( ratio = 60 side = cl_gui_docking_container=>dock_at_bottom ).
  lcl_demo=>go( io_container_grid = docker_grid
                io_container_prot = docker_prot ).


    "Demo for showing how to use the extra protocol outside alv data handling
    lcl_demo=>set_message( 'Not allowed to enter something in parameter!!' ).
To report this post you need to login first.


You must be Logged on to comment or reply to a post.

  1. Michelle Crapo

    Very nice!!!   I’ve been adding my messages as a field in the table.    Of course the field isn’t long enough and contains very little information.   This will be a nice addition to my development.


    1. Enno Wulff Post author

      Thanks for your comment, Michelle! The advantage of the implemented protocol technique is that you can link a message to one cell. The affected cell will be framed with a red box and double clicking on the message leads you to the assigned cell.

    2. Jelena Perfiljeva

      “Great minds think alike” (or make the same mistakes 🙂 ) – I’ve been handling it the same way, through a column that shows items that need to be corrected.

      Thanks for sharing, Enno Wulff ! Now we just need to rewrite this for 7.3 syntax… 🙂


        1. Michelle Crapo

          Yes, I do have to rewrite it.   My next project that runs into this requirement will be getting a nice message upgrade.

          Still LOVE this blog!


  2. Shai Sinai

    Interesting approach.

    That made we wonder:
    Instead of using both protocol instances simultaneously,
    cannot you use only the protocol of the local/clone of CL_ALV_CHANGED_DATA_PROTOCOL instance?
    (You can suppress the display of standard protocol with method CL_GUI_ALV_GRID->ACTIVATE_DISPLAY_PROTOCOL)

    This way, you may combine all the messages in the same screen.


    1. Enno Wulff Post author

      Thanks for your comment, Shai!

      yes, you might be right! I’ll try this ASAP.

      But I think that the internal functionality will be lost (double clicking on a message sets the focus on the field where the message belongs to).

      Plus: I will have to do all the handling that is now done by cal_gui_alv_grid itself (displaying the protocol if there were errors, clearing the protocol etc).


      But I will gibe it a try next time.

      1. Shai Sinai

        Well, it’s worth a try.

        1. Since CL_ALV_CHANGED_DATA_PROTOCOL clone uses the same CL_GUI_ALV_GRID instance, I don’t see why standard functionality will be lost.
        2. Yes, you are right. You’ll have to call to methods REFRESH_PROTOCOL, DISPLAY_PROTOCOL on handle_data_changed. You’ll also have to add manually all existing messages to the clone instance (LOOP AT mt_protocol … ADD_PROTOCOL_ENTRY … ENDLOOP or something similar).

Leave a Reply