ABAP – ALV with custom F4 field

Here you can find a code snippet about how to enable specific fields of your ALV to be F4 responsive with a custom programmed search help.

The most important are the following methods:

  • GET_ALV_F4_FIELDS (here we define which fields will respond to F4 and how…at which moments)
  • GET_FCAT_4_ITAB (here we define which fields of the ALV will show the F4 icon)
  • ALV_ON_F4 (event handler which pops up a dialog with the search help values)
  • DISPLAY_ALV (here we register the event handler and set the grid be responsive to F4 for specific fields by calling standard method REGISTER_F4_FOR_FIELDS …where we use the result of our method GET_ALV_F4_FIELDS as an input parameter)
REPORT z_mvoy.
CLASS lcl_application DEFINITION CREATE PRIVATE.
  PUBLIC SECTION.
    TYPES:
      BEGIN OF ty_s_alv_line,
        matnr TYPE mara-matnr,
        werks TYPE marc-werks,
        kdmat TYPE knmt-kdmat,
      END OF ty_s_alv_line,

      ty_t_alv_lines TYPE STANDARD TABLE OF ty_s_alv_line WITH DEFAULT KEY.

    CLASS-DATA:
      BEGIN OF gs_screen,
        okcode TYPE sy-ucomm,
      END OF gs_screen.


    CLASS-METHODS:
      pai,
      pbo.

  PRIVATE SECTION.
    DATA:
      mt_alv_data  TYPE ty_t_alv_lines,

      mo_container TYPE REF TO cl_gui_docking_container,
      mo_grid      TYPE REF TO cl_gui_alv_grid.

    METHODS:
      constructor,
      get_data,
      display_alv,
      get_alv_f4_fields RETURNING VALUE(rt_f4) TYPE lvc_t_f4,
      get_fcat_4_itab IMPORTING it_table       TYPE ANY TABLE
                      RETURNING VALUE(rt_fcat) TYPE lvc_t_fcat,
      get_alv_excl_funcs RETURNING VALUE(rt_excludes) TYPE ui_functions,

*      alv_hotspot      FOR EVENT hotspot_click OF cl_gui_alv_grid
*        IMPORTING
*            e_row_id  "Type LVC_S_ROW
*            e_column_id  "Type LVC_S_COL
*            es_row_no,  "Type LVC_S_ROID,
*
*      alv_data_changed FOR EVENT data_changed  OF cl_gui_alv_grid
*        IMPORTING
*            er_data_changed "Type Ref To  CL_ALV_CHANGED_DATA_PROTOCOL
*            e_onf4  "Type CHAR01
*            e_onf4_before  "Type CHAR01
*            e_onf4_after  "Type CHAR01
*            e_ucomm,  "Type sy-uCOMM.
      alv_on_f4 FOR EVENT onf4 OF cl_gui_alv_grid
        IMPORTING e_fieldname
                    es_row_no
                    er_event_data
                    et_bad_cells
                    e_display.

    CLASS-METHODS:
      get_instance RETURNING VALUE(ro_instance) TYPE REF TO lcl_application.

    CLASS-DATA:
      mo_instance TYPE REF TO lcl_application.
ENDCLASS.

*----------------------------------------------------------------------*
***INCLUDE LYVVA_PRICINGP01.
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&       Class (Implementation)  WF_DETAILS_HELPER
*&---------------------------------------------------------------------*
*        Text
*----------------------------------------------------------------------*

