Wednesday, September 7, 2016

Field Symbol

Field symbols and Data reference variables help us in dynamic programming. Which means, we can access the contents of the data objects whose name and properties are not known to us until the run-time.

1. What is Field Symbols?

Field symbols does not have any memory space when we declare them but instead they will point to an existing data object via its memory location.

Field symbol name should always be within <>, example:<FS_MARA>.
Syntax for declaring a field symbol.
FIELD-SYMBOLS : <FIELD_SYMBOL> TYPE MARA-MATNR. "here MARA-MATNR is a variable type
ASSIGNING and ASSIGN are the keywords which are used to assign a value to the field symbol.

Example of using field symbol as work area.

In the below example we are going to use field symbol as work area.
REPORT ZSAPN_FIELDSYMBOLS.

DATA : IT_MARA TYPE TABLE OF MARA.
DATA : WA_MARA TYPE MARA.
FIELD-SYMBOLS : <FS_MARA> TYPE MARA.
SELECT * FROM MARA
 INTO TABLE IT_MARA UP TO 50 ROWS.

LOOP AT IT_MARA ASSIGNING <FS_MARA>.
 IF <FS_MARA> IS  ASSIGNED.
   WRITE :/ <FS_MARA>-MATNR, <FS_MARA>-MTART, <FS_MARA>-MEINS.
 ENDIF.
ENDLOOP.
Check weather the field symbol is assigned or not before processing field symbol, it is very important to check field symbol, if it is not assigned it will get a run-time error, use the below syntax to check field symbol assignment.
IF <FS_MARA> IS  ASSIGNED.
**process field symbol
 ENDIF.
Untyped field symbols point to the built in data object space once the program starts. space has type c and length 1. Typed field symbols do not point to any field before a data object is assigned to them.

A field symbol is usually used for dynamic internal table or in a loop of an internal table that it can update internal table directly without calling MODIFY statement.

2. Basic forms of the ASSIGN Statement

2.1. Static Assign:
If you already know the name of the field that you want to assign to the field symbol when you write a program, use the static ASSIGN statement:
ASSIGN dobj TO <fs>.
When you assign the data object, the system checks whether the technical attributes of the data object dobj correspond to the type specifications for the field symbol <fs>. The field symbol adopts any generic attributes of dobj that are not contained in its own type specification. After the assignment, it points to this field in the memory.
REPORT demo_field_symbols_stat_ASSIGN .

FIELD-SYMBOLS:
 <f1> TYPE ANY,
 <f2> TYPE i.
DATA:
 text(20) TYPE c VALUE 'Hello, how are you?',
 num        TYPE i VALUE 5,
 BEGIN OF line1,
   col1 TYPE f VALUE '1.1e+10',
   col2 TYPE i VALUE '1234',
 END OF line1,
 line2 LIKE line1.

ASSIGN text TO <f1>.
ASSIGN num TO <f2>.
DESCRIBE FIELD <f1> LENGTH <f2>.
WRITE: / <f1>, 'has length', num.
ASSIGN line1 TO <f1>.
ASSIGN line2-col2 TO <f2>.
MOVE <f1> TO line2.
ASSIGN 'LINE2-COL2 =' TO <f1>.
WRITE: / <f1>, <f2>.
The list output is:
Hello, how are you? has length  20
LINE-COL2 = 1,234

The example declares two field symbols <f1> and <f2>. <f2> may only have fields of type I since it has been typed accordingly. <f1> and <f2> both point to different fields during the program.


Static ASSIGN with Offset Specification

In a static ASSIGN statement, you can use positive offset and length specifications to assign a subfield to a field symbol.

ASSIGN dobj[+off][(len)] TO <fs>.

When you assign parts of fields to a field symbol, the following special conditions apply:

·  The system does not check whether the selected part lies inside the field dobj. Both offset off  and length len can be larger than the length of dobj. You can address memory beyond the boundary of dobj, but not beyond the data areas for field symbols.

