Application Development and Automation Discussions
Join the discussions or start your own on all things application development, including tools and APIs, programming models, and keeping your skills sharp.
cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Combine Two dynamic tables

former_member212705
Active Participant
0 Likes
4,258

Hi experts,

I have one requirement to combine two dynamiclly build tables into one final table.

for example dynamic table has structure

table :: F_sheet_row

field1(length 2)    field2(length 3)    field3(length 4)

12                        ABC                    ABCD

header table::

table gi_header (1 field col_length =50) (It also filled dynamically in program)

Col_Value

ID

Value

Name Employee

both value table and header table is mapped, i have to just combine into one.

currently i populated the header at the first row of my value table using the below code

    DATA: lv_spalte TYPE i,
        lv_nrows TYPE i,
         lv_ncols TYPE i,
         lv_data_cols TYPE i,
         lv_subrc TYPE sy-subrc,
         lv_col_select TYPE char01,
         lv_col_select_mask TYPE char255.

    FIELD-SYMBOLS: <f>,
                 <field> TYPE any,
                 <f_sheet_row_wa> TYPE any,
                 <fieldname> TYPE any.

  lv_subrc = 0.
  lv_spalte = 1.
  WHILE lv_subrc = 0.
    ASSIGN COMPONENT lv_spalte OF STRUCTURE f_sheet_row TO <f>.
    IF sy-subrc = 0.
      lv_data_cols = lv_data_cols + 1.
      lv_spalte = lv_spalte + 1.
    ELSE.
      lv_subrc = 1.
    ENDIF.
  ENDWHILE.
  lv_spalte = lv_spalte - 1.
*   add the header to the data table
  INSERT INITIAL LINE INTO f_sheet_row INDEX 1.

  DESCRIBE TABLE gi_header LINES lv_ncols.
  IF lv_ncols > 0.
    READ TABLE f_sheet_row INDEX 1 ASSIGNING <f_sheet_row_wa>.
    CHECK sy-subrc EQ 0.
    lv_cnt = 0.
    WHILE sy-subrc EQ 0.
      lv_cnt = lv_cnt + 1.
      ASSIGN COMPONENT lv_cnt OF STRUCTURE <f_sheet_row_wa> TO <field>.
      CHECK sy-subrc EQ 0.
      READ TABLE gi_header INDEX lv_cnt ASSIGNING <fieldname>.
      IF sy-subrc EQ 0.
        <field> = <fieldname>.
      ELSE.
        sy-subrc = 0.
        WRITE lv_cnt TO <field> LEFT-JUSTIFIED.
      ENDIF.
    ENDWHILE.

    DO lv_ncols TIMES.
      CONCATENATE lv_col_select_mask 'X' INTO lv_col_select_mask.
    ENDDO.
    lv_col_select = 'X'.
  ENDIF.

But as i am inserting at first line so header values is getting truncated according to the field length of table f_sheet_row:

Finally f_sheet_row

field1(length 2)    field2(length 3)    field3(length 4)

ID                         Val                    Name

12                         ABC                   ABCD

Now i am confused how to populate both the tables.

As the tables are dynamic so i can not judge about the fields and headers.

Please help me how to do this.

I searched already in SDN.

Thanks

Ashish

1 ACCEPTED SOLUTION
Read only

Pawan_Kesari
Active Contributor
0 Likes
2,932

Try this subroutine.

Logic in subroutine create new internal table, comparing data and header internal table, to find out optimum length required to fit in the contents.  All fields in final internal table has type C. It will take care out output format of date and time field if any in data internal table.

Simply make a call to routine

DATA : ref_table TYPE REF TO data .
FIELD-SYMBOLS : <fs_table> TYPE table .

PERFORM merge_tables USING f_sheet_row gi_header CHANGING ref_table .

ASSIGN ref_table->* TO <fs_table> .

FORM merge_tables USING f_sheet_row TYPE table
                         gi_header   TYPE table
                   CHANGING ref_table TYPE REF TO data .