CLASS lcl_application IMPLEMENTATION.
  METHOD constructor.
    me->get_data( ).
  ENDMETHOD.

  METHOD get_instance.
    IF mo_instance IS INITIAL.
      CREATE OBJECT mo_instance.
    ENDIF.
    ro_instance = mo_instance.
  ENDMETHOD.

  METHOD get_data.
    CLEAR mt_alv_data[].

    SELECT matnr
      INTO CORRESPONDING FIELDS OF TABLE mt_alv_data
      FROM mara UP TO 50 ROWS.
  ENDMETHOD.

  METHOD pai.
    DATA:
      lv_answer   TYPE c.

    CASE lcl_application=>gs_screen-okcode.
      WHEN 'BACK' OR 'EXIT' OR 'CANCEL'.
        CALL FUNCTION 'POPUP_TO_CONFIRM'
          EXPORTING
            text_question         = |{ 'Do you really want to cancel saving changes?'(q01) }|
            display_cancel_button = ' '
          IMPORTING
            answer                = lv_answer.
        IF lv_answer = 1.
          LEAVE TO SCREEN 0.
        ENDIF.
    ENDCASE.
  ENDMETHOD.

  METHOD pbo.
    SET PF-STATUS 'STATUS0100'.
    SET TITLEBAR  'TITLE0100'.

    DATA(lo_instance) = get_instance( ).

    lo_instance->display_alv( ).

  ENDMETHOD.

  METHOD get_alv_excl_funcs.
    """""""""""""""""""""""""""""""""""""""""""""""""
    " hide these all the time                       "
    """""""""""""""""""""""""""""""""""""""""""""""""
    APPEND cl_gui_alv_grid=>mc_fc_loc_delete_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_append_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_graph TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_sum TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_subtot TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_info TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_check TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_detail TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_average TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_insert_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_move_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_paste TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_paste_new_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_undo TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_copy TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_copy_row TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_loc_cut TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_refresh TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_views TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_print TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_word_processor TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_to_office TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_send TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_html TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_expmdb TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_to_rep_tree TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_view_excel TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_maximum TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_minimum TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_expcrdata TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_pc_file TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_abc TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_master_data TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_more TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_xint TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_report TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_xml_export TO rt_excludes.
    APPEND cl_gui_alv_grid=>mc_fc_call_xxl TO rt_excludes.
  ENDMETHOD.

  METHOD get_alv_f4_fields.
    DATA:
      ls_f4 LIKE LINE OF rt_f4.
*  Register the field for which the custom F4 has to be displayed
*    (note: chngeafter set to 'X' only if any other field value has to be set based
*    on the selected f4 value)
    ls_f4-fieldname  = 'WERKS'.
    ls_f4-register   = 'X'.
    ls_f4-getbefore  = space.
    ls_f4-chngeafter = space.
    APPEND ls_f4 TO rt_f4.
  ENDMETHOD.

  METHOD get_fcat_4_itab.
    DATA:
      lo_columns      TYPE REF TO cl_salv_columns_table,
      lo_aggregations TYPE REF TO cl_salv_aggregations,
      lo_salv_table   TYPE REF TO cl_salv_table,
      lr_table        TYPE REF TO data.
    FIELD-SYMBOLS:
      <table>         TYPE STANDARD TABLE.
* create unprotected table from import data
    CREATE DATA lr_table LIKE it_table.
    ASSIGN lr_table->* TO <table>.
*...New ALV Instance ...............................................
    TRY.
        cl_salv_table=>factory(
          EXPORTING
            list_display = abap_false
          IMPORTING
            r_salv_table = lo_salv_table
          CHANGING
            t_table      = <table> ).
      CATCH cx_salv_msg.                                "#EC NO_HANDLER
    ENDTRY.
    lo_columns  = lo_salv_table->get_columns( ).
    lo_aggregations = lo_salv_table->get_aggregations( ).
    rt_fcat =
      cl_salv_controller_metadata=>get_lvc_fieldcatalog(
        r_columns             = lo_columns
        r_aggregations        = lo_aggregations ).

    LOOP AT rt_fcat ASSIGNING FIELD-SYMBOL(<ls_fcat>).
      CASE <ls_fcat>-fieldname.
        WHEN 'WERKS'.
          <ls_fcat>-edit       = 'X'.
          <ls_fcat>-f4availabl = 'X'.

        WHEN OTHERS.
*          ?
      ENDCASE.
    ENDLOOP.
  ENDMETHOD.

  METHOD alv_on_f4.
    TYPES:
      BEGIN OF ty_s_marc,
        werks TYPE marc-werks,
        pstat TYPE marc-pstat,
      END OF ty_s_marc,

      ty_t_marc TYPE TABLE OF ty_s_marc.


    DATA:
      lt_marc TYPE ty_t_marc,
      ls_modi TYPE lvc_s_modi,
      lt_ret  TYPE TABLE OF ddshretval.
    FIELD-SYMBOLS:
      <lt_itab> TYPE lvc_t_modi.

    CHECK e_fieldname = 'WERKS'.

    DATA(ls_line) = mt_alv_data[ es_row_no-row_id ].

    SELECT *
      INTO CORRESPONDING FIELDS OF TABLE lt_marc
      FROM marc
      WHERE matnr = ls_line-matnr.

    CHECK lt_marc IS NOT INITIAL.

