Quantcast
Channel: ABAP Development
Viewing all articles
Browse latest Browse all 948

Creating internal table at runtime and display it (dynamic design) - beginners

$
0
0

Hi at all! I am relatively new to ABAP and I am just sitting in on creating some templates for often used topics.

The problem I have is that a lot of posts are not explained very well, hence it is often hard to understand what the person who blogged something about a topic is really doing within the code. Therefore I provide now – in my eyes – an important topic regarding the creation of internal tables at runtime.This gives you more flexibility and this class can also be reused.
I try to describe this topic as clear as possible to you.

Moreover i have decided to not use the plain text editor because this is pretty impractical reagarding copying.

If you have any questions or suggestions please let me now!!!

There is also a picture of the report attached

 

Regards Patrick.

 

 

Below you can see the class zcl_dynamic_db_query which handles the dynamic creation of an internal table.


CLASS zcl_dynamic_db_query DEFINITION

   PUBLIC

   FINAL

   CREATE PUBLIC .

 

PUBLIC SECTION.

*  public static method 'main' receives 3 input parameters from the calling program ->

*  the name of the DB-Table, the Columns which are needed and the where clause

   CLASS-METHODS main

     IMPORTING

       !dbtab TYPE csequence

       !cols   TYPE csequence

       !where TYPE csequence.

 

PROTECTED SECTION.

 

 

PRIVATE SECTION.

*  private static method 'display'; is used to give out the table header and

*  the result of the SELECT Statement executed in static method 'main'

   CLASS-METHODS display

     IMPORTING

       VALUE(result) TYPE STANDARD TABLE

       !struct_header TYPE REF TO cl_abap_structdescr .

 

 

ENDCLASS.          "end of definition

 

 

CLASS zcl_dynamic_db_query IMPLEMENTATION.

 

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Static Public Method ZCL_DYNAMIC_DB_QUERY=>MAIN

* +-------------------------------------------------------------------------------------------------+

* | [--->] DBTAB                         TYPE        CSEQUENCE

* | [--->] COLS                           TYPE        CSEQUENCE

* | [--->] WHERE                        TYPE        CSEQUENCE

* +--------------------------------------------------------------------------------------</SIGNATURE>

 

 

  METHOD main.

 

*     here we make use of the ABAP RTTS (Run Time Type Services) and

*     RTTI (Run Time Type Information) Classes which help us to find out

*    the structure of a table at runtime and also the types of its columns

    DATA: type_descr   TYPE REF TO cl_abap_typedescr,

               struct_descr TYPE REF TO cl_abap_structdescr,

               table_descr  TYPE REF TO cl_abap_tabledescr,

               table_ref    TYPE REF TO data,

              components   TYPE cl_abap_structdescr=>component_table,

              component    LIKE LINE OF components,

              error        TYPE REF TO cx_root.

 

*   field symbols are place holder for existing data objects and parts of existing data objects.

*  we need them to create the table to fill in the input of the query

    FIELD-SYMBOLS: <table>      TYPE ANY TABLE.

 

*   this creates a bunch of type descriptions of the table 'dbtab' and

*   saves the typeinformation into the variable 'type_descr'

    cl_abap_typedescr=>describe_by_name(

                       EXPORTING  p_name = dbtab

                       RECEIVING  p_descr_ref = type_descr

                       EXCEPTIONS type_not_found = 4 ).

    IF sy-subrc = 4.

      MESSAGE 'Type not found error' TYPE 'I' DISPLAY LIKE 'E'.

      RETURN.

    ENDIF.

 

    TRY.

*     now we use a down cast. the downcast is used when the static type of the

*     source variable is 'data' and the static type of the target variable

*     is completely typed. if not the exception cx_sy_move_cast_error is raised

      struct_descr ?= type_descr.

 

      CATCH cx_sy_move_cast_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

      RETURN.

    ENDTRY.

 

*   get components saves all components(== columns) of the table into the variable 'components'

    components = struct_descr->get_components( ).

 

 

