2

I have a dynamic internal table <ft_dyn_tab>. I want to cast each row of the internal table to the type string via the field symbol <lf_string>:

LOOP AT <ft_dyn_tab> ASSIGNING <fs_dyn_wa>.
  ASSIGN <fs_dyn_wa> to <lf_string> CASTING.
  ...
  "other logic
  ...
ENDLOOP.

Normally, CASTING works fine when all fields of the structure are of type character. But when one field is of type string, it gives a runtime error. Can anyone explain why? And how to resolve this issue?

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
divScorp
  • 498
  • 1
  • 8
  • 17
  • it is because the any type needs a type declaration when casting. So it will be CASTING TYPE c for example. – mrdeadsven May 02 '19 at 10:58
  • What are you doing with this string of concatenated field values? Perhaps there is a better solution to accomplish your goal without working with such a string... – futu May 02 '19 at 13:15
  • You said "anyway I've got the solution" to people trying to help you. So please be kind and post the solution ([quote](https://meta.stackoverflow.com/questions/255583/what-can-i-do-when-getting-we-are-no-longer-accepting-questions-answers-from-th): "Stack Exchange is a network of question and answer sites, not help forums. This implies that all posts are expected to have value for later visitors, in addition to helping the asker.") – Sandra Rossi May 02 '19 at 16:49
  • 2
    @SandraRossi the solution by futu I marked as accepted. And I've written in comment that I've same solution figured it out. Again posting the same solution doesn't change anything. And when I was writing the answer , I got his(futu) notification that's why I did't post my answer. – divScorp May 02 '19 at 17:00
  • 1
    @divScorp sorry, the answer was not the one I expected, and I didn't read its bottom part, nor your comment. My bad. As stackoverflow encourages the improvement of answers, I will edit it. – Sandra Rossi May 02 '19 at 18:01

3 Answers3

4

Why a structure with only character-like and String components can't be "casted" as a text variable

The reason is given by the ABAP documentation of Strings:

"A structure that contains a string is a deep structure and cannot be used as a character-like field in the same way as a flat structure.".

and of Deep:

"Deep: [...] the content [...] is addressed internally using references ([...], strings..."

and of Memory Requirement for Deep Data Objects:

"The memory requirement for the reference is 8 byte. [...] In strings, [...] an implicit reference is created internally."

and of ASSIGN - casting_spec:

"If the data type determined by CASTING is deep or if deep data objects are stored in the assigned memory area, the deep components must appear with exactly the same type and position in the assigned memory area. In particular, this means that individual reference variables can be assigned to only one field symbol that is typed as a reference variable by the same static type."

Now, the reason why the compiler and the run time don't let you do that, is that if you cast a whole deep structure, you could change the 8-bytes reference to access any place in the memory, that could be dangerous (How dangerous is it to access an array out of bounds?) and very difficult to analyze the subsequent bugs. In all programming languages, as far as possible, the compiler prevents out-of-bounds accesses or the checks are done at run time (Bounds checking).

Workaround

Your issue happens at run time because you use dynamically-created data objects, but you'd have exactly the same issue at compile time with statically-defined data objects. Below is a simple solution with a statically-defined structure.

You can access each field of the structure and concatenate it to a string:

DATA: BEGIN OF dyn_wa,
         country TYPE c LENGTH 3,
         city    TYPE string,
       END OF dyn_wa,
       lf_string TYPE string.
FIELD-SYMBOLS: <lf_field> TYPE clike.

dyn_wa = VALUE #( country = 'FR' city = 'Paris' ).

DO.
  ASSIGN COMPONENT sy-index OF STRUCTURE dyn_wa TO <lf_field>.
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
  CONCATENATE lf_string <lf_field> INTO lf_string RESPECTING BLANKS.
ENDDO.

ASSERT lf_string = 'FR Paris'. " one space because country is 3 characters

RESPECTING BLANKS keeps trailing spaces, to mimic ASSIGN ... CASTING.

Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
futu
  • 868
  • 6
  • 12
  • This is the same solution i figured it out. As you said there is better solution for concatenated string (I agree with that), but what you could recommend when you have to send structure data in file on application server.? – divScorp May 02 '19 at 14:29
  • So you want to store the data in a file? Then it depends on who is consuming this file afterwards. In general, I would prefer a standardized format: XLSX, CSV, XML, JSON... – futu May 02 '19 at 14:36
  • I think it would be better to store text file in application server. – divScorp May 02 '19 at 14:40
  • As I said, it depends on the purpose for which you are storing the data there. In the end it is your decision to make what is sufficient/best fitting :) – futu May 02 '19 at 14:49
  • 1
    I have improved the answer to include the reason why a "casting" is not possible. I excluded the internal table from the explanation because it's all just about deep structure. Note that I don't see why there would be a better solution to concatenate the fields: for example, you must use such a solution for transferring a table to a CSV file. – Sandra Rossi May 02 '19 at 19:46
1

Sounds like you want to assign the complete structured row to a plain string field symbol. This doesn't work. You can only assign the individual type-compatible components of the structured row to the string field symbol.

Otherwise, this kind of assignment works fine. For a table with a single column with type string:

TYPES table_type TYPE STANDARD TABLE OF string WITH EMPTY KEY.
DATA(filled_table) = VALUE table_type( ( `Test` ) ).
ASSIGN filled_table TO FIELD-SYMBOL(<dynamic_table>).
FIELD-SYMBOLS <string> TYPE string.

LOOP AT <dynamic_table> ASSIGNING FIELD-SYMBOL(<row>).
  ASSIGN <row> TO FIELD-SYMBOL(<string>).
ENDLOOP.

For a table with a structured row type:

TYPES:
  BEGIN OF row_type,
    some_character_field TYPE char80,
    the_string_field     TYPE string,
  END OF row_type.
TYPES table_type TYPE STANDARD TABLE OF row_type WITH EMPTY KEY.
DATA(filled_table) = VALUE table_type( ( some_character_field = 'ABC'
                                         the_string_field     = `Test` ) ).
ASSIGN filled_table TO FIELD-SYMBOL(<dynamic_table>).
FIELD-SYMBOLS <string> TYPE string.

LOOP AT <dynamic_table> ASSIGNING FIELD-SYMBOL(<row>).
  ASSIGN <row>-the_string_field TO <string>.
ENDLOOP.
Florian
  • 4,821
  • 2
  • 19
  • 44
  • Yes, I've to send complete structure data in string variable. but your solution works for only one field of structure. Anyway, I got the solution. thanks for your help. – divScorp May 02 '19 at 13:56
0

I have just tested this and it gives runtime error also when the structure does not have any string typed field.

I change the ASSIGN to a simple MOVE to a string variable g_string and it fails with runtime. If this fail it means that such an assignment is not possible, so the casting will not be either.

REPORT ZZZ.

TYPES BEGIN OF t_test.
  TYPES: f1 TYPE c LENGTH 2,
  f2 TYPE n LENGTH 4,
  f3 TYPE string.
TYPEs END OF t_test.

TYPES BEGIN OF t_test2.
  TYPES: f1 TYPE c LENGTH 2,
  f2 TYPE n LENGTH 4,
  f3 TYPE c LENGTH 80.
TYPES END OF t_test2.

TYPES: tt_test TYPE STANDARD TABLE OF t_test WITH EMPTY KEY,
tt_test2 TYPE STANDARD TABLE OF t_test2 WITH EMPTY KEY.

DATA(gt_test) = VALUE tt_test( ( f1 = '01' f2 = '1234' f3 = `Test`) ).
DATA(gt_test2) = VALUE tt_test2( ( f1 = '01' f2 = '1234' f3 = 'Test') ).
DATA: g_string TYPE string.

FIELD-SYMBOLS: <g_any_table> TYPE ANY TABLE,
  <g_string> TYPE string.

ASSIGN gt_test2 TO <g_any_table>.
ASSERT <g_any_table> IS ASSIGNED.
LOOP AT <g_any_table> ASSIGNING FIELD-SYMBOL(<g_any_wa2>).
*  ASSIGN <g_any_wa2> TO <g_string> CASTING.
  g_string = <g_any_wa2>.
ENDLOOP.
UNASSIGN <g_any_table>.

ASSIGN gt_test TO <g_any_table>.
ASSERT <g_any_table> IS ASSIGNED.
LOOP AT <g_any_table> ASSIGNING FIELD-SYMBOL(<g_any_wa>).
*  ASSIGN <g_any_wa> TO <g_string> CASTING.
  g_string = <g_any_wa>.
ENDLOOP.
Jagger
  • 10,350
  • 9
  • 51
  • 93
  • It works when all the fields in internal table is character type. I didn't tested for int or dec fields (sorry for that) I'll update the question. Anyway i got the solution. Thanks. – divScorp May 02 '19 at 13:47