Strange behaviour using string templates and new COND syntax - abap

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.

Related

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 ).

Which Netweaver version do I need for BASE CORRESPONDING?

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.

Creating a range for a field from internal table using RTTS

I want to create a function/custom class method that takes in 2 parameters:
1) IM_ITAB type ANY TABLE
2) IM_COMPONENT type STRING
and returns 1 parameter:
1) EX_RANGE type PIQ_SELOPT_T
So, algorithm is like this:
First of all, we check if the column with a component name at all exists
Then, we check that internal table is not empty.
Then, we loop through internal table assigning component and filling range table. Code is below.
METHODS compose_range_from_itab
IMPORTING
IM_ITAB type ANY TABLE
IM_COMPONENT type STRING
EXPORTING
EX_RANGE type PIQ_SELOPT_T.
...
METHOD compose_range_from_itab.
DATA: lo_obj TYPE REF TO cl_abap_tabledescr,
wa_range TYPE selopt,
lt_range TYPE piq_selopt_t.
FIELD-SYMBOLS: <fs_line> TYPE ANY,
<fs_component> TYPE ANY.
lo_obj ?= cl_abap_typedescr=>describe_by_data( p_data = im_itab ).
READ TABLE lo_obj->key TRANSPORTING NO FIELDS WITH KEY name = im_component.
IF sy-subrc IS INITIAL.
IF LINES( im_itab ) GT 0.
LOOP AT im_itab ASSIGNING <fs_line>.
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO <fs_component>.
wa_range-sign = 'I'.
wa_range-option = 'EQ'.
wa_range-low = <fs_component>.
APPEND wa_range TO lt_range.
ENDLOOP.
SORT lt_range BY low.
DELETE ADJACENT DUPLICATES FROM lt_range COMPARING low.
ex_range[] = lt_range[].
ENDIF.
ENDIF.
ENDMETHOD.
But I want to improve the method further. If the imported internal table has, let's say, 255 columns, then it will take longer to loop through such table. But I need only one column to compose the range.
So I want to get components of internal table, then choose only one component, create a new line type containing only that component, then create internal table with that line type and copy.
Here is the pseudo code corresponding to what I want to achieve:
append corresponding fields of im_itab into new_line_type_internal_table.
How can I "cut out" one component and create a new line type using RTTS?
You are overcomplicating everything, you don't need RTTS for that.
DEFINE make_range.
ex_range = VALUE #( BASE ex_range ( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
LOOP AT im_itab ASSIGNING FIELD-SYMBOL(<fs_line>).
ASSIGN COMPONENT im_component OF STRUCTURE <fs_line> TO FIELD-SYMBOL(<fs_field>).
CHECK sy-subrc = 0 AND <fs_field> IS NOT INITIAL.
make_range <fs_field>.
ENDLOOP.
And yes, as Sandra said, you won't gain any performance with RTTS, just the opposite.
Surprisingly, this variant turned out to be faster:
CLASS-METHODS make_range_variant_2
IMPORTING
sample TYPE table_type
column TYPE string
RETURNING
VALUE(result) TYPE range_type.
METHOD make_range_variant_2.
TYPES:
BEGIN OF narrow_structure_type,
content TYPE char32,
END OF narrow_structure_type.
TYPES narrow_table_type TYPE STANDARD TABLE OF narrow_structure_type WITH EMPTY KEY.
DATA narrow_table TYPE narrow_table_type.
DATA(mapping) =
VALUE cl_abap_corresponding=>mapping_table_value(
( kind = cl_abap_corresponding=>mapping_component srcname = column dstname = 'CONTENT' ) ).
DATA(mover) =
cl_abap_corresponding=>create_with_value(
source = sample
destination = narrow_table
mapping = mapping ).
mover->execute(
EXPORTING
source = sample
CHANGING
destination = narrow_table ).
LOOP AT narrow_table ASSIGNING FIELD-SYMBOL(<row>).
INSERT VALUE #(
sign = 'I'
option = 'EQ'
low = <row>-content )
INTO TABLE result.
ENDLOOP.
ENDMETHOD.
CL_ABAP_CORRESPONDING delegates to a kernel function for the structure-to-structure move, which apparently is faster than the ABAP-native ASSIGN COMPONENT [...] OF STRUCTURE [...] TO FIELD-SYMBOL [...]. The actual loop then seems to be faster because it uses fixed-name assignments.
Maybe somebody could verify.
I would not go for a Macro.
Data:
lr_data type ref to data.
FIELD-SYMBOLS:
<lv_component> TYPE any,
<ls_data> TYPE any.
CREATE DATA lr_data LIKE LINE OF im_itab.
ASSIGN lr_data->* TO <ls_data>.
"Check whether im_component exists
ASSIGN COMPONENT im_component OF STRUCTURE <ls_data> TO <lv_component>.
CHECK sy-subrc EQ 0.
LOOP AT im_itab INTO <ls_data>.
APPEND VALUE #( sign = 'I' option = 'EQ' low = <lv_component> ) TO ex_range.
ENDLOOP.

