Generic solution for F4 search help in OO ALV grid

Marcel picture Marcel · May 3, 2018 · Viewed 7.3k times · Source

I have an easy to use function module to create an ALV grid for almost any type of table, especially without a DDIC type. Editing is supported as well.

Basically it creates a field catalog by RTTI and instantiates the standard CL_GUI_ALV_GRID class in a fixed internal Dynpro.

The problem: The F4 search help is not working when the column is not part of a DDIC structure or transparent table. The reason is that the standard ALV overwrites the field REF_FIELD in the field catalog if it is empty.

* Excerpt from LVC_FCAT_COMPLETE_NEW in LSLVCF02
if not <ls_fcat>-ref_table is initial
   and <ls_fcat>-ref_field is initial
   and r_fcat_complete eq abap_false.
  <ls_fcat>-ref_field = <ls_fcat>-fieldname.
endif.

But to get the search help for a data element using the function module DD_SHLP_GET_HELPMETHOD (internally used by CL_GUI_ALV_GRID in method F4) TABNAME must contain the data element name and FIELDNAME must be initial.

If I clear REF_FIELD in the debugger after it has been assigned everything works as expected.

I know that the documentation of the field catalog includes the feature to leave out the REF_FIELD name if it is identical to FIELDNAME. But the automatism does not make sense for non DDIC structures.

Any idea how to get rid of this behavior without a modification? Preferably without writing my own F4 invocation routine for each type of search help in the (undocumented) ONF4 event handler.

Unfortunately it is almost impossible to provide a working test case because of the required Dynpro stuff. But I can provide the ABAP part. It assumes the existence of Dynpro 500 with a container control named CC_ALV.

" test table
TYPES: BEGIN OF t_test,
         date  TYPE dats,
         time  TYPE time,
         werks TYPE werks_d,
       END OF t_test.
DATA it_data TYPE STANDARD TABLE OF t_test.
APPEND VALUE #( date = '20180102' time = '123059' werks = '2020' ) TO it_data.

" field catalog
DATA it_fc TYPE lvc_t_fcat.
APPEND VALUE #( fieldname = 'DATE' f4availabl = abap_true ref_table = 'DATS' ) TO it_fc.
APPEND VALUE #( fieldname = 'TIME' f4availabl = abap_true ref_table = 'TIMS' ) TO it_fc.
APPEND VALUE #( fieldname = 'WERKS' f4availabl = abap_true ref_table = 'WERKS_D' ) TO it_fc.

" show ALV
DATA: r_alv       TYPE REF TO cl_gui_alv_grid.
CREATE OBJECT r_parent
  EXPORTING
    container_name = 'CC_ALV'.
CREATE OBJECT r_alv
  EXPORTING
    i_parent = r_parent.
r_alv->set_table_for_first_display(
  EXPORTING is_layout = VALUE #( edit = abap_true )
  CHANGING  it_fieldcatalog = it_fc
            it_outtab = it_data ).
CALL SCREEN 500.

Answer

Marcel picture Marcel · May 3, 2018

I found a solution, although it is somewhat ugly. Better solution are still welcome.

CLASS lcl_alv_util DEFINITION FINAL CREATE PRIVATE.
  PUBLIC SECTION.
    INTERFACES if_alv_rm_grid_friend.
    CLASS-METHODS enable_f4_in_fcat
      IMPORTING r_alv TYPE REF TO cl_gui_alv_grid.
ENDCLASS.
CLASS lcl_alv_util IMPLEMENTATION.
  METHOD enable_f4_in_fcat.
    DATA wa_fc TYPE lvc_s_fcat.
    MODIFY r_alv->m_cl_variant->mt_fieldcatalog FROM wa_fc TRANSPORTING ref_field
      WHERE tabname IS INITIAL AND ref_field IS NOT INITIAL AND ref_table IS NOT INITIAL.
  ENDMETHOD.
ENDCLASS.

The method lcl_alv_util=>enable_f4_in_fcat has to be called after set_table_for_first_display and before the Dynpro is invoked by CALL SCREEN. Furthermore you need to ensure that the field TABNAME is filled for all members of a DDIC structures because this is used to distinguish between DDIC based and not DDIC based structure fields.

Alternatively you might call enable_f4_in_fcat only if you have a local line type. But this will not cover the case when some of the columns are part of DDIC structure where the standard implementation actually works, i.e. when the local type refers to a DDIC structure by INCLUDE TYPE or nested.

In fact I simply clear REF_FIELD if there is no TABNAME supplied. Because REF_FIELD is only read when F4 is actually pressed, doing this after set_table_for_first_display is sufficient. But the hack with if_alv_rm_grid_friend to access the private field m_cl_variant has some bad aftertaste.