·  If you do not specify the length len, the system automatically uses the length of the field dobj. If off is greater than zero, <fs> always points to an area beyond the limits of dobj.

·  If off is smaller than the length of dobj, you can enter an asterisk (*) for len to prevent <fs> from referring to an address beyond the limits of dobj.

REPORT demo_field_symbols_stat_as_off .

FIELD-SYMBOLS <fs> TYPE ANY.

DATA: BEGIN OF line,

string1(10) VALUE '0123456789',

string2(10) VALUE 'abcdefghij',

END OF line.

WRITE / line-string1+5.

ASSIGN line-string1+5 TO <fs>.

WRITE / <fs>.

ASSIGN line-string1+5(*) TO <fs>.

WRITE / <fs>.

The list output is:

56789

56789abcde

56789

In this example, you can see the difference between an offset specification in a WRITE statement and an offset specification in an ASSIGN statement. With WRITE , the output is truncated at the end of line-string1. Specifying an offset greater than 9 would lead to an error during the syntax check. In the first ASSIGN statement, the memory area of length 10 beginning with offset 5 in line-string1 is assigned to the field symbol <fs>. The output then makes sense because the memory area behind line-string1 belongs to line-string2. In the second ASSIGN statement, the length specification * prevents the system from addressing the memory area after line-string1.

Casting data object

When you assign a data object to a field symbol, you can cast to any data type. This means that any area of memory can be viewed as having assumed a given type. You can then address parts of fields symbolically without having to use offset/length addressing.
A cast is performed using the CASTING addition of the ASSIGN statement. The CASTING addition allows you to assign a data object to a field symbol where the type of the data object is incompatible with that of the field symbol. There are two types of casting: casting with an implicit type declaration and casting with an explicit type declaration.

Casting with an Implicit Type Declaration

Provided field symbol is either fully typed or has one of the generic built-in ABAP types – c, n, p, or x – you can use the following ASSIGN statement:
ASSIGN ... TO <fs> CASTING.
When the system accesses the field symbol, the content of the assigned data object is interpreted as if it had the same type as the field symbol. The length and alignment of the data object must be compatible with the field symbol type. Otherwise the system returns a runtime error. If the type of either the field symbol or the data object is – or contains – a string, reference type, or internal table, the type and position of these components must match exactly. Otherwise, a runtime error occurs.
REPORT demo_field_symbols_casting.
TYPES: BEGIN OF t_date,
         year(4)  TYPE n,
         month(2) TYPE n,
         day(2)   TYPE n,
   END OF t_date.
FIELD-SYMBOLS <fs> TYPE t_date.
ASSIGN sy-datum TO <fs> CASTING.
WRITE / sy-datum.
SKIP.
WRITE: / <fs>-year , / <fs>-month, / <fs>-day.
The output looks something like this:
1999/05/19
1999
05
19
In this example, the field symbol <fs> is fully typed using the local program type t_date. The sy-datum field can be treated like a structure as a result of the CASTING addition of the ASSIGN statement. This would not be possible without the CASTING addition, since sy-datum is incompatible with the field symbol type.

Casting with an Explicit Type Declaration

If the field symbol is neither fully typed nor generically typed, use the following form of the ASSIGN statement:

ASSIGN ... TO <fs> CASTING {TYPE type}|{LIKE dobj} [DECIMALS dec].

When the system accesses the field symbol, the content of the assigned data object is interpreted as if it had the type declared in the statement. After the TYPE addition, you can declare the name of a data object enclosed in parentheses. The content of this data object indicates the data type at runtime.

You cannot enter a type unless an explicit cast to the data object is logical. For example, there is no point casting a standard table to a sorted table, or an object reference to a data reference. Thus, you cannot declare table types (such as SORTED TABLE) or reference types (using REF TO) after the TYPEaddition. If the data type contains implicit string, reference types, or internal tables, these components must also occur in the assigned data object with their type and position.. Otherwise, the system returns a syntax or runtime error.

