This is a test message to test the length of the message box.
Login
ABAP Deep Dive FOR
Created by Software-Heroes

ABAP Deep Dive - FOR (Loops)

1182

Let's take a closer look at the FOR loop. How does it work? What do I have to consider and what can I do with it?

With the introduction of new statements in the ABAP language, an addition for the loop was also developed. You can use FOR to map a loop to a line to iterate over data. In the following sections we will take a closer look at the manifestations of this form.

 

Introduction

One thing has to be said in advance, the FOR loop is not a substitute for the LOOP. It only works within the statements REDUCE, NEW and VALUE, so-called constructor expressions. In the FOR loop, you cannot add arbitrary statements, as is the case in the LOOP.

 

Preparation

Before we start with the examples, let's create the appropriate structures that we will work with in the examples. The structures are defined as follows:

TYPES:
  td_key TYPE c LENGTH 5,

  BEGIN OF ts_simple_data,
    tkey   TYPE td_key,
    text   TYPE string,
    number TYPE i,
    date   TYPE d,
  END OF ts_simple_data,
  tt_simple_data TYPE STANDARD TABLE OF ts_simple_data WITH EMPTY KEY,

  BEGIN OF ts_easy_data,
    tkey   TYPE td_key,
    text   TYPE string,
    number TYPE i,
  END OF ts_easy_data,
  tt_easy_data TYPE STANDARD TABLE OF ts_easy_data WITH EMPTY KEY,

  tt_numbers   TYPE STANDARD TABLE OF i WITH EMPTY KEY.

 

To do this, we implement a method that returns a set of test data:

METHOD generate_data.
  rt_result = VALUE #(
    ( tkey = 'A' text = `Banana` number = 14 date = '20230101' )
    ( tkey = 'B' text = `Tomato` number = 12 date = '20230201' )
    ( tkey = 'C' text = `Apple` number = 23 date = '20231201' )
    ( tkey = 'E' text = `Strawberry` number = 31 date = '20230101' )
    ( tkey = 'F' text = `Salad` number = 20 date = '20230601' )
  ).
ENDMETHOD.

 

Count variable

You will certainly know the counting loop from other programming languages. A loop that tells you to count from where to where and then increase the number accordingly. To do this, let's create an empty table with numbers. In the VALUE expression we now implement the loop and start with FOR, then the variable and the start value and up to where we want to count. Finally, the structure to be created is placed in brackets:

DATA(lt_numbers_until) = VALUE tt_numbers(
  FOR i = 1 UNTIL i >= 10 ( i )
).

 

In addition to the UNTIL statement, there is also WHILE, depending on what you prefer to use. An example of this type of loop looks something like this:

DATA(lt_numbers_while) = VALUE tt_numbers(
  FOR i = 1 WHILE i <= 10 ( i )
).

 

If nothing is specified, then the variable is increased by +1, but here there is also the possibility to adjust the counting after THEN. In the following example we increase the counter by +3:

DATA(lt_numbers_then) = VALUE tt_numbers(
  FOR i = 1 THEN i + 3 WHILE i <= 10 ( i )
).

 

The output from the three loops looks like this:

 

Data type

In the above examples we have always counted with integers, but other data types such as date (D), time (T) or numeric (N) are also possible. Next, an example for a counter variable with a date, we only include every odd day in our new table:

DATA(lt_date_variable) = VALUE tt_simple_data(
  FOR i = CONV d( '20230101' ) THEN i + 2 WHILE i <= '20230201' ( date = i )
).

 

In order to create the correct data type, we convert the value into the variable, the calculation can handle the date field afterwards. The result of the table then looks like this:

 

FOREACH

In other programming languages, the loop is called FOREACH. This loop is about processing all the records in a table. You could do this with a COUNT and a counting loop, but why make it complicated when it can be easy. First of all we need a base table:

DATA(lt_base) = generate_data( ).

 

In the next step we build two loops, one loop that does a simple transformation with CORRESPONDING and a second loop that takes the fields but treats some fields differently:

DATA(lt_corresponding) = VALUE tt_easy_data(
  FOR ls_base IN lt_base ( CORRESPONDING #( ls_base ) )
).

DATA(lt_simple_mapping) = VALUE tt_easy_data(
  FOR ls_base IN lt_base ( tkey = ls_base-tkey text = ls_base-text number = 1 )
).

 

The result of the two loops looks like this:

 

WHERE

Similar to the LOOP, we also have the option of restricting the data and delimiting it based on the content. In the following example, we restrict the data using the date, we also have the option of providing the index of the current line in the loop:

DATA(lt_where) = VALUE tt_easy_data(
  FOR ls_base IN lt_base INDEX INTO ld_idx WHERE ( date > '20230101' )
  ( tkey = ls_base-tkey text = ls_base-text number = ld_idx )
).

 

We transfer the row to the new data type and set the "number" field to the index of the source row so that we can find the data record again later. The result after the loop now looks like this:

 

REDUCE

As a final example, let's take a look at the REDUCE statement, which is intended to reduce or summarize content. It is also possible to use the FOR loop here. To do this, we will look at three different scenarios and how they can be used.

First, we use a counting loop and sum the square of the counting variable together. We define a local variable with INIT, here you can create different variables for calculation and storage, but the first variable is decisive, the data type of which should be mappable to the result:

DATA(ld_number) = REDUCE i(
  INIT num = 0
  FOR i = 1 THEN i + 3 WHILE i <= 10
  NEXT num = num + ( i * i )
).

 

In the second example, we sum all the numbers in our base table and return the result from the REDUCE:

DATA(ld_sum) = REDUCE i(
  INIT sum = 0
  FOR ls_base IN lt_base
  NEXT sum = sum + ls_base-number
).

 

As a last example, we don't add anything together, but rather compose a text from the contents of columns in the table. For this it is important that the variable is initialized with the string literal, otherwise it will be defined as CHAR1 and the concatenation will not work:

DATA(ld_keys) = REDUCE string(
  INIT keys = ``
  FOR ls_base IN lt_base
  NEXT keys = keys && ls_base-tkey
).

 

Finally, the output from the three examples and what they would look like in the console:

 

Full example

As always, finally, the full executable class we used for the examples:

CLASS zcl_bs_demo_for DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

    TYPES:
      td_key TYPE c LENGTH 5,

      BEGIN OF ts_simple_data,
        tkey   TYPE td_key,
        text   TYPE string,
        number TYPE i,
        date   TYPE d,
      END OF ts_simple_data,
      tt_simple_data TYPE STANDARD TABLE OF ts_simple_data WITH EMPTY KEY,

      BEGIN OF ts_easy_data,
        tkey   TYPE td_key,
        text   TYPE string,
        number TYPE i,
      END OF ts_easy_data,
      tt_easy_data TYPE STANDARD TABLE OF ts_easy_data WITH EMPTY KEY,

      tt_numbers   TYPE STANDARD TABLE OF i WITH EMPTY KEY.

  PROTECTED SECTION.
  PRIVATE SECTION.
    METHODS:
      generate_data
        RETURNING VALUE(rt_result) TYPE tt_simple_data,

      simple_for_with_counter
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out,

      simple_for_with_mapping
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out,

      for_with_reduce
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out,

      for_with_where_condition
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out,
      simple_for_with_date
        IMPORTING
          io_out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.


CLASS zcl_bs_demo_for IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    simple_for_with_counter( out ).
    simple_for_with_date( out ).
    simple_for_with_mapping( out ).
    for_with_reduce( out ).
    for_with_where_condition( out ).
  ENDMETHOD.


  METHOD generate_data.
    rt_result = VALUE #(
      ( tkey = 'A' text = `Banana` number = 14 date = '20230101' )
      ( tkey = 'B' text = `Tomato` number = 12 date = '20230201' )
      ( tkey = 'C' text = `Apple` number = 23 date = '20231201' )
      ( tkey = 'E' text = `Strawberry` number = 31 date = '20230101' )
      ( tkey = 'F' text = `Salad` number = 20 date = '20230601' )
    ).
  ENDMETHOD.


  METHOD simple_for_with_counter.
    DATA(lt_numbers_until) = VALUE tt_numbers(
      FOR i = 1 UNTIL i >= 10 ( i )
    ).

    io_out->write( `Result table with NUMBERS (UNTIL):` ).
    io_out->write( lt_numbers_until ).

    DATA(lt_numbers_while) = VALUE tt_numbers(
      FOR i = 1 WHILE i <= 10 ( i )
    ).

    io_out->write( `Result table with NUMBERS (WHILE):` ).
    io_out->write( lt_numbers_while ).

    DATA(lt_numbers_then) = VALUE tt_numbers(
      FOR i = 1 THEN i + 3 WHILE i <= 10 ( i )
    ).

    io_out->write( `Result table with NUMBERS (THEN):` ).
    io_out->write( lt_numbers_then ).
  ENDMETHOD.


  METHOD simple_for_with_mapping.
    DATA(lt_base) = generate_data( ).

    DATA(lt_corresponding) = VALUE tt_easy_data(
      FOR ls_base IN lt_base ( CORRESPONDING #( ls_base ) )
    ).

    io_out->write( `Result table with CORRESPONDING:` ).
    io_out->write( lt_corresponding ).

    DATA(lt_simple_mapping) = VALUE tt_easy_data(
      FOR ls_base IN lt_base ( tkey = ls_base-tkey text = ls_base-text number = 1 )
    ).

    io_out->write( `Result table with simple mapping:` ).
    io_out->write( lt_simple_mapping ).
  ENDMETHOD.


  METHOD for_with_reduce.
    DATA(lt_base) = generate_data( ).

    DATA(ld_number) = REDUCE i(
      INIT num = 0
      FOR i = 1 THEN i + 3 WHILE i <= 10
      NEXT num = num + ( i * i )
    ).

    io_out->write( |Result from table reduce: { ld_number }| ).

    DATA(ld_sum) = REDUCE i(
      INIT sum = 0
      FOR ls_base IN lt_base
      NEXT sum = sum + ls_base-number
    ).

    io_out->write( |Sum of all items: { ld_sum }| ).

    DATA(ld_keys) = REDUCE string(
      INIT keys = ``
      FOR ls_base IN lt_base
      NEXT keys = keys && ls_base-tkey
    ).

    io_out->write( |All keys concatenated: { ld_keys }| ).
  ENDMETHOD.


  METHOD for_with_where_condition.
    DATA(lt_base) = generate_data( ).

    DATA(lt_where) = VALUE tt_easy_data(
      FOR ls_base IN lt_base INDEX INTO ld_idx WHERE ( date > '20230101' )
      ( tkey = ls_base-tkey text = ls_base-text number = ld_idx )
    ).

    io_out->write( `Result with date greater than 01/01/2023:` ).
    io_out->write( lt_where ).
  ENDMETHOD.


  METHOD simple_for_with_date.
    DATA(lt_date_variable) = VALUE tt_simple_data(
      FOR i = CONV d( '20230101' ) THEN i + 2 WHILE i <= '20230201' ( date = i )
    ).

    io_out->write( `Result table with date type:` ).
    io_out->write( lt_date_variable ).
  ENDMETHOD.
ENDCLASS.

 

Conclusion

Loops with FOR can already be used today, but do not necessarily improve readability. Furthermore, they are not a substitute for LOOPs, since they only work in given statements. Nevertheless, the new construct should be mastered.

 

Source:
ABAP Documentation - FOR Iteration Expressions
ABAP Documentation - FOR Conditional Iteration


Included topics:
Deep DiveFORLoopNew ABAP
Comments (0)



And further ...

Are you satisfied with the content of the article? We post new content in the ABAP area every Friday and irregularly in all other areas. Take a look at our tools and apps, we provide them free of charge.


ABAP Deep Dive - Table access (internal)

Category - ABAP

In this article, let's take a look at table access to internal tables and how they replace READ TABLE.

02/03/2023

ABAP Deep Dive - VALUE

Category - ABAP

In this article we want to look at the value statement again in all its forms and how you can use it in your daily work.

11/11/2022

ABAP Deep Dive - CORRESPONDING

Category - ABAP

In this article, a little more about the new Corresponding Statement and how to use it in detail. Let's take a look at the additional features.

09/16/2022

ABAP Tools - Work with Eclipse (Performance Analysis)

Category - ABAP

In this article we look at the performance analysis of objects using the ABAP development tools and the possibilities of traces.

11/24/2023

ABAP Quick - Adobe Forms too big

Category - ABAP

In this little tip we want to look at why, in the worst case, Adobe forms become larger than they should be.

11/18/2022