2011 Nov 21 11:56 PM
Hello everyone
I need to copy the structure of an internal table that is pass by reference into a method.
Actually everything is fine else than the field type P with decimal is not created properly in the new itab.
Scenario:
An internal table is pass by reference to a method. We need to trait the data without modifying the original table. The Idea is to copy the structure and the data of the referenced internal table into an internal table created dymanically in the method.
Here is what I did and working fine when there are no field of data type "CURR".
Extract the structure of the reference data.
Create a dynamic internal table.
So far so good. Everything seams to work fine. BUT
when I am trying to copy the data from the reference table to the just created internal table the field with data type "CURR" doesn't work.
Here is my example:
FIELD-SYMBOLS: <FS_TABLE> TYPE STANDARD TABLE,
<TMP_TABLE> TYPE STANDARD TABLE,
<LS_TMP_TABLE> TYPE ANY,
<LS_TABLE> TYPE ANY,
<LS_VALUE> TYPE ANY.
DATA: lt_data TYPE STANDARD TABLE OF vbak,
ls_data LIKE LINE OF lt_sortfield,
ref_data TYPE REF TO data,
l_structure TYPE REF TO DATA,
lv_ltname TYPE string.
select * from vbak UP TO 10 rows INTO CORRESPONDING FIELDS OF TABLE lt_data.
* --- Assign the reference variable to the table
* ---- Only use to simulate a parameter that is assign to a reference to a internal table
unassign <FS_TABLE>.
lv_ltname = 'lt_data[]'.
ASSIGN (lv_ltname) to <FS_TABLE>.
GET REFERENCE OF <FS_TABLE>[] INTO ref_data.
* --- Assign the reference to the field-symbol
UNASSIGN <FS_TABLE>.
ASSIGN ref_data->* TO <FS_TABLE>.
* --- Create a working area for the reference table to a field-table
CREATE DATA l_structure LIKE LINE OF <FS_TABLE>.
ASSIGN l_structure->* TO <LS_TABLE>.
* --- Retrieve the structure of the field-symbol pointing to the internal table
DATA: lr_tabledescr TYPE REF TO cl_abap_tabledescr, " Internal Table description
_r_structdescr TYPE REF TO cl_abap_structdescr.
lr_tabledescr ?= cl_abap_tabledescr=>describe_by_data( <fs_table> ).
_r_structdescr ?= lr_tabledescr->get_table_line_type( ).
* --- Read internal table structure to create dynamic internal table
data: ls_struc like LINE OF _r_structdescr->components,
xfc type lvc_s_fcat,
ifc type lvc_t_fcat.
* ??????????????????????????????????????????????????????????????????
* --- Why the field (component) NETWR length is now 8 instead of 15?
* ??????????????????????????????????????????????????????????????????
LOOP AT _r_structdescr->components into ls_struc.
clear xfc.
xfc-fieldname = ls_struc-name .
xfc-datatype = ls_struc-type_kind.
xfc-inttype = ls_struc-type_kind.
xfc-intlen = ls_struc-length.
xfc-decimals = ls_struc-decimals.
append xfc to ifc.
ENDLOOP.
DATA: dy_table type ref to data,
* --- Create dynamic internal table
call method cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = ifc
IMPORTING
ep_table = dy_table.
* --- assign reference internal table to Field-symbol
assign dy_table->* to <tmp_table>.
unassign <ls_tmp_table>.
DATA: ls_tmp_struc type REF TO DATA.
CREATE DATA ls_tmp_struc like LINE OF <tmp_table>.
ASSIGN ls_tmp_struc->* TO <ls_tmp_table>.
Loop at <fs_table> INTO <LS_TABLE>.
MOVE-CORRESPONDING <ls_table> TO <ls_tmp_table>.
APPEND <ls_tmp_table> TO <tmp_table>.
ENDLOOP.
* ?????????????????????????????????????????????????????
* <fs_table>-netwr length is 15
* <ls_tmp_table>-netwr length is 8
* ??????????? Why the length is different?
* ??????????? It should a structure copy and have the
* ??????????? same length
I use VBAK as example, and the field NETWR is using data type "NETWR_AK" where it us a data type "CURR" with length 15 and decimal 2.
When reading the structure, the method get_table_line_type of the class cl_abap_tabledescr return a length of 8 instead of 15.
Any idea how to get the exact structure of a variable that is refering to a data type?
Regards
Daniel
2011 Nov 22 5:31 PM
Hello Everyone
Thank you for your replies.
I think I didn't explain myself clearly.
My goal is to be able to create an exact structure copy of a "Type ref to data" into a new internal table that is not defined yet.
Example:
A method contain a parameter that is a ref to DATA type.
That parameter is refering to an internal table from the calling program.
Now I want to create an internal table into the method where this one will be an exact structure copy of the parameter.
So, lets put some name here.
parameter: ip_data type ref to data.
FIELD-SYMBOLS: <FS_REF_DATA> TYPE STANDARD TABLE,
<FS_CP_DATA> TYPE STANDARD TABLE.
ASSIGN ip_data->* TO <FS_REF_DATA>.
" some code to assign the same structure to <FS_CP_DATA> from <FS_REF_DATA>
" than copy the data from <FS_REF_DATA> to <FS_CP_DATA>.
<FS_CP_DATA> [ ] = <FS_REF_DATA> [ ]. " This is working if no type P with decimal exist into the structure
" Than I can play with the data of <FS_CP_DATA> without modifying the data of <FS_REF_DATA>.
My problem would be solved if I can create dynamically an internal table that has an exact structure copy of the passed parameter.
Regards
Daniel
Hello everyone
I need to copy the structure of an internal table that is pass by reference into a method.
Actually everything is fine else than the field type P with decimal is not created properly in the new itab.
Scenario:
An internal table is pass by reference to a method. We need to trait the data without modifying the original table. The Idea is to copy the structure and the data of the referenced internal table into an internal table created dymanically in the method.
Here is what I did and working fine when there are no field of data type "CURR".
Extract the structure of the reference data.
Create a dynamic internal table.
So far so good. Everything seams to work fine. BUT
when I am trying to copy the data from the reference table to the just created internal table the field with data type "CURR" doesn't work.
Here is my example:
FIELD-SYMBOLS: <FS_TABLE> TYPE STANDARD TABLE,
<TMP_TABLE> TYPE STANDARD TABLE,
<LS_TMP_TABLE> TYPE ANY,
<LS_TABLE> TYPE ANY,
<LS_VALUE> TYPE ANY.
DATA: lt_data TYPE STANDARD TABLE OF vbak,
ls_data LIKE LINE OF lt_sortfield,
ref_data TYPE REF TO data,
l_structure TYPE REF TO DATA,
lv_ltname TYPE string.
select * from vbak UP TO 10 rows INTO CORRESPONDING FIELDS OF TABLE lt_data.
* --- Assign the reference variable to the table
* ---- Only use to simulate a parameter that is assign to a reference to a internal table
unassign <FS_TABLE>.
lv_ltname = 'lt_data[]'.
ASSIGN (lv_ltname) to <FS_TABLE>.
GET REFERENCE OF <FS_TABLE>[] INTO ref_data.
* --- Assign the reference to the field-symbol
UNASSIGN <FS_TABLE>.
ASSIGN ref_data->* TO <FS_TABLE>.
* --- Create a working area for the reference table to a field-table
CREATE DATA l_structure LIKE LINE OF <FS_TABLE>.
ASSIGN l_structure->* TO <LS_TABLE>.
* --- Retrieve the structure of the field-symbol pointing to the internal table
DATA: lr_tabledescr TYPE REF TO cl_abap_tabledescr, " Internal Table description
_r_structdescr TYPE REF TO cl_abap_structdescr.
lr_tabledescr ?= cl_abap_tabledescr=>describe_by_data( <fs_table> ).
_r_structdescr ?= lr_tabledescr->get_table_line_type( ).
* --- Read internal table structure to create dynamic internal table
data: ls_struc like LINE OF _r_structdescr->components,
xfc type lvc_s_fcat,
ifc type lvc_t_fcat.
* ??????????????????????????????????????????????????????????????????
* --- Why the field (component) NETWR length is now 8 instead of 15?
* ??????????????????????????????????????????????????????????????????
LOOP AT _r_structdescr->components into ls_struc.
clear xfc.
xfc-fieldname = ls_struc-name .
xfc-datatype = ls_struc-type_kind.
xfc-inttype = ls_struc-type_kind.
xfc-intlen = ls_struc-length.
xfc-decimals = ls_struc-decimals.
append xfc to ifc.
ENDLOOP.
DATA: dy_table type ref to data,
* --- Create dynamic internal table
call method cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = ifc
IMPORTING
ep_table = dy_table.
* --- assign reference internal table to Field-symbol
assign dy_table->* to <tmp_table>.
unassign <ls_tmp_table>.
DATA: ls_tmp_struc type REF TO DATA.
CREATE DATA ls_tmp_struc like LINE OF <tmp_table>.
ASSIGN ls_tmp_struc->* TO <ls_tmp_table>.
Loop at <fs_table> INTO <LS_TABLE>.
MOVE-CORRESPONDING <ls_table> TO <ls_tmp_table>.
APPEND <ls_tmp_table> TO <tmp_table>.
ENDLOOP.
* ?????????????????????????????????????????????????????
* <fs_table>-netwr length is 15
* <ls_tmp_table>-netwr length is 8
* ??????????? Why the length is different?
* ??????????? It should a structure copy and have the
* ??????????? same length
I use VBAK as example, and the field NETWR is using data type "NETWR_AK" where it us a data type "CURR" with length 15 and decimal 2.
When reading the structure, the method get_table_line_type of the class cl_abap_tabledescr return a length of 8 instead of 15.
Any idea how to get the exact structure of a variable that is refering to a data type?
Regards
Daniel
2011 Nov 22 1:24 AM
The equivalent type definition of NETWR dictionary data type in ABAP is
DATA: netwr(8) TYPE P DECIMALS 2.
The actual length of NETWR is only 8 bytes. But since a type P field can only carry numbers 0 to 9, a sign and an implicit decimal position (unlike a character byte that can carry any of characters from for example the 255 character ANSI set), they can be compressed (packed, hence the name) so that a field length of 8 can carry information that can accommodate twice the amount (2 x 😎 of numeric information. That is 15 places for numbers and 1 place for carrying +/- sign. Out of 15 places, 2 are given to decimal part (as per the DECIMALS declaration in TYPE P data type) and the rest 13 hold integer part. The position of the decimal point is implicit from the type definition and a decimal point is actually not stored.
Type conversion of TYPE P variable automatically happens when we assign it to a character field or even when we use WRITE statement on it or see it in debugger. But what actually is there in case of NETWR is only 8 bytes.
The real length of NETWR data type is only 8 and the 15 that you see in the data dictionary is the uncompressed length (excluding separators and decimal point) after you unpack the TYPE P variable using UNPACK statement.
So the NETWR column in your dynamic internal table is working as it is designed to work. What you need to do is, when you are using the column, you need to assign it to a TYPE P (if the row of your internal table is not typed)
2011 Nov 22 5:19 AM
Hi Daniel,
In case of this class/method go to include LSKBHF06 line 127 where the currency line is executed where the decimals in hardcoded. So pass it like
if xfc-datatype ne 'CURR'.
xfc-datatype = ls_struc-type_kin
endif.
then it should work.
Similarly for type p in line 199 check the code. Pass the relevant data for type p too
Is this what you were trying to do ? Also i would recommend you to use RTTS methods to create dynamic tables
FIELD-SYMBOLS: <fs_table> TYPE STANDARD TABLE,
<tmp_table> TYPE STANDARD TABLE.
DATA: lt_data TYPE STANDARD TABLE OF vbak,
ref_data TYPE REF TO data,
l_structure TYPE REF TO data,
lv_ltname TYPE string.
SELECT * FROM vbak UP TO 10 ROWS INTO CORRESPONDING FIELDS OF TABLE
lt_data.
UNASSIGN <fs_table>.
lv_ltname = 'lt_data[]'.
ASSIGN (lv_ltname) TO <fs_table>.
GET REFERENCE OF <fs_table>[] INTO ref_data.
* --- Assign the reference to the field-symbol
UNASSIGN <fs_table>.
ASSIGN ref_data->* TO <tmp_table>. "<tmp_table> will have the contents of <fs_table>
Break-point.
2011 Nov 22 5:31 PM
Hello Everyone
Thank you for your replies.
I think I didn't explain myself clearly.
My goal is to be able to create an exact structure copy of a "Type ref to data" into a new internal table that is not defined yet.
Example:
A method contain a parameter that is a ref to DATA type.
That parameter is refering to an internal table from the calling program.
Now I want to create an internal table into the method where this one will be an exact structure copy of the parameter.
So, lets put some name here.
parameter: ip_data type ref to data.
FIELD-SYMBOLS: <FS_REF_DATA> TYPE STANDARD TABLE,
<FS_CP_DATA> TYPE STANDARD TABLE.
ASSIGN ip_data->* TO <FS_REF_DATA>.
" some code to assign the same structure to <FS_CP_DATA> from <FS_REF_DATA>
" than copy the data from <FS_REF_DATA> to <FS_CP_DATA>.
<FS_CP_DATA> [ ] = <FS_REF_DATA> [ ]. " This is working if no type P with decimal exist into the structure
" Than I can play with the data of <FS_CP_DATA> without modifying the data of <FS_REF_DATA>.
My problem would be solved if I can create dynamically an internal table that has an exact structure copy of the passed parameter.
Regards
Daniel
2011 Nov 22 6:03 PM
> My problem would be solved if I can create dynamically an internal table that has an exact structure copy of the passed parameter.
Please check if the code snippet below helps to solve your issue.
REPORT zytest.
PARAMETERS: p_table TYPE tabname.
DATA:
o_table TYPE REF TO data,
o_table_copy TYPE REF TO data,
o_rtti TYPE REF TO cl_abap_tabledescr.
FIELD-SYMBOLS:
<fs_table> TYPE STANDARD TABLE,
<fs_table_copy> TYPE STANDARD TABLE.
START-OF-SELECTION.
CREATE DATA o_table TYPE STANDARD TABLE OF (p_table).
IF o_table IS BOUND.
ASSIGN o_table->* TO <fs_table>.
IF <fs_table> IS ASSIGNED.
SELECT * FROM (p_table) INTO TABLE <fs_table> UP TO 20 ROWS.
o_rtti ?= cl_abap_tabledescr=>describe_by_data( <fs_table> ).
IF o_rtti IS BOUND.
CREATE DATA o_table_copy TYPE HANDLE o_rtti.
IF o_table_copy IS BOUND.
ASSIGN o_table_copy->* TO <fs_table_copy>.
IF <fs_table_copy> IS ASSIGNED.
<fs_table_copy> = <fs_table>.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.-Rajesh
2011 Nov 22 8:37 PM
Hello Rajesh
It is exactly what I was looking for,
Your solution is way easier that what I was expecting.
Thank you
Daniel
2011 Nov 23 5:09 AM
Hi Rajesh,
We need not create another dyn table here, we can just assign the reference parameter to a field-symbol.
DATA:o_table_copy TYPE REF TO data,
it TYPE STANDARD TABLE OF mara.
FIELD-SYMBOLS:<fs_table> TYPE table.
START-OF-SELECTION.
ASSIGN it TO <fs_table>.
SELECT * FROM mara INTO TABLE <fs_table> UP TO 20 ROWS.
GET REFERENCE OF <fs_table>[] INTO o_table_copy.
CALL FUNCTION 'YTEST_REFERENCE'
EXPORTING
ref = o_table_copy.
FUNCTION ytest_reference.
*"----------------------------------------------------------------------
*"*"Local interface:
*" IMPORTING
*" REFERENCE(REF) TYPE REF TO DATA
*"----------------------------------------------------------------------
FIELD-SYMBOLS:<fs_tab> TYPE table,
<fs_line> TYPE ANY.
DATA:wf_ref TYPE REF TO data.
ASSIGN ref->* TO <fs_tab>.
CHECK sy-subrc = 0.
CREATE DATA wf_ref LIKE LINE OF <fs_tab>.
ASSIGN wf_ref->* TO <fs_line>.
IF sy-subrc = 0.
LOOP AT <fs_tab> ASSIGNING <fs_line>.
ENDLOOP.
ENDIF.
ENDFUNCTION.
I dont know why this is not helping OP
Got it now...May be the OP doesn't want to alter the actual data inside the function.
Kesav
Edited by: Keshav.T on Nov 23, 2011 11:06 AM
2011 Nov 23 3:48 PM
Hi Kesav,
Yes, as you have already pointed out, we have to 'CREATE' a new data object to avoid any changes in the duplicate from being reflected in the original.
-Rajesh.
| User | Count |
|---|---|
| 3 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |