Dynamic Programming in ABAP
Dynamic Programming in ABAP
Field symbol is a placeholder for data object, which points to the value present at the memory address of
a data object. It does not reserve any physical memory space when we declare them. It only points to a
data object at run time. Field symbols are of two types:
NOTE:
Typed field symbols can point to the data objects of specified type only.
After assigning a data object to a field symbol, if we make any changes to the field symbol value,
then the value of corresponding data object is also updated.
Modifying internal table records – We can declare a field symbol of type any structure, which we can
use while looping through an internal table.
NOTE:
If we change any field of structure in field symbol, the corresponding field in internal will get
updated. We don’t need to write the MODIFY statement which we would have written if we had
used work area. This is because work area stores a copy of the internal table row, whereas field
symbol directly references the internal table row.
1
Hence processing of internal table with field symbol is faster than the processing of internal table
with work area.
Appending to internal table – Now suppose we want to append some values to one internal table, then
we can use field symbol as below:
After executing this, the internal table will hold two rows.
NOTE:
Always perform a check on field symbol that if it is assigned before doing any operation to avoid
short dump. Also after doing the operation, unassign the field symbol.
Reading internal table – We can read a record of internal table using field symbol as below:
Dynamic programming is actually implemented using generic field symbols. The most commonly used
generic types are TYPE ANY and TYPE ANY TABLE.
2
Here we can assign any data object to TYPE ANY field symbol whereas TYPE ANY TABLE field symbol
is used for assigning any internal table.
TYPE ANY:
Let us assign a work area of type MARA to a TYPE ANY field symbol and then populate the work area
using field symbol.
NOTE:
After assigning lw_mara to <fs_str>, we cannot directly use the ‘-‘ operator on field symbol to
access the fields of MARA structure i.e. <fs_str>-matnr would produce syntax error. This is
because the field symbol type is declared only at runtime not at compile time.
So to access the matnr field with field symbol, first we need to assign that field component to a
different field symbol and then use the new field symbol to update the matnr field as show in
above code snippet.
After execution of above code snippet, the value of lw_mara-matnr would be MAT001.
We can assign any internal table to this field symbol. Let us analyze the below code snippet to
understand how we could use such field symbol.
3
IF <fs_str> IS ASSIGNED.
ASSIGN COMPONENT 'MATKL' OF STRUCTURE <fs_str> TO <fs_data>.
IF <fs_data> IS ASSIGNED.
IF <fs_data> EQ '01'.
*********** Do some processing *********
ENDIF.
UNASSIGN <fs_data>.
ENDIF.
ENDIF.
ENDLOOP.
NOTE:
Since <fs_tab> is a generic field symbol, its type will be known only at runtime, hence we cannot
directly write the fields of MARA structure after WITH KEY, instead we have to write the field
name within parenthesis as shown above.
In ABAP, this parenthesis indicates the compiler that the value of the operand will be decided at
runtime, hence we don’t get any compilation error.
In my next blog i have explained about data references and its significance in dynamic programming.
Below is the link for same.
https://blogs.sap.com/2017/09/11/dynamic-programming-in-abap-part-2-introduction-to-data-reference/
4
Dynamic Programming in ABAP – Part 2 –
Introduction to Data Reference
25 Likes 36,593 Views 13 Comments
Hi,
In my last blog I explained about field symbols, below is the link for same:
https://blogs.sap.com/2017/09/05/dynamic-programming-in-abap-part-1-introduction-to-field-symbols/
In this blog I am going to explain about data references and its significance in dynamic programming.
According to SAP documentation, Data references can point to any data objects or to their parts
(components, rows of internal tables, or sections specified by offsets and lengths).
So data references are nothing but pointers. It stores the memory address of any data object. But to
access the actual data object which data reference is pointing to, we first need to deference it using
dereferencing operator ->*.
Field symbol is a placeholder for data object to which it is assigned and points to the content of data
object hence it can be used at any operand position (no need to dereference it) and works with the
content of the referenced memory area (value semantics).
Data references are pointers to data objects and it contains the memory address of data object (reference
semantics). Data reference cannot be used at operand position directly; it should be dereferenced first.
5
DATA lr_num TYPE REF TO i.
CREATE DATA lr_num.
Here first statement declares a reference variable lr_num which can point to any data object of type “i”.
And second statement creates an anonymous data object of type “i” and assigns the reference of this
data object to lr_num. Now if we want to change the value of data object, then it can be done by
dereferencing lr_num by using dereference operator ->* as shown below:
lr_num->* = 2.
WRITE: / lr_num->*.
NOTE:
With ABAP 7.40, instead of CREATE DATA, the NEW operator can also be used to create an
anonymous data object and assigns its reference to a data reference variable.
If you want to assign the reference of an existing data object to a data reference, you can use GET
REFERENCE statement.
Here lv_num is an existing data object (not anonymous data object). The output would be 4.
NOTE:
With ABAP 7.40, instead of GET REFERENCE, the REF operator also can be used to assign the
reference of an existing data object to a data reference.
6
Working with structures:
Here individual components of the structure can be accessed with -> operator on data reference variable.
While processing internal table row, we can use REFERENCE INTO statement to set references to table
rows as shown below:
Here first statement declares a generic data reference lr_num which can point to any data object. And
second statement creates an anonymous data object of type “i” and assigns its reference to lr_num.
Now since lr_num is generic, lr_num->* cannot be directly used at operand position. Hence the below
statement would not be allowed.
7
lr_num->* = 2.
So in case of generic data reference, it can only be dereferenced using a field symbol, and this field
symbol can be used at any operand position to manipulate the value of data object as shown below:
<num> = 3.
NOTE:
After ASSIGN statement you should check sy-subrc If field symbol assignment is successful, sy-
subrc will be 0 otherwise it will be 4.
Here CREATE DATA statement creates an anonymous data object (MARA structure) and assigns its
reference to the generic data reference lr_str, which then can be dereferenced into a generic field
symbol <str>. Now, to access individual component of MARA structure, ASSIGN
COMPONENT statement can be used.
Requirement: Selection screen parameter “Table Name” will take a table name as input and display the
corresponding table entries as output.
Solution:
8
PARAMETERS: p_tname TYPE tabname.
DATA: lr_tab TYPE REF TO data.
FIELD-SYMBOLS: <tab> TYPE ANY TABLE.
Explanation:
Here lr_tab is a generic data reference and <tab> is a generic field symbol for internal table. In CREATE
DATA statement, the type of data object is mentioned in parenthesis which means that the type will be
determined at runtime based on the value of parameter p_tname. After that we have dereferenced the
data reference lr_tab into a generic field symbol <tab>. Now this field symbol can be used to do any valid
operation on the internal table.
Data reference variable can store the reference to any data object (variable, structures, internal tables
etc.) whereas Object reference variable can store the reference to any class object.
For data reference variables, either the generic data type or a completely specified data type can be
specified. For object reference variables, either a class or an interface can be specified.
https://blogs.sap.com/2017/09/29/dynamic-programming-in-abap-part-3-an-example-abap-rtts/
9
Dynamic Programming in ABAP – Part 3 – An
Example – ABAP RTTS
6 Likes 13,885 Views 5 Comments
Hi,
In my last blog I explained about the significance of field symbol and data references in dynamic
programming.
https://blogs.sap.com/2017/09/05/dynamic-programming-in-abap-part-1-introduction-to-field-symbols/
https://blogs.sap.com/2017/09/11/dynamic-programming-in-abap-part-2-introduction-to-data-reference/
Now here we will see one example of dynamic programming approach and also a brief introduction to
ABAP RTTS.
Runtime Type Identification (RTTI) – Provides the methods to get the type definition of data
objects at runtime.
Runtime Type Creation (RTTC) – Provides the methods to create the data objects at runtime
with any type definition.
Basically, ABAP RTTS provides a set of classes, whose methods can be used for runtime type
identification and runtime type creation. To know more about ABAP RTTS you can follow below link:
https://wiki.scn.sap.com/wiki/pages/viewpage.action?pageId=42965
Requirement: As an ABAP developer, very often we get the situation where we need to write data from
an internal table to a file on application server.
Solution: We will build one class having a method which will take any internal table as input and write its
content in a file on application server.
Class Definition:
10
ev_message TYPE string.
ENDCLASS.
Here importing parameter it_data is of TYPE ANY TABLE so that it can receive any internal table.
Class Implementation:
* Using RTTS to get the runtime type information of the internal table
lo_type_def = cl_abap_tabledescr=>describe_by_data( it_data ).
lo_table_def ?= lo_type_def.
lo_data_def = lo_table_def->get_table_line_type( ).
lo_struct_def ?= lo_data_def.
CLEAR: lo_data_def.
11
EXPORTING
i_data_element = lw_field_info-rollname
i_language = sy-langu
IMPORTING
e_scrtext_m = ls_comp_detail-descr
EXCEPTIONS
error = 1.
IF ls_comp_detail-descr IS INITIAL.
ls_comp_detail-descr = wa_components-name.
ENDIF.
APPEND ls_comp_detail TO lt_comp_detail.
CLEAR: ls_comp_detail.
ENDLOOP.
ENDIF.
12
Here the classes CL_ABAP_*DESCR are provided by the ABAP RTTS and used to get the type
definition of data objects at runtime. Also we have extracted the data element name of each component
of line type structure of internal table it_data using RTTS classes. Then we fetched the data element
label using the FM WCGW_DATA_ELEMENT_TEXT_GET. This label is used to write the header for
each column of internal table it_data if WRITE_HEADER parameter of class is provided with
ABAP_TRUE.
Using the Class – The above designed class can be used as:
cl_appserver_writer=>write(
EXPORTING
iv_filename = 'D:\usr\sap\testdata.csv'
it_data = lt_data
write_header = abap_true
IMPORTING
ev_message = lv_message
).
WRITE: / lv_message.
Here we are passing one internal table of structure MARA to the class, and subsequently its content will
be written on application server as comma separated values. However, we can pass internal table of any
structure. This file can also be downloaded from application server to an excel spreadsheet.
So this is how field symbol, data reference, generic data type, RTTS helps in dynamic programming
approach.
https://github.com/rkgupta94/ABAP-Development
13
Field Symbols and Data Reference Variables.
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 the properties are not known to us until the
runtime. Another big advantage of them( Field Symbols) is the performance improvement when we use
them with the internal table. This will be discussed in detail later.
1. Field Symbols
Field symbols can be considered as the symbolic name for the data objects. They do not physically reserve
any memory space when we declare them. They only point to an existing data object by using Value
semantics. Which means, when we access the field symbol, we are actually working with the contents of
the data object which is pointed by the field symbol, and not the content of the field symbol itself. In order to
access the content of the data object by using the field symbol, we need to assign that data object to the field
symbol first.
14
This will give a run time error as shown below.
The statement in the line 15 will be the cause the of the error. Remember that the dynamic values that we
give in the braces are not syntax checked and that is the reason why we do not get any error when we check
the syntax before running. It will be checked only during the run time. Here since, the target of the
assignment statement in the line is an integer variable, it is expecting the source to be an integer, or it will try
to interpret the source as a number. However, the dynamic data object access is not supported here and that
is the reason why it is giving an error.
However, the piece of the code below will work without any issue.
Here we have a field symbol <fs_var2>. To this field symbol we are assigning a data object dynamically.
This is one of the advantages of the field symbols. After this assignment, we can work with the field symbol
just as how we would with the original data object. So the above code will print the value 90.
Please refer the debugger snap shown below. The control has reached the line 15 , which means the field
symbol is assigned with the original data object. Now, on the right hand side, both the original data
object (lv_var1) and the field symbol (<fs_var2>) are showing the same value.
15
Now, change the content of the field symbol dynamically in the debugger itself and you can see that the
content of the original data object is also changed.
Click on the pencil icon near the field symbol for enabling editing.
The keyword field-symbols is used to define a field symbol. The angular brackets
(‘< ‘ and ‘>‘ ) are the part of the field symbol definition.
If you do not specify any type after the name of the field symbol, it can take any type of data object that is
assigned to it. We can also define a field symbol by specifying a generic type like any, any table,
simple etc.
16
Field-symbols : <fs_table> type any table.
There are however, certain limitations when we use generic type when we use them to work with reference
variables and structured data objects( like internal tables ). It will not get the specific properties of the object
that is assigned to it. Because this information is not known until the runtime. And you will get a syntax error
in this case.
Ex : If we assign a reference variable to a field symbol, we will not be able to access the attributes of the
objects using the field symbol. Please refer the screenshot below.
Another example, if we assign an internal table to a field symbol, it will not get the keys of the internal table.
In this case we need to dynamically specify the key in brackets.
If you assign a structure( work area) to a field symbol of the generic type, you will not be able to access the
components of the structure by using the ‘–‘ operator as we would do with the original structure variable.
However, you can access the individual component of the field symbol by assigning them to another field
symbol. This is discussed in detail later.
17
When we assign a data object dynamically to the field symbol, the sy-subrc will be set 0 if the assignment
was successful. Otherwise it will be set to 4. So, it is always recommended that we check the sy-subrc value
immediately after the assignment. Otherwise, the field symbol may refer to an old value.
You can also use offset and length addition to the data object when assigning them to the field symbol.
However this is not possible when assigning a data object dynamically.
If you want to loop an internal table into a work area and process each records, field symbols can be found
very helpful here.
The above example shows how we can use field symbols for processing individual lines of the internal table.
Here the performance is drastically improved when compared to the similar operation by using the work area
or the header line of the table. This is because the individual contents of the internal table is physically not
moved around as in the case of the work area. The field symbol is pointing to the individual records of the
internal table and for every loop pass it will point to the next record in the internal table.
If you want to modify the contents of the internal table, this can be found very useful. An example is given
below.
18
Here we are not writing any modify statement itself. When we change the content of the field symbol, the
content of the record to which it is pointing in the internal table itself is also changed. Here we do not have to
check if the field symbol is assigned. This is because if there is no records in the internal table, that will not
enter the loop itself.
You can use the assigning addition when we process single records of the internal table with the read
table statement. Here we need to check the sy-subrc value to see if the read operation was successful.
Another operation that is supported is appending an initial line to a field symbol which is again of internal
table type. An example is given below.
This operation is useful when we are working with the internal table which are in the form of a field symbols.
Most of the standard SAP methods which will return an internal table will always return it in the form of
a reference variable. First we need to dereference them into a field symbol. Remember that the
generically types data reference variables can only be dereferenced by the use of a field symbol. (This is
discussed in detail later)
19
1.3.5. Access individual components of the generic field symbol
As mentioned earlier in this tutorial, when we use a generically declared field symbol to point to a structured
data object, it is not possible to access the components of the structure by using the hyphen operator.
Using the keyword below, we will be able to dynamically access the individual components of the structure.
Here the component can be specified by giving the position number of the structure. We can also use a
variable which has the name of the component instead. This offers a great advantage when it comes to the
dynamic access of the components of the structure whose names are not known till the run time.
The statement which we can use in order to check if the field symbol is assigned to a data object is is
assigned. This will be true if the field symbol is assigned to a data object and false if it is not assigned. Also,
we can explicitly unassign a field symbol from a data object by using the unassign keyword.
Data reference variables are the equalant of the pointers in other languages like C. As you guess, it is the data
object which will hold the address of other data object. So, when we access the content of a data reference
variable, we are accessing the address of another data object. In order to access the contents of the data
object which is pointed by the data reference variable, a special technique called dereferencing has to be
done. So, it is told that the data reference variable uses reference semantics to work with data objects.
20
One difference between the pointers in other language and the data reference variable is that, you will not be
able to increment or decrement them to pint to a next address location.
For example.
Here we have declared a data reference variable lr_a by using the complete type i. Which means lr_a can
from now hold the address of any other data object of type integer. However, we will not be able to declare a
data reference variable with an incomplete type like c or n (Incomplete type means, those data types which
requires a length specification).
We need to use the keyword get reference of in order to assign the address of any data object to the
data reference variable. After this process, for accessing the actual content of the data object using the data
reference variable, we use the dereferencing operator ( ->* ). The example code will print the below
output.
21
3. Creating a data object explicitly by using the reference variable.
So far we have assigned the address of an existing data object to the data reference variable. Now, we will
see another variation of the data object declaration by using a generic type. The only two supported generic
type are data and object. A data reference variable declared by using the type data can point to any
data object where as the ones which are declared by using the object can point to objects of
classes.
Here we have declared a generic data reference variable. And we used the create data statement to create
it. This statement will create a data object in the memory and assign the address of the data object to the
data reference variable lr_data. The original name of the data object that was created by this statement is
not known and it is of no interest. In this method, we will be able to use the incomplete type like c and n with
the length specification as well. However will not be able to give a default value by adding
the value keyword. We can also use the like keyword to refer to an object already existing. The memory for
the data object is not assigned till the create data statement. We can even declare the data reference
variable with internal table type as below.
However, one difference of using this method is that we will not be able to work with the contents of the
created data object by using only the dereferencing
operator ->*. This operator cannot be used with the data reference variable of generic type as a rule. So,
we need to assign such variables to a field symbol explicitly and then we can work with the field
symbol seamlessly as we work with the original data object.
22
In the above code, we have created a data object(internal table) of type sflight by using the generic data
reference variable lr_data. Now, in order to access the contents of the internal table itself, we need to
assign it to a field symbol as in the line 46. Please see the debugger snapshot, where we can see the field
symbol <fs_table> is populated with the line type of sflight.
Here the type of the data object is given in the braces dynamically. This must be a character data
object. This is one big advantage of the data reference variable. Note that we will not be able to
use like keyword when we declare the data objects dynamically as shown above. So, using this method, we
are able to create data objects whose type and properties are not known to us in the beginning.
23
In the below example, the data reference variable lr_data is pointing to a structure variable ls_data. Now,
if we need to access the components of the structure using the data reference variable lr_data, we use
the component selector operator ( -> ) and not the hyphen (-) or dereferencing operator ( ->*).
7. Some Scenarios
24
We have an importing parameter im_table which is a generic data reference variable. Now, imagine that you
need to call those method from a report and pass an internal table to it.
You can see that we have populated an internal table with values. We are taking the reference of this internal
table to the data reference variable lr_data and passing to the interface of the generic_int method of the
zcl_utilities class. Now, inside this method, as we know we need to have a field symbol to access the contents
of the internal table.
25
Now, let us see the field symbol in the debugger mode.
So, the internal table is successfully passed to this method through the generic importing
parameter im_table. Like this, it can take any data object whose type are not known to us. We just need to
assign this to a field symbol for accessing the actual content of it. Now imagine that we need to print the
internal table values from this method. How do we do that?
The internal table is already available in the form of the field symbol <fs_table>. We need to loop it
record by record to a work area and then print it. We can declare another field symbol as work area. This will
again be a generic one since we do not know the type of the internal table till the run time. Please refer the
code below.
We have declared another field symbol <fs_line> for the work area. We are looping the internal
table <fs_table> to <fs_line> one by one and printing the individual fields. This code might look okay
at the first time. However this will give us a syntax error as below.
26
Note that the field symbol <fs_line> is a generic one ( type any ) and it has to be a generic one since we
do not know the line type of the internal table when we write this method. So, any statement which is trying
to access the components of this generic field symbol will throw an error as above. So, in this we need to
access the fields/ components of the work area (ls_line) using the assign component of
structure keyword which we saw earlier.
Since we do not know how many components are there in the line type of the internal table, we need a
mechanism to know it. When we assign each components of the structure to another field
symbol <fs_field>, if the assignment was successful, the sy-subrc will be initial. So, when it is not
initial, we can assume that there are no more components or columns.
27
dynamically created internal table, we need to assign it to a field symbol. Finally, we call the standard
method factory() of the class cl_salv_table to create an instance of the alv class to lr_alv object
reference variable by passing the internal table(<fs_table>). After getting this reference, we use the
instance method display() to display the table in the ALV format.
Input:
Output:
28
29