Which Netweaver version do I need for BASE CORRESPONDING? - abap

I have the following piece of code.
REPORT zzz.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
DATA:
lt_t100 TYPE t000_t,
ls_t000_template TYPE t000.
lt_t100 = VALUE #( BASE ( CORRESPONDING #( ls_t000_template ) ) cccategory = 'P' ).
lt_t100 = VALUE #( BASE lt_t100
( VALUE #( BASE ( CORRESPONDING #( ls_t000_template ) ) cccategory = 'E' ) )
).
ENDMETHOD.
ENDCLASS.
In the editor it looks like it should be compilable, because everything is highlighted in a right way.
Even though this does not compile. My assumption here is that I do not have high enough a version of the SAP Netweaver.
Which version at least do I need to make this code compile?

The CORRESPONDING constructor operator was introduced with Netweaver 7.40 SP05.
The addition of BASE to the VALUE constructor operator for tables was introduced with NetWeaver 7.40 SP08.
So when you patch your SAP_BASIS component to 7.40 Service Pack 08, then you should be able to use both keywords.

Thanks to Philipp's comment I realised that I was doing it completely wrong.
Here is the right syntax that compiles flawlessly.
REPORT zzz.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
DATA:
lt_t100 TYPE t000_t,
ls_t000_template TYPE t000.
lt_t100 = VALUE #( ( VALUE #( BASE CORRESPONDING #( ls_t000_template ) cccategory = 'P' ) ) ).
lt_t100 = VALUE #( BASE lt_t100
( VALUE #( BASE CORRESPONDING #( ls_t000_template ) cccategory = 'E' ) )
( VALUE #( BASE CORRESPONDING #( ls_t000_template ) cccategory = 'C' ) )
( VALUE #( BASE CORRESPONDING #( ls_t000_template ) cccategory = 'D' ) )
( VALUE #( BASE CORRESPONDING #( ls_t000_template ) cccategory = 'S' ) )
).
ENDMETHOD.
ENDCLASS.

Related

Concatenate using 'FOR' loop in VALUE operator with 'BASE' addition?

Is it possible to mix in a FOR with CONCATENATE along with BASE statement?
Normally, itab1 = VALUE #( BASE itab1 ( value1 ) ) will append line1 into itab1 without overwriting. Shouldn't it be the same when using FOR along with BASE?
This is my thought process, but I get the No component exists with the name "FOR" error:
itab1 =
VALUE #(
BASE itab1
( value1 && value2 )
( VALUE #(
FOR line in itab2
( line-fld1 && line-fld2 ) )
).
Shouldn't it be the same when using FOR along with BASE
Yes, the semantics is the same. You use BASE for preserving the rows of the LHS when adding rows of RHS, and line specification is the same:
itab1 = VALUE #( BASE itab1 FOR line in itab2 ( matnr = line-matnr
maktx = line-matnr && line-spras
spras = line-spras ) ).
However, there is a nuance you should remember here: you cannot put the same itab to the inline-declared LHS, to the BASE source and to the FOR loop, it will give you infinite loop and TSV_TNEW_PAGE_ALLOC_FAILED dump.
I have tried out what Sandra had suggested in the comments and it worked like a charm:
You may append the lines of an internal table only by using ( LINES OF
itab ), so in your case it should be ( LINES OF VALUE #( ... ) ) –
Sandra Rossi
itab1 =
VALUE #( BASE itab1 ( value1 && value2 )
( LINES OF VALUE #( FOR line in itab2 ( line-fld1 && line-fld2 ) ) ).

Prevent CL_SALV_TABLE from removing leading zeros?

Please take a look on this following piece of code in which I put zeros in Test2 as value and two zeros in Test3 as value.
i used set_leading_zero but still leading zeros are removed.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
TYPES: BEGIN OF l_tys_test,
name TYPE string,
value TYPE i,
END OF l_tys_test,
l_tyt_test TYPE STANDARD TABLE OF l_tys_test WITH EMPTY KEY.
DATA(lt_test) = VALUE l_tyt_test(
( name = `Test1` value = 1 )
( name = `Test2` value = 02 )
( name = `Test3` value = 003 )
).
cl_salv_table=>factory(
IMPORTING
r_salv_table = DATA(lo_salv_table)
CHANGING
t_table = lt_test
).
lo_salv_table->get_columns( )->get_column( 'VALUE' )->set_leading_zero( abap_true ).
lo_salv_table->display( ).
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).
Agree with Jozsef and Sandra, there is no way you can do it with integer data type.
The only way how to implement this by means of ALV grid is to redeclare you VALUE field as numchar
TYPES: BEGIN OF
...
value TYPE n LENGTH 10,
...
END OF.
and utilize EDIT_MASK function, which is available both for WRITE statement and for ALV grid as well.
Put this instead of set_leading_zero( ) call in your method
lo_salv_table->get_columns( )->get_column( 'VALUE' )->set_edit_mask( '___________' ).
LENGTH specification in type definition is the number of leading zeroes to put.
You can use set_zero method to false.
DATA(lo_column) = lo_alv->get_columns( )->get_column( 'PERNR' ). lo_column->set_long_text( 'Staff No' ). lo_column->set_zero( abap_false ).

abap: create dynamic internal table from existing one

I have following internal table:
VBELN POSNR ELEMENT VALUE
4711 10 E1 12
4711 10 E2 23
Is there any possibility in ABAP (Framework, Class, etc), so I can fast create a new internal table at runtime which would look like this:
VBELN POSNR E1 E2
4711 10 12 23
Would appreciate any kind of help.
Thanks and BR.
Yes. What you want are the ABAP Runtime Type Services (RTTS), more precisely the ABAP Runtime Type Creation (RTTC).
DATA(vbeln_descriptor) = CAST cl_abap_datadescr( cl_abap_typedescr=>describe_by_name( 'VBELN' ) ).
DATA(posnr_descriptor) = CAST cl_abap_datadescr( cl_abap_typedescr=>describe_by_name( 'POSNR' ) ).
DATA(components) = VALUE abap_component_tab( ( name = 'VBELN'
type = vbeln_descriptor )
( name = 'POSNR'
type = posnr_descriptor ) ).
DATA(value_descriptor) = cl_abap_typedescr=>describe_by_name( 'VALUE' ).
LOOP AT vbeln_rows INTO DATA(vbeln_row).
INSERT VALUE #(
name = vbeln_row-element
type = value_descriptor )
INTO TABLE components.
ENDLOOP.
DATA(row_descriptor) = cl_abap_structdescr=>get( components ).
DATA(table_descriptor) = cl_abap_tabledescr=>create( row_descriptor ).
DATA itab TYPE REF TO data.
CREATE DATA itab TYPE HANDLE table_descriptor.

