Build ALV fieldcat from any structure¶
Use RTTI to generate a complete
SLIS_T_FIELDCAT_ALVautomatically — no hard-coded column definitions.
Purpose¶
Hand-coding a field catalog for every ALV report is tedious and brittle: adding a field to the structure means editing the catalog too. This pattern introspects the structure at runtime using RTTI (CL_ABAP_STRUCTDESCR) and builds the full field catalog — column labels, output lengths, DDIC texts — in a single reusable function module call.
Because the catalog is derived from the actual ABAP dictionary type, column headers come from the DDIC short/medium/long texts automatically. The caller passes any flat structure (work area of the internal table they want to display) and gets back a ready-to-use field catalog.
Signature¶
| Parameter | Direction | Type | Notes |
|---|---|---|---|
I_STRUC |
IMPORTING | ANY (pass by reference) |
A work area typed like the internal table you will display. |
I_TABNAME |
IMPORTING | CHAR50 (optional) |
Written into TABNAME of every catalog entry. Needed for F4 help on some ALV variants. |
E_FCAT |
EXPORTING | SLIS_T_FIELDCAT_ALV |
The generated field catalog, ready to pass to REUSE_ALV_GRID_DISPLAY. |
How it works¶
The function module walks through four RTTI calls:
CL_ABAP_STRUCTDESCR=>describe_by_data_ref— obtain a structure descriptor from a data reference.componentsgives you every field name and its raw byte length.lcl_descr->get_component_type— retrieve the type descriptor for a single component by name.lcl_typedescr->get_relative_name— get the DDIC type name (e.g.MATNR,MENGE) as a string so it can be resolved.CL_ABAP_ELEMDESCR=>describe_by_name+get_ddic_field— fetch the fullDFIESrecord, which carriesscrtext_s/m/l,reptext, andoutputlenfrom the DDIC.
The resulting DFIES data is mapped into a SLIS_FIELDCAT_ALV entry via MOVE-CORRESPONDING, then the text fields and position are set explicitly.
Full implementation¶
FUNCTION z_build_fieldcat_from_struct.
*"----------------------------------------------------------------------
*" IMPORTING
*" REFERENCE(I_STRUC) TYPE ANY
*" REFERENCE(I_TABNAME) TYPE CHAR50 OPTIONAL
*" EXPORTING
*" REFERENCE(E_FCAT) TYPE SLIS_T_FIELDCAT_ALV
*"----------------------------------------------------------------------
DATA: lv_pos TYPE i,
lw_dfies TYPE dfies,
lt_fieldcat TYPE slis_t_fieldcat_alv,
lv_name TYPE string.
FIELD-SYMBOLS: <l_fcat> LIKE LINE OF lt_fieldcat,
<l_comp> TYPE abap_compdescr.
DATA: lo_struct TYPE REF TO cl_abap_structdescr,
lo_elem TYPE REF TO cl_abap_elemdescr,
lo_type TYPE REF TO cl_abap_typedescr,
lo_ref TYPE REF TO data.
GET REFERENCE OF i_struc INTO lo_ref.
lo_struct ?= cl_abap_structdescr=>describe_by_data_ref( lo_ref ).
LOOP AT lo_struct->components ASSIGNING <l_comp>.
lo_struct->get_component_type(
EXPORTING p_name = <l_comp>-name
RECEIVING p_descr_ref = lo_type
EXCEPTIONS OTHERS = 1 ).
IF sy-subrc <> 0.
EXIT.
ENDIF.
lo_type->get_relative_name(
RECEIVING p_relative_name = lv_name ).
lo_elem ?= cl_abap_typedescr=>describe_by_name( lv_name ).
lo_elem->get_ddic_field(
EXPORTING p_langu = sy-langu
RECEIVING p_flddescr = lw_dfies
EXCEPTIONS OTHERS = 3 ).
APPEND INITIAL LINE TO lt_fieldcat ASSIGNING <l_fcat>.
ADD 1 TO lv_pos.
MOVE-CORRESPONDING lw_dfies TO <l_fcat>.
<l_fcat>-fieldname = <l_comp>-name.
<l_fcat>-outputlen = <l_comp>-length.
<l_fcat>-ddic_outputlen = lw_dfies-outputlen.
<l_fcat>-seltext_s = lw_dfies-scrtext_s.
<l_fcat>-seltext_m = lw_dfies-scrtext_m.
<l_fcat>-seltext_l = lw_dfies-scrtext_l.
<l_fcat>-reptext_ddic = lw_dfies-reptext.
<l_fcat>-col_pos = lv_pos.
<l_fcat>-tabname = i_tabname.
ENDLOOP.
e_fcat[] = lt_fieldcat.
ENDFUNCTION.
Example — display MARA with auto-generated catalog¶
REPORT z_demo_dynamic_alv.
DATA: lt_mara TYPE STANDARD TABLE OF mara,
ls_mara TYPE mara,
lt_fcat TYPE slis_t_fieldcat_alv.
START-OF-SELECTION.
SELECT * FROM mara INTO TABLE lt_mara UP TO 50 ROWS.
" Pass a work area typed like the table — the FM inspects it at runtime
CALL FUNCTION 'Z_BUILD_FIELDCAT_FROM_STRUCT'
EXPORTING
i_struc = ls_mara
i_tabname = 'MARA'
IMPORTING
e_fcat = lt_fcat.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
it_fieldcat = lt_fcat
TABLES
t_outtab = lt_mara
EXCEPTIONS
OTHERS = 1.
Common pitfalls¶
Non-DDIC fields are skipped silently
get_ddic_field raises no_ddic_type for local types (e.g. a CHAR10 field defined inline with TYPES rather than as a DDIC data element). The current implementation does not raise an exception in that case — the field still appears in the catalog but with no label text. Add explicit label assignment for any local-type fields, or exclude them.
Nested structures are not flattened
If your work area contains a nested structure (e.g. INCLUDE TYPE address_line), components returns the nested component as a single entry whose type is CL_ABAP_STRUCTDESCR, not CL_ABAP_ELEMDESCR. The ?= cast to lo_elem will throw CX_SY_MOVE_CAST_ERROR. Either flatten the structure before passing it in, or add a type check (lo_type->kind = cl_abap_typedescr=>kind_elem) before casting.
Works best with pure DDIC types
The richest output (correct output lengths, all label variants, currency/quantity reference fields) comes from structures built entirely from DDIC data elements. Structures that mix DDIC types with locally-defined ones will have partial metadata.
- Column order matches the field order in the structure, controlled by
lv_pos. Reorder the structure or adjustcol_posafterwards if a different display order is needed. CL_SALV_TABLEalternative: if you switch toCL_SALV_TABLEinstead ofREUSE_ALV_GRID_DISPLAY, the catalog is not needed —factorybuilds its own column list automatically. This function module is specifically for the classic FM-based ALV.
See also¶
REUSE_ALV_GRID_DISPLAY— the classic ALV display FM that consumes the field catalogCL_SALV_TABLE— the modern OO ALV that does not need a field catalogCL_ABAP_STRUCTDESCR— SAP ABAP RTTI documentation