The data type declared in the TYPE or LIKEaddition must be compatible with the generic type of the field symbol. The generic type can be left as it is or specialized. However, you cannotreset known technical attributes of the field symbol. For example, if the field symbol has the completely generic  type ANY , you can declare another permitted generic type. If the field symbol has the generic type c, n, p, or x, you can only specify the length and the number of decimal places. You cannot make an explicit type declaration for a fully typed field symbol, since, if the field symbol is fully typed already, you cannot specialize it further. In any case, the system checks statically for this at runtime, where possible.

You should use the DECIMALS addition if the content of the assigned data object can be interpreted as a packed number. The field symbol is then given dec decimal places. DECIMALS can only be used if no type specification is made of if the type p is specified after TYPE. If there is no type specification, type p is used implicitly. Moreover, you cannot use the LIKE and DECIMALS additions together.

REPORT demo_field_symbols_casting_typ.

TYPES: BEGIN OF t_date,

         year(4)  TYPE n,

         month(2) TYPE n,

         day(2)   TYPE n,

   END OF t_date.

FIELD-SYMBOLS: <fs> TYPE ANY,

           <f>  TYPE n.

ASSIGN sy-datum TO <fs> CASTING TYPE t_date.

WRITE / sy-datum.

SKIP.

DO.

 ASSIGN COMPONENT sy-index OF STRUCTURE <fs> TO <f>.

 IF sy-subrc <> 0.

   EXIT.

 ENDIF.

 WRITE / <f>.

ENDDO.

The output looks something like this:

1999/05/19

1999

05

19

In this example, the field symbol <fs> is completely generic. A cast is performed on the field sy-datum  to the local program type t_date using the CASTING addition of the ASSIGN statement. The field symbol <fs> can now be treated like a structure, but it does not know any components. Therefore, it must be assigned – component by component – to another field symbol <f>.

2.2. Dynamic ASSIGN

If you do not know the name of the field that you want to assign to the field symbol when you write a program, you can use a dynamic ASSIGN statement:
ASSIGN (dobj) TO <fs>.
This statement assigns the data object whose name is contained in the dobj field to the field symbol <fs>. You cannot use subfields in a dynamic ASSIGN.
At runtime, the system searches for the corresponding data object in the following order:
 1.  If the ASSIGN statement is in a procedure, the system searches first in its local data.
 2.  If it cannot find the object in the local data (or if the ASSIGN statement is not in a procedure), it then looks in the local data of the program.
 3.  If the field is not found in the global data of the program, the system looks in the table work areas declared with the TABLES statement in the main program of the current program group. A program group consists of a main program and all of the programs that are loaded into the same internal session as a result of other program calls.
If the search is successful and a field can be assigned to the field symbol, sy-subrc is set to 0. Otherwise, it is set to 4, and the field symbol remains unchanged. For security reasons, you should always check the value of sy-subrc after a dynamic ASSIGN to prevent the field symbol pointing to the wrong area.
Searching for the field in this way slows down the response time. You should therefore only use the dynamicASSIGNstatement where absolutely necessary. If you know when you create the program that you want to assign atable work area to the field symbol, you can also use the following variant of the dynamic ASSIGNstatement:
ASSIGN TABLE FIELD (dobj) TO <fs>.
The system then only searches for the data object to be assigned within the table work areas declared using TABLES in the main program of the current program group. This addition is forbidden in ABAP Objects, since the latter does not support table work areas.
Suppose we have three programs. The main program:
REPORT demo_field_symbols_dynami_as_1.
TABLES sbook.
sbook-fldate = sy-datum.
PERFORM form1 IN PROGRAM demo_form1.
The other two programs are:
REPORT demo_form1.
FORM form1.
PERFORM form2 IN PROGRAM demo_form2.
ENDFORM.
and
REPORT demo_form2.
FORM form2.
DATA name(20) TYPE c VALUE 'SBOOK-FLDATE'.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN (name) TO <fs>.
IF sy-subrc EQ 0.
  WRITE / <fs>.