* Read gi_header and create internal table with component just enough long to
* fit description
   DATA : lo_header_table_descr TYPE REF TO cl_abap_tabledescr  ,
          lo_header_line_type   TYPE REF TO cl_abap_structdescr ,
          lo_data_table_descr   TYPE REF TO cl_abap_tabledescr  ,
          lo_data_line_type     TYPE REF TO cl_abap_structdescr ,
          lo_newtab_table_descr TYPE REF TO cl_abap_tabledescr  ,
          lo_newtab_line_descr  TYPE REF TO cl_abap_structdescr ,
          lo_element_descr      TYPE REF TO cl_abap_elemdescr   ,
          ls_newtab_comp        TYPE        abap_componentdescr ,
          li_newtab_comps       TYPE        abap_component_tab  ,
          ls_component          TYPE        abap_compdescr      .

   DATA : lv_header_string      TYPE string ,
          lv_length             TYPE i      .

   DATA : ref_line_header     TYPE REF TO data ,
          ref_line_data       TYPE REF TO data ,
          ref_line_newtab     TYPE REF TO data .

   FIELD-SYMBOLS : <fs_header>   TYPE ANY     ,
                   <fs_data_wa>  TYPE ANY     ,
                   <fs_data_fld> TYPE ANY     ,
                   <fs_new_tab>  TYPE table   ,
                   <fs_new_wa>   TYPE ANY     ,
                   <fs_new_fld>  TYPE ANY     .


* Get runtime information of internal tables
   lo_data_table_descr ?= cl_abap_typedescr=>describe_by_data( f_sheet_row ) .
   lo_data_line_type   ?= lo_data_table_descr->get_table_line_type(  ) .

   lo_header_table_descr ?= cl_abap_typedescr=>describe_by_data( gi_header ) .
   lo_header_line_type   ?= lo_header_table_descr->get_table_line_type( ) .

* Sanity test
* Number of lines in header table should be equal to number of
* columns in data table
   IF LINES( lo_data_line_type->components ) <> LINES( gi_header ) .
     MESSAGE 'Error' TYPE 'A'.
   ENDIF.

* Create work area of header table
   CREATE DATA ref_line_header TYPE HANDLE lo_header_line_type .
   ASSIGN ref_line_header->* TO <fs_header> .

* Create work are of data table
   CREATE DATA ref_line_data TYPE HANDLE lo_data_line_type .
   ASSIGN ref_line_data->* TO <fs_data_wa> .

* Loop on header internal table to get length of each header, based on this
* information new table will be created to accomodate data without any truncation
   LOOP AT gi_header ASSIGNING <fs_header> .
     CLEAR lv_header_string .
     lv_header_string = <fs_header> .
     lv_length        = STRLEN( lv_header_string ) .  "header text length

     READ TABLE lo_data_line_type->components INTO ls_component INDEX sy-tabix .
     CLEAR ls_newtab_comp .

*   Also get length of data field, in case that is more than length of header text
     ASSIGN COMPONENT ls_component-name OF STRUCTURE <fs_data_wa> TO <fs_data_fld> .
     lo_element_descr ?= cl_abap_typedescr=>describe_by_data( <fs_data_fld> ).
     IF lo_element_descr->output_length > lv_length .
       lv_length = lo_element_descr->output_length .
     ENDIF.

     ls_newtab_comp-name = ls_component-name .
     ls_newtab_comp-type ?= cl_abap_elemdescr=>get_c( lv_length ) .

     INSERT ls_newtab_comp INTO TABLE li_newtab_comps .
   ENDLOOP .

* Create new table based on new structure
   lo_newtab_line_descr  = cl_abap_structdescr=>create( li_newtab_comps ).
   lo_newtab_table_descr = cl_abap_tabledescr=>create( lo_newtab_line_descr ) .

   CREATE DATA ref_table TYPE HANDLE lo_newtab_table_descr .
   ASSIGN ref_table->* TO <fs_new_tab> .

* Fill header data into new table
   CREATE DATA ref_line_newtab TYPE HANDLE lo_newtab_line_descr .
   ASSIGN ref_line_newtab->* TO <fs_new_wa> .

   APPEND INITIAL LINE TO <fs_new_tab> .
   READ TABLE <fs_new_tab> ASSIGNING <fs_new_wa> INDEX sy-tabix .

   LOOP AT gi_header ASSIGNING <fs_header> .
     ASSIGN COMPONENT sy-tabix OF STRUCTURE <fs_new_wa> TO <fs_new_fld>.
     <fs_new_fld> = <fs_header> .
   ENDLOOP .

