Manual Field Catalog and Report Events (Program 2)
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.
| Field | Purpose |
|---|---|
fieldname | Column name in your output table. Use capitals. |
tabname | Name of the output table in capitals, for example 'GT_VBAK'. |
col_pos | Column position, starting at 1. |
seltext_s / _m / _l | Short, medium and long headings. |
outputlen | Width 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. |
cfieldname | Name of the currency field for an amount column. |
no_out | 'X' hides the column by default. The user can show it later. |
just | Alignment: '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.
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.
| Order | Event | Runs when | Typical use |
|---|---|---|---|
| 1 | LOAD-OF-PROGRAM | Program is loaded | Rare |
| 2 | INITIALIZATION | Before the selection screen appears | Set default values |
| 3 | AT SELECTION-SCREEN OUTPUT | Each time the screen is shown | Show or hide fields (Blog 7) |
| 4 | AT SELECTION-SCREEN | User presses Enter or F8 | Validate input |
| 5 | START-OF-SELECTION | User presses F8 | Read data, main logic |
| 6 | END-OF-SELECTION | All data is processed | Display the result |
| 7 | TOP-OF-PAGE | A new list page starts | Page header (classical lists) |
| 8 | AT LINE-SELECTION | User double-clicks a list line | Drill-down (Blogs 8 and 9) |
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
| Part | What it does |
|---|---|
TYPES ty_vbak | A local structure. No SE11 object is needed. It includes VBTXT, which does not exist in the database. |
START-OF-SELECTION | Reads the data. |
END-OF-SELECTION | Runs after the data is ready, so it builds the catalog and shows the grid. |
SWITCH in get_data | Fills the calculated category text for each row. |
add_col | A helper that builds one catalog row, so the catalog stays short and readable. |
NETWR row | Sets 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_layout | Zebra stripes and optimized widths. Blog 10 covers layouts in depth. |
i_callback_top_of_page | Names the form ALV calls to draw the header. |
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.
7. The ALV header
The header is a table of lines of type slis_t_listheader. Each line has a type that controls its style:
| typ | Style | Fields used |
|---|---|---|
H | Large heading | info |
S | Selection information, shown as label and value | key and info |
A | Action text, shown in italics | info |
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-PAGE | ALV header | |
|---|---|---|
| Used with | WRITE lists | ALV grid |
| How it is triggered | Event keyword in your program | Callback named in i_callback_top_of_page |
| Content | WRITE statements | A header table and REUSE_ALV_COMMENTARY_WRITE |
| Form name | No form, an event block | Any form name you choose |
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
VBTYPcolumn by default withno_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_collines. - Add a second
Sline to the header showing the user’s selected maximum rows. - Add a new calculated column Size showing
'Large'whennetwris 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_fcatbetween columns, so settings carry over. - Missing currency column when
cfieldnameis set. - Duplicate
col_posvalues. 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-PAGEevent 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.
WhatsApp us