Skip to Content

Hello everyone! The purpose of this blog is to provide a solution to add columns in a table view at runtime. So far, tableviews the most extensively used html element has to be defined in the view configuration directly or use an iterator to introduce images in individual cells. It was hankering in my mind to come up with a solution to define columns dynamically at runtime and bend the functionality of tableview as we wish and finally i was able to figure a solution.

The idea is to create dynamic structures & workarea using runtime type services. Let me elaborate it with an example.

In the below picture, the table has 9 columns in total, out of which 4 are static columns that is the attribuutes are defined at the time of creating the view and the remaining five columns are created at runtime.

DynCol1.jpg

For instance, lets define the dynamic columns in a custom table “ZDYN_COLUMNS”. The table stores the columns name, its data type and its technical name.

DynCol3.jpg

To start with, create a view with a value node, lets call it “DYNTV” and add the static attributes to it. This is the basic structure of our table view,

DynCol2.jpg

Now, the dynamic columns must be added to the table structure and also to the value node “DYNTV”. To add columns to our value node we must redefine the method “IF_BSP_MODEL~INIT” of our context node class. Create an internal table of type abap_components_tab and add our static fields to it. Pass the field name and elementary data type using runtime type services.

METHOD if_bsp_model~init.

* Structure with static columns

TYPES: BEGIN OF ltype_attr_struct,
     position        TYPE crmt_number_int,
     productid     
TYPE comt_product_id,
     configurable 
TYPE comt_product_configurable,
     quantity      
TYPE crmt_schedlin_quan,
END OF ltype_attr_struct.

* Data declarations 

DATA: lt_comp             TYPE abap_component_tab,
         
ls_comp             TYPE abap_componentdescr,
          lt_dynamic_cols 
TYPE TABLE OF zdyn_columns,
          ls_dynamic_cols
TYPE zdyn_columns,
          ls_struct            
TYPE ltype_attr_struct.

* Add the static columns to internal table

lr_element ?= cl_abap_elemdescr=>describe_by_data( ls_struct-position ).
ls_comp-name = ‘Position’.
ls_comp-type = lr_element.
INSERT ls_comp INTO TABLE lt_comp.

lr_element ?= cl_abap_elemdescr=>describe_by_data( ls_struct-productid ).
ls_comp-name = ‘Description’.
ls_comp-type = lr_element.
INSERT ls_comp INTO TABLE lt_comp.

lr_element ?= cl_abap_elemdescr=>describe_by_data( ls_struct-configurable ).
ls_comp-name = ‘Configurable’.
ls_comp-type = lr_element.
INSERT ls_comp INTO TABLE lt_comp.

lr_element ?= cl_abap_elemdescr=>describe_by_data( ls_struct-quantity ).
ls_comp-name = ‘Quantity’.
ls_comp-type = lr_element.
INSERT ls_comp INTO TABLE lt_comp.

Get the dynamic columns form the custom table and pass them to the abap component descriptor. 

SELECT * FROM zdyn_columns

                INTO TABLE lt_dynamic_cols.

* Loop into the dynamic columns and assign them to abap components tab

LOOP AT lt_dynamic_cols INTO ls_dynamic_cols.
     lr_element        ?= cl_abap_elemdescr=>describe_by_data( ls_dynamic_cols-field_type ).
     ls_comp-name    = ls_dynamic_cols-technical_name.
     ls_comp-type      = lr_element.
     INSERT ls_comp INTO TABLE lt_comp.
ENDLOOP
.

* Declare a global internal table and assign itab lt_comp
* The global table wil be used in method GET_TABLE_LINE_SAMPLE and tableview iterator
gt_comp = lt_comp.

Now, create a structure and craete a value node and add it to the collection wrapper.

* Create the structure type

lr_struct ?= cl_abap_structdescr=>create( p_components = lt_comp p_strict = abap_false ).
* Create data with reference to the type object

CREATE DATA dref TYPEHANDLE lr_struct.
super->if_bsp_model~init(
id = id
                                   owner = owner ).
* Create a value node
CREATE OBJECT lr_value_node
                    EXPORTING iv_data_ref = dref.
* Create a BO collection
CREATE OBJECT lv_bo_coll TYPE cl_crm_bol_bo_col.
* Add the value node to the BO collection
lv_bo_coll->add( lr_value_node ).
* Set the collection wrapper
set_collection( lv_bo_coll ).

The second part is to add the dynamic columns to the table structure by redefining the method GET_TABLE_LINE_SAMPLE and using the global internal table gt_comp.

METHOD get_table_line_sample.

* Data declarations

DATA: lr_struct     TYPE REF TO  cl_abap_structdescr,
           lr_itab        T