*   If all columns are selected all components of the structure remain in the components variable

    IF cols = '*'.

*   else sort out those who are not needed

 

 

    ELSE.

      LOOP AT components INTO component.

        CONCATENATE '\b' component-name '\b' INTO component-name.

 

*     search for  all components which are inside of 'cols' and sort

*     out those columns inside the' components ' variable which are not needed

        FIND REGEX component-name IN cols.

 

 

        IF sy-subrc <> 0.

          DELETE components INDEX sy-tabix.

        ENDIF.

 

 

      ENDLOOP.

 

 

    ENDIF.

 

 

    TRY.

*     now we overwrite the existing structure with a new structure which

*     holds only those columns which are needed

      struct_descr = cl_abap_structdescr=>create( components ).

 

 

*     now we 'create' the description of the table which  will be needed in the end

      table_descr  = cl_abap_tabledescr=>create( struct_descr ).

 

      CATCH cx_sy_struct_creation cx_sy_table_creation INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

    ENDTRY.

    TRY.

*     with 'TYPE HANDLE' we are able to reference a typed object of RTTS

*     the information was gathered with the aid of RTTI and now

*     the information is saved into the variable table_ref. This is necessary

*     because we cannot assign  with a RTTS object --> we need a data variable to do so

      CREATE DATA table_ref TYPE HANDLE table_descr.

 

 

*     now assign the structure of the table to the field symbol

      ASSIGN table_ref->* TO <table>.

 

      CATCH cx_sy_create_data_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

     ENDTRY.

 

 

*     now we have to query the needed data from the table and save it into our table

     TRY.

     SELECT (cols)

      FROM (dbtab)

      INTO CORRESPONDING FIELDS OF TABLE <table>

      WHERE (where).

 

 

      CATCH cx_sy_sql_error INTO error.

        MESSAGE error TYPE 'I' DISPLAY LIKE 'E'.

        RETURN.

 

 

     ENDTRY.

 

*     now we call the display function exporting the table with our information

*     and the structure of the table (which is needed for the header line)

      display(

            EXPORTING result = <table>

                      struct_header = struct_descr

                       ).

 

  ENDMETHOD.                    "main

 

 

* <SIGNATURE>---------------------------------------------------------------------------------------+

* | Static Private Method ZCL_DYNAMIC_DB_QUERY=>DISPLAY

* +------------------------------------      -------------------------------------------------------------+

* | [--->] RESULT                             TYPE        STANDARD TABLE

* | [--->] STRUCT_HEADER          TYPE REF TO CL_ABAP_STRUCTDESCR

* +--------------------------------------------------------------------------------------</SIGNATURE>

 

 

METHOD display.

    FIELD-SYMBOLS: <wa>              TYPE any,

                                <component>  TYPE any,

                                <wa_header>   LIKE LINE OF struct_header->components.

 

 

*      reading and displaying the header of the dynamically created table

       LOOP AT struct_header->components ASSIGNING <wa_header>.

         WRITE <wa_header>-name.

       ENDLOOP.

 

*      reading out the content of the internal table

       NEW-LINE.

       LOOP AT result ASSIGNING <wa>.

         DO.

          ASSIGN COMPONENT sy-index OF STRUCTURE <wa>

          TO <component>.

          IF sy-subrc <> 0.

            EXIT. "no more components

         ENDIF.

        WRITE: <component>.

      ENDDO.

      NEW-LINE.

      ENDLOOP.


 

   ENDMETHOD. " end of method 'display'


ENDCLASS. "end of class implementation




Now the report with a call of the class.


*&---------------------------------------------------------------------*
*& Report  ZLP_DYN_DB
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ZLP_DYN_DB.

parameters:
  p_dbtab Type c length 132,
  p_cols  Type c length 132,
  p_where Type c length 132.


START-OF-SELECTION.

zcl_dynamic_db_query=>main(
        EXPORTING dbtab = p_dbtab
                  cols  = p_cols
                  where = p_where ).


Viewing all articles
Browse latest Browse all 948

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>