Skip to content
Skip to content
Menu
SAP ABAP DWIMAN
  • About
SAP ABAP DWIMAN

SAP ABAP Fast Coding With This Template – Editable ALV With Events

By juananda.satria on July 30, 2026July 30, 2026

Bismillah.

This template is need to complete with some action before run.

*&———————————————————————*
*& MANUAL OBJECTS TO CREATE (cannot be generated from source code)
*&———————————————————————*
*& 1. SCREEN 0100 (SE51)
*&    – Attributes : Screen type = Normal, Next screen = 0
*&    – Element list -> add a “Custom Control” named CC_0100_ALV
*&      (resizing: vertical + horizontal = X so the ALV grows)
*&    – OK code field (Element list -> tab “OK”) = OK_CODE
*&    – Flow logic :
*&
*&      PROCESS BEFORE OUTPUT.
*&        MODULE status_0100.
*&        MODULE display_alv_0100.
*&
*&      PROCESS AFTER INPUT.
*&        MODULE exit_0100 AT EXIT-COMMAND.
*&        MODULE user_command_0100.
*&
*& 2. GUI STATUS ‘ST_0100’ (SE41)
*&    – Function keys : BACK (F3), EXIT (Shift+F3), CANC (F12)
*&    – Application toolbar (optional) : SAVE, REFRESH
*&    – Set BACK / EXIT / CANC as type “E” (Exit command)
*&
*& 3. GUI TITLE ‘T_0100’ (SE41) : e.g. “ALV Template – Maintenance”
*&
*& 4. TEXT SYMBOL : TEXT-B01 = “Selection”
*&———————————————————————*

*&---------------------------------------------------------------------*
*& Copyright (c) 2026 <COMPANY NAME>. All rights reserved.
*&
*& This program is the confidential and proprietary information of
*& <COMPANY NAME>. Unauthorized copying, modification, distribution or
*& use of this program, in whole or in part, via any medium, is
*& strictly prohibited without prior written consent.
*&---------------------------------------------------------------------*
*& Program Name : ZR_ALV_TEMPLATE_0100
*& Title        : <SHORT TITLE OF THE PROGRAM>
*& Author       : <YOUR NAME / SAP USER ID>
*& Created On   : <DD.MM.YYYY>
*& Package      : <Z_PACKAGE>
*& Type         : Report (Dynpro + OO ALV Grid)
*&---------------------------------------------------------------------*
*& Description  :
*&   <Describe the business purpose here>
*&   <e.g. Maintain and display XXX data, allow inline editing of the
*&    editable columns and save the changes back to table ZXXX.>
*&
*& Related Objects :
*&   Screen        : 0100
*&   GUI Status    : ST_0100
*&   GUI Title     : T_0100
*&   Custom Control: CC_0100_ALV
*&---------------------------------------------------------------------*
*& CHANGE LOG
*&---------------------------------------------------------------------*
*& No. | Date       | Author          | TR Number   | Description
*&-----|------------|-----------------|-------------|-------------------
*& 001 | DD.MM.YYYY | <NAME>          | <DEVK9xxxxx>| Initial creation
*& 002 |            |                 |             |
*& 003 |            |                 |             |
*&---------------------------------------------------------------------*
REPORT ztemplate.

TYPE-POOLS: icon.

*&---------------------------------------------------------------------*
*& G L O B A L   T Y P E S
*&---------------------------------------------------------------------*
TYPES: BEGIN OF ty_data,
         carrid   TYPE c LENGTH 3,        "editable + custom F4
         connid   TYPE c LENGTH 4,        "hotspot
         fldate   TYPE dats,
         price    TYPE p LENGTH 9 DECIMALS 2, "editable + validation
         currency TYPE waers,
         remark   TYPE c LENGTH 40,       "editable
         locked   TYPE flag,              "row lock flag -> celltab demo
         "--- ALV technical fields -------------------------------------
         celltab  TYPE lvc_t_styl,        "cell level edit control
         rowcolor TYPE c LENGTH 4,        "row color (layout-info_fname)
       END OF ty_data,

       tt_data TYPE STANDARD TABLE OF ty_data WITH NON-UNIQUE DEFAULT KEY.