Conversion exception while working with constructor expressions

I'm working on a routine which moves the lines of a string table (in this case fui_elements) into a structure of unknown type (fcwa_struct).
DATA(li_temp) = ... "fill assignment table here
LOOP AT fui_elements ASSIGNING FIELD-SYMBOL(<lfs_element>).
ASSIGN COMPONENT li_temp[ sy-tabix ] OF STRUCTURE fcwa_struct
TO FIELD-SYMBOL(<lfs_field>).
IF sy-subrc <> 0.
"somethings wrong with the fui_elements data
ENDIF.
<lfs_field> = <lfs_element>.
ENDLOOP.
If the table i_field_customizing (STANDARD TABLE OF string) is not initial, I want to use its values.
Otherwise I want to generate an integer table (so that the loop runs equally often regardless of the table's values). Here lw_max is the amount of fields the imported structure has:
DATA(li_temp) = COND #( WHEN i_field_customizing[] IS INITIAL
THEN VALUE t_integer_tt( FOR X = 1
THEN X + 1
WHILE X <= lw_max
( X ) )
ELSE i_field_customizing ).
But when I run the report with i_field_customizing like that:
DATA(i_field_customizing) = VALUE t_string_tt( ( `KUNNR` ) ( `NAME1` ) ).
I get this exception on the line where I try to construct li_temp:
CX_SY_CONVERSION_NO_NUMBER (KUNNR cannot be interpreted as a number)
My current guess is that COND gets its type statically. Does anybody know how I can get around this?
What you are trying to achieve will not be possible because the type of an inline definition of a variable using COND is decided at compilation time and not at runtime.
Please see my question here. The type that will be taken is always the type of the variable that stands directly after THEN. You can decide what type will be chosen at compilation time by fiddling with negating the condition and switching places of variables after THEN at ELSE but it will be always either or and from what I understand you want to be able to do it dynamically so your ASSIGN COMPONENT statement works as expected with integers.
Even by specifically casting the variable after ELSE one gets the same short dump as you do.
DATA(li_temp) = COND #( WHEN i_field_customizing IS INITIAL
THEN VALUE t_integer_tt( ( 1 ) ( 2 ) )
ELSE CAST t_string_tt( REF #( i_field_customizing ) )->* ).
Alternatively you could cast to REF TO DATA but then you have to dereference it to a field symbol of type STANDARD TABLE.
REPORT zzy.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
TYPES:
t_integer_tt TYPE STANDARD TABLE OF i WITH EMPTY KEY,
t_string_tt TYPE STANDARD TABLE OF string WITH EMPTY KEY.
FIELD-SYMBOLS:
<fs_table> TYPE STANDARD TABLE.
DATA: BEGIN OF l_str,
kunnr TYPE kunnr,
name1 TYPE name1,
END OF l_str.
* DATA(i_field_customizing) = VALUE t_string_tt( ( `KUNNR` ) ( `NAME1` ) ).
DATA(i_field_customizing) = VALUE t_string_tt( ).
DATA(li_temp) = COND #( WHEN i_field_customizing IS INITIAL
THEN CAST data( NEW t_integer_tt( ( 1 ) ( 2 ) ) )
ELSE CAST data( REF #( i_field_customizing ) ) ).
ASSIGN li_temp->* TO <fs_table>.
LOOP AT <fs_table> ASSIGNING FIELD-SYMBOL(<fs_temp>).
ASSIGN COMPONENT <fs_temp> OF STRUCTURE l_str TO FIELD-SYMBOL(<fs_field>).
ENDLOOP.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).

Strange behaviour using string templates and new COND syntax

I have spotted a strange behaviour of new COND syntax when used inside a string template. It is about string length defaulting. It looks like the length of the string will be defaulted always to what stands after THEN even if the condition is not met.
Check out the following piece of code!
REPORT zzz.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
DATA(l_bool) = abap_true.
DATA(l_v_line) = |{ COND #( WHEN l_bool IS INITIAL THEN 'AAA' ELSE 'BBBB' ) }|.
DATA(l_v_line2) = |{ COND #( WHEN l_bool IS INITIAL THEN 'AAA' ELSE 'BBBB' ) WIDTH = 4 }|.
DATA(l_v_line3) = |{ COND #( WHEN l_bool IS INITIAL THEN 'AAA ' ELSE 'BBBB' ) }|.
DATA(l_v_line4) = |{ COND #( WHEN l_bool IS NOT INITIAL THEN 'BBBB' ELSE 'AAA' ) }|.
WRITE /: l_v_line, l_v_line2, l_v_line3, l_v_line4.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).
The output
BBB
BBB·
BBBB
BBBB
The first two variables l_v_line and l_v_line2 are truncated even if the condition evaluates to false. If I put space after AAA in l_v_line3 then it is OK. Putting BBBB after THEN for l_v_line4 solves the problem.
My question is: is this behaviour documented anywhere in SAP documentation? I could not find any clues that would have led me to it.
from ABAP documentation
The # character as a symbol for the operand type.
...
If the operand type is not fully identifiable, an operand with a
statically identifiable type must be specified after the first
THEN. This type is then used.