ABAP – Grouping fields in field catalog

SAPIn some cases you find a report with ALV output where there are maybe hundreds of fields available to be displayed. This can be VERY confusing for the user when he tries to select just few fields he wants to display but all fields are listed in one HUGE list together.

This example shows how to group fields that can be separated with some logic, e.g. fields from MARA, fields from MARC, fields from MARD, …

When you create such groups, user can make a pre-selection by selecting the GROUP and then only fields belonging to that specific group are being offered for selection in ALV FILTER or LAYOUT change.

Let’s take a look at how such code might look like

First we define our global data and their types

TYPES:
* Type definition for an ALV line
  BEGIN OF ts_data,
    mara TYPE mara,
    marc TYPE marc,
    mard TYPE mard,
  END OF ts_data,

* ALV lines table type definition
  tt_data TYPE TABLE OF ts_data.

DATA:
  gt_data       TYPE tt_data,     "ALV data
  gt_fcat       TYPE lvc_t_fcat,  "ALV Field Calatog
  gt_alv_groups TYPE lvc_t_sgrp,  "ALV Field Groups
  go_grid       TYPE REF TO cl_gui_alv_grid,
  go_container  TYPE REF TO cl_gui_custom_container.

Now we add the core functionality – we assume there is a screen 0100 created with custom control called GO_CONTAINER

START-OF-SELECTION.
  PERFORM load_data CHANGING gt_data.

  PERFORM build_fcat CHANGING gt_fcat
                              gt_alv_groups.
  CALL SCREEN 100.

* This is the only PBO module of screen 0100
MODULE 0100_pbo OUTPUT.
  PERFORM display_alv.
ENDMODULE.

We load data from MARA (up to 10 entries) and all their corresponding sub-entries from tables MARC and MARD.

* Load data from MARA-MARC-MARD for up to 10 materials
FORM load_data CHANGING ct_data TYPE tt_data.
  DATA:
    lt_mara TYPE TABLE OF mara,
    lt_marc TYPE TABLE OF marc,
    lt_mard TYPE TABLE OF mard,
    ls_data TYPE ts_data.

  SELECT *
    FROM mara
    INTO TABLE lt_mara
    UP TO 10 ROWS.

  SELECT *
    FROM marc
    INTO TABLE lt_marc
    FOR ALL ENTRIES IN lt_mara
    WHERE matnr = lt_mara-matnr.

  SELECT *
    FROM mard
    INTO TABLE lt_mard
    FOR ALL ENTRIES IN lt_marc
    WHERE matnr = lt_marc-matnr
      AND werks = lt_marc-werks.

  LOOP AT lt_mara ASSIGNING FIELD-SYMBOL(<ls_mara>).
    CLEAR ls_data.
    ls_data-mara = <ls_mara>.

    READ TABLE lt_marc 
      TRANSPORTING NO FIELDS 
      WITH KEY matnr = <ls_mara>-matnr.
    IF sy-subrc <> 0.
      APPEND ls_data TO ct_data.
    ELSE.

      LOOP AT lt_marc ASSIGNING FIELD-SYMBOL(<ls_marc>)
        WHERE matnr = <ls_mara>-matnr.

        ls_data-marc = <ls_marc>.

        READ TABLE lt_mard 
          TRANSPORTING NO FIELDS 
          WITH KEY matnr = <ls_mara>-matnr 
                   werks = <ls_marc>-werks.
        IF sy-subrc <> 0.
          APPEND ls_data TO ct_data.
        ELSE.

          LOOP AT lt_mard ASSIGNING FIELD-SYMBOL(<ls_mard>)
            WHERE matnr = <ls_mara>-matnr 
              AND werks = <ls_marc>-werks.

            ls_data-mard = <ls_mard>.
            APPEND ls_data TO ct_data.

          ENDLOOP.
        ENDIF.
      ENDLOOP.
    ENDIF.
  ENDLOOP.
ENDFORM.

Here comes the interesting part – building field catalog where we specify the Field-Groups

* Generate field catalog automatically for the 3 given tables
* Also group their fields
FORM build_fcat CHANGING ct_fcat       TYPE lvc_t_fcat
                         ct_alv_groups TYPE lvc_t_sgrp.
  PERFORM append_table_2_fcat USING 'MARA' 'A' CHANGING ct_fcat ct_alv_groups.
  PERFORM append_table_2_fcat USING 'MARC' 'C' CHANGING ct_fcat ct_alv_groups.
  PERFORM append_table_2_fcat USING 'MARD' 'D' CHANGING ct_fcat ct_alv_groups.
ENDFORM.

FORM append_table_2_fcat USING iv_tabname
                               iv_groupname
                         CHANGING ct_fcat   TYPE lvc_t_fcat
                                  ct_groups TYPE lvc_t_sgrp.
  DATA:
    lv_structure_name TYPE dd02l-tabname,
    lt_fcat           TYPE lvc_t_fcat.

  FIELD-SYMBOLS:
    <ls_fcat>  LIKE LINE OF ct_fcat,
    <ls_group> LIKE LINE OF ct_groups.

* Create new group of fields if it does not exist yet
  READ TABLE ct_groups 
    TRANSPORTING NO FIELDS 
    WITH KEY sp_group = iv_groupname.
  IF sy-subrc <> 0.
    APPEND INITIAL LINE TO ct_groups ASSIGNING .
    <ls_group>-sp_group = iv_groupname.
    <ls_group>-text     = iv_tabname.
  ENDIF.

* Generate field catalog entries for given table name
  lv_structure_name = iv_tabname.
  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name       = lv_structure_name
      i_client_never_display = 'X'
      i_bypassing_buffer     = 'X'
    CHANGING
      ct_fieldcat            = lt_fcat
    EXCEPTIONS
      inconsistent_interface = 1
      program_error          = 2
      OTHERS                 = 3.
  CHECK sy-subrc = 0.

* Modify the field catalog to match our data structure
  LOOP AT lt_fcat ASSIGNING <ls_fcat>.
    <ls_fcat>-ref_field = <ls_fcat>-fieldname.
    <ls_fcat>-ref_table = iv_tabname.

    <ls_fcat>-tabname   = 'GT_DATA'.
    <ls_fcat>-fieldname = |{ iv_tabname }-{ <ls_fcat>-fieldname }|.

**********************************************************************
* THIS IS THE IMPORTANT PART
    <ls_fcat>-sp_group  = iv_groupname.
**********************************************************************

*   Show only first 50 columns
    IF lines( ct_fcat ) >= 50.
      <ls_fcat>-no_out = abap_true.
    ENDIF.

    APPEND <ls_fcat> TO ct_fcat.
  ENDLOOP.
ENDFORM.

Now we just have to display data

FORM display_alv.
  IF go_container IS INITIAL.
    CREATE OBJECT go_container
      EXPORTING
        container_name = 'GO_CONTAINER'.

    CREATE OBJECT go_grid
      EXPORTING
        i_parent = go_container.

    go_grid->set_table_for_first_display(
      EXPORTING
        it_special_groups             =    gt_alv_groups
      CHANGING
        it_outtab                     =    gt_data
        it_fieldcatalog               =    gt_fcat " Field Catalog
    ).
  ENDIF.
ENDFORM.

This is the output and if you go to the FILTER or LAYOUT modification, you should be able to filter by the groups you defined:

Filtering fields in LAYOUT change

Filtering fields in FILTER change

Leave a Reply