Skip to Content

Dear all,

In this blog an example of dynamic tables in an ALV with RTTI is showed.

RTTI stands for Run Time Type Identification. It’s used to get the definition of existing variables or existing types.

This can be used to create a dynamic structure and table type at runtime. These structure can easily change.

The next example have twoo screens:

  • One to give a name of an SAP table in parameter.
  • One to show all the values in the ALV with the given table from previous screen.

Below an example of a dynamic ALV with RTTI (code)

All the data that will be used.


TYPE-POOLS : abap, slis.
FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE,
                <fs_wa>,
                <fs_field>.
DATA: zdyn_table    TYPE REF TO data,
       zdyn_line     TYPE REF TO data,
       zwa_fieldcat  TYPE lvc_s_fcat,
       zit_fieldcat  TYPE lvc_t_fcat.
*ALV data declarations
DATA: zfieldcatalog  TYPE slis_t_fieldcat_alv WITH HEADER LINE,
       zgd_tab_group  TYPE slis_t_sp_group_alv,
       zgd_layout     TYPE slis_layout_alv,
       zgd_repid      LIKE sy-repid.
PARAMETERS: zp_table(30) TYPE c .
DATA : zit_tabdescr TYPE abap_compdescr_tab,
        zwa_tabdescr TYPE abap_compdescr.
DATA : zref_table_descr TYPE REF TO cl_abap_structdescr.

Return structure of the filled parameter. ZIT_TABDESCR[] will now have the structure and details (datatype, decimals, … ) from the table.


zref_table_descr ?= cl_abap_typedescr=>describe_by_name( zp_table ).
zit_tabdescr[] = zref_table_descr->components[].

Set the structure of the table in the FIELDCAT, the structure of the ALV is based on this.


LOOP AT zit_tabdescr INTO zwa_tabdescr.
   CLEAR zwa_fieldcat.
   zwa_fieldcat-fieldname = zwa_tabdescr-name .
   zwa_fieldcat-datatype  = zwa_tabdescr-type_kind.
   zwa_fieldcat-inttype   = zwa_tabdescr-type_kind.
   zwa_fieldcat-intlen    = zwa_tabdescr-length.
   zwa_fieldcat-decimals  = zwa_tabdescr-decimals.
   APPEND zwa_fieldcat TO zit_fieldcat.
ENDLOOP.


Create dynamic internal table and assign to Field Symbol


CALL METHOD cl_alv_table_create=>create_dynamic_table
   EXPORTING
     it_fieldcatalog = zit_fieldcat
   IMPORTING
     ep_table        = zdyn_table.
ASSIGN zdyn_table->* TO <fs_table>.

Create dynamic work area and assign to Field Symbol


CREATE DATA zdyn_line LIKE LINE OF <fs_table>.
ASSIGN zdyn_line->* TO <fs_wa>.

When the dynamic table is setted up, this one can be filled with an SELECT statement. It gets all the values from the filed parameter.


SELECT * INTO CORRESPONDING FIELDS OF TABLE  <fs_table>
FROM (zp_table).

An ALV Function module to build field catalog from the dynamic created table.


DATA: zit_fcat  TYPE slis_t_fieldcat_alv.
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
   EXPORTING
     i_structure_name       = zp_table
   CHANGING
     ct_fieldcat            = zit_fcat
   EXCEPTIONS
     inconsistent_interface = 1
     program_error          = 2
     OTHERS                 = 3.
IF sy-subrc <> 0.
   MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
           WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

Fieldcatalog is moved to a new fieldcatalog


zfieldcatalog[] =  zit_fcat[].

To optimize every field length:


zgd_layout-colwidth_optimize = 'X'.

The ALV will be showed with the next function module. Layout, fieldcatalog and repid are given in EXPORTING, also the table with al the values.


zgd_repid = sy-repid.
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
   EXPORTING
     i_callback_program = zgd_repid
     is_layout          = zgd_layout
     it_fieldcat        = zfieldcatalog[]
     i_save             = 'X'
   TABLES
     t_outtab           = <fs_table>
   EXCEPTIONS
     program_error      = 1