Custom Search Help from Application Server Directory ABAP

I have requirement to provider customer search help for user and data to be retrieved from application server directory.
Following is the detail of directory and File type.
Application Server Directory: /usr/sap/tmp/
File type extension .txt should only be available in search help.
Custom Search help should display Directory Name and File having extension .txt.
Users should not be able to select files from any other directory.
Example of Search help output:
Directory Name File Name
-------------- --------------
/usr/sap/tmp/ file_name1.txt
/usr/sap/tmp/ file_name2.txt
/usr/sap/tmp/ file_name3.txt
Following links are helpful but my requirement is not fulfilled.
https://archive.sap.com/discussions/thread/285999
F4_FILENAME
cl_gui_frontend_services=>directory_browse
/SAPDMC/LSM_F4_SERVER_FILE
https://archive.sap.com/discussions/thread/715635
F4_DXFILENAME_TOPRECURSION
is there any one who has better solution?
regards,
Umar Abdullah
Doesn't function module /SAPDMC/LSM_F4_SERVER_FILE fullfil your requirement?
Edit:
In order for users to not be able to select anything from different directories, you can write a wrapper around the function call to make sure the right directory is selected.
Probably not the ideal solution, but one that requires no development effort.
CONSTANTS:
lco_directory TYPE char30 VALUE '/usr/sap/tmp/',
lco_filemask TYPE char5 VALUE '*'.
DATA:
lv_filename TYPE rlgrap-filename,
lv_path TYPE string.
WHILE 1 NE 2.
CLEAR: lv_filename, lv_path.
CALL FUNCTION '/SAPDMC/LSM_F4_SERVER_FILE'
EXPORTING
directory = lco_directory
filemask = lco_filemask
IMPORTING
serverfile = lv_filename
EXCEPTIONS
canceled_by_user = 1
OTHERS = 2.
IF sy-subrc = 0 AND sy-ucomm NE 'CANC' AND lv_filename IS NOT INITIAL.
CALL FUNCTION 'TRINT_SPLIT_FILE_AND_PATH'
EXPORTING
full_name = lv_filename
IMPORTING
file_path = lv_path
EXCEPTIONS
x_error = 1
OTHERS = 2 .
IF sy-subrc = 0 AND lv_path NE lco_directory.
* Wrong directory was chosen
MESSAGE 'Invalid directory' TYPE 'S' DISPLAY LIKE 'W'.
ELSE.
* Directory is ok
EXIT.
ENDIF.
ELSE.
* Action cancelled
CLEAR: lv_filename, lv_path.
EXIT.
ENDIF.
ENDWHILE.
I have created custom logic for the requirement. I would like to share.
REPORT YUA_LIST_DIRECTORY.
CLASS ff_intf DEFINITION.
PUBLIC SECTION.
METHODS: listdirectory IMPORTING iv_dir TYPE c
EXPORTING ev_ldir TYPE c ev_file TYPE c ,
get_file_list IMPORTING iv_ldir TYPE c iv_today TYPE c.
TYPES: BEGIN OF t_directory,
log_name TYPE dirprofilenames,
phys_path TYPE dirname_al11,
END OF t_directory.
DATA: lt_int_list TYPE TABLE OF abaplist,
lt_string_list TYPE list_string_table,
lt_directories TYPE TABLE OF t_directory,
ls_directory TYPE t_directory.
DATA: BEGIN OF gs_file,
directory(500) TYPE c, " name of directory.
name(75) TYPE c, " name of entry." (possibly truncated.)
type(10) TYPE c, " type of entry: directory, file
len(16) TYPE p, " length in bytes
owner(8) TYPE c, " owner of the entry
mtime(6) TYPE p, " last modification date, " seconds since 1970
mode(9) TYPE c, " like "rwx-r-x--x":" protection mode
errno(3) TYPE c,
errmsg(40) TYPE c,
mod_date TYPE d,
mod_time(8) TYPE c, " hh:mm:ss
subrc LIKE sy-subrc,
END OF gs_file.
DATA:
ls_file LIKE gs_file,
pt_file LIKE TABLE OF gs_file.
CLASS-METHODS: p6_to_date_time_tz IMPORTING iv_time TYPE p EXPORTING ev_time TYPE c ev_date TYPE d.
ENDCLASS. "ff_intf DEFINITION
*----------------------------------------------------------------------*
* CLASS ff_intf IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS ff_intf IMPLEMENTATION.
METHOD listdirectory.
FIELD-SYMBOLS: <l_line> TYPE string.
CONCATENATE 'FF' sy-datum '.txt' INTO ev_file. " file name
SUBMIT rswatch0 EXPORTING LIST TO MEMORY AND RETURN.
CALL FUNCTION 'LIST_FROM_MEMORY'
TABLES
listobject = lt_int_list.
CALL FUNCTION 'LIST_TO_ASCI'
EXPORTING
with_line_break = 'X' "abap_true
IMPORTING
list_string_ascii = lt_string_list
TABLES
listobject = lt_int_list.
* remove the separators and the two header lines
DELETE lt_string_list WHERE table_line CO '-'.
DELETE lt_string_list INDEX 1.
DELETE lt_string_list INDEX 1.
* parse the individual lines
LOOP AT lt_string_list ASSIGNING <l_line>.
* If you're on a newer system, you can do this in a more elegant way using regular expressions
CONDENSE <l_line>.
SHIFT <l_line> LEFT DELETING LEADING '|'.
SHIFT <l_line> RIGHT DELETING TRAILING '|'.
SPLIT <l_line>+1 AT '|' INTO ls_directory-log_name ls_directory-phys_path.
APPEND ls_directory TO lt_directories.
ENDLOOP.
READ TABLE lt_directories INTO ls_directory WITH KEY log_name = iv_dir .
IF sy-subrc EQ 0.
ev_ldir = ls_directory-phys_path.
ENDIF.
ENDMETHOD. "listdirectory
METHOD get_file_list.
DATA:
l_counter TYPE i,
l_counter_package TYPE i,
l_char10(10),
l_text(100),
l_subrc LIKE sy-subrc,
lv_cmptoday TYPE c LENGTH 11.
*-----------------------------------*
DATA lv_compstr TYPE c LENGTH 5.
lv_compstr = '*.TXT'.
CONCATENATE '*' sy-datum+0(4) sy-datum+4(2) sy-datum+6(2) '*' INTO lv_cmptoday. " YYYYMMDD
CALL 'C_DIR_READ_FINISH'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
CALL 'C_DIR_READ_START'
ID 'DIR' FIELD iv_ldir " logical directory
ID 'FILE' FIELD '*'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
IF sy-subrc <> 0.
IF NOT ls_file-errmsg IS INITIAL.
MESSAGE i034(/sapdmc/lsmw_obj_060) WITH ls_file-errmsg.
ENDIF.
EXIT.
ENDIF.
DO .
CLEAR ls_file.
CALL 'C_DIR_READ_NEXT'
ID 'TYPE' FIELD ls_file-type
ID 'NAME' FIELD ls_file-name
ID 'LEN' FIELD ls_file-len
ID 'OWNER' FIELD ls_file-owner
ID 'MTIME' FIELD ls_file-mtime
ID 'MODE' FIELD ls_file-mode
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
l_subrc = sy-subrc.
ls_file-subrc = sy-subrc.
IF l_subrc = 1.
EXIT.
ELSEIF l_subrc = 5.
ls_file-type = '???'.
ls_file-owner = '???'.
ls_file-mode = '???'.
ENDIF.
ls_file-directory = iv_ldir.
ADD 1 TO l_counter.
ADD 1 TO l_counter_package.
IF l_counter_package = 100.
l_text = '& Enteries Read'.
l_char10 = l_counter.
REPLACE '&' WITH l_char10 INTO l_text.
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
text = l_text.
l_counter_package = 0.
ENDIF.
* Machine time into date/time of day convert
IF iv_today EQ 'X'. " only files of current date
CALL METHOD ff_intf=>p6_to_date_time_tz( EXPORTING iv_time = ls_file-mtime
IMPORTING ev_time = ls_file-mod_time ev_date = ls_file-mod_date ).
IF ls_file-mod_date EQ sy-datum.
* Only the files, which fit the sample(mask)
CASE ls_file-type(1).
WHEN 'F' OR 'f'. " File
IF ( ls_file-name CP lv_compstr ) AND ls_file-name+0(2) = 'FF' AND ls_file-name CP lv_cmptoday. " Only Text File to compare
APPEND ls_file TO pt_file.
ENDIF.
* WHEN OTHERS.
* APPEND ls_file TO pt_file.
ENDCASE.
ENDIF.
ELSE. " ALL files in directory
* Only the files, which fit the sample(mask)
CASE ls_file-type(1).
WHEN 'F' OR 'f'. " File
IF ( ls_file-name CP lv_compstr ) AND ls_file-name+0(2) = 'FF'. " Only Text File to compare and PODEL & Today
APPEND ls_file TO pt_file.
ENDIF.
ENDCASE.
ENDIF.
ENDDO.
SORT pt_file BY type DESCENDING name DESCENDING.
CALL 'C_DIR_READ_FINISH'
ID 'ERRNO' FIELD ls_file-errno
ID 'ERRMSG' FIELD ls_file-errmsg.
ENDMETHOD. "get_file_list
METHOD p6_to_date_time_tz.
DATA: opcode TYPE x,
unique, not_found,
timestamp TYPE i,
date TYPE d,
time TYPE t,
tz LIKE sy-zonlo,
timestring(10),
abapstamp(14),
abaptstamp TYPE timestamp.
timestamp = iv_time.
IF sy-zonlo = space.
* Der Benutzer hat keine Zeitzone gepflegt: nehme lokale des App. Srv.
CALL FUNCTION 'TZON_GET_OS_TIMEZONE'
IMPORTING
ef_timezone = tz
ef_not_unique = unique
ef_not_found = not_found.
IF unique = 'X' OR not_found = 'X'. .
tz = sy-tzone.
CONCATENATE 'UTC+' tz INTO tz.
ENDIF.
ELSE.
tz = sy-zonlo.
ENDIF.
* wandle den Timestamp in ABAP Format um und lass den ABAP konvertieren
opcode = 3.
CALL 'RstrDateConv'
ID 'OPCODE' FIELD opcode
ID 'TIMESTAMP' FIELD timestamp
ID 'ABAPSTAMP' FIELD abapstamp.
abaptstamp = abapstamp.
CONVERT TIME STAMP abaptstamp TIME ZONE tz INTO DATE date
TIME time.
IF sy-subrc <> 0.
date = abapstamp(8).
time = abapstamp+8.
ENDIF.
WRITE: time(2) TO timestring(2),
':' TO timestring+2(1),
time+2(2) TO timestring+3(2),
':' TO timestring+5(1),
time+4(2) TO timestring+6(2).
MOVE timestring TO ev_time.
MOVE date TO ev_date.
ENDMETHOD. "P6_TO_DATE_TIME_TZ
ENDCLASS.
DATA lo_pi TYPE REF TO ff_intf.
DATA ls_pt LIKE LINE OF lo_pi->pt_file.
DATA v_csv TYPE c LENGTH 1 VALUE space.
DATA v_separator TYPE c LENGTH 2.
DATA: lt_file TYPE ztt_file,
ls_file LIKE LINE OF lt_file,
ls_ptfile LIKE LINE OF lo_pi->pt_file.
SELECTION-SCREEN: BEGIN OF BLOCK a WITH FRAME TITLE text-001.
PARAMETERS p_dir TYPE c LENGTH 50 DEFAULT '/usr/sap/tmp/'.
PARAMETERS: p_sfile LIKE rlgrap-filename.
SELECTION-SCREEN: END OF BLOCK a.
AT SELECTION-SCREEN OUTPUT.
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_sfile.
REFRESH lo_pi->pt_file.
CALL METHOD lo_pi->get_file_list( EXPORTING iv_ldir = p_dir iv_today = '' ). " Directory logical name.
REFRESH lt_file.
LOOP AT lo_pi->pt_file INTO ls_ptfile.
MOVE ls_ptfile-directory TO ls_file-directory.
MOVE ls_ptfile-name TO ls_file-fname.
APPEND ls_file TO lt_file.
ENDLOOP.
CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
EXPORTING
retfield = 'FNAME'
dynpprog = sy-repid
dynpnr = sy-dynnr
dynprofield = 'so_tmpl-low'
value_org = 'S'
TABLES
value_tab = lt_file
EXCEPTIONS
parameter_error = 1
no_values_found = 2
OTHERS = 3.
CASE sy-subrc.
WHEN 1.
MESSAGE 'Parameter Error' TYPE 'I' DISPLAY LIKE 'W'.
WHEN 2.
MESSAGE 'No values found' TYPE 'I' DISPLAY LIKE 'W'.
WHEN 3.
MESSAGE 'Error Processing help' TYPE 'I' DISPLAY LIKE 'W'.
ENDCASE.
********************************* INITIALIZATION. ************************************
INITIALIZATION.
CREATE OBJECT lo_pi.
********************************* START-OF-SELECTION ************************************
START-OF-SELECTION.
********************************* END-OF-SELECTION ************************************
END-OF-SELECTION.

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( ).