In 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: