Manual Field Catalog + Report Events (Program 2)

Manual Field Catalog and Report Events (Program 2)
ABAP Reports Series · Blog 6 of 15

Manual Field Catalog and Report Events (Program 2)

Beginner to intermediate · 16 min read · Needs Blog 5

1. Why a manual field catalog?

In Blog 5, ALV built the field catalog from a dictionary structure. That is quick, but it has limits. You need a manual catalog when you want to:

  • Use a local type instead of a dictionary structure (no SE11 needed).
  • Show a calculated column that is not in the database, such as a status text.
  • Choose your own column headings and order.
  • Hide columns, mark key columns, or add totals.
  • Control column width and alignment.

2. SLIS_FIELDCAT_ALV: the essential fields

The field catalog is an internal table of type slis_t_fieldcat_alv. Each row is a structure of type slis_fieldcat_alv and describes one column.

FieldPurpose
fieldnameColumn name in your output table. Use capitals.
tabnameName of the output table in capitals, for example 'GT_VBAK'.
col_posColumn position, starting at 1.
seltext_s / _m / _lShort, medium and long headings.
outputlenWidth in characters.
key'X' marks a key column. It is highlighted and stays fixed when scrolling.
do_sum'X' shows a total for a numeric column.
cfieldnameName of the currency field for an amount column.
no_out'X' hides the column by default. The user can show it later.
justAlignment: 'L', 'R' or 'C'.
hotspot'X' makes cells clickable (used in Blog 10).

3. The pattern for building a catalog

For each column, fill one structure and append it. A small helper routine avoids repeating the same lines.

" Long way: one column
DATA ls_fcat TYPE slis_fieldcat_alv.

ls_fcat-fieldname = 'VBELN'.
ls_fcat-tabname   = 'GT_VBAK'.
ls_fcat-col_pos   = 1.
ls_fcat-seltext_m = 'Sales Doc.'.
ls_fcat-outputlen = 10.
ls_fcat-key       = 'X'.
APPEND ls_fcat TO gt_fcat.
CLEAR ls_fcat.
Always CLEAR the structure

If you reuse ls_fcat for the next column without clearing it, settings such as key leak into columns that should not have them.

4. Report events: the lifecycle

A report is not read top to bottom. ABAP runs event blocks in a fixed order. Code placed under an event runs only when that event is triggered.

OrderEventRuns whenTypical use
1LOAD-OF-PROGRAMProgram is loadedRare
2INITIALIZATIONBefore the selection screen appearsSet default values
3AT SELECTION-SCREEN OUTPUTEach time the screen is shownShow or hide fields (Blog 7)
4AT SELECTION-SCREENUser presses Enter or F8Validate input
5START-OF-SELECTIONUser presses F8Read data, main logic
6END-OF-SELECTIONAll data is processedDisplay the result
7TOP-OF-PAGEA new list page startsPage header (classical lists)
8AT LINE-SELECTIONUser double-clicks a list lineDrill-down (Blogs 8 and 9)
Do not use the same event twice

Each event may appear once. Statements written before any event are treated as part of START-OF-SELECTION, which can cause confusing behaviour. Always write the event keyword explicitly.

5. Program 2: full code

This report uses a local type, a calculated column (VBTXT), a manual field catalog, and an ALV header.

REPORT zalv_program2.

*---------------------------------------------------------------------*
* Types and data
*---------------------------------------------------------------------*
TYPES: BEGIN OF ty_vbak,
         vbeln TYPE vbak-vbeln,
         erdat TYPE vbak-erdat,
         ernam TYPE vbak-ernam,
         vbtyp TYPE vbak-vbtyp,
         vbtxt TYPE c LENGTH 15,    " calculated, not in the database
         netwr TYPE vbak-netwr,
         waerk TYPE vbak-waerk,
       END OF ty_vbak.

DATA: gt_vbak   TYPE STANDARD TABLE OF ty_vbak WITH DEFAULT KEY,
      gt_fcat   TYPE slis_t_fieldcat_alv,
      gs_layout TYPE slis_layout_alv,
      gv_repid  TYPE sy-repid,
      gv_erdat  TYPE vbak-erdat.

*---------------------------------------------------------------------*
* Selection screen
*---------------------------------------------------------------------*
SELECT-OPTIONS s_erdat FOR gv_erdat.
PARAMETERS p_max TYPE i DEFAULT 500.

*---------------------------------------------------------------------*
* Events
*---------------------------------------------------------------------*
INITIALIZATION.
  s_erdat-sign   = 'I'.
  s_erdat-option = 'BT'.
  s_erdat-low    = sy-datum - 30.
  s_erdat-high   = sy-datum.
  APPEND s_erdat.

AT SELECTION-SCREEN.
  IF p_max <= 0.
    MESSAGE 'Maximum rows must be greater than zero' TYPE 'E'.
  ENDIF.

START-OF-SELECTION.
  PERFORM get_data.

END-OF-SELECTION.
  IF gt_vbak IS NOT INITIAL.
    PERFORM build_fieldcat.
    PERFORM display_alv.
  ENDIF.

*---------------------------------------------------------------------*
* FORM get_data: read data and fill the calculated column
*---------------------------------------------------------------------*
FORM get_data.
  SELECT vbeln, erdat, ernam, vbtyp, netwr, waerk
    FROM vbak
    WHERE erdat IN @s_erdat
    ORDER BY erdat DESCENDING, vbeln
    INTO CORRESPONDING FIELDS OF TABLE @gt_vbak
    UP TO @p_max ROWS.

  IF sy-subrc <> 0.
    MESSAGE 'No sales orders found for your selection'
            TYPE 'S' DISPLAY LIKE 'E'.
    RETURN.
  ENDIF.

  LOOP AT gt_vbak ASSIGNING FIELD-SYMBOL(<ls_vbak>).
    <ls_vbak>-vbtxt = SWITCH #( <ls_vbak>-vbtyp
                          WHEN 'A' THEN 'Inquiry'
                          WHEN 'B' THEN 'Quotation'
                          WHEN 'C' THEN 'Order'
                          ELSE         'Other' ).
  ENDLOOP.
ENDFORM.

*---------------------------------------------------------------------*
* FORM add_col: helper to add one column to the field catalog
*---------------------------------------------------------------------*
FORM add_col USING pv_field TYPE slis_fieldname
                    pv_text  TYPE scrtext_m
                    pv_len   TYPE i
                    pv_key   TYPE c.
  DATA ls_fcat TYPE slis_fieldcat_alv.

  ls_fcat-fieldname = pv_field.
  ls_fcat-tabname   = 'GT_VBAK'.
  ls_fcat-col_pos   = lines( gt_fcat ) + 1.
  ls_fcat-seltext_s = pv_text.
  ls_fcat-seltext_m = pv_text.
  ls_fcat-seltext_l = pv_text.
  ls_fcat-outputlen = pv_len.
  ls_fcat-key       = pv_key.
  APPEND ls_fcat TO gt_fcat.
ENDFORM.

*---------------------------------------------------------------------*
* FORM build_fieldcat: define all columns
*---------------------------------------------------------------------*
FORM build_fieldcat.
  DATA ls_fcat TYPE slis_fieldcat_alv.

  PERFORM add_col USING 'VBELN' 'Sales Doc.'  12 'X'.
  PERFORM add_col USING 'ERDAT' 'Created on'  12 ''.
  PERFORM add_col USING 'ERNAM' 'Created by'  12 ''.
  PERFORM add_col USING 'VBTYP' 'Cat.'        5  ''.
  PERFORM add_col USING 'VBTXT' 'Category'    15 ''.

  " Amount column: needs a currency field and a total
  ls_fcat-fieldname  = 'NETWR'.
  ls_fcat-tabname    = 'GT_VBAK'.
  ls_fcat-col_pos    = lines( gt_fcat ) + 1.
  ls_fcat-seltext_s  = 'Net value'.
  ls_fcat-seltext_m  = 'Net value'.
  ls_fcat-seltext_l  = 'Net value'.
  ls_fcat-outputlen  = 16.
  ls_fcat-cfieldname = 'WAERK'.
  ls_fcat-do_sum     = 'X'.
  APPEND ls_fcat TO gt_fcat.
  CLEAR ls_fcat.

  PERFORM add_col USING 'WAERK' 'Currency' 8 ''.
ENDFORM.

*---------------------------------------------------------------------*
* FORM display_alv
*---------------------------------------------------------------------*
FORM display_alv.
  gv_repid = sy-repid.
  gs_layout-zebra             = 'X'.
  gs_layout-colwidth_optimize = 'X'.

  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      i_callback_program     = gv_repid
      i_callback_top_of_page = 'ALV_TOP_OF_PAGE'
      is_layout              = gs_layout
      it_fieldcat            = gt_fcat
    TABLES
      t_outtab               = gt_vbak
    EXCEPTIONS
      program_error          = 1
      OTHERS                 = 2.

  IF sy-subrc <> 0.
    MESSAGE 'ALV could not be displayed' TYPE 'S' DISPLAY LIKE 'E'.
  ENDIF.
