Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
johannes_gilbert
Employee
Employee
0 Kudos

Introduction

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:

  • Data is selected (for this example data from the context of tables but000, but020, adrc and adcp is used).
  • The table which is meant to contain all data for the ALV-grid is built. Here, relevant components need to be specified.
  • The table is filled with data. For this example we would like to get following output: For each Business Partner we would like to show all addresses as well as all person-related addresses for each address.
  • The ALV-grid is created via a factory method and displayed.

Code Snippet(s)

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.

Explanation

In a first step the data is selected. For this example we will work with Business Partners and its addresses. Thus, we choose tables

  • BUT000 (Business Partner central table)
  • BUT020 (Relation between Business Partner and its address(es); one partner might have 0..* addresses)
  • ADRC (Address central table)
  • ADCP (Address for person).


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:

  1. Via RTTS we gather a structure description.
  2. The description does provide information about each component of the structure.
  3. We keep only those components that are needed later on in the ALV-grid.
  4. Save these component information for later use.

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.

Availability

KeyValue
Software ComponentSAP_BASIS                                                               
Requires Client-Side Software LibraryNo
Code Snippet is OS dependentNo