* Now fill content

   LOOP AT f_sheet_row ASSIGNING <fs_data_wa> .

     APPEND INITIAL LINE TO <fs_new_tab> .
     READ TABLE <fs_new_tab> ASSIGNING <fs_new_wa> INDEX sy-tabix .

*   Loop at components of data table
     LOOP AT lo_data_line_type->components INTO ls_component .
       ASSIGN COMPONENT ls_component-name  OF STRUCTURE <fs_data_wa> TO <fs_data_fld> .
       ASSIGN COMPONENT ls_component-name  OF STRUCTURE <fs_new_wa>  TO <fs_new_fld> .
       WRITE <fs_data_fld> TO <fs_new_fld> . "this will take care of conversion exit
     ENDLOOP.

   ENDLOOP .

ENDFORM.                    "merge_tables

Regards,

Pawan

Hi experts,

I have one requirement to combine two dynamiclly build tables into one final table.

for example dynamic table has structure

table :: F_sheet_row

field1(length 2)    field2(length 3)    field3(length 4)

12                        ABC                    ABCD

header table::

table gi_header (1 field col_length =50) (It also filled dynamically in program)

Col_Value

ID

Value

Name Employee

both value table and header table is mapped, i have to just combine into one.

currently i populated the header at the first row of my value table using the below code

    DATA: lv_spalte TYPE i,
        lv_nrows TYPE i,
         lv_ncols TYPE i,
         lv_data_cols TYPE i,
         lv_subrc TYPE sy-subrc,
         lv_col_select TYPE char01,
         lv_col_select_mask TYPE char255.

    FIELD-SYMBOLS: <f>,
                 <field> TYPE any,
                 <f_sheet_row_wa> TYPE any,
                 <fieldname> TYPE any.

  lv_subrc = 0.
  lv_spalte = 1.
  WHILE lv_subrc = 0.
    ASSIGN COMPONENT lv_spalte OF STRUCTURE f_sheet_row TO <f>.
    IF sy-subrc = 0.
      lv_data_cols = lv_data_cols + 1.
      lv_spalte = lv_spalte + 1.
    ELSE.
      lv_subrc = 1.
    ENDIF.
  ENDWHILE.
  lv_spalte = lv_spalte - 1.
*   add the header to the data table
  INSERT INITIAL LINE INTO f_sheet_row INDEX 1.

  DESCRIBE TABLE gi_header LINES lv_ncols.
  IF lv_ncols > 0.
    READ TABLE f_sheet_row INDEX 1 ASSIGNING <f_sheet_row_wa>.
    CHECK sy-subrc EQ 0.
    lv_cnt = 0.
    WHILE sy-subrc EQ 0.
      lv_cnt = lv_cnt + 1.
      ASSIGN COMPONENT lv_cnt OF STRUCTURE <f_sheet_row_wa> TO <field>.
      CHECK sy-subrc EQ 0.
      READ TABLE gi_header INDEX lv_cnt ASSIGNING <fieldname>.
      IF sy-subrc EQ 0.
        <field> = <fieldname>.
      ELSE.
        sy-subrc = 0.
        WRITE lv_cnt TO <field> LEFT-JUSTIFIED.
      ENDIF.
    ENDWHILE.

    DO lv_ncols TIMES.
      CONCATENATE lv_col_select_mask 'X' INTO lv_col_select_mask.
    ENDDO.
    lv_col_select = 'X'.
  ENDIF.

But as i am inserting at first line so header values is getting truncated according to the field length of table f_sheet_row:

Finally f_sheet_row

field1(length 2)    field2(length 3)    field3(length 4)

ID                         Val                    Name

12                         ABC                   ABCD

Now i am confused how to populate both the tables.

As the tables are dynamic so i can not judge about the fields and headers.

Please help me how to do this.

I searched already in SDN.

Thanks

Ashish

13 REPLIES 13
Read only

former_member212705
Active Participant
0 Likes
2,932

Is it possible using field symbol ?

Read only

0 Likes
2,932

I am not sure whether I understood your question!

But here is what i feel....

You have a generic internal table F_sheet_row with the first column of length 2 and then you have another internal table gi_header with the first column of length 50.

You are trying to pass the first column value from gi_header to f_sheet_row using column 1 as common field.

While doing so....u r saying that value is being truncated in f_sheet_row as the length of first column  is only 2 (instead of 50)?

Is this ur question?

Read only

0 Likes
2,932

