
The following code snippet shows an exemplary implementation how to dynamically built up a table whereas a single entry in that table contains data from different DB-tables. Despite coding the whole stuff about field catalog etc. on your own, this implementation keeps the relation to the DDIC and the only decisions to be made is about which data should be shown in the ALV-grid.
The implementation is structured as follows:
TABLES:
but000.
DATA:
lt_but000 TYPE STANDARD TABLE OF but000,
ls_but000 TYPE but000,
lt_but020 TYPE STANDARD TABLE OF but020,
ls_but020 TYPE but020,
lt_adrc TYPE STANDARD TABLE OF adrc,
ls_adrc TYPE adrc,
lt_adcp TYPE STANDARD TABLE OF adcp,
ls_adcp TYPE adcp,
lt_addr_no_range TYPE RANGE OF ad_addrnum,
ls_addr_no_range LIKE LINE OF lt_addr_no_range.
SELECT-OPTIONS: s_pno FOR but000-partner.
* Select the corresponding partners.
SELECT * FROM but000
INTO TABLE lt_but000
WHERE partner IN s_pno.
* Check if there were any partners found.
IF lt_but000 IS INITIAL.
return.
ENDIF.
* Select address numbers for these partners.
SELECT * FROM but020
INTO TABLE lt_but020
WHERE partner IN s_pno.
* Built-up an address number range.
LOOP AT lt_but020 INTO ls_but020.
ls_addr_no_range-sign = 'I'.
ls_addr_no_range-option = 'EQ'.
ls_addr_no_range-low = ls_but020-addrnumber.
APPEND ls_addr_no_range TO lt_addr_no_range.
ENDLOOP.
IF lt_addr_no_range IS NOT INITIAL.
* Select the addresses.
SELECT * FROM adrc
INTO TABLE lt_adrc
WHERE addrnumber IN lt_addr_no_range.
* Select the person/address assignments.
SELECT * FROM adcp
INTO TABLE lt_adcp
WHERE addrnumber IN lt_addr_no_range.
ENDIF.
* So far we got all data.
* Now we will built-up a corresponding table.
DATA:
lr_struc_descr TYPE REF TO cl_abap_structdescr, "RTTS for structures
lr_table_descr TYPE REF TO cl_abap_tabledescr, "RTTS for tables
lt_components TYPE cl_abap_structdescr=>component_table, "Temp. table of component RTTI descriptions
lt_table_of_components TYPE cl_abap_structdescr=>component_table, "Table of component RTTI descriptions
lx_error TYPE REF TO cx_root, "Error object
lr_data_ref TYPE REF TO data, "Reference to a component RTTI description
lr_table_ref TYPE REF TO data. "Reference to the table of component RTTI descriptions
FIELD-SYMBOLS: <fs_merge> TYPE any,
<dyntable> TYPE table.
* Get fields of but000.
lr_struc_descr ?= cl_abap_structdescr=>describe_by_data( ls_but000 ).
lt_components = lr_struc_descr->get_components( ).
CLEAR lr_struc_descr.
* Delete non-relevant fields.
DELETE lt_components
WHERE name NE 'PARTNER' AND
name NE 'TYPE'.
APPEND LINES OF lt_components TO lt_table_of_components.
* Get fields of but020.
lr_struc_descr ?= cl_abap_structdescr=>describe_by_data( ls_but020 ).
lt_components = lr_struc_descr->get_components( ).
CLEAR lr_struc_descr.
* Delete non-relevant fields.
DELETE lt_components
WHERE name NE 'ADDRNUMBER' AND
name NE 'XDFADR'.
APPEND LINES OF lt_components TO lt_table_of_components.
* Get fields of adrc.
lr_struc_descr ?= cl_abap_structdescr=>describe_by_data( ls_adrc ).
lt_components = lr_struc_descr->get_components( ).
CLEAR lr_struc_descr.
* Delete non-relevant fields.
DELETE lt_components
WHERE name NE 'STREET' AND
name NE 'HOUSE_NUM1' AND
name NE 'POST_CODE1' AND
name NE 'CITY1'.
APPEND LINES OF lt_components TO lt_table_of_components.
* Get fields of adcp.
lr_struc_descr ?= cl_abap_structdescr=>describe_by_data( ls_adcp ).
lt_components = lr_struc_descr->get_components( ).
CLEAR lr_struc_descr.
* Delete non-relevant fields.
DELETE lt_components
WHERE name NE 'PERSNUMBER' AND
name NE 'COMP_PERS'.
APPEND LINES OF lt_components TO lt_table_of_components.
* Create a RTTS instance for the merged structure.
TRY.
lr_struc_descr = cl_abap_structdescr=>create( p_components = lt_table_of_components ).
CATCH cx_sy_struct_creation INTO lx_error.
ENDTRY.
CREATE DATA lr_data_ref TYPE HANDLE lr_struc_descr. "Create data ref. variable
ASSIGN lr_data_ref->* TO <fs_merge>. "Dereference the data reference
* Create a RTTS instance for a table of the merged structure.
TRY.
lr_table_descr = cl_abap_tabledescr=>create( p_line_type = lr_struc_descr ).
CATCH cx_sy_table_creation INTO lx_error.
ENDTRY.
CREATE DATA lr_table_ref TYPE HANDLE lr_table_descr. "Create data ref. variable
ASSIGN lr_table_ref->* TO <dyntable>. "Dereference the data reference
* Now we have a corresponding line structure and table to work with.
* It contains components for all field we'd specified.
* Fill the table...
* Loop at all partners.
LOOP AT lt_but000 INTO ls_but000.
* Loop at all addresses of the current partner.
LOOP AT lt_but020 INTO ls_but020
WHERE partner = ls_but000-partner.
MOVE-CORRESPONDING ls_but020 TO <fs_merge>.
* Loop at address entries.
LOOP AT lt_adrc INTO ls_adrc
WHERE addrnumber = ls_but020-addrnumber.
MOVE-CORRESPONDING ls_adrc TO <fs_merge>.
LOOP AT lt_adcp INTO ls_adcp
WHERE addrnumber = ls_but020-addrnumber.
MOVE-CORRESPONDING ls_adcp TO <fs_merge>.
APPEND <fs_merge> TO <dyntable>.
ENDLOOP.
IF sy-subrc EQ 4.
APPEND <fs_merge> TO <dyntable>.
ENDIF.
ENDLOOP.
IF sy-subrc EQ 4.
APPEND <fs_merge> TO <dyntable>.
ENDIF.
ENDLOOP.
ENDLOOP.
* The table is filled. For this Hands On we just
* would like to present the data in a Popup containing
* a corresponding ALV-grid.
DATA lo_alv TYPE REF TO cl_salv_table.
* Create an ALV-grid.
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = lo_alv
CHANGING
t_table = <dyntable> ).
CATCH cx_salv_msg INTO lx_error.
ENDTRY.
* Enable some functions.
DATA: lr_functions TYPE REF TO cl_salv_functions_list.
lr_functions = lo_alv->get_functions( ).
lr_functions->set_all( abap_true ).
IF lo_alv IS BOUND.
* Set display properties.
lo_alv->set_screen_popup(
start_column = 25 "i_start_column
end_column = 275 "i_end_column
start_line = 2 "i_start_line
end_line = 45 "i_end_line
).
* Show the result.
lo_alv->display( ).
ENDIF.
In a first step the data is selected. For this example we will work with Business Partners and its addresses. Thus, we choose tables
The relations and cardinalities are as follows (never mind if they are different in reality):
The second step is the construction of a dynamic structure whereas the components of the structure do have the same specification as the ones we would like to display in the ALV-grid. Imporant is that we don not want to provide all the meta information about that component but just "keep" the connection to the DDIC. For each table the approach is the same:
Afterwards, all gather components or rather component information is used in order to create a new structure description via RTTS. This time, this structure description is for a structure that consists of exactly the components we kept. Using this structure description we assign a field-symbol that is of that structure type. Furthermore using this structure description a table description is created and a field-symbol is assigned using it. As result there are a dynamic structure and table.
The third step is just about filling the dynamic table. Therefore the dynamic structure is filled correspondingly from each data set of the mentioned tables. Last but not least an ALV-grid in created and shown.
Key | Value |
---|---|
Software Component | SAP_BASIS |
Requires Client-Side Software Library | No |
Code Snippet is OS dependent | No |