*&---------------------------------------------------------------------*
*& G L O B A L   D A T A  (dynpro related only)
*&---------------------------------------------------------------------*
DATA: ok_code TYPE sy-ucomm,
      gs_data TYPE ty_data.          "work area for SELECT-OPTIONS only

*&---------------------------------------------------------------------*
*& S E L E C T I O N   S C R E E N
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b01 WITH FRAME TITLE TEXT-b01.
  SELECT-OPTIONS: s_carrid FOR gs_data-carrid.
SELECTION-SCREEN END OF BLOCK b01.

*&---------------------------------------------------------------------*
*& L O C A L   C L A S S   D E F I N I T I O N
*&---------------------------------------------------------------------*
CLASS lcl_app DEFINITION FINAL CREATE PRIVATE.

  PUBLIC SECTION.

    CONSTANTS:
      BEGIN OF c_fcode,
        insert TYPE ui_func VALUE 'ZINS',
        delete TYPE ui_func VALUE 'ZDEL',
        save   TYPE ui_func VALUE 'ZSAV',
        toggle TYPE ui_func VALUE 'ZTGL',
      END OF c_fcode.

    CLASS-METHODS get_instance
      RETURNING VALUE(ro_app) TYPE REF TO lcl_app.

    METHODS:
      load_data,
      "! PBO of screen 0100 - creates container/grid on first call
      pbo_0100,
      "! PAI of screen 0100
      "! @parameter rv_leave | 'X' -> caller must leave the screen
      pai_0100 IMPORTING iv_ok_code      TYPE sy-ucomm
               RETURNING VALUE(rv_leave) TYPE abap_bool,
      "! AT EXIT-COMMAND of screen 0100
      exit_0100 IMPORTING iv_ok_code      TYPE sy-ucomm
                RETURNING VALUE(rv_leave) TYPE abap_bool.

  PRIVATE SECTION.

    CLASS-DATA go_app TYPE REF TO lcl_app.

    DATA:
      mo_container TYPE REF TO cl_gui_custom_container,
      mo_grid      TYPE REF TO cl_gui_alv_grid,
      mt_data      TYPE tt_data,
      mt_fcat      TYPE lvc_t_fcat,
      ms_layout    TYPE lvc_s_layo,
      ms_variant   TYPE disvariant,
      mt_exclude   TYPE ui_functions,
      mv_edit      TYPE abap_bool VALUE abap_true,
      mv_changed   TYPE abap_bool.

    METHODS:
      build_fieldcat,
      build_layout,
      build_exclude,
      set_celltab,
      register_f4,
      display_alv,
      refresh_alv IMPORTING iv_soft TYPE char01 DEFAULT abap_true,
      toggle_edit_mode,
      insert_row,
      delete_selected_rows,
      save_data,
      "&------------------------------------------------------------ *
      "& A L V   E V E N T   H A N D L E R S
      "&------------------------------------------------------------ *
      on_toolbar
        FOR EVENT toolbar OF cl_gui_alv_grid
        IMPORTING e_object e_interactive,

      on_user_command
        FOR EVENT user_command OF cl_gui_alv_grid
        IMPORTING e_ucomm,

      on_hotspot_click
        FOR EVENT hotspot_click OF cl_gui_alv_grid
        IMPORTING e_row_id e_column_id es_row_no,

      on_double_click
        FOR EVENT double_click OF cl_gui_alv_grid
        IMPORTING e_row e_column es_row_no,

      "! Fires per changed cell block - use for validation
      on_data_changed
        FOR EVENT data_changed OF cl_gui_alv_grid
        IMPORTING er_data_changed e_onf4 e_onf4_before e_onf4_after e_ucomm,

      "! Fires once AFTER all changes are applied to the output table
      on_data_changed_finished
        FOR EVENT data_changed_finished OF cl_gui_alv_grid
        IMPORTING e_modified et_good_cells,

      "! Custom search help (F4) inside the editable cell
      on_f4
        FOR EVENT onf4 OF cl_gui_alv_grid
        IMPORTING e_fieldname e_fieldvalue es_row_no er_event_data
                  et_bad_cells e_display.

ENDCLASS.

