06-21-2012 3:55 PM
Hi guys,
While i was playing with dynamic tables and i can't figure how to get the exact data type from data elements.
I'll explain better in code
* Declare Data. ( dynamic fields )
DATA: gt_fields TYPE STANDARD TABLE OF char30,
gs_fields TYPE char30,
gt_comp TYPE cl_abap_structdescr=>component_table,
gs_comp LIKE LINE OF gt_comp,
go_element TYPE REF TO cl_abap_elemdescr,
go_struct TYPE REF TO cl_abap_structdescr.
LOOP AT gt_fields INTO gs_fields.
* Element descripiton
go_element ?= cl_abap_elemdescr=>describe_by_name( gs_fields ).
* Field name
MOVE gs_fields TO gs_comp-name.
* Field type
gs_comp-type = cl_abap_elemdescr=>get_c( go_element->length ).
APPEND gs_comp TO gt_comp.
ENDLOOP.
This code is good and i can manage to build a dynamic table from this.
But:
1) gs_fields ( where i store the name of the fields ) can only be chart type ( get_c () ). if i send a field which type is integer i get dump and is normal.
2) when i display with alv i don't get any description in my column header.
I managed to get a better result but not as i wanted. ( i want a completely dynamic table )
-> Define a type in my program. add fields. ( ex: matnr type mara-matnr, mara-mtart etc )
-> Get components from existing type:
go_struct ?= cl_abap_typedescr=>describe_by_name( 'TY_MY_TYPE' ).
gt_comp = lo_struct->get_components( ).
I tried different options but none was good. I think is still something regarding how i fill my go_element i think. Do you have any ideas?
Thank you,
Alex F.
06-22-2012 4:24 PM
Hi Alexandru Fediuc,
the best thing is to use existing data elements to create the dynamic table.
So you may extend your table that it carries a fieldname and a datatype (data element or DDIC structure and component) for each field to be created.
See here the (tested) sample program:
FORM dyndata .
TYPES:
BEGIN OF ty_dyndata,
fieldname TYPE fieldname,
data_type TYPE string,
END OF ty_dyndata,
ty_t_dyndata TYPE STANDARD TABLE OF ty_dyndata.
DATA:
lt_dyndata TYPE ty_t_dyndata,
lo_salv_table TYPE REF TO cl_salv_table,
lo_structdescr TYPE REF TO cl_abap_structdescr,
lo_typedescr TYPE REF TO cl_abap_typedescr,
lo_tabledescr TYPE REF TO cl_abap_tabledescr,
lr_data TYPE REF TO data,
lr_dyntable TYPE REF TO data,
lt_component TYPE cl_abap_structdescr=>component_table.
FIELD-SYMBOLS:
<dyndata> TYPE ty_dyndata,
<component> TYPE LINE OF cl_abap_structdescr=>component_table,
<dyntable> TYPE table.
* example with 2 fields
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'ORDER'.
<dyndata>-data_type = 'VBAK-VBELN'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'ITEM'.
<dyndata>-data_type = 'VBAP-POSNR'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'COMPANY'.
<dyndata>-data_type = 'BUKRS'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'COUNT'.
<dyndata>-data_type = 'I'.
* creation of dynamic table
LOOP AT lt_dyndata ASSIGNING <dyndata>.
TRY.
CREATE DATA lr_data TYPE (<dyndata>-data_type).
APPEND INITIAL LINE TO lt_component ASSIGNING <component>.
<component>-type ?= cl_abap_datadescr=>describe_by_data_ref( lr_data ).
<component>-name = <dyndata>-fieldname.
CATCH cx_root.
* error handling
* ... cannot create data of type <dyndata>-data_type
ENDTRY.
ENDLOOP.
* new description object for structured type
lo_structdescr = cl_abap_structdescr=>create( lt_component ).
* create table description for structure decription
lo_tabledescr = cl_abap_tabledescr=>create(
p_line_type = lo_structdescr
p_table_kind = cl_abap_tabledescr=>tablekind_std
p_unique = abap_false ).
* create dynamic data object (table)
CREATE DATA lr_dyntable TYPE HANDLE lo_tabledescr.
* use table
ASSIGN lr_dyntable->* TO <dyntable>.
* append a couple of records
DO 10 TIMES.
APPEND INITIAL LINE TO <dyntable>.
ENDDO.
* create SALV object
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = lo_salv_table
CHANGING
t_table = <dyntable>
).
CATCH cx_salv_msg .
ENDTRY.
* display table
lo_salv_table->display( ).
ENDFORM. " DYNDATA
As you may have noticed, I used field-symbols quite frequently. For a reason: INTO <work area> is NEVER faster than the use of field-symbols, field-symbols save memory and they can be used much more flexible.
We have column headers for data created based on structure fields (VBAK-VBELN) and data elements (BUKRS), not for direct type (I).
Also, the ALV consistency check reports a warning for this field:
BTW: The ALV consistency check can be invoked by holding CTRL and SHIFT keys, pointing in an empty area of the grid and double-right-click the mouse. (If someone can tell me how to catch a double-right-click and the CTRL-SHIFT key press, he or she is invited for dinner)
The description in column header is taken from field catalog. If you use SALV object model, the object model will create the field catalog it self. It works better if the data element refers to a dictionary DOMAIN, direct data type in data element causes inconsistencies.
Hope you can make use of this,
Regards,
Clemens
06-22-2012 10:48 AM
Hi,
Please refer the blog for you queries
http://scn.sap.com/people/arunkumar.prabakaran/blog
Here a FM is used to generate dynamic internal table with different data type
06-23-2012 9:26 AM
06-23-2012 3:26 PM
Hi,
well at least the search function still works 🙂
I would recommend not to use the code presented here. The used METHOD cl_alv_table_create=>create_dynamic_table
is from pre-RTTS times and uses obsolete coding technique including limited use (generate subroutine) and unwanted database commit.
Though, the code may be changed and adapted to RTTS easily.
Regards
Clemens
06-22-2012 4:24 PM
Hi Alexandru Fediuc,
the best thing is to use existing data elements to create the dynamic table.
So you may extend your table that it carries a fieldname and a datatype (data element or DDIC structure and component) for each field to be created.
See here the (tested) sample program:
FORM dyndata .
TYPES:
BEGIN OF ty_dyndata,
fieldname TYPE fieldname,
data_type TYPE string,
END OF ty_dyndata,
ty_t_dyndata TYPE STANDARD TABLE OF ty_dyndata.
DATA:
lt_dyndata TYPE ty_t_dyndata,
lo_salv_table TYPE REF TO cl_salv_table,
lo_structdescr TYPE REF TO cl_abap_structdescr,
lo_typedescr TYPE REF TO cl_abap_typedescr,
lo_tabledescr TYPE REF TO cl_abap_tabledescr,
lr_data TYPE REF TO data,
lr_dyntable TYPE REF TO data,
lt_component TYPE cl_abap_structdescr=>component_table.
FIELD-SYMBOLS:
<dyndata> TYPE ty_dyndata,
<component> TYPE LINE OF cl_abap_structdescr=>component_table,
<dyntable> TYPE table.
* example with 2 fields
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'ORDER'.
<dyndata>-data_type = 'VBAK-VBELN'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'ITEM'.
<dyndata>-data_type = 'VBAP-POSNR'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'COMPANY'.
<dyndata>-data_type = 'BUKRS'.
APPEND INITIAL LINE TO lt_dyndata ASSIGNING <dyndata>.
<dyndata>-fieldname = 'COUNT'.
<dyndata>-data_type = 'I'.
* creation of dynamic table
LOOP AT lt_dyndata ASSIGNING <dyndata>.
TRY.
CREATE DATA lr_data TYPE (<dyndata>-data_type).
APPEND INITIAL LINE TO lt_component ASSIGNING <component>.
<component>-type ?= cl_abap_datadescr=>describe_by_data_ref( lr_data ).
<component>-name = <dyndata>-fieldname.
CATCH cx_root.
* error handling
* ... cannot create data of type <dyndata>-data_type
ENDTRY.
ENDLOOP.
* new description object for structured type
lo_structdescr = cl_abap_structdescr=>create( lt_component ).
* create table description for structure decription
lo_tabledescr = cl_abap_tabledescr=>create(
p_line_type = lo_structdescr
p_table_kind = cl_abap_tabledescr=>tablekind_std
p_unique = abap_false ).
* create dynamic data object (table)
CREATE DATA lr_dyntable TYPE HANDLE lo_tabledescr.
* use table
ASSIGN lr_dyntable->* TO <dyntable>.
* append a couple of records
DO 10 TIMES.
APPEND INITIAL LINE TO <dyntable>.
ENDDO.
* create SALV object
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = lo_salv_table
CHANGING
t_table = <dyntable>
).
CATCH cx_salv_msg .
ENDTRY.
* display table
lo_salv_table->display( ).
ENDFORM. " DYNDATA
As you may have noticed, I used field-symbols quite frequently. For a reason: INTO <work area> is NEVER faster than the use of field-symbols, field-symbols save memory and they can be used much more flexible.
We have column headers for data created based on structure fields (VBAK-VBELN) and data elements (BUKRS), not for direct type (I).
Also, the ALV consistency check reports a warning for this field:
BTW: The ALV consistency check can be invoked by holding CTRL and SHIFT keys, pointing in an empty area of the grid and double-right-click the mouse. (If someone can tell me how to catch a double-right-click and the CTRL-SHIFT key press, he or she is invited for dinner)
The description in column header is taken from field catalog. If you use SALV object model, the object model will create the field catalog it self. It works better if the data element refers to a dictionary DOMAIN, direct data type in data element causes inconsistencies.
Hope you can make use of this,
Regards,
Clemens
06-23-2012 9:34 AM
Wow, thx! Very good example and very useful.
I found myself a way to , to refer directly to a data dictionary type by using:
go_data type ref to cl_abap_datadescr
and use in my loop :
go_data ?= cl_abap_datadescr=>describe_by_name ( gs_fields )
and then just use
gs_comp-type = go_data.
This is a bit faster for exercise. But it all depends on what you have to do.
BTW: The ALV consistency check can be invoked by holding CTRL and SHIFT keys, pointing in an empty area of the grid and double-right-click the mouse. (If someone can tell me how to catch a double-right-click and the CTRL-SHIFT key press, he or she is invited for dinner)
Did you try handling double_click in alv oo? making a local class , and maybe registering the events? i'm a start so i'm not sure
06-23-2012 3:18 PM
Thanks for the comment. Yes you are right, that's what I found out later that you can always use cl_abap_datadescr=>describe_by_name, it works identical. But if you look into the code of describe_by_name, you will see that it is more complex than describe_by_data_ref.
I did not take measures regarding speed in comparison. Usually dynamic table creation is used only once per execution, the difference can't be noticed. Even for a mass run, I have serious doubts that this action will be significant at all - compared to the rest of using the table.
Thank you for the hint for catching the double-right-click. I tried some time ago, even used pretty much time debugging - no success whatsoever.
Regards
Clemens