Usually , there is a need for custom customizing tables to accommodate project specific requirements. Uploading the data into these tables through “Table maintenance” can get difficult for each and every table ( if the records are more or more columns are there in table).  In such situations , we typically write custom (SE38) programs / LSMW to load the data into these tables using data files. Also, we need to provide GUI access along with Web UI access to maintain these tables.

To overcome all these complexities, I developed a custom Web UI component to facilitate data load for any given custom table ( preferably customizing tables).

Features of this tool:

1. Works with any table.

2. Provided table columns will be displayed dynamically.

2. Uploaded file data will be displayed in the assignment block columns in sequential order of the file data.

3. Works with text and csv files.

4. File data gets saved to the specified table.

However , depending on your additional requirements – like data validation, mismatch of file columns order with table columns order etc, you have to develop further to meet your requirements.

Please follow below steps to develop this component:

Component.jpg

Component Details :

Created a component “Z_TABL_UPD” with MainWindow, then created three views – “TableView”, “FileUpload” , “DataView” and an overview page “FileUpdOvrPage”.

Created a custom component “CuCoDataUpd” with context nodes ‘FILEPARAM’ and ‘DBTABLE’ then performed context node binding with views – “FileUpload” view context node ‘FILEPARM’, “TableView”  view context node ‘DBTABLE’.

Custom Component “CuCoDataUpd” Details :

Custom Controller.JPG

OverviewPage “FileUpdOvrPage” Details :

OverViewPage.jpg

Over View Page Configuration.JPG

“FileUpload” View Details:

FileUpload-1.JPG

FileUpload-2.jpg

Upload Event Details :

It is same like GS_FILE_UPLOAD component , View VFileUpload , Event “Upload”  and Bounded the FILEPARAM context node with custom controller context node.

Custom Controller FILEPARAM Bounding.JPG

File Type Selection Event Details :