*&---------------------------------------------------------------------*
*& L O C A L   C L A S S   I M P L E M E N T A T I O N
*&---------------------------------------------------------------------*
CLASS lcl_app IMPLEMENTATION.

*&---------------------------------------------------------------------*
  METHOD get_instance.
    IF go_app IS NOT BOUND.
      go_app = NEW lcl_app( ).
    ENDIF.
    ro_app = go_app.
  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD load_data.
    " Replace the subroutine content with your real SELECT.
    PERFORM f_get_data USING    s_carrid[]
                       CHANGING mt_data.
    set_celltab( ).
  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD pbo_0100.

    IF mo_container IS BOUND.
      " Screen is already built -> only refresh
      refresh_alv( ).
      RETURN.
    ENDIF.

    mo_container = NEW cl_gui_custom_container(
                         container_name = 'CC_0100_ALV' ).

    mo_grid = NEW cl_gui_alv_grid( i_parent = mo_container ).

    build_fieldcat( ).
    build_layout( ).
    build_exclude( ).

    " Register the event handlers of this local class
    SET HANDLER: me->on_toolbar               FOR mo_grid,
                 me->on_user_command          FOR mo_grid,
                 me->on_hotspot_click         FOR mo_grid,
                 me->on_double_click          FOR mo_grid,
                 me->on_data_changed          FOR mo_grid,
                 me->on_data_changed_finished FOR mo_grid,
                 me->on_f4                    FOR mo_grid.

    " When shall DATA_CHANGED be raised?
    "   MC_EVT_ENTER    -> only when ENTER is pressed
    "   MC_EVT_MODIFIED -> whenever a cell is left after modification
    mo_grid->register_edit_event(
      i_event_id = cl_gui_alv_grid=>mc_evt_modified ).

    register_f4( ).
    display_alv( ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD build_fieldcat.

    CLEAR mt_fcat.

    " Built manually so the template has no DDIC dependency.
    " In a real program prefer:
    "   LVC_FIELDCATALOG_MERGE (FM) or CL_SALV_TABLE metadata,
    "   then only overwrite the properties you need.
    mt_fcat = VALUE lvc_t_fcat(
      ( fieldname = 'CARRID'   col_pos = 1  outputlen = 3
        coltext   = 'Airline'  edit = abap_true
        f4availabl = abap_true )                      "enable F4 button
      ( fieldname = 'CONNID'   col_pos = 2  outputlen = 4
        coltext   = 'Conn.'    hotspot = abap_true )   "hotspot column
      ( fieldname = 'FLDATE'   col_pos = 3  outputlen = 10
        coltext   = 'Date' )
      ( fieldname = 'PRICE'    col_pos = 4  outputlen = 15
        coltext   = 'Price'    edit = abap_true
        cfieldname = 'CURRENCY' )
      ( fieldname = 'CURRENCY' col_pos = 5  outputlen = 5
        coltext   = 'Curr.' )
      ( fieldname = 'REMARK'   col_pos = 6  outputlen = 40
        coltext   = 'Remark'   edit = abap_true )
      ( fieldname = 'LOCKED'   col_pos = 7  outputlen = 6
        coltext   = 'Locked'   checkbox = abap_true ) ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD build_layout.

    CLEAR ms_layout.

    " SEL_MODE:
    "   'A' multiple rows + column selection
    "   'B' single row (simple)
    "   'C' multiple rows, no cell selection
    "   'D' cell + multiple row selection  <-- used here
    ms_layout-sel_mode   = 'D'.
    ms_layout-cwidth_opt = abap_true.
    ms_layout-zebra      = abap_true.
    ms_layout-stylefname = 'CELLTAB'.    "cell level edit control
    ms_layout-info_fname = 'ROWCOLOR'.   "row coloring
    ms_layout-grid_title = 'ALV Template - Screen 0100'.

    " Optional: extra checkbox column synchronized with row selection
    " ms_layout-box_fname = 'MARK'.  "requires a FLAG field in ty_data

    " Layout variant (i_save = 'A' -> user + global variants allowed)
    ms_variant-report  = sy-repid.
    ms_variant-handle  = '0100'.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD build_exclude.
    " "SET FUNCTION ALL":
    " CL_GUI_ALV_GRID shows ALL standard functions when
    "   I_DEFAULT = 'X' and IT_TOOLBAR_EXCLUDING is empty.
    " Only fill this table if you really need to hide something, e.g.:
    "   APPEND cl_gui_alv_grid=>mc_fc_graph      TO mt_exclude.
    "   APPEND cl_gui_alv_grid=>mc_fc_info       TO mt_exclude.
    CLEAR mt_exclude.
  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD register_f4.

    DATA lt_f4 TYPE lvc_t_f4.

    lt_f4 = VALUE lvc_t_f4(
      ( fieldname   = 'CARRID'
        register    = abap_true    "raise ONF4 for this field
        getbefore   = abap_true    "supply current cell value
        chngeafter  = abap_true ) )."allow value change afterwards

    mo_grid->register_f4_for_fields( it_f4 = lt_f4 ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD display_alv.

    mo_grid->set_table_for_first_display(
      EXPORTING
        is_variant           = ms_variant
        i_save               = 'A'
        i_default            = abap_true
        is_layout            = ms_layout
        it_toolbar_excluding = mt_exclude
      CHANGING
        it_outtab            = mt_data
        it_fieldcatalog      = mt_fcat
      EXCEPTIONS
        invalid_parameter_combination = 1
        program_error                = 2
        too_many_lines               = 3
        OTHERS                       = 4 ).

    IF sy-subrc <> 0.
      MESSAGE 'Error while building the ALV grid' TYPE 'E'.
    ENDIF.

    " Global edit mode switch (1 = ready for input, 0 = display only)
    mo_grid->set_ready_for_input( i_ready_for_input = COND i( WHEN mv_edit = abap_true
                                                    THEN 1 ELSE 0 ) ).

    " Allow the user to change the toolbar interactively
    mo_grid->set_toolbar_interactive( ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD set_celltab.

    DATA lt_styl TYPE lvc_t_styl.

    LOOP AT mt_data ASSIGNING FIELD-SYMBOL(<ls_data>).

      CLEAR: lt_styl, <ls_data>-celltab, <ls_data>-rowcolor.

      IF <ls_data>-locked = abap_true.
        " Whole row not editable + highlighted
        lt_styl = VALUE lvc_t_styl(
          ( fieldname = 'CARRID' style = cl_gui_alv_grid=>mc_style_disabled )
          ( fieldname = 'PRICE'  style = cl_gui_alv_grid=>mc_style_disabled )
          ( fieldname = 'REMARK' style = cl_gui_alv_grid=>mc_style_disabled ) ).
        <ls_data>-rowcolor = 'C610'.   "C + intensity + inverse
      ELSE.
        lt_styl = VALUE lvc_t_styl(
          ( fieldname = 'CARRID' style = cl_gui_alv_grid=>mc_style_enabled )
          ( fieldname = 'PRICE'  style = cl_gui_alv_grid=>mc_style_enabled )
          ( fieldname = 'REMARK' style = cl_gui_alv_grid=>mc_style_enabled ) ).
      ENDIF.

      <ls_data>-celltab = lt_styl.

    ENDLOOP.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD refresh_alv.

    IF mo_grid IS NOT BOUND.
      RETURN.
    ENDIF.

    mo_grid->refresh_table_display(
      EXPORTING
        is_stable      = VALUE lvc_s_stbl( row = abap_true col = abap_true )
        i_soft_refresh = iv_soft
      EXCEPTIONS
        finished       = 1
        OTHERS         = 2 ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD toggle_edit_mode.

    mv_edit = COND abap_bool( WHEN mv_edit = abap_true
                              THEN abap_false ELSE abap_true ).

    mo_grid->set_ready_for_input( i_ready_for_input = COND i( WHEN mv_edit = abap_true
                                                    THEN 1 ELSE 0 ) ).
    refresh_alv( ).

    MESSAGE |Edit mode: { COND string( WHEN mv_edit = abap_true
                                       THEN 'ON' ELSE 'OFF' ) }| TYPE 'S'.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD insert_row.

    APPEND VALUE ty_data( currency = 'IDR' ) TO mt_data.
    set_celltab( ).
    refresh_alv( iv_soft = abap_false ).
    mv_changed = abap_true.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD delete_selected_rows.

    DATA lt_rows TYPE lvc_t_row.

    " MULTIPLE ROW SELECTION is read here
    mo_grid->get_selected_rows( IMPORTING et_index_rows = lt_rows ).

    IF lt_rows IS INITIAL.
      MESSAGE 'Please select at least one row' TYPE 'S' DISPLAY LIKE 'W'.
      RETURN.
    ENDIF.

    " Delete from the highest index downwards
    SORT lt_rows BY index DESCENDING.
    LOOP AT lt_rows INTO DATA(ls_row).
      DELETE mt_data INDEX ls_row-index.
    ENDLOOP.

    refresh_alv( iv_soft = abap_false ).
    mv_changed = abap_true.
    MESSAGE |{ lines( lt_rows ) } row(s) deleted| TYPE 'S'.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD save_data.

    " IMPORTANT: force the grid to hand over the cells that are still
    " in the frontend buffer. This triggers DATA_CHANGED.
    mo_grid->check_changed_data( IMPORTING e_valid = DATA(lv_valid) ).

    IF lv_valid = abap_false.
      MESSAGE 'Data contains errors - correct them first' TYPE 'S'
              DISPLAY LIKE 'E'.
      RETURN.
    ENDIF.

    PERFORM f_save_data USING mt_data.

    mv_changed = abap_false.
    refresh_alv( ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD pai_0100.

    rv_leave = abap_false.

    CASE iv_ok_code.
      WHEN 'BACK' OR 'EXIT' OR 'CANC'.
        rv_leave = exit_0100( iv_ok_code ).

      WHEN 'SAVE'.                 "function code of the GUI status
        save_data( ).

      WHEN 'REFRESH'.
        load_data( ).
        refresh_alv( iv_soft = abap_false ).

      WHEN OTHERS.
        " ALV toolbar commands are handled in ON_USER_COMMAND
    ENDCASE.

  ENDMETHOD.

*&---------------------------------------------------------------------*
  METHOD exit_0100.

    rv_leave = abap_true.

    IF mv_changed = abap_true AND iv_ok_code <> 'EXIT'.
      DATA(lv_answer) = ``.
      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          titlebar              = 'Unsaved data'
          text_question         = 'Data has been changed. Leave anyway?'
          default_button        = '2'
          display_cancel_button = abap_false
        IMPORTING
          answer                = lv_answer
        EXCEPTIONS
          OTHERS                = 0.
      IF lv_answer <> '1'.
        rv_leave = abap_false.
        RETURN.
      ENDIF.
    ENDIF.

    " Free the controls before leaving the screen
    IF mo_grid IS BOUND.
      mo_grid->free( ).
      CLEAR mo_grid.
    ENDIF.
    IF mo_container IS BOUND.
      mo_container->free( ).
      CLEAR mo_container.
    ENDIF.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: TOOLBAR - add your own buttons
*&---------------------------------------------------------------------*
  METHOD on_toolbar.

    " butn_type: 0 = button, 1 = menu+default, 2 = menu, 3 = separator
    APPEND VALUE stb_button( butn_type = 3 ) TO e_object->mt_toolbar.

    APPEND VALUE stb_button( function  = c_fcode-insert
                             icon      = icon_insert_row
                             quickinfo = 'Insert row'
                             text      = 'Insert'
                             butn_type = 0 ) TO e_object->mt_toolbar.

    APPEND VALUE stb_button( function  = c_fcode-delete
                             icon      = icon_delete_row
                             quickinfo = 'Delete selected rows'
                             text      = 'Delete'
                             butn_type = 0 ) TO e_object->mt_toolbar.

    APPEND VALUE stb_button( function  = c_fcode-save
                             icon      = icon_system_save
                             quickinfo = 'Save changes'
                             text      = 'Save'
                             butn_type = 0 ) TO e_object->mt_toolbar.

    APPEND VALUE stb_button( function  = c_fcode-toggle
                             icon      = icon_toggle_display_change
                             quickinfo = 'Toggle display / change'
                             text      = 'Display<->Change'
                             butn_type = 0 ) TO e_object->mt_toolbar.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: USER_COMMAND - reaction to the buttons added above
*&---------------------------------------------------------------------*
  METHOD on_user_command.

    CASE e_ucomm.
      WHEN c_fcode-insert.
        insert_row( ).
      WHEN c_fcode-delete.
        delete_selected_rows( ).
      WHEN c_fcode-save.
        save_data( ).
      WHEN c_fcode-toggle.
        toggle_edit_mode( ).
      WHEN OTHERS.
        " standard functions are processed by the grid itself
    ENDCASE.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: HOTSPOT_CLICK
*&---------------------------------------------------------------------*
  METHOD on_hotspot_click.

    READ TABLE mt_data INTO DATA(ls_data) INDEX e_row_id-index.
    IF sy-subrc <> 0.
      RETURN.
    ENDIF.

    CASE e_column_id-fieldname.
      WHEN 'CONNID'.
        " Example: jump to another transaction / display detail
        " SET PARAMETER ID 'XXX' FIELD ls_data-connid.
        " CALL TRANSACTION 'XXXX' AND SKIP FIRST SCREEN.
        MESSAGE |Hotspot on { ls_data-carrid } / { ls_data-connid }|
                TYPE 'S'.
      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: DOUBLE_CLICK
*&---------------------------------------------------------------------*
  METHOD on_double_click.

    READ TABLE mt_data INTO DATA(ls_data) INDEX e_row-index.
    IF sy-subrc = 0.
      MESSAGE |Double click row { e_row-index } column { e_column-fieldname }|
              TYPE 'S'.
    ENDIF.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: DATA_CHANGED - validation of the changed cells
*&        er_data_changed->mt_good_cells : successfully typed cells
*&        er_data_changed->mt_mod_cells  : all modified cells
*&---------------------------------------------------------------------*
  METHOD on_data_changed.

    LOOP AT er_data_changed->mt_good_cells INTO DATA(ls_cell).

      CASE ls_cell-fieldname.

        WHEN 'PRICE'.
          " Read the new value in the correct type
          DATA: lv_price TYPE sflight-price.
          er_data_changed->get_cell_value(
            EXPORTING i_row_id    = ls_cell-row_id
                      i_fieldname = ls_cell-fieldname
            IMPORTING e_value     = lv_price ).

          IF lv_price < 0.
            er_data_changed->add_protocol_entry(
              i_msgid     = '00'
              i_msgty     = 'E'
              i_msgno     = '001'
              i_msgv1     = 'Price must not be negative'
              i_fieldname = ls_cell-fieldname
              i_row_id    = ls_cell-row_id ).

            " Reset the cell to zero
            er_data_changed->modify_cell(
              i_row_id    = ls_cell-row_id
              i_fieldname = ls_cell-fieldname
              i_value     = 0 ).
          ENDIF.

        WHEN 'CARRID'.
          DATA: lv_carrid TYPE sflight-carrid.
          er_data_changed->get_cell_value(
            EXPORTING i_row_id    = ls_cell-row_id
                      i_fieldname = ls_cell-fieldname
            IMPORTING e_value     = lv_carrid ).

          TRANSLATE lv_carrid TO UPPER CASE.
          er_data_changed->modify_cell(
            i_row_id    = ls_cell-row_id
            i_fieldname = ls_cell-fieldname
            i_value     = lv_carrid ).

          " Example of a check against a check table:
          " SELECT SINGLE ... IF sy-subrc <> 0 -> add_protocol_entry.

        WHEN OTHERS.
      ENDCASE.

    ENDLOOP.

    " Show the collected messages in an application log popup
    IF er_data_changed->mt_protocol IS NOT INITIAL.
      er_data_changed->display_protocol( ).
    ENDIF.

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: DATA_CHANGED_FINISHED
*&        Raised ONCE after all changes have been written into MT_DATA.
*&        Best place for: recalculation, re-building CELLTAB, refresh.
*&---------------------------------------------------------------------*
  METHOD on_data_changed_finished.

    IF e_modified <> abap_true.
      RETURN.
    ENDIF.

    mv_changed = abap_true.

    " Example: derive dependent fields for every changed row
    LOOP AT et_good_cells INTO DATA(ls_cell).
      READ TABLE mt_data ASSIGNING FIELD-SYMBOL(<ls_data>)
                         INDEX ls_cell-row_id.
      IF sy-subrc = 0 AND <ls_data>-currency IS INITIAL.
        <ls_data>-currency = 'IDR'.
      ENDIF.
    ENDLOOP.

    set_celltab( ).
    refresh_alv( iv_soft = abap_false ).

  ENDMETHOD.

*&---------------------------------------------------------------------*
*& EVENT: ONF4 - custom search help inside the ALV cell
*&---------------------------------------------------------------------*
  METHOD on_f4.

    TYPES: BEGIN OF ty_f4,
             carrid   TYPE c LENGTH 3,
             carrname TYPE c LENGTH 30,
           END OF ty_f4.

    DATA: lt_values TYPE STANDARD TABLE OF ty_f4 WITH EMPTY KEY,
          lt_return TYPE STANDARD TABLE OF ddshretval WITH EMPTY KEY.

    FIELD-SYMBOLS <lt_modi> TYPE lvc_t_modi.

    CASE e_fieldname.

      WHEN 'CARRID'.

        " Fill the value list. In a real program: SELECT from your
        " check table / CDS view / call a search help exit.
        lt_values = VALUE #(
          ( carrid = 'GA' carrname = 'Garuda Indonesia' )
          ( carrid = 'JT' carrname = 'Lion Air' )
          ( carrid = 'QG' carrname = 'Citilink' )
          ( carrid = 'ID' carrname = 'Batik Air' )
          ( carrid = 'SQ' carrname = 'Singapore Airlines' ) ).

        CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
          EXPORTING
            retfield        = 'CARRID'
            value_org       = 'S'
            window_title    = 'Airline Code'
          TABLES
            value_tab       = lt_values
            return_tab      = lt_return
          EXCEPTIONS
            parameter_error = 1
            no_values_found = 2
            OTHERS          = 3.

        IF sy-subrc = 0 AND lt_return IS NOT INITIAL.
          " Hand the chosen value back to the grid
          ASSIGN er_event_data->m_data->* TO <lt_modi>.
          IF <lt_modi> IS ASSIGNED.
            APPEND VALUE lvc_s_modi(
                     row_id    = es_row_no-row_id
                     fieldname = e_fieldname
                     value     = lt_return[ 1 ]-fieldval ) TO <lt_modi>.
          ENDIF.
        ENDIF.

        " Tell the grid that we handled F4 ourselves
        er_event_data->m_event_handled = abap_true.

      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

ENDCLASS.

*&---------------------------------------------------------------------*
*& M A I N
*&---------------------------------------------------------------------*
START-OF-SELECTION.

  lcl_app=>get_instance( )->load_data( ).
  CALL SCREEN 0100.

*&---------------------------------------------------------------------*
*& D Y N P R O   M O D U L E S   -   S C R E E N   0 1 0 0
*&---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.
  SET PF-STATUS 'ST_0100'.
  SET TITLEBAR  'T_0100'.
ENDMODULE.

MODULE display_alv_0100 OUTPUT.
  lcl_app=>get_instance( )->pbo_0100( ).
ENDMODULE.

MODULE user_command_0100 INPUT.
  DATA(lv_ucomm) = ok_code.
  CLEAR ok_code.
  IF lcl_app=>get_instance( )->pai_0100( lv_ucomm ) = abap_true.
    SET SCREEN 0.
    LEAVE SCREEN.
  ENDIF.
ENDMODULE.

MODULE exit_0100 INPUT.
  DATA(lv_exit) = ok_code.
  CLEAR ok_code.
  IF lcl_app=>get_instance( )->exit_0100( lv_exit ) = abap_true.
    SET SCREEN 0.
    LEAVE SCREEN.
  ENDIF.
ENDMODULE.

*&---------------------------------------------------------------------*
*& S U B R O U T I N E S   (optional - data access layer)
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form  F_GET_DATA
*&---------------------------------------------------------------------*
*& Replace the demo data with your own SELECT statement.
*&---------------------------------------------------------------------*
FORM f_get_data USING    it_carrid TYPE ANY TABLE
                CHANGING ct_data   TYPE tt_data.

  CLEAR ct_data.

  " ------------------------------------------------------------------
  " Example of the real implementation:
  "
  " SELECT carrid, connid, fldate, price, currency
  "   FROM sflight
  "   WHERE carrid IN @it_carrid
  "   INTO CORRESPONDING FIELDS OF TABLE @ct_data.
  " ------------------------------------------------------------------

  ct_data = VALUE tt_data(
    ( carrid = 'GA' connid = '0100' fldate = sy-datum
      price = '1250000.00' currency = 'IDR' remark = 'Demo row 1' )
    ( carrid = 'JT' connid = '0200' fldate = sy-datum + 1
      price = '890000.00'  currency = 'IDR' remark = 'Demo row 2' )
    ( carrid = 'QG' connid = '0300' fldate = sy-datum + 2
      price = '760000.00'  currency = 'IDR' remark = 'Locked row'
      locked = abap_true )
    ( carrid = 'SQ' connid = '0400' fldate = sy-datum + 3
      price = '4200000.00' currency = 'IDR' remark = 'Demo row 4' ) ).

  IF it_carrid IS NOT INITIAL.
    DELETE ct_data WHERE carrid NOT IN s_carrid.
  ENDIF.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form  F_SAVE_DATA
*&---------------------------------------------------------------------*
*& Put your update / BAPI / enqueue logic here.
*&---------------------------------------------------------------------*
FORM f_save_data USING it_data TYPE tt_data.

  " ------------------------------------------------------------------
  " 1. ENQUEUE the object
  " 2. MODIFY ztable FROM TABLE lt_db.  (or call a BAPI)
  " 3. COMMIT WORK AND WAIT.
  " 4. DEQUEUE
  " ------------------------------------------------------------------

  MESSAGE |{ lines( it_data ) } record(s) ready to be saved (dummy)|
          TYPE 'S'.

ENDFORM.

*&---------------------------------------------------------------------*
*& MANUAL OBJECTS TO CREATE (cannot be generated from source code)
*&---------------------------------------------------------------------*
*& 1. SCREEN 0100 (SE51)
*&    - Attributes : Screen type = Normal, Next screen = 0
*&    - Element list -> add a "Custom Control" named CC_0100_ALV
*&      (resizing: vertical + horizontal = X so the ALV grows)
*&    - OK code field (Element list -> tab "OK") = OK_CODE
*&    - Flow logic :
*&
*&      PROCESS BEFORE OUTPUT.
*&        MODULE status_0100.
*&        MODULE display_alv_0100.
*&
*&      PROCESS AFTER INPUT.
*&        MODULE exit_0100 AT EXIT-COMMAND.
*&        MODULE user_command_0100.
*&
*& 2. GUI STATUS 'ST_0100' (SE41)
*&    - Function keys : BACK (F3), EXIT (Shift+F3), CANC (F12)
*&    - Application toolbar (optional) : SAVE, REFRESH
*&    - Set BACK / EXIT / CANC as type "E" (Exit command)
*&
*& 3. GUI TITLE 'T_0100' (SE41) : e.g. "ALV Template - Maintenance"
*&
*& 4. TEXT SYMBOL : TEXT-B01 = "Selection"
*&---------------------------------------------------------------------*

Post navigation

SAP ABAP – Generate Fiori URL
SAP ABAP – ALV with Dock Header and Footer

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • SAP ABAP – ALV Dock with Approval 2 Columns
  • SAP ABAP – ALV with Dock Header and Footer
  • SAP ABAP Fast Coding With This Template – Editable ALV With Events
  • SAP ABAP – Generate Fiori URL
  • SAP ABAP – Workflow Agents CDS

Recent Comments

  1. SAP ABAP – Simple Interface FTP Inbound (SAP Consume File From FTP) – SAP ABAP DWIMAN on SAP ABAP – String Encode & Decode BASE64
  2. Upload file – SAP ABAP DWIMAN on F4 Search Help File

Archives

  • August 2026
  • July 2026
  • May 2025
  • August 2024
  • June 2024
  • May 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • May 2023
  • April 2023

Categories

  • Uncategorized
©2026 SAP ABAP DWIMAN | WordPress Theme by SuperbThemes.com