YPE REF TO cl_abap_tabledescr,
           lr_line       
TYPE REF TO data,
           dref          
TYPE REF TO data.

FIELD-SYMBOLS : <lt_outtab> TYPE ANY TABLE,
                             <ls_outtab>
TYPE ANY.

IF gt_comp IS NOT INITIAL.
* Create a structure type using the global internal table gt_comp
     lr_struct ?= cl_abap_structdescr=>create( p_components = gt_comp  p_strict = abap_false ).
* Create a new table type
     lr_itab    ?= cl_abap_tabledescr=>create( lr_struct ).
* Create a data with reference to type object
     CREATE DATA dref TYPE HANDLE lr_itab.
     ASSIGN dref->* TO <lt_outtab>.
* Create dynamic work area and assign to FS

     CREATE DATA lr_line LIKE LINE OF <lt_outtab>.
     rv_sample = lr_line.

ENDIF.
ENDMETHOD.

  Create a table view iterator to define the column name and its properties. This is necessary since we do not use the configuration tab to define column properties. Redefine the method “GET_COLUMN_DEFINITIONS” and fill in the column properties,


ls_col_def-columnname           = ls_comp-name.
ls_col_def-title                         = ls_dynamic_cols-field_name. 
  

ls_col_def-wrapping                 = abap_false.
ls_col_def-width                      = ‘100px’.
ls_col_def-horizontalalignment  =
‘LEFT’.  

APPEND

ls_col_def TO p_column_definitions.

Define the layout page and pass the iterator,

<%@page language=”abap” %>

<%@extension name=”thtmlb” prefix=”thtmlb” %>

<%@extension name=”chtmlb” prefix=”chtmlb” %>

<%@extension name=”bsp” prefix=”bsp” %>

<%

  Data: lr_iterator TYPE REF TO ZDYN_COLUMN_ITERATOR.

  CREATE OBJECT lr_ITERATOR EXPORTING ir_context_node = dyntv.

%>

<thtmlb:cellerator editMode                  = “ALL”

                          id                             = “TableView”

                          actionsMaxInRow      = “6”

                          onRowSelection        = “select”

                          headerText               = “Dynamic Columns-Example”

                          personalizable          = “TRUE”

                          table                        = “//dyntv/Table”

                          usage                      = “EDITLIST”

                          iterator                     = “<%= lr_ITERATOR %>” />

Output:

DynCol4.jpg

 

Regards,
Arun
ArunKumar Balakrishnan.
To report this post you need to login first.

8 Comments

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

    1. ArunKumar Balakrishnan Post author

      Hi Anil,

      There are different approaches to dynamically display a field in form view,

      1. Get the configurtion data using method GET_CONFIG_DATA, replace the attribute and then pass the XML string to SET_CONFIG_DATA.
      2. Create thtml field elements directly in view layout and make them visible/hidden based on some conditional check.
      3. Create different configuration with/without the particular field and toggle between them in do_config_determintion method

      Regards,

      Arun

      (0) 
      1. ANIL TURUMELLA

        Hi Arun,

        Thanks for the quick reply.

        for me the 3rd option is not valid as i dont know which field i am going to add. So, i cannot add them in the configuration.

        For me, i need to show the fields dynamically in the form with out adding them in configuration at design time.

        For the first point u mentioned, can i add them even if they are are not present in the configuration at design time ?

        Regards,

        Anil

        (0) 
        1. ANIL TURUMELLA

          For the attributes to be added into the Form view i don’t have them in the Context node. The attributes which i want to show in the form view dynamically need to be added may be by a value node.

          (0) 
          1. ArunKumar Balakrishnan Post author

            You can get the configuration data, convert the xml data to internal table, add the respective fields, convert the itab to xml and finally set the configuration data by calling set_config_data.

            Regards,

            Arun

            (0) 
            1. ANIL TURUMELLA

              Hi Arun,

              Can you please provide me an example how to use set_config_data and get_config_data and create. Which methods we need to use to convert XML to ITAB and vice Versa.

              Thanks,

              Anil

              (0) 
  1. Anne Lubig

    Hello Arun,

    thanks for this create blog.

    I have done all the steps but I have a problem with these lines:

    CREATE DATA dref TYPEHANDLE lr_struct.
    super->if_bsp_model~init(
    id = id
                                       owner = owner ).
    * Create a value node
    CREATE OBJECT lr_value_node
                        EXPORTING iv_data_ref = dref.

    Can you tell me what is the data type of dref and where does it come from?

    I used the type ltype_attr_struct but then I get this error message:

    Type error when assigning data references

    Regards,

    Anne

    (0) 

Leave a Reply