METHOD eh_onsel_fltyp.

  DATA : lv_selection   TYPE string,

         lr_htmlb_ddlb  TYPE REF TO cl_htmlb_event_selection.

  IF htmlb_event_ex->event_class EQ ‘CL_HTMLB_EVENT_SELECTION’.

    lr_htmlb_ddlb ?= htmlb_event_ex.

    lv_selection  = lr_htmlb_ddlb->selection.

    me->typed_context->fileparam->set_type( attribute_path = ‘//FILEPARAM/TYPE’ value = lv_selection ).

  ENDIF.

ENDMETHOD.

“DataView” View Details :

DataView-1.jpg

DataView-2.jpg

Context Node INIT Method :

METHOD if_bsp_model~init.

  DATA:

        lr_custom_controller TYPE REF TO zl_z_tabl_u_cucodataupd_impl,

        lr_controller        TYPE REF TO zl_z_tabl_u_dataview_impl,

        lr_coll_wrapper      TYPE REF TO cl_bsp_wd_collection_wrapper,

        lr_entity            TYPE REF TO cl_crm_bol_entity,

        lr_table             TYPE REF TO if_bol_bo_property_access,

        lv_table             TYPE string,

        lv_tabname           TYPE ddobjname,

        lt_fields            TYPE ddfields,

        ls_field             TYPE dfies,

        lt_columns           TYPE abap_component_tab,

        ls_column            TYPE abap_componentdescr,

        lr_element           TYPE REF TO cl_abap_datadescr,

        lr_struct            TYPE REF TO  cl_abap_structdescr,

        lr_itab              TYPE REF TO cl_abap_tabledescr,

        lr_line              TYPE REF TO data,

        lr_dref              TYPE REF TO data,

        lr_value_node        TYPE REF TO cl_bsp_wd_value_node,

        lr_bo_coll           TYPE REF TO if_bol_bo_col.

  super->if_bsp_model~init( id   = id

                            owner = owner ).

  CHECK owner IS BOUND.

  lr_controller       ?= owner.

  lr_custom_controller = lr_controller->get_cust_controller( ).

  gr_cuco             ?= lr_custom_controller.

  lr_coll_wrapper = lr_custom_controller->typed_context->dbtable->get_collection_wrapper( ).

  lr_table       ?= lr_coll_wrapper->get_current( ).

  lv_table       = lr_table->get_property_as_string( iv_attr_name = ‘TBMA_VAL’ ).

  lv_tabname = lv_table.

  CHECK NOT lv_tabname IS INITIAL.

  CALL METHOD lr_custom_controller->get_table_fields

    EXPORTING

      iv_tabname = lv_tabname

    IMPORTING

      et_fields = lt_fields.

  LOOP AT lt_fields INTO ls_field.

    lr_element        ?= cl_abap_elemdescr=>describe_by_data( ls_field-datatype ).

    ls_column-name    = ls_field-fieldname.

    ls_column-type    = lr_element.

    INSERT ls_column INTO TABLE lt_columns.

  ENDLOOP.

  gt_columns[] = lt_columns.

* Create the structure type

  lr_struct ?= cl_abap_structdescr=>create( p_components = lt_columns p_strict = abap_false  ).

* Create data with reference to the type object

  CREATE DATA lr_dref

         TYPE HANDLE lr_struct.

* Create a value node

  CREATE OBJECT lr_value_node

    EXPORTING

      iv_data_ref = lr_dref.

* Create a BO collection

  CREATE OBJECT lr_bo_coll TYPE cl_crm_bol_bo_col.

* Add the value node to the BO collection

  lr_bo_coll->add( lr_value_node ).

* Set the collection wrapper

  set_collection( lr_bo_coll ).

ENDMETHOD.

GET_TABLE_LINE_SAMPLE Method :

METHOD get_table_line_sample.

  DATA:

      lr_custom_controller TYPE REF TO zl_z_tabl_u_cucodataupd_impl,

      lr_coll_wrapper      TYPE REF TO cl_bsp_wd_collection_wrapper,

      lr_entity            TYPE REF TO cl_crm_bol_entity,

      lr_table             TYPE REF TO if_bol_bo_property_access,

      lv_table             TYPE string,

      lv_tabname           TYPE ddobjname,

      lt_fields            TYPE ddfields,

      ls_field             TYPE dfies,

      lt_columns           TYPE abap_component_tab,

      ls_column            TYPE abap_componentdescr,

      lr_element           TYPE REF TO cl_abap_datadescr,

      lr_struct            TYPE REF TO cl_abap_structdescr,

      lr_itab              TYPE REF TO cl_abap_tabledescr,

      lr_line              TYPE REF TO data,

      lr_dref              TYPE REF TO data.

  FIELD-SYMBOLS :

      <fs_outtab_t>        TYPE ANY TABLE,

      <fs_outtab_s>        TYPE any.

  lr_custom_controller ?= gr_cuco.

  lr_coll_wrapper = lr_custom_controller->typed_context->dbtable->get_collection_wrapper( ).

  lr_table       ?= lr_coll_wrapper->get_current( ).

  lv_table       = lr_table->get_property_as_string( iv_attr_name = ‘TBMA_VAL’ ).

  lv_tabname = lv_table.

  CHECK lv_tabname IS NOT INITIAL.

  CALL METHOD lr_custom_controller->get_table_fields

    EXPORTING

      iv_tabname = lv_tabname

    IMPORTING

      et_fields = lt_fields.

  LOOP AT lt_fields INTO ls_field.

    lr_element        ?= cl_abap_elemdescr=>describe_by_data( ls_field-datatype ).

    ls_column-name    = ls_field-fieldname.

    ls_column-type    = lr_element.

    INSERT ls_column INTO TABLE lt_columns.

  ENDLOOP.

  gt_columns[] = lt_columns.

  IF lt_columns IS NOT INITIAL.

    lr_struct ?= cl_abap_structdescr=>create( p_components = lt_columns  p_strict = abap_false ).

    lr_itab   ?= cl_abap_tabledescr=>create( lr_struct ).

*   Create a data with reference to type object

    CREATE DATA lr_dref TYPE HANDLE lr_itab.

    ASSIGN lr_dref->* TO <fs_outtab_t>.

*   Create dynamic work area and assign to FS

    CREATE DATA lr_line LIKE LINE OF <fs_outtab_t>.

    rv_sample = lr_line.

  ENDIF.

ENDMETHOD.

Save Data Method :

METHOD eh_onsave.

  DATA:

      lr_coll_wrapper              TYPE REF TO cl_bsp_wd_collection_wrapper,

      lr_entity                    TYPE REF TO if_bol_bo_property_access,

      lr_table                     TYPE REF TO if_bol_bo_property_access,

      lv_table                     TYPE string,

      lv_selection                 TYPE string,

      lv_tabname                   TYPE ddobjname,

      lt_fields                    TYPE ddfields,

      ls_field                     TYPE dfies,

      lt_tabledata                 TYPE REF TO data,

      lv_sy_subrc                  TYPE sy-subrc VALUE 0,

      lv_field_name                TYPE char40,

      lt_dref_seltable             TYPE REF TO data,

      ls_dref_line                 TYPE REF TO data,

      lt_field                     TYPE string_table,

      lt_field_val                 TYPE string_table,

      lv_last_field                TYPE string,

      lv_index                     TYPE i,

      lv_tabix                     TYPE i,

      lr_value_node                TYPE REF TO cl_bsp_wd_value_node,

      lr_res_coll                  TYPE REF TO if_bol_bo_col,

      lv_counter                   TYPE i,

      lv_file_content_string       TYPE string,

      lr_custom_controller         TYPE REF TO zl_z_tabl_u_cucodataupd_impl,

      lr_collection                TYPE REF TO if_bol_bo_col,

      lr_msg_service               TYPE REF TO cl_bsp_wd_message_service.

  FIELD-SYMBOLS:

     <lv_field>                    TYPE string,

     <lv_field_val>                TYPE string,

     <ls_field>                    TYPE any,

     <fs_dyn_table>                TYPE table,

     <fs_tabline>                  TYPE any.

  CONSTANTS:

         lc_comma                  TYPE c VALUE ‘,’.

  lr_custom_controller   = me->get_cust_controller( ).

  lr_coll_wrapper        = lr_custom_controller->typed_context->dbtable->get_collection_wrapper( ).

  lr_table               ?= lr_coll_wrapper->get_current( ).

  lv_table               = lr_table->get_property_as_string( iv_attr_name = ‘TBMA_VAL’ ).

  lr_coll_wrapper        = lr_custom_controller->typed_context->fileparam->get_collection_wrapper( ).

  lr_entity              ?= lr_coll_wrapper->get_current( ).

  lv_file_content_string = lr_entity->get_property_as_string( iv_attr_name = ‘FILEDATA’ ).

  lv_selection           = lr_entity->get_property_as_string( iv_attr_name = ‘TYPE’ ).

  CHECK lv_table IS NOT INITIAL.

  lv_tabname = lv_table.

  CALL METHOD lr_custom_controller->get_table_fields

    EXPORTING

      iv_tabname = lv_tabname

    IMPORTING

      et_fields = lt_fields.

  SPLIT lv_file_content_string AT cl_abap_char_utilities=>cr_lf INTO TABLE lt_field.

  TRY.

      CREATE DATA lt_dref_seltable TYPE TABLE OF (lv_tabname)  .

    CATCH cx_sy_create_data_error.

      RETURN.

  ENDTRY.

  ASSIGN lt_dref_seltable->* TO <fs_dyn_table>.

  TRY.

      CREATE DATA ls_dref_line LIKE LINE OF <fs_dyn_table>.

    CATCH cx_sy_create_data_error.

      RETURN.

  ENDTRY.

  ASSIGN ls_dref_line->* TO <fs_tabline>.

  lv_counter = 1.

  LOOP AT lt_field ASSIGNING <lv_field>.

    IF lv_counter EQ 1.

      READ TABLE lt_fields INTO ls_field INDEX lv_counter.

      CONCATENATE ‘<fs_tabline>-‘ ls_field-fieldname INTO lv_field_name.

      ASSIGN (lv_field_name) TO <ls_field>.

      <ls_field> = sy-mandt.

      lv_counter = lv_counter + 1.

    ENDIF.

    CASE lv_selection.

      WHEN ‘1’.

        SPLIT <lv_field> AT cl_abap_char_utilities=>horizontal_tab INTO TABLE lt_field_val.

      WHEN ‘2’.

        SPLIT <lv_field> AT lc_comma INTO TABLE lt_field_val.

    ENDCASE.

    LOOP AT lt_field_val ASSIGNING <lv_field_val>.

      lv_tabix = sy-tabix.

      READ TABLE lt_fields INTO ls_field INDEX lv_counter.

      CONCATENATE ‘<fs_tabline>-‘ ls_field-fieldname INTO lv_field_name.

      ASSIGN (lv_field_name) TO <ls_field>.

      <ls_field> = <lv_field_val>.

      lv_counter = lv_counter + 1.

    ENDLOOP.

    APPEND <fs_tabline> TO <fs_dyn_table>.

    lv_counter = 1.

  ENDLOOP.

  IF NOT <fs_dyn_table>[] IS INITIAL.

    CALL FUNCTION ‘ENQUEUE_E_TABLEE’

      EXPORTING

        mode_rstable  = ‘E’

        tabname       = lv_tabname

*       VARKEY         =

*       X_TABNAME      = ‘ ‘

*       X_VARKEY       = ‘ ‘

*       _SCOPE         = ‘2’

*       _WAIT          = ‘ ‘

*       _COLLECT       = ‘ ‘

      EXCEPTIONS

        foreign_lock  = 1

        system_failure = 2

        OTHERS        = 3.

    IF sy-subrc EQ 0.

      MODIFY (lv_tabname) FROM TABLE <fs_dyn_table>.

      IF sy-subrc EQ 0.

        lr_msg_service = cl_bsp_wd_message_service=>get_instance( ).

        lr_msg_service->add_message( iv_msg_type   = ‘S’

                                     iv_msg_id     = ’00’

                                     iv_msg_number = ‘001’

                                     iv_msg_v1     = ‘Data Saved Successfully’ ).

        COMMIT WORK.

      ELSE.

        ROLLBACK WORK.

      ENDIF.

      CALL FUNCTION ‘DEQUEUE_E_TABLEE’

        EXPORTING

          mode_rstable = ‘E’

          tabname     = lv_tabname.

*         VARKEY       =

*         X_TABNAME    = ‘ ‘

*         X_VARKEY     = ‘ ‘

*         _SCOPE       = ‘3’

*         _SYNCHRON    = ‘ ‘

*         _COLLECT     = ‘ ‘

    ENDIF.

  ENDIF.

ENDMETHOD.

Display Data :

METHOD do_prepare_output.

  DATA:

        lr_coll_wrapper              TYPE REF TO cl_bsp_wd_collection_wrapper,

        lr_entity                    TYPE REF TO if_bol_bo_property_access,

        lr_table                     TYPE REF TO if_bol_bo_property_access,

        lv_table                     TYPE string,

        lv_selection                 TYPE string,

        lv_tabname                   TYPE ddobjname,

        lt_fields                    TYPE ddfields,

        ls_field                     TYPE dfies,

        lt_tabledata                 TYPE REF TO data,

        lv_sy_subrc                  TYPE sy-subrc VALUE 0,

        lv_field_name                TYPE char40,

        lt_dref_seltable             TYPE REF TO data,

        ls_dref_line                 TYPE REF TO data,

        lt_field                     TYPE string_table,

        lt_field_val                 TYPE string_table,

        lv_last_field                TYPE string,

        lv_index                     TYPE i,

        lv_tabix                     TYPE i,

        lr_value_node                TYPE REF TO cl_bsp_wd_value_node,

        lr_res_coll                  TYPE REF TO if_bol_bo_col,

        lv_counter                   TYPE i,

        lv_file_content_string       TYPE string,

        lr_custom_controller         TYPE REF TO zl_z_tabl_u_cucodataupd_impl,

        lr_collection                TYPE REF TO if_bol_bo_col.

  FIELD-SYMBOLS:

       <lv_field>                    TYPE string,

       <lv_field_val>                TYPE string,

       <ls_field>                    TYPE any,

       <fs_dyn_table>                TYPE table,

       <fs_tabline>                  TYPE any.

  CONSTANTS:

        lc_comma                     TYPE c VALUE ‘,’.

  lr_custom_controller = me->get_cust_controller( ).

  lr_coll_wrapper     = lr_custom_controller->typed_context->dbtable->get_collection_wrapper( ).

  lr_table            ?= lr_coll_wrapper->get_current( ).

  lv_table            = lr_table->get_property_as_string( iv_attr_name = ‘TBMA_VAL’ ).

  lr_coll_wrapper   = lr_custom_controller->typed_context->fileparam->get_collection_wrapper( ).

  lr_entity              ?= lr_coll_wrapper->get_current( ).

  lv_file_content_string = lr_entity->get_property_as_string( iv_attr_name = ‘FILEDATA’ ).

  lv_selection           = lr_entity->get_property_as_string( iv_attr_name = ‘TYPE’ ).

  CHECK lv_table IS NOT INITIAL.

  CALL METHOD super->do_prepare_output.

*  EXPORTING

*    iv_first_time = ABAP_FALSE

  lv_tabname = lv_table.

  CALL METHOD lr_custom_controller->get_table_fields

    EXPORTING

      iv_tabname = lv_tabname

    IMPORTING

      et_fields = lt_fields.

  SPLIT lv_file_content_string AT cl_abap_char_utilities=>cr_lf

   INTO TABLE lt_field.

  TRY.

      CREATE DATA lt_dref_seltable TYPE TABLE OF (lv_tabname)  .

    CATCH cx_sy_create_data_error.

      RETURN.

  ENDTRY.

  ASSIGN lt_dref_seltable->* TO <fs_dyn_table>.

  TRY.

      CREATE DATA ls_dref_line LIKE LINE OF <fs_dyn_table>.

    CATCH cx_sy_create_data_error.

      RETURN.

  ENDTRY.

  ASSIGN ls_dref_line->* TO <fs_tabline>.

  lv_counter = 1.

  LOOP AT lt_field ASSIGNING <lv_field>.

    IF lv_counter EQ 1.

      READ TABLE lt_fields INTO ls_field INDEX lv_counter.

      CONCATENATE ‘<fs_tabline>-‘ ls_field-fieldname INTO lv_field_name.

      ASSIGN (lv_field_name) TO <ls_field>.

      <ls_field> = sy-mandt.

      lv_counter = lv_counter + 1.

    ENDIF.

    CASE lv_selection.

      WHEN ‘1’.

        SPLIT <lv_field> AT cl_abap_char_utilities=>horizontal_tab

         INTO TABLE lt_field_val.

      WHEN ‘2’.

        SPLIT <lv_field> AT lc_comma INTO TABLE lt_field_val.

    ENDCASE.

    LOOP AT lt_field_val ASSIGNING <lv_field_val>.

      lv_tabix = sy-tabix.

      READ TABLE lt_fields INTO ls_field INDEX lv_counter.

      CONCATENATE ‘<fs_tabline>-‘ ls_field-fieldname INTO lv_field_name.

      ASSIGN (lv_field_name) TO <ls_field>.

      <ls_field> = <lv_field_val>.

      lv_counter = lv_counter + 1.

    ENDLOOP.

    APPEND <fs_tabline> TO <fs_dyn_table>.

    lv_counter = 1.

  ENDLOOP.

  CREATE OBJECT lr_collection TYPE cl_crm_bol_bo_col.

  LOOP AT <fs_dyn_table> ASSIGNING <fs_tabline>.

    CREATE OBJECT lr_value_node

      EXPORTING

        iv_data_ref = ls_dref_line.

    lr_value_node->set_properties( <fs_tabline> ).

    CALL METHOD lr_collection->add

      EXPORTING

        iv_entity = lr_value_node.

  ENDLOOP.

* Display data

  me->typed_context->filedata->set_collection( lr_collection  ).

ENDMETHOD.

Passing Table Name to .htm page :

METHOD set_models.

  DATA :

     lv_table                TYPE tabname16,

     lr_custom_controller    TYPE REF TO zl_z_tabl_u_cucodataupd_impl,

     lr_coll_wrapper         TYPE REF TO cl_bsp_wd_collection_wrapper,

     lr_entity               TYPE REF TO cl_crm_bol_entity,

     lr_table                TYPE REF TO if_bol_bo_property_access,

     lv_tabname              TYPE ddobjname.

  lr_custom_controller = me->get_cust_controller( ).

  lr_coll_wrapper     = lr_custom_controller->typed_context->dbtable->get_collection_wrapper( ).

  lr_table            ?= lr_coll_wrapper->get_current( ).

  lv_table            = lr_table->get_property_as_string( iv_attr_name = ‘TBMA_VAL’ ).

  CALL METHOD super->set_models

    EXPORTING

      view = view.

  view->set_attribute(

         name   = ‘TableName’                              “#EC NOTEXT

         value  = lv_table ).

ENDMETHOD.

Iterator Details :

Created a class ZCL_HTMLB_TABLEVIEW_ITERATOR , added interface IF_HTMLB_TABLEVIEW_ITERATOR implemented Method GET_COLUMN_DEFINITIONS and also implemented CONSTRUCTOR to pass columns data

DataView-3.jpg

Iterator Get Column Definitions Method details :

METHOD if_htmlb_tableview_iterator~get_column_definitions.

  DATA:

        ls_table_view  TYPE tableviewcontrol,

        lt_table_view  TYPE tableviewcontroltab,

        lr_filedata    TYPE REF TO zl_z_tabl_u_dataview_cn00,

        lt_columns     TYPE abap_component_tab,

        ls_column      TYPE abap_componentdescr.

  lt_columns[] = gr_filedata->gt_columns[].

  LOOP AT lt_columns INTO ls_column.

    ls_table_view-columnname          = ls_column-name.

    ls_table_view-title               = ls_column-name.

    ls_table_view-wrapping            = abap_false.

    ls_table_view-width               = ‘100px’.

    ls_table_view-horizontalalignment = ‘LEFT’.

    APPEND ls_table_view TO p_column_definitions.

  ENDLOOP.

ENDMETHOD.

Constructor Details :

METHOD constructor.

  gr_filedata ?= ir_context_node.

ENDMETHOD.

TableView Details :

TableView-1.JPG

TableView-2.jpg

GET_V Method

METHOD get_v_tbma_val.

  DATA:

   ls_map    TYPE if_bsp_wd_valuehelp_f4descr=>gtype_param_mapping,

   lt_inmap  TYPE if_bsp_wd_valuehelp_f4descr=>gtype_param_mapping_tab,

   lt_outmap TYPE if_bsp_wd_valuehelp_f4descr=>gtype_param_mapping_tab.

  ls_map-context_attr = ‘TBMA_VAL’.

  ls_map-f4_attr     = ‘TABNAME’.

  APPEND ls_map TO: lt_inmap,lt_outmap.

  CREATE OBJECT rv_valuehelp_descriptor TYPE

    cl_bsp_wd_valuehelp_f4descr

    EXPORTING

      iv_help_id       = ‘AXT_DBTABLE_SEARCH_HELP’

      iv_help_id_kind  = if_bsp_wd_valuehelp_f4descr=>help_id_kind_name

      iv_input_mapping = lt_inmap

      iv_output_mapping = lt_outmap.

ENDMETHOD.

Runtime Repository Details :

The below snapshot shows the final runtime repository objects.
Runtime Repository.JPG

Component Execution Details :

File Types:

FileTypes.jpg

File Contents – Text File :

File Contents Example - TXT.jpg

File Contents – CSV File

File Contents Example - CSV.jpg

Sample Table – 1:

Table-1.jpg

Sample Table -2 :

Table-2.jpg

Table ZCONFIG_DATA_1  provided in the component , columns displayed in the table view as per the provided table , selected the text file and loaded the text file using “Upload” button:

Table-1 Load.jpg

Saved the data using “Save” button , table data after successful data load

Table-1 Data.jpg

Table ZCONFIG_DATA_2  provided in the component , columns displayed in the table view as per the provided table , selected the CSV file and loaded the CSV file using “Upload” button:

Table-2 Load CSV.JPG

Table-2 Load CSV Data.JPG

Saved the data using “Save” button , table data display after successful data load

Table-2 Data.jpg

To report this post you need to login first.

4 Comments

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

  1. ram ram

    great info Laxmana!! long time back we got the same requirement but managed some other way.

    anyhow good blog.

    regards,

    ram

    (0) 

Leave a Reply