Yes, How should i combine both. As f_sheet_row is dynamic so i can not declare a structure in advance.

Read only

0 Likes
2,932

or else while inserting how to increase length of f_sheet_row's field? Is this possible?

Read only

0 Likes
2,932

I am not sure about this requirement....u want to move data to another field which is not big enough..

Who is creating f_sheet_row internal table....is it you? Then why can't u handle this in your code?

Also, why not create another new dynamic internal table based on data that you would want to move?

Read only

0 Likes
2,932

There is no way...that u can increase the length of a field of dynamic internal table after creating it! It needs to be handled at creation time.

Read only

0 Likes
2,932

ok how to create dynamic table and move both tables data. as everything is dynamic so we will be not be sure about the values. but always header's 1 value will point f_sheet_row's 1st and so on.

Read only

philipdavy
Contributor
0 Likes
2,932

Go through this link, it may be helpful. http://wiki.sdn.sap.com/wiki/display/ABAP/Runtime+Type+Services+%28RTTS%29  In this link there is another link which guides you to comparing two internal tables.

Regards,

Philip.

Read only

0 Likes
2,932

Hi Phili,

But how compare would be able to solve problem. here i have to combine data from dynamic tables which are filling dynamically in program. Means may be for some data table f_sheet_row has 32 columns and corresponding header table has 32 header rows. and for some other data f_sheet_row will have 94 columns and header table will have 94 header rows. Header table has only character type data, but in value table data types are different for ex. date, numric etc...

Read only

0 Likes
2,932

You cannot combine in this way.

The option would be to keep all the datatypes as character....in the new internal table.

Moreover is there any specific reason why you want headers for each column in the same table?

Read only

0 Likes
2,932

yes as i have to use FM SAP_CONVERT_TO_EXCEL... where i need to pass one internal table. Previously we were using EXCEL_OLE_DAT. in that FM we were passing values and header seperately.. but now requirement says use SAP_CONVERT...... That is the reason i want both data in one table.

Read only

Former Member
0 Likes
2,932

I am not sure if I  understand your code.

But if you got two dynamic tables, then you can combine them in a third field catalog.

create a third field catalog with all fields in the field catalog of the first dynamic table and the field catalog of the second field catalog.

Loop at first field catalog created for the first dyn table.

   append to the third field catalog table.

endloop.

Loop at second field catalog created for the second dyn table.

   append to the third field catalog table.

endloop.

Create a dynamic table with this third field catalog.

Then populate the values by loop this third field catalog and reading corresponding values from the first two tables.

Read only

Pawan_Kesari
Active Contributor
0 Likes
2,933

Try this subroutine.

Logic in subroutine create new internal table, comparing data and header internal table, to find out optimum length required to fit in the contents.  All fields in final internal table has type C. It will take care out output format of date and time field if any in data internal table.

Simply make a call to routine

DATA : ref_table TYPE REF TO data .
FIELD-SYMBOLS : <fs_table> TYPE table .

PERFORM merge_tables USING f_sheet_row gi_header CHANGING ref_table .

ASSIGN ref_table->* TO <fs_table> .

FORM merge_tables USING f_sheet_row TYPE table
                         gi_header   TYPE table
                   CHANGING ref_table TYPE REF TO data .

* Read gi_header and create internal table with component just enough long to
* fit description
   DATA : lo_header_table_descr TYPE REF TO cl_abap_tabledescr  ,
          lo_header_line_type   TYPE REF TO cl_abap_structdescr ,
          lo_data_table_descr   TYPE REF TO cl_abap_tabledescr  ,
          lo_data_line_type     TYPE REF TO cl_abap_structdescr ,
          lo_newtab_table_descr TYPE REF TO cl_abap_tabledescr  ,
          lo_newtab_line_descr  TYPE REF TO cl_abap_structdescr ,
          lo_element_descr      TYPE REF TO cl_abap_elemdescr   ,
          ls_newtab_comp        TYPE        abap_componentdescr ,
          li_newtab_comps       TYPE        abap_component_tab  ,
          ls_component          TYPE        abap_compdescr      .

   DATA : lv_header_string      TYPE string ,
          lv_length             TYPE i      .

   DATA : ref_line_header     TYPE REF TO data ,
          ref_line_data       TYPE REF TO data ,
          ref_line_newtab     TYPE REF TO data .

   FIELD-SYMBOLS : <fs_header>   TYPE ANY     ,
                   <fs_data_wa>  TYPE ANY     ,
                   <fs_data_fld> TYPE ANY     ,
                   <fs_new_tab>  TYPE table   ,
                   <fs_new_wa>   TYPE ANY     ,
                   <fs_new_fld>  TYPE ANY     .