*Call the function module to display the custom F4 values
    CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
      EXPORTING
        retfield        = 'WERKS'
        window_title    = 'Avaliable plants for material'
        value_org       = 'S'
      TABLES
        value_tab       = lt_marc[]
        return_tab      = lt_ret[]
      EXCEPTIONS
        parameter_error = 1
        no_values_found = 2
        OTHERS          = 3.
* (note: gt_ret[] contains the row id selected by the user from the list of f4 values)
    IF sy-subrc = 0 AND lt_ret IS NOT INITIAL.
      READ TABLE lt_ret ASSIGNING FIELD-SYMBOL(<ls_ret>) INDEX 1.

      ASSIGN er_event_data->m_data->* TO <lt_itab>.

      ls_modi-row_id   = es_row_no-row_id.
      ls_modi-fieldname = 'WERKS'.
      ls_modi-value     = <ls_ret>-fieldval.
      APPEND ls_modi TO <lt_itab>.

      er_event_data->m_event_handled = 'X'. "(to inform grid that f4 was handled manually)
    ENDIF.
  ENDMETHOD.

  METHOD display_alv.
    DATA:
      ls_layout  TYPE lvc_s_layo,
      ls_variant TYPE disvariant,
      ls_stable  TYPE lvc_s_stbl.

    IF me->mo_container IS INITIAL.
      CREATE OBJECT mo_container
        EXPORTING
          extension = 10000
          parent    = cl_gui_container=>screen0
          side      = cl_gui_docking_container=>dock_at_left.


      CREATE OBJECT mo_grid
        EXPORTING
          i_parent = mo_container.

      ls_layout-sel_mode   = 'A'.
      ls_layout-no_merging = 'X'.   "No merging of cells
      ls_layout-no_rowmark = 'X'.

*      ALV title
      ls_layout-grid_title = 'Material details'.

      " style field name
*      ls_layout-stylefname = 'STYLE'.
*      ls_layout-ctab_fname = 'CELL_COLORS'.

*     ALV Variant
      ls_variant-report   = sy-repid.
      ls_variant-username = sy-uname.

      DATA(lt_fcat) = me->get_fcat_4_itab( me->mt_alv_data ).

      " get excluded buttons
      DATA(lt_excl_funcs) = me->get_alv_excl_funcs( ).

*      SET HANDLER me->alv_toolbar FOR me->mo_grid.
*      SET HANDLER me->alv_button_click FOR me->mo_grid.
*      SET HANDLER me->alv_user_command FOR me->mo_grid.
*      SET HANDLER me->alv_data_changed FOR me->mo_grid.
*      SET HANDLER me->alv_hotspot      FOR me->mo_grid.
      SET HANDLER me->alv_on_f4        FOR me->mo_grid.

      " be enter reactive
      me->mo_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_enter ).
      " register modified event for toolbar buttons
      me->mo_grid->register_edit_event( i_event_id = cl_gui_alv_grid=>mc_evt_modified ).
      me->mo_grid->register_f4_for_fields(
        it_f4 = me->get_alv_f4_fields( )
      ).

      CALL METHOD me->mo_grid->set_table_for_first_display
        EXPORTING
          is_variant           = ls_variant
          i_save               = 'A'          " U,X,
          i_default            = 'X'          " Layout can be pre-set
          is_layout            = ls_layout    " Default layout
          it_toolbar_excluding = lt_excl_funcs
        CHANGING
          it_outtab            = mt_alv_data[]
          it_fieldcatalog      = lt_fcat.

    ELSE.

*     Keep cursor position by refresh
      ls_stable-row        = 'X'.
      ls_stable-col        = 'X'.

      CALL METHOD mo_grid->refresh_table_display
        EXPORTING
          is_stable = ls_stable
        EXCEPTIONS
          finished  = 1
          OTHERS    = 2.
    ENDIF.
  ENDMETHOD.

ENDCLASS.               "WF_DETAILS_HELPER


END-OF-SELECTION.

  CALL SCREEN 100.
*&---------------------------------------------------------------------*
*&      Module  0100_PBO  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE 0100_pbo OUTPUT.
  lcl_application=>pbo( ).
ENDMODULE.
*&---------------------------------------------------------------------*
*&      Module  0100_PAI  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE 0100_pai INPUT.
  lcl_application=>pai( ).
ENDMODULE.

Output:

Leave a Reply