OTHERS             = 2.

Kind regards,

Pieter Lemaire

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Tudor Riscutia

    Hello Pieter,

    This is a very good post, especially for beginners in dynamic data display. My suggestion would be to consider using SALV class instead the old function modules. This way, your code will be much lighter and easier to maintain.

    Here’s a short example: (I wrote it in notepad++, so I’m not really sure it works)

    PARAMETERS:

      p_table TYPE tabname.

    DATA:

      lr_table        TYPE REF TO cl_salv_table,

      lr_data         TYPE REF TO data,

      lr_typedescr TYPE REF TO cl_abap_typedescr,

      lv_sql           TYPE string VALUE `*`.

    FIELD-SYMBOLS:

      <ft_data>           TYPE any,

      <fs_component> TYPE abap_compdescr.

    “create table

    CREATE DATA lr_data TYPE (p_table).

    ASSIGN lr_data->* TO <ft_data>.

    CHECK <ft_data> IS ASSIGNED.

    lr_typedescr ?= cl_abap_typedescr=>describe_by_name( p_table ). 

    IF lr_typedescr IS BOUND.

      LOOP AT lr_typedescr->components[] ASSIGNING <fs_component>. 

      CONCATENATE lv_sql <fs_component>-name

                               INTO lv_sql

                               SEPARATED BY space.

      ENDLOOP.

    ENDIF.

    SELECT (lv_sql)

                  FROM (p_table)

                  INTO TABLE <ft_table>.

    IF sy-subrc IS INITIAL.

      TRY.

         cl_salv_table=>factory( IMPORTING r_salv_table = lr_table

                                           CHANGING  t_table        = <ft_data> ).

      CATCH cx_salv_msg.

      “handle errors

      ENDTRY.

      IF lr_table IS BOUND.

         lr_table->display( ).

      ENDIF.

    ENDIF.

    Of course you’ll have to check the P_TABNAME in the beginning if it really is a DDIC table.

    Hope this is helpful 🙂

    Tudor

    (0) 
    1. Pieter Lemaire Post author

      Thanks, I have combinded it with mine code and there is one thing I don’t know.

      The values are showed without the header (where the description of the field stands), like you can see in the image below.

      Capture.PNG

      Pieter

      (0) 
      1. Tudor Riscutia

        Hmm,

        I’ve had a chance to copy-paste my code into the ABAP editor, so I’ve made a few corrections:

        parameters:
          p_table type tabname.

        data:
          lr_table       type ref to cl_salv_table,
          lr_data        type ref to data,
        lr_structdescr type ref to cl_abap_structdescr,
          lv_sql         type string value `*`.

        field-symbols:
          <ft_data>      type table,
          <fs_component> type abap_compdescr.

        “create table
        create data lr_data type standard table of (p_table).
        assign lr_data->* to <ft_data>.

        ” SAP doesn’t recomment `SELECT *`, so we basically get all components
        lr_structdescr ?= cl_abap_structdescr=>describe_by_name( p_table ).
        if lr_structdescr is bound.
          loop at lr_structdescr->components[] assigning <fs_component>.
            concatenate lv_sql <fs_component>-name
                        into lv_sql
                        separated by space.
          endloop.
        endif.

        select (lv_sql)
               from (p_table)
               into table <ft_data>.

        if sy-subrc is initial.
          try.
              cl_salv_table=>factory( importing r_salv_table = lr_table
                                                    changing  t_table      = <ft_data> ).
            catch cx_salv_msg.
              “handle errors
          endtry.

          if lr_table is bound.
            lr_table->display( ).
          endif.

        endif.

        I have no idea why you don’t get any headers.. try to run the code above and tell me if you still get the same result.

        Untitled.png

        As far as I know, if this is a DDIC structure, it will automatically take the Field Labels for every data element.

        For locally created types, it’s a little more complicated..

        Tudor

        (0) 

Leave a Reply