ENDFORM.

*---------------------------------------------------------------------*
* FORM alv_top_of_page: ALV header (called by ALV itself)
*---------------------------------------------------------------------*
FORM alv_top_of_page.
  DATA lt_header TYPE slis_t_listheader.
  DATA ls_header TYPE slis_listheader.

  " Title
  ls_header-typ  = 'H'.
  ls_header-info = 'Sales Orders Report'.
  APPEND ls_header TO lt_header.
  CLEAR ls_header.

  " Selection info
  ls_header-typ  = 'S'.
  ls_header-key  = 'Period:'.
  ls_header-info = |{ s_erdat-low DATE = USER } to { s_erdat-high DATE = USER }|.
  APPEND ls_header TO lt_header.
  CLEAR ls_header.

  ls_header-typ  = 'S'.
  ls_header-key  = 'Records:'.
  ls_header-info = |{ lines( gt_vbak ) }|.
  APPEND ls_header TO lt_header.
  CLEAR ls_header.

  " Action line (shown in italics)
  ls_header-typ  = 'A'.
  ls_header-info = |Run by { sy-uname } on { sy-datum DATE = USER }|.
  APPEND ls_header TO lt_header.

  CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE'
    EXPORTING
      it_list_commentary = lt_header.
ENDFORM.

6. Walkthrough

PartWhat it does
TYPES ty_vbakA local structure. No SE11 object is needed. It includes VBTXT, which does not exist in the database.
START-OF-SELECTIONReads the data.
END-OF-SELECTIONRuns after the data is ready, so it builds the catalog and shows the grid.
SWITCH in get_dataFills the calculated category text for each row.
add_colA helper that builds one catalog row, so the catalog stays short and readable.
NETWR rowSets cfieldname so amounts display with the right decimals, and do_sum for a total.
tabname = 'GT_VBAK'Must match the output table name in capitals.
is_layoutZebra stripes and optimized widths. Blog 10 covers layouts in depth.
i_callback_top_of_pageNames the form ALV calls to draw the header.
Why is the currency column still in the table?

cfieldname = 'WAERK' points to a column of the output table. That column must exist in the table, even if you decide to hide it with no_out.

The header is a table of lines of type slis_t_listheader. Each line has a type that controls its style:

typStyleFields used
HLarge headinginfo
SSelection information, shown as label and valuekey and info
AAction text, shown in italicsinfo

After filling the table, call REUSE_ALV_COMMENTARY_WRITE inside the callback form. The header appears above the grid on every display.

8. TOP-OF-PAGE vs. ALV header

Classical TOP-OF-PAGEALV header
Used withWRITE listsALV grid
How it is triggeredEvent keyword in your programCallback named in i_callback_top_of_page
ContentWRITE statementsA header table and REUSE_ALV_COMMENTARY_WRITE
Form nameNo form, an event blockAny form name you choose
Do not mix them up

The TOP-OF-PAGE event does not draw the header of an ALV grid. For a grid you must use the callback form. That is why the form here is named alv_top_of_page.

9. Try it yourself

  • Hide the VBTYP column by default with no_out = 'X', then show it again from the layout settings.
  • Right-align the Created by column with just = 'R'.
  • Change the order of the columns by editing the PERFORM add_col lines.
  • Add a second S line to the header showing the user’s selected maximum rows.
  • Add a new calculated column Size showing 'Large' when netwr is above 10,000.

10. Common mistakes

  • Wrong tabname. It must be the output table name in capitals. Otherwise columns are missing.
  • Lowercase fieldname. Use 'VBELN', not 'vbeln'.
  • Not clearing ls_fcat between columns, so settings carry over.
  • Missing currency column when cfieldname is set.
  • Duplicate col_pos values. Columns jump around or disappear.
  • Header form name misspelled in i_callback_top_of_page. The header is simply missing.
  • Header form in another program. Callback forms must be in the same program as i_callback_program.
  • Expecting the TOP-OF-PAGE event to draw the grid header. Use the callback instead.

Up next: Blog 7

Dynamic Selection Screens. Show and hide fields while the user is working, using AT SELECTION-SCREEN OUTPUT and LOOP AT SCREEN.

ABAP Reports: Zero to Hero · Blog 6 of 15
WhatsApp WhatsApp us
Call Now Button