ENDIF.
ENDFORM.
The output looks something like this:
02.06.1998
The program group in the internal session now consists of the programs DEMO, MYFORMS1 and MYFORMS2. The field symbol <fs> is defined in MYFORMS2. After the dynamic ASSIGN statement, it points to the component FLDATE of the table work area SBOOK declared in the main program DEMO.

REPORT demo_field_symbols_dynami_as_2 .
TABLES sbook.
DATA:
  name1(20) TYPE c VALUE 'SBOOK-FLDATE',
  name2(20) TYPE c VALUE 'NAME1'.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN TABLE FIELD (name1) TO <fs>.
WRITE: / 'sy-subrc:', sy-subrc.
ASSIGN TABLE FIELD (name2) TO <fs>.
WRITE: / 'sy-subrc:', sy-subrc.

The list output is:
sy-subrc: 0
sy-subrc: 4

In the first ASSIGN statement, the system finds the component FLDATE of the table work area SBOOK, and sy-subrc is set to 0. In the second ASSIGN statement, the system does not find the field name1 because it is declared by the DATA statement and not by the TABLES statement. sy-

Field Symbol Assigns to Field Symbol

Instead of using the names of data objects, you can also assign field symbols to field symbols in all variants of the ASSIGN statement.
ASSIGN <fs1>[+off][(len)] TO <fs2>.
in a static ASSIGN and:
ASSIGN [TABLE FIELD] (dobj) TO <fs2>.
in a dynamic ASSIGN, where the field dobj contains the name of a field symbol <fs1>. <fs1> and <fs2> may be identical.

Note that the same code in Unicode system will produce different results than in non-Unicode systems:
REPORT demo_field_symbols_dynami_as_3 .
DATA: BEGIN OF s,
a TYPE c VALUE '1',
b TYPE c VALUE '2',
c TYPE c VALUE '3',
d TYPE c VALUE '4',
e TYPE c VALUE '5',
f TYPE c VALUE '6',
g TYPE c VALUE '7',
h TYPE c VALUE '8',
END OF s.
DATA off TYPE i.
FIELD-SYMBOLS <fs> TYPE ANY.
ASSIGN s-a TO <fs>.
DO 4 TIMES.
 off = sy-index - 1.
 IF <fs> IS ASSIGNED.
 ASSIGN <fs>+off(1) TO <fs>.
 IF <fs> IS ASSIGNED.
 WRITE <fs>.
 ENDIF.
 ENDIF.
ENDDO.
In non-Unicode systems, the output is as follows:
1 2 4 7
The program declares a structure with eight components s-a  to s-h, and fills them with the digits 1 to 8. These character strings are stored regularly in memory. The component s-a is assigned initially to the field symbol <fs>. The effect of the statements in the DO loop is:
Loop pass 1:
<fs> points to s-a, off is zero, and s-a is assigned to <fs>
Loop pass 2:
<fs> points to s-a, off is zero, and s-b is assigned to <fs>
Loop pass 3:
<fs> points to s-b, off is two, and s-d is assigned to <fs>
Loop pass 4:
<fs> points to s-d, off is three, and s-g is assigned to <fs>
In a Unicode environment (where the Unicode flag is set in the editor settings), the output is simply:
1
No data object is assigned to <fs> from the second loop pass onwards.

No comments:

Post a Comment

SAP giới thiệu mã hỗ trợ AI trong ngôn ngữ ABAP riêng của mình

SAP đã ra mắt một loạt tính năng mã hỗ trợ AI trong môi trường phát triển ứng dụng dựa trên đám mây của mình, đồng thời tham gia vào danh sá...