ALV Reports Part 8: Toolbar Buttons, PF-STATUS and User Commands
Add your own functions to an ALV: a copied PF-STATUS with i callback pf status set for REUSE ALV, the toolbar and user command events of CL GUI ALV GRID, reading selected rows, and refreshing the grid after an action.
Explanation
📌 KEY POINTS
✅ REUSE_ALV: copy status STANDARD_FULLSCREEN (program SAPLKKBL) into your program, add buttons, set it in the FORM named in i_callback_pf_status_set.
✅ CL_GUI_ALV_GRID: add buttons in the TOOLBAR event handler and handle them in the USER_COMMAND event.
✅ Read the user's selection: rs_selfield / GET_SELECTED_ROWS, then refresh the display after changes.
⚠️ Always refresh after changing the output table, and check sy-subrc / authorization before mass actions.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 6 reacted to clicks on cells. Now users select rows and press your own buttons — e.g. "Release", "Send e-mail", "Recalculate".\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 1. REUSE_ALV WITH OWN STATUS\n• SE41 (or SE80 → GUI status → copy): copy status STANDARD_FULLSCREEN from program SAPLKKBL to your report, name ZSTANDARD. It keeps all standard ALV functions.
- Add a button, e.g. function code REFRESH or RELEASE with icon and text.
- i_callback_pf_status_set = 'SET_PF_STATUS' → FORM set_pf_status USING rt_extab TYPE slis_t_extab. SET PF-STATUS 'ZSTANDARD' EXCLUDING rt_extab.
- i_callback_user_command = 'USER_COMMAND' → your codes arrive in r_ucomm.
- rs_selfield-refresh = 'X' tells the ALV to refresh after the callback.
- Selected rows: add a checkbox column or use layout box_fieldname (SLIS) with a SEL field.\n\n━━━━━━━━━━━━━━━━━━━━\n▶ 2. CL_GUI_ALV_GRID TOOLBAR EVENT\n• Handler FOR EVENT toolbar OF cl_gui_alv_grid IMPORTING e_object: APPEND a stb_button (function, icon, quickinfo, text) to e_object->mt_toolbar.
- Handler FOR EVENT user_command IMPORTING e_ucomm: CASE e_ucomm.
- go_grid->get_selected_rows( IMPORTING et_index_rows = lt_rows ) — needs sel_mode 'A' or 'D' in layout.
- go_grid->refresh_table_display( ) after changes.
- SET HANDLER before set_table_for_first_display so the toolbar event fires; or call go_grid->set_toolbar_interactive( ) afterwards.
━━━━━━━━━━━━━━━━━━━━
▶ 3. DESIGN OF ACTIONS
- Confirm destructive actions with POPUP_TO_CONFIRM.
- Process selected rows, collect messages, show them (e.g. in a message log or popup).
- Lock objects (ENQUEUE) before changes, COMMIT once at the end.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Copy STANDARD_FULLSCREEN to your report as ZSTANDARD and add button REFRESH (and RELEASE).
- Run the code example; select rows and press Release.
- Check that the status column updates after the refresh.
✅ CHECKPOINT: users can select rows and trigger your actions from the ALV toolbar.
Code example
REPORT zalv_user_command. TYPES: BEGIN OF ty_out, sel TYPE char1, " selection box carrid TYPE s_carr_id, connid TYPE s_conn_id, fldate TYPE s_date, seatsocc TYPE s_seatsocc, status TYPE char10, END OF ty_out. DATA: gt_out TYPE STANDARD TABLE OF ty_out, gt_fcat TYPE slis_t_fieldcat_alv, gs_fcat TYPE slis_fieldcat_alv, gs_layout TYPE slis_layout_alv. START-OF-SELECTION. PERFORM get_data. PERFORM add_field USING 'CARRID' 'Airline'. PERFORM add_field USING 'CONNID' 'Connection'. PERFORM add_field USING 'FLDATE' 'Date'. PERFORM add_field USING 'SEATSOCC' 'Occupied'. PERFORM add_field USING 'STATUS' 'Status'. gs_layout-box_fieldname = 'SEL'. " row selection column gs_layout-colwidth_optimize = 'X'. CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY' EXPORTING i_callback_program = sy-repid i_callback_pf_status_set = 'SET_PF_STATUS' i_callback_user_command = 'USER_COMMAND' is_layout = gs_layout it_fieldcat = gt_fcat TABLES t_outtab = gt_out. *----------------------------------------------------------------------*FORM get_data. SELECT carrid connid fldate seatsocc FROM sflight INTO CORRESPONDING FIELDS OF TABLE gt_out WHERE carrid = 'LH'.ENDFORM. FORM add_field USING iv_field TYPE slis_fieldname iv_text TYPE c. CLEAR gs_fcat. gs_fcat-fieldname = iv_field. gs_fcat-seltext_m = iv_text. APPEND gs_fcat TO gt_fcat.ENDFORM. *----------------------------------------------------------------------** ZSTANDARD = copy of STANDARD_FULLSCREEN (program SAPLKKBL)* with extra functions RELEASE and REFRESH*----------------------------------------------------------------------*FORM set_pf_status USING rt_extab TYPE slis_t_extab. SET PF-STATUS 'ZSTANDARD' EXCLUDING rt_extab.ENDFORM. FORM user_command USING r_ucomm LIKE sy-ucomm rs_selfield TYPE slis_selfield. DATA: lv_answer TYPE c, lv_count TYPE i. FIELD-SYMBOLS <ls_out> TYPE ty_out. CASE r_ucomm. WHEN 'RELEASE'. CALL FUNCTION 'POPUP_TO_CONFIRM' EXPORTING titlebar = 'Release flights' text_question = 'Release all selected flights?' IMPORTING answer = lv_answer. CHECK lv_answer = '1'. " 1 = Yes LOOP AT gt_out ASSIGNING <ls_out> WHERE sel = 'X'. <ls_out>-status = 'RELEASED'. " real code: lock, update, collect messages CLEAR <ls_out>-sel. lv_count = lv_count + 1. ENDLOOP. MESSAGE s000(0k) WITH lv_count 'flight(s) released'. rs_selfield-refresh = 'X'. " redraw the grid WHEN 'REFRESH'. PERFORM get_data. rs_selfield-refresh = 'X'. ENDCASE.ENDFORM. * ===== CL_GUI_ALV_GRID variant =====* METHODS on_toolbar FOR EVENT toolbar OF cl_gui_alv_grid IMPORTING e_object.* METHODS on_command FOR EVENT user_command OF cl_gui_alv_grid IMPORTING e_ucomm.** METHOD on_toolbar.* DATA ls_button TYPE stb_button.* ls_button-function = 'RELEASE'.* ls_button-icon = icon_release.* ls_button-quickinfo = 'Release selected flights'.* ls_button-text = 'Release'.* APPEND ls_button TO e_object->mt_toolbar.* ENDMETHOD.** METHOD on_command.* DATA lt_rows TYPE lvc_t_row.* IF e_ucomm = 'RELEASE'.* go_grid->get_selected_rows( IMPORTING et_index_rows = lt_rows ).* " process rows ... then:* go_grid->refresh_table_display( ).* ENDIF.* ENDMETHOD.** SET HANDLER: go_handler->on_toolbar FOR go_grid, go_handler->on_command FOR go_grid.Real project scenario
A credit control team released blocked orders one by one in VKM1. A custom ALV listed blocked orders with a "Release" button: users selected rows, confirmed, and the program called the release BAPI per order, collected messages and refreshed the grid.
In the first version, the grid was not refreshed and users pressed Release twice, triggering duplicate processing errors. Adding the refresh and a status column that showed "Released" solved it.
Common mistakes
- Creating a new PF-STATUS from scratch and losing standard ALV functions.
- Forgetting EXCLUDING rt_extab.
- Not refreshing the grid after changing data.
- get_selected_rows without a selection mode in the layout.
- Mass actions without confirmation, locking or message collection.
Best practices
- Copy STANDARD_FULLSCREEN and add your functions.
- Confirm destructive actions.
- Lock, process, collect messages and commit once.
- Refresh with stable scroll position.
- Keep action logic in separate routines or classes.
Interview angle
Questions: "How do you add a custom button to an ALV?", "How do you get selected rows?", "Which events are used in CL_GUI_ALV_GRID?"
Strong answer: REUSE_ALV — copy STANDARD_FULLSCREEN from SAPLKKBL, set it in i_callback_pf_status_set FORM, handle r_ucomm in user_command, rs_selfield-refresh; OO — TOOLBAR event to add stb_button to e_object->mt_toolbar, USER_COMMAND event with e_ucomm, get_selected_rows with sel_mode, refresh_table_display.
Practice this lesson
Quick check
1. To add a custom button to a REUSE_ALV_GRID_DISPLAY toolbar while keeping standard functions, you should:
2. Where should the database update for a "Block delivery" ALV toolbar button be implemented?
3. Which method of CL_GUI_ALV_GRID is used to retrieve the row indices that a user has currently marked using the selection column?
Interview questions
1. A logistics cockpit implements delivery blocking directly inside the ALV toolbar event handler, including SELECTs, updates and COMMIT per row. What is wrong and how would you restructure it?
Answer it in your own words first, then compare.
2. What is a layout variant?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- ALV Reports Part 1: ALV Basics with REUSE_ALV_GRID_DISPLAY
- ALV Reports Part 10: Authorization and Sensitive Data in ALV Reports
- ALV Reports Part 2: Quick ALV with CL_SALV_TABLE
- ALV Reports Part 3: OO ALV with CL_GUI_ALV_GRID and a Custom Container
- ALV Reports Part 4: The Field Catalog in Depth
- ALV Reports Part 5: Layout, Sort, Filter, Totals and Variants
- ALV Reports Part 6: Hotspot and Double-Click Drill-Down
- ALV Reports Part 7: Colors, Icons and Traffic Lights