This examples shows steps how you can create ALV report from scratch.
Goal: create ALV report where user can choose parameters on initial selection screen of program and then get result using SALV framework.
Outcom: you will have two templates in explanation below:
- Template
Add PROGRAM with class
- Template
Add PROGRAM with class of ALV report
Path to do it:
Name: ZML_INVOICES Description: Invoices report
Notice: Description will be excly the name of report which customer expects from you as a developer.
Type lcl
and press Ctrl+Space to get code completion proposals. Select lcl - Local class
adjust the name of local class to lcl_main
using inline editing:
Choose the name of class by cursor and press Ctrl+1 keys to open the Quick Fix menu. Use Generate factory method create
to create static factory method.
Code at this moment will be:
Type in public sction of lcl_main class definition method run:
METHODS: run.
and choose method run by cursor and press Ctrl+1 to get proposals from Quickfix menu and choose Add implementation for run
Add a START-OF-SELECTION
event to your report after endclass of your lcl_main class and add code of executing run method from selection area.
START-OF-SELECTION.
lcl_main=>create( )->run( ).
Now you code looks like below, i recomment to create using this code template to save time when you develop new report.
*&---------------------------------------------------------------------*
*& Report zml_invoices
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zml_invoices.
CLASS lcl_main DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS create
RETURNING
VALUE(r_result) TYPE REF TO lcl_main.
METHODS: run.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD create.
r_result = NEW #( ).
ENDMETHOD.
METHOD run.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>create( )->run( ).
You can create new template into your Eclipse ADT using Templates
view and just choosing from Context menu the New..
button:
Where you can paste your code and change name report in comment area and into operator node by insert variable: ${enclosing_object}
Your template can be as below. Such template lets you after creating program put all previouse code in one sec and name will be taken from name of your new program:
*&---------------------------------------------------------------------*
*& Report ${enclosing_object}
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ${enclosing_object}.
CLASS lcl_main DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS create
RETURNING
VALUE(r_result) TYPE REF TO lcl_main.
METHODS: run.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD create.
r_result = NEW #( ).
ENDMETHOD.
METHOD run.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>create( )->run( ).
Before open ALV report developers have requirements how to filter data. Assume, in our exmple you have requirements:
- company can be selected ( if not then all companies can be requested)
- currency code can be selected (if not then all currency codes can be requested)
Add selection parameters to the beginning of report:
TYPES: BEGIN OF ts_selection,
company_name TYPE snwd_bpa-company_name,
currency_code TYPE snwd_so_inv_item-currency_code,
END OF ts_selection.
DATA: lv_company_name TYPE ts_selection-company_name.
DATA: lv_currency TYPE ts_selection-currency_code.
SELECTION-SCREEN BEGIN OF BLOCK a.
SELECT-OPTIONS: s_cname FOR lv_company_name.
SELECT-OPTIONS: s_curr FOR lv_currency.
SELECTION-SCREEN END OF BLOCK a.
Notice: the names of parameters s_cname
and s_curr
should be provided by text elements:
You can do it by context meny after selecting your parameter:
Add type of records ts_records
and table type tt_records
In private section of lcl_main add type of records and table type with your supposed structure. In this example we use educational table from SAP so we would like to return such records:
TYPES: BEGIN OF ts_items,
company_name TYPE snwd_bpa-company_name,
gross_amount TYPE snwd_so_inv_item-gross_amount,
currency_code TYPE snwd_so_inv_item-currency_code,
payment_status TYPE snwd_so_inv_head-payment_status,
END OF ts_items.
TYPES: tt_items TYPE STANDARD TABLE OF ts_items.
Add itab gt_items`
DATA: gt_items TYPE tt_items.
In method run you shoudl add itab lv_items
where extracted data from databse will be saved, before those come to ALV.
gt_items = me->get_data( ).
and generate method get_data by using Ctrl+1 combination keys:
after generating method to follow name conventions use this name in definition mehtod get_data for returning: rt_result
instead of r_result
:
METHODS get_data
RETURNING
value(rt_result) LIKE gt_items.
Your select should return the simmilar structure which you described into type ts_items
. Notice: your select should return structure which is compatible with structure of table GT_ITEMS or use corresponding to fill in RT_RESULT with corresponding fields.
METHOD get_data.
SELECT
snwd_bpa~company_name,
snwd_so_inv_item~gross_amount,
snwd_so_inv_item~currency_code,
snwd_so_inv_head~payment_status
FROM
snwd_so_inv_item
JOIN snwd_so_inv_head
ON snwd_so_inv_item~parent_key = snwd_so_inv_head~node_key
JOIN snwd_bpa
ON snwd_so_inv_head~buyer_guid = snwd_bpa~node_key
WHERE
snwd_so_inv_item~currency_code IN @s_curr
AND
snwd_bpa~company_name IN @s_cname
ORDER BY
snwd_bpa~company_name
INTO CORRESPONDING FIELDS OF TABLE @rt_result.
ENDMETHOD.
Notice: if you have parameters you can point those directly from selection parameters. In our case we have two:
- @s_curr
- @s_cname
Add this file to be able adjust GUI settings as you need and let do it for user.
Copy file from this project 'SALV_STANDARD' to your own project just to save time.
Into method run
add this code (study comments to understand how this code prepare your data to ALV GRID and display it:
METHOD run.
gt_items = me->get_data( ).
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(alv_table)
CHANGING
t_table = gt_items
).
CATCH cx_salv_msg.
"handle exception
ENDTRY.
DATA: lr_columns TYPE REF TO cl_salv_columns_table,
lr_column TYPE REF TO cl_salv_column_table.
lr_columns = alv_table->get_columns( ).
" modify here technical representation of the columns if it is needing
data: ls_color type lvc_s_colo.
TRY.
lr_column ?= lr_columns->get_column( 'CURRENCY_CODE' ).
ls_color-col = col_negative.
ls_color-int = 0.
ls_color-inv = 0.
lr_column->set_color( ls_color ).
CATCH cx_salv_not_found.
ENDTRY.
" optimize column width
lr_columns->set_optimize( abap_true ).
" show panel with function buttons
alv_table->get_functions( )->set_default( abap_true ).
" remove restrictions on saving layouts
alv_table->get_layout( )->set_save_restriction( if_salv_c_layout=>restrict_none ).
" show rows with a zebra effect
alv_table->get_display_settings( )->set_striped_pattern( if_salv_c_bool_sap=>true ).
"Register a custom GUI status for an ALV
alv_table->set_screen_status(
pfstatus = gui_status_name
report = sy-repid
set_functions = alv_table->c_functions_all ).
alv_table->display( ).
ENDMETHOD.
Activate all code before test. -- Execute code by using F8 key to get selection screen:
-- Execute your selection to get report:
Create new template into your Eclipse ADT and add code from below, and use this code to get program with your name and then you should change code with comments to your own code:
*&---------------------------------------------------------------------*
*& Report ${enclosing_object}
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ${enclosing_object}.
**********************************************************************
*
* SELECTION PAARAMETERS
*
**********************************************************************
"TYPES: BEGIN OF ts_selection,
" company_name TYPE snwd_bpa-company_name,
" currency_code TYPE snwd_so_inv_item-currency_code,
" END OF ts_selection.
"DATA: lv_company_name TYPE ts_selection-company_name.
"DATA: lv_currency TYPE ts_selection-currency_code.
"
"SELECTION-SCREEN BEGIN OF BLOCK a.
" SELECT-OPTIONS: s_cname FOR lv_company_name.
" SELECT-OPTIONS: s_curr FOR lv_currency.
"SELECTION-SCREEN END OF BLOCK a.
**********************************************************************
CLASS lcl_main DEFINITION CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS create
RETURNING
VALUE(r_result) TYPE REF TO lcl_main.
METHODS: run.
PROTECTED SECTION.
PRIVATE SECTION.
TYPES: BEGIN OF ts_items,
changeme TYPE string,
"company_name TYPE snwd_bpa-company_name,
"gross_amount TYPE snwd_so_inv_item-gross_amount,
"currency_code TYPE snwd_so_inv_item-currency_code,
"payment_status TYPE snwd_so_inv_head-payment_status,
END OF ts_items.
TYPES: tt_items TYPE STANDARD TABLE OF ts_items.
DATA: gt_items TYPE tt_items.
"CONSTANTS: gui_status_name TYPE sypfkey VALUE 'SALV_STANDARD'.
METHODS get_data
RETURNING
VALUE(rt_result) LIKE gt_items.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD create.
r_result = NEW #( ).
ENDMETHOD.
METHOD run.
gt_items = me->get_data( ).
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(alv_table)
CHANGING
t_table = gt_items
).
CATCH cx_salv_msg.
"handle exception
ENDTRY.
DATA: lr_columns TYPE REF TO cl_salv_columns_table,
lr_column TYPE REF TO cl_salv_column_table.
lr_columns = alv_table->get_columns( ).
" modify here technical representation of the columns if it is needing
"data: ls_color type lvc_s_colo.
"TRY.
" lr_column ?= lr_columns->get_column( 'CURRENCY_CODE' ).
" ls_color-col = col_negative.
" ls_color-int = 0.
" ls_color-inv = 0.
" lr_column->set_color( ls_color ).
" CATCH cx_salv_not_found.
"ENDTRY.
" optimize column width
lr_columns->set_optimize( abap_true ).
" show panel with function buttons
alv_table->get_functions( )->set_default( abap_true ).
" remove restrictions on saving layouts
alv_table->get_layout( )->set_save_restriction( if_salv_c_layout=>restrict_none ).
" show rows with a zebra effect
alv_table->get_display_settings( )->set_striped_pattern( if_salv_c_bool_sap=>true ).
"Register a custom GUI status for an ALV
"alv_table->set_screen_status(
" pfstatus = gui_status_name
" report = sy-repid
" set_functions = alv_table->c_functions_all ).
alv_table->display( ).
ENDMETHOD.
METHOD get_data.
"SELECT
" snwd_bpa~company_name,
" snwd_so_inv_item~gross_amount,
" snwd_so_inv_item~currency_code,
" snwd_so_inv_head~payment_status
" FROM
" snwd_so_inv_item
" JOIN snwd_so_inv_head
" ON snwd_so_inv_item~parent_key = snwd_so_inv_head~node_key
" JOIN snwd_bpa
" ON snwd_so_inv_head~buyer_guid = snwd_bpa~node_key
" WHERE
" snwd_so_inv_item~currency_code IN @s_curr
" AND
" snwd_bpa~company_name IN @s_cname
" ORDER BY
" snwd_bpa~company_name
" INTO CORRESPONDING FIELDS OF TABLE @rt_result.
rt_result = VALUE #( ( changeme = 'test1' ) ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>create( )->run( ).
If you need event hundlers, or creating own specific functions you can find patterns of code into sap.community blog here:
Happy programming,
Yours sincerely,
Mikhail.