* Get runtime information of internal tables
   lo_data_table_descr ?= cl_abap_typedescr=>describe_by_data( f_sheet_row ) .
   lo_data_line_type   ?= lo_data_table_descr->get_table_line_type(  ) .

   lo_header_table_descr ?= cl_abap_typedescr=>describe_by_data( gi_header ) .
   lo_header_line_type   ?= lo_header_table_descr->get_table_line_type( ) .

* Sanity test
* Number of lines in header table should be equal to number of
* columns in data table
   IF LINES( lo_data_line_type->components ) <> LINES( gi_header ) .
     MESSAGE 'Error' TYPE 'A'.
   ENDIF.

* Create work area of header table
   CREATE DATA ref_line_header TYPE HANDLE lo_header_line_type .
   ASSIGN ref_line_header->* TO <fs_header> .

* Create work are of data table
   CREATE DATA ref_line_data TYPE HANDLE lo_data_line_type .
   ASSIGN ref_line_data->* TO <fs_data_wa> .

* Loop on header internal table to get length of each header, based on this
* information new table will be created to accomodate data without any truncation
   LOOP AT gi_header ASSIGNING <fs_header> .
     CLEAR lv_header_string .
     lv_header_string = <fs_header> .
     lv_length        = STRLEN( lv_header_string ) .  "header text length

     READ TABLE lo_data_line_type->components INTO ls_component INDEX sy-tabix .
     CLEAR ls_newtab_comp .

*   Also get length of data field, in case that is more than length of header text
     ASSIGN COMPONENT ls_component-name OF STRUCTURE <fs_data_wa> TO <fs_data_fld> .
     lo_element_descr ?= cl_abap_typedescr=>describe_by_data( <fs_data_fld> ).
     IF lo_element_descr->output_length > lv_length .
       lv_length = lo_element_descr->output_length .
     ENDIF.

     ls_newtab_comp-name = ls_component-name .
     ls_newtab_comp-type ?= cl_abap_elemdescr=>get_c( lv_length ) .

     INSERT ls_newtab_comp INTO TABLE li_newtab_comps .
   ENDLOOP .

* Create new table based on new structure
   lo_newtab_line_descr  = cl_abap_structdescr=>create( li_newtab_comps ).
   lo_newtab_table_descr = cl_abap_tabledescr=>create( lo_newtab_line_descr ) .

   CREATE DATA ref_table TYPE HANDLE lo_newtab_table_descr .
   ASSIGN ref_table->* TO <fs_new_tab> .

* Fill header data into new table
   CREATE DATA ref_line_newtab TYPE HANDLE lo_newtab_line_descr .
   ASSIGN ref_line_newtab->* TO <fs_new_wa> .

   APPEND INITIAL LINE TO <fs_new_tab> .
   READ TABLE <fs_new_tab> ASSIGNING <fs_new_wa> INDEX sy-tabix .

   LOOP AT gi_header ASSIGNING <fs_header> .
     ASSIGN COMPONENT sy-tabix OF STRUCTURE <fs_new_wa> TO <fs_new_fld>.
     <fs_new_fld> = <fs_header> .
   ENDLOOP .

* Now fill content

   LOOP AT f_sheet_row ASSIGNING <fs_data_wa> .

     APPEND INITIAL LINE TO <fs_new_tab> .
     READ TABLE <fs_new_tab> ASSIGNING <fs_new_wa> INDEX sy-tabix .

*   Loop at components of data table
     LOOP AT lo_data_line_type->components INTO ls_component .
       ASSIGN COMPONENT ls_component-name  OF STRUCTURE <fs_data_wa> TO <fs_data_fld> .
       ASSIGN COMPONENT ls_component-name  OF STRUCTURE <fs_new_wa>  TO <fs_new_fld> .
       WRITE <fs_data_fld> TO <fs_new_fld> . "this will take care of conversion exit
     ENDLOOP.

   ENDLOOP .

ENDFORM.                    "merge_tables

Regards,

Pawan