This commit is contained in:
danrega
2024-01-10 15:29:32 +01:00
parent 7d6992a516
commit 01e87ce987

View File

@@ -14,9 +14,10 @@
- [COND](#cond)
- [SWITCH](#switch)
- [FILTER](#filter)
- [REDUCE](#reduce)
- [Iteration Expressions with FOR](#iteration-expressions-with-for)
- [LET Expressions](#let-expressions)
- [Iteration Expressions](#iteration-expressions)
- [Iteration Expressions Using FOR](#iteration-expressions-using-for)
- [REDUCE](#reduce)
- [Executable Example](#executable-example)
## Introduction
@@ -64,11 +65,12 @@
go: `DATA(dec) = VALUE decfloat34( '1.23' )`.
> **✔️ Hint**<br>
> The construction of a result, i. e. a target [data
>- The construction of a result, i. e. a target [data
object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry"),
implies that the data object is initialized. However, for some
constructor operators, there is an addition with which the
initialization can be avoided.
>- As is true for many of the following syntax options, you can do a lot with constructor expressions, often with fewer lines (than older syntax equivalents) of code in a very elegant way. However, keep in mind the readability, maintainability, and debuggability of your code.
<p align="right"><a href="#top">⬆️ back to top</a></p>
@@ -701,6 +703,7 @@ DATA(b) = SWITCH #( a
<p align="right"><a href="#top">⬆️ back to top</a></p>
## FILTER
- The
@@ -770,76 +773,138 @@ DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num =
<p align="right"><a href="#top">⬆️ back to top</a></p>
## REDUCE
- The
[`REDUCE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_reduce.htm)
operator creates a result of a specified or derived type from one or
more [iteration
expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry").
- It basically reduces sets of data objects to a single data object.
For example, the numeric values of a table column are summed up. As
a result, the total number is constructed.
## LET Expressions
The following example calculates the total of the numbers from 1 to 10
using the `REDUCE` operator:
``` abap
"sum: 55
DATA(sum) = REDUCE i( INIT s = 0
FOR  i = 1 UNTIL i > 10
NEXT s += i ) ).
- Define one or more variables (field symbols are also possible) as local (i.e. local to the expression) helper fields and assigns values to them.
- In the definition, the right-hand side value is declared as if an inline declaration is used. The data type is derived accordingly.
- Only to be used in constructor expressions (see the syntax diagrams in the ABAP Keyword Documentation where exactly [`LET`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaplet.htm) expressions can be specified).
See the following simple examples to get an idea about the use:
```abap
"Data type and object to work with in the example
TYPES: BEGIN OF st_type,
comp1 TYPE c LENGTH 5,
comp2 TYPE i,
comp3 TYPE i,
END OF st_type.
DATA it TYPE TABLE OF st_type WITH EMPTY KEY.
it = VALUE #( ( comp1 = 'a' comp2 = 1 comp3 = 30 )
( comp1 = 'bb' comp2 = 2 comp3 = 10 )
( comp1 = 'ccc' comp2 = 3 comp3 = 20 ) ).
"Constructing a data object with elementary data type using the CONV operator
"One or more helper variables are possible specified after LET
DATA(hi) = CONV string(
LET name = cl_abap_context_info=>get_user_technical_name( )
date = cl_abap_context_info=>get_system_date( )
IN |Hi { name }. Today's date is { date DATE = ISO }.| ).
"Construction similar to the previous example
"Depending on the time, a string is created. In the example, a LET expression
"is specified for each constructor expression.
DATA(time_of_day) = CONV string(
LET time = cl_abap_context_info=>get_system_time( ) IN
COND string( LET good = `Good` ending = `ing` IN
WHEN time BETWEEN '050001' AND '120000' THEN good && ` morn` && ending "Good morning
WHEN time BETWEEN '120001' AND '180000' THEN good && ` afternoon`
WHEN time BETWEEN '180001' AND '220000' THEN good && ` even` && ending
ELSE `night` ) ).
"Getting a particular column name of an existing internal table using a RTTI
"An internal table (it contains information on the table's structured type; the
"component names, among others) is assigned to a data object that is declared
"inline. This is an example of how powerful constructor expressions (and inline
"declarations) are: You can make code more concise. Think of extra declarations
"for the data objects, or using the older ?= operator for the casts. Many more
"lines of code would be required.
DATA(components) = CAST cl_abap_structdescr( CAST cl_abap_tabledescr(
cl_abap_typedescr=>describe_by_data( it ) )->get_table_line_type( ) )->components.
DATA(comp2_a) = components[ 2 ]-name. "COMP2
"Achieving the result from above even in one statement using LET
DATA(comp2_b) = CONV abap_compname(
LET comps = CAST cl_abap_structdescr( CAST cl_abap_tabledescr(
cl_abap_typedescr=>describe_by_data( it ) )->get_table_line_type( ) )->components
IN comps[ 2 ]-name ).
"Constructing a structure using local variables
"The example uses the NEW operator to create an anonymous data object
DATA(new_struc) = NEW st_type( LET num = 2 ch = 'AP' IN
comp1 = 'AB' && ch comp2 = 2 * num comp3 = 3 * num ).
"Structure content:
"COMP1 COMP2 COMP3
"ABAP 4 6
"Constructing an internal table using local variables
"The example uses the VALUE operator.
"Note the parentheses ( ... ) representing table lines.
DATA(itab_value) = VALUE string_table( LET line = 1 IN
( |Line { line }| )
( |Line { line + 1 }| )
( |Line { line + 2 }| ) ).
"Table line content:
"Line 1
"Line 2
"Line 3
"Using a local field symbol in LET expressions
"- The right-hand side value must be the result of a writable expression, i.e.
" an operand that can be written to
"- This value is then assigned to the local field symbol (as if ASSIGN is used)
"- In the examples above, a specification such as ... LET <a> = 1 IN ... is not
" possible as they are not writable expressions.
"- Writable expressions:
" - Constructor expressions NEW class( ... )->attr and CAST type( ... )->dobj
" - Table expressions itab[ ... ] and their chainings, e.g. itab[ 1 ]-comp
"In the following example, an internal table is looped over. A string is created
"from the table line content. In the constructor expression, a LET expression is
"specified that uses a field symbol. It is assigned the line of the internal table.
"The sy-index value represents the table index value.
DATA str_tab TYPE string_table.
DO lines( it ) TIMES.
DATA(concatenated_tab) = CONV string(
LET <li> = it[ sy-index ]
comma = `, `
IN |{ <li>-comp1 }{ comma }{ <li>-comp2 }{ comma }{ <li>-comp3 }| ).
str_tab = VALUE #( BASE str_tab ( concatenated_tab ) ).
ENDDO.
"Table line content:
"a, 1, 30
"bb, 2, 10
"ccc, 3, 20
```
> **💡 Note**<br>
> - `INIT ...`: A temporary variable is specified that sets an
initial value for the result variable.
>- `FOR ...`: Represents a loop. The loop is carried out until
the condition is met after `UNTIL`.
>- `NEXT ...`: Represents the assignment to the temporary
variable after every iteration.
>- Once the loop has finished, the target variable is assigned the
resulting value.
<p align="right"><a href="#top">⬆️ back to top</a></p>
## Iteration Expressions with FOR
## Iteration Expressions
- Using [iteration
expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry")
with the language element
[`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm),
you can carry out [conditional
iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor_conditional.htm)
- Iteration expressions are expressions ...
- that perform an iteration and that are possible in specific constructor expressions (`NEW`, `VALUE`, `REDUCE`).
- that are introduced by the iteration operator `FOR`.
- that can optionally be used to create lines in internal tables.
- `REDUCE` operator: Special reduction operator that is based on [iteration expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry"), i.e. it is mandatory to specify iteration expressions with `FOR` when using `REDUCE`.
### Iteration Expressions Using FOR
- Two flavors for iterations using [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm):
- [Conditional iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor_conditional.htm)
(including the ABAP words `UNTIL` and `WHILE` which
have the semantics of ABAP statements
[`DO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdo.htm)
and
[`WHILE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhile.htm))
or [table
iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_iteration_glosry.htm "Glossary Entry")
(having the semantics of [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm);
the expressions include the ABAP word `IN`).
- Such expressions are possible in the following contexts:
- `REDUCE`: The reduction result is created in the
iteration steps.
- `NEW` and `VALUE`: Used in the context of
[`WHILE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhile.htm))
- [Table iterations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_iteration_glosry.htm "Glossary Entry"):
Have the semantics of [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm) and
include the addition `IN`.
- Where possible:
- `REDUCE`: Mandatory `FOR` specification. The reduction result is created in the
iteration steps.
- `NEW` and `VALUE`: Optional `FOR` specification. Used in the context of
looping across internal tables. New table lines are created in
the iteration steps and inserted into a target table.
`FOR ... WHILE`: The following example with `REDUCE`
has the same effect as the example using `UNTIL` shown above.
``` abap
DATA(sum) = REDUCE i( INIT y = 0
FOR n = 1 THEN n + 1 WHILE n < 11
NEXT y += n ).
```
`FOR ... UNTIL`: See the example in the `REDUCE`
section.
`FOR ... IN`:
- The operand specified after `FOR` represents an iteration
variable, i. e. a [work
area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry")
@@ -856,77 +921,384 @@ section.
- In contrast to `LOOP` statements, the sequential processing
cannot be debugged.
Some examples for looping across tables and storing values in target
tables:
``` abap
"Looping across table and storing the whole line in a new table;
"the target table must have the same table type as the source table itab;
"without the WHERE condition, all lines are respected
```abap
"Data objects and types to work with in the examples
TYPES: BEGIN OF s,
col1 TYPE c LENGTH 5,
col2 TYPE i,
col3 TYPE i,
END OF s.
TYPES itab_type TYPE TABLE OF s WITH EMPTY KEY.
DATA(itab) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 30 )
( col1 = 'bb' col2 = 2 col3 = 10 )
( col1 = 'ccc' col2 = 3 col3 = 20 ) ).
TYPES t_type LIKE itab.
"-------------- Table iterations --------------
... = VALUE t_type( FOR wa IN itab
"WHERE ( comp1 > 2 )
( wa ) ).
DATA(it1) = VALUE itab_type( FOR wa IN itab ( col1 = wa-col1 && 'z'
col2 = wa-col2 + 1 ) ).
"Storing specific components having different names by specifying the assignment
"individually; assumption: the target type is not compatible to the type of itab;
"a field mapping is provided; pay attention to potential type conversion
"LOOP AT equivalent
CLEAR it1.
LOOP AT itab REFERENCE INTO DATA(ref).
APPEND VALUE #( col1 = ref->col1 && 'z'
col2 = ref->col2 + 1 ) TO it1.
ENDLOOP.
... = VALUE t_type( FOR wa IN itab
"WHERE ( comp1 > 2 )
( compX = wa-comp1
compY = wa-comp2 ) ).
*COL1 COL2 COL3
*az 2 0
*bbz 3 0
*cccz 4 0
"Storing specific components having the same names;
"assumption: Target type is not compatible to the type of itab;
"if there are identically named components in the table types, you might
"also use CORRESPONDING
"The following example shows more syntax options
"- Field symbol specifed after FOR
"- LET expressions after FOR: Denotes that the LET
" expressions is evaluated for each loop pass
"- INDEX INTO addition (the variable that follows implicitly
" has the type i): Storing the sy-tabix value for each
" loop pass
DATA(it2) = VALUE itab_type( FOR <line> IN itab INDEX INTO idx
LET idxplus1 = idx + 1 IN
( col1 = <line>-col1 col2 = idx col3 = idxplus1 ) ).
... = VALUE t_type( FOR wa IN itab
"WHERE ( comp1 > 2 )
( CORRESPONDING #( wa ) ) ).
*COL1 COL2 COL3
*a 1 2
*bb 2 3
*ccc 3 4
"Multiple iteration expressions
"Similar to the example above, the following example uses the INDEX INTO
"addition, as well as a LET expression with multiple local variables
DATA(it3) = VALUE string_table( FOR <str> IN itab INDEX INTO idx
LET col1 = |COL1: "{ <str>-col1 }"|
col2 = |COL2: "{ <str>-col2 }"|
col3 = |COL3: "{ <str>-col3 }"|
str_to_be_added = |Table index { idx } -> { col1 } / { col2 } / { col3 }|
IN ( str_to_be_added ) ).
... = VALUE t_type( FOR wa1 IN itab1 WHERE ( comp1 = 4 )
FOR wa2 IN itab2 WHERE ( comp2 > 5 )
FOR wa3 IN itab3 WHERE ( comp3 < 3 )
( compX = wa1-comp1
compY = wa2-comp2
compZ = wa3-comp3 ) ).
*Table index 1 -> COL1: "a" / COL2: "1" / COL3: "30"
*Table index 2 -> COL1: "bb" / COL2: "2" / COL3: "10"
*Table index 3 -> COL1: "ccc" / COL2: "3" / COL3: "20"
"---------- Excursions ----------
"FOR expression are very handy, for example, in EML and other statements.
"The following example commented out shows an EML statement in the implementation
"of a handler method taken from an EML cheat sheet example.
"'result' is an input parameter/internal table containing RAP BO instance data on whose
"basis, an EML MODIFY statement is executed. A suitable internal table is constructed
"in place and that is used as operand of the MODIFY ... UPDATE FIELDS ... WITH ...
"statement.
"MODIFY ENTITIES OF zdemo_abap_rap_ro_u IN LOCAL MODE
" ENTITY root
" UPDATE FIELDS ( field3 field4 ) WITH VALUE #( FOR key IN result ( %tky = key-%tky
" field3 = key-field3 * 2
" field4 = key-field4 * 2 ) ).
"Merging tables
"In the following example, the content of two existing internal tables is merged.
"In the simple example, the index is used for the table index. You can also imagine
"that you merge two internal tables, both having multiple columns. You could refer
"to the specific component values, for example, using a free key in a table expression
"such as ... VALUE #( some_itab[ comp_x = wa-comp_y ]-comp_z DEFAULT ... ) ...
TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY.
DATA(inttab) = VALUE int_tab_type( ( 99 ) ( 100 ) ).
DATA(it4) = VALUE itab_type( FOR wa IN itab INDEX INTO idx
( col1 = wa-col1 col2 = VALUE #( inttab[ idx ] DEFAULT 0 ) ) ).
*COL1 COL2 COL3
*a 99 0
*bb 100 0
*ccc 0 0
"Retaining non-specified column values using the BASE addition
"In the example, the original value of col3 is retained.
DATA(it5) = VALUE itab_type( FOR wa IN itab ( VALUE #( BASE wa col1 = wa-col1 && 'y'
col2 = wa-col2 + 3 ) ) ).
*COL1 COL2 COL3
*ay 4 30
*bby 5 10
*cccy 6 20
"Using the CORRESPONDING operator to handle different types
TYPES: BEGIN OF s2,
col1 TYPE c LENGTH 5,
col2 TYPE i,
str TYPE string,
END OF s2.
TYPES itab_type_2 TYPE TABLE OF s2 WITH EMPTY KEY.
DATA(it6) = VALUE itab_type_2( FOR wa IN itab ( CORRESPONDING #( wa ) ) ).
*COL1 COL2 STR
*a 1
*bb 2
*ccc 3
"Multiple FOR expressions that work like nested loops
DATA(it7) = VALUE string_table( FOR wa1 IN itab
FOR wa2 IN inttab
( |Comp. 1st itab: "{ wa1-col1 }", comp. 2nd itab: "{ wa2 }"| ) ).
*Comp. 1st itab: "a", comp. 2nd itab: "99"
*Comp. 1st itab: "a", comp. 2nd itab: "100"
*Comp. 1st itab: "bb", comp. 2nd itab: "99"
*Comp. 1st itab: "bb", comp. 2nd itab: "100"
*Comp. 1st itab: "ccc", comp. 2nd itab: "99"
*Comp. 1st itab: "ccc", comp. 2nd itab: "100"
"LOOP AT equivalent
CLEAR it7.
LOOP AT itab INTO DATA(wa3).
LOOP AT inttab INTO DATA(wa4).
it7 = VALUE #( BASE it7 ( |Comp. 1st itab: "{ wa3-col1 }", comp. 2nd itab: "{ wa4 }"| ) ).
ENDLOOP.
ENDLOOP.
"More additions can be specified such as WHERE, USING KEY, FROM/TO, STEP
"WHERE condition
"The WHERE condition must be placed in parentheses.
DATA(it8) = VALUE itab_type( FOR wa IN itab WHERE ( col2 < 3 ) ( col1 = wa-col1 && 'w'
col2 = 5
col3 = wa-col2 ) ).
*COL1 COL2 COL3
*aw 5 1
*bbw 5 2
"FROM/TO additions
DATA(it9) = VALUE itab_type( FOR wa IN itab FROM 2 TO 3 ( col1 = wa-col1 && 'v'
col2 = 6
col3 = wa-col2 + 5 ) ).
*COL1 COL2 COL3
*bbv 6 7
*cccv 6 8
"STEP addition
DATA(it10) = VALUE itab_type( FOR wa IN itab STEP -1 ( col1 = wa-col1 && 'u'
col2 = 7
col3 = wa-col2 + 8 ) ).
*COL1 COL2 COL3
*cccu 7 11
*bbu 7 10
*au 7 9
"USING KEY addition
DATA(it11) = VALUE itab_type( FOR wa IN itab USING KEY primary_key ( col1 = wa-col1 && 't'
col2 = 9
col3 = wa-col2 + 10 ) ).
*COL1 COL2 COL3
*at 9 11
*bbt 9 12
*ccct 9 13
"---------- Conditional iterations ----------
"FOR ... WHILE ...
DATA(it12) = VALUE itab_type( FOR x = 1 WHILE x < 4
( col1 = x col2 = x + 1 col3 = x + 2 ) ).
*COL1 COL2 COL3
* 1 2 3
* 2 3 4
* 3 4 5
"FOR ... UNTIL ...
"The THEN addition is also possible for ... WHILE ...
DATA(it13) = VALUE itab_type( FOR y = 31 THEN y - 10 UNTIL y < 10
( col1 = y col2 = y + 1 col3 = y + 2 ) ).
*COL1 COL2 COL3
* 31 32 33
* 21 22 23
* 11 12 13
```
<p align="right"><a href="#top">⬆️ back to top</a></p>
### REDUCE
## LET Expressions
- The
[`REDUCE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_reduce.htm)
operator creates a result of a specified or derived type from one or
more [iteration expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeniteration_expression_glosry.htm "Glossary Entry") with `FOR`.
- As covered for `FOR`, conditional iterations (reducing sets of data objects to a single data object in custom iteration steps) and table iterations (evaluation of table lines, reducing the table content to summary value) are possible. For example, the numeric values of a table column are summed up. As a result, the total number is constructed.
- Additions:
- Optional `LET` expressions (the following additions are mandatory)
- `INIT ...`: A temporary variable (or field symbol) to specify an initial value for the result variable. At least, one variable/field symbol must be specified. The first specified determines the result of the expression (any others that are additionally specified can be used after `NEXT`).
- `FOR ...`: Iteration expression as covered above.
- `NEXT ...`: Represents the assignment to the temporary variable after every iteration. Once the loop has finished, the target variable is assigned the resulting value.
- [`LET`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaplet.htm)
expressions allow you to declare local helper fields (variables or
fields symbols) and assign values (the type is derived from the
defined value) to be used in constructor expressions, for example,
in iteration expressions using `FOR` or results specified in
the conditional expressions of `COND` and `SWITCH`.
- Note that the helper field is only valid in the context in which the
`LET` expression is specified.
Examples:
``` abap
"Creating a string table using a LET expression
```abap
"Data objects and types to work with in the examples
TYPES: BEGIN OF s,
col1 TYPE c LENGTH 5,
col2 TYPE i,
col3 TYPE i,
END OF s.
TYPES itab_type TYPE TABLE OF s WITH EMPTY KEY.
DATA(itab) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 30 )
( col1 = 'bb' col2 = 2 col3 = 10 )
( col1 = 'ccc' col2 = 3 col3 = 20 ) ).
DATA(str_tab) = VALUE string_table( LET it = `be` IN
                    ( |To { it } is to do| )
                    ( |To { it } or not to { it }| )
                    ( |To do is to { it }| )
                    ( |Do { it } do { it } do| ) ).
"---------- Table iterations ----------
"Conditional expressions
"Calculating the sum of values in a table column
"Result: 6
DATA(sum_val) = REDUCE i( INIT len = 0
FOR <line> IN itab
NEXT len = len + <line>-col2 ).
DATA(a) = COND #( LET b = c IN
WHEN b > x THEN ...
WHEN b < y THEN ...
...
ELSE ... ).
"Getting the longest string in a table column
"Result: ccc
DATA(long_str) = REDUCE s-col1( INIT str = VALUE #( )
FOR <line> IN itab
NEXT str = COND #( WHEN strlen( <line>-col1 ) > strlen( str )
THEN <line>-col1
ELSE str ) ).
"Getting the maximum value (other than using SORT)
"Unlike above, a variable is used instead of a field symbol.
"Result: 3
DATA(max_val) = REDUCE i( INIT max = 0
FOR line IN itab
NEXT max = COND #( WHEN line-col2 > max
THEN line-col2
ELSE max ) ).
"Creating a new internal table using REDUCE
"In the example, the sum of two values is calculated.
"A VALUE expression with the BASE addition is used to
"add a line to a table (retaining the existing lines).
DATA(itstr) = REDUCE string_table( INIT strtab = VALUE string_table( )
FOR wa IN itab
NEXT strtab = VALUE #( BASE strtab
( |The sum of { wa-col2 } and { wa-col3 } is { wa-col2 + wa-col3 }.| ) ) ).
*The sum of 1 and 30 is 31.
*The sum of 2 and 10 is 12.
*The sum of 3 and 20 is 23.
"More additions are possible, such as specifying a WHERE condition (which
"must be specified in parentheses). The following example creates a new
"internal table based on a WHERE condition.
TYPES: BEGIN OF s3,
num1 TYPE i,
num2 TYPE i,
sum TYPE i,
END OF s3.
TYPES s3_tab_type TYPE TABLE OF s3 WITH EMPTY KEY.
DATA(itred) = REDUCE s3_tab_type( INIT tab = VALUE s3_tab_type( )
FOR wa IN itab
WHERE ( col2 < 3 )
NEXT tab = VALUE #( BASE tab
( num1 = wa-col2 num2 = wa-col3 sum = wa-col2 + wa-col3 ) ) ).
*NUM1 NUM2 SUM
*1 30 31
*2 10 12
"---------- Conditional iterations ----------
"UNTIL addition
"Iteratively calculating the sum from 1 to 10
"Result: 55
DATA(reduce_until) = REDUCE i( INIT sum = 0
FOR int = 1 UNTIL int > 10
NEXT sum += int ).
"WHILE addition
"The example corresponds to the previous one.
DATA(reduce_while) = REDUCE i( INIT sum = 0
FOR int = 1 WHILE int <= 10
NEXT sum += int ).
"THEN addition
"The following example constructs a text string. The THEN addition is used
"to decrement the iteration variable. Additionally, a LET expression is used
"to specify a helper variable.
"Result: Counting downwards starting with 10: 10 9 8 7 6 5 4 3 2 1
DATA(count) = REDUCE string( LET start = 10 IN
INIT text = |Counting downwards starting with { start }:|
FOR n = start THEN n - 1 WHILE n > 0
NEXT text &&= | { n }| ).
"Example similar to the previous one. Using UNTIL, a text string is enlarged until
"it has reached a specific size.
"Result: ab abap abapap abapapap abapapapap abapapapapap abapapapapapap
DATA(abap_str) = REDUCE string( INIT text = ``
FOR t = `ab` THEN t && `ap` UNTIL strlen( t ) > 15
NEXT text &&= |{ t } | ).
"---------- Excursion: Grouping lines in internal tables with VALUE/REDUCE ----------
"The following examples show equivalents of LOOP AT GROUP ... GROUP BY ... statements.
"Find more information and examples about grouping in the ABAP Keyword Documentation.
"Internal table to work with in the examples
DATA(itab4grp) = VALUE itab_type( ( col1 = 'a' col2 = 1 col3 = 2 )
( col1 = 'a' col2 = 3 col3 = 4 )
( col1 = 'a' col2 = 5 col3 = 6 )
( col1 = 'b' col2 = 7 col3 = 8 )
( col1 = 'b' col2 = 9 col3 = 10 )
( col1 = 'c' col2 = 11 col3 = 12 ) ).
"Constucting a result using VALUE
"The following example returns the values of identified groups in an internal table
"Table lines are evaluated by grouping all lines that meet the condition
"specified in GROUP BY (group key binding). The group key is stored in the variable
"after FOR GROUPS (gr). The constructed result just consists of the group keys in
"the example. The content of the members is not relevant.
DATA(it_val_1) = VALUE string_table( FOR GROUPS gr OF wa IN itab4grp
GROUP BY wa-col1 ASCENDING
WITHOUT MEMBERS
( |{ gr }| ) ).
*a
*b
*c
"As above, the following example returns the values of identified groups in an internal table.
"Additionally, a LET expression (that itself contains an iteration expression) is specified
"to collect column values by group in an internal table. The lines of this (string) table
"are concatenated and inserted in the target table.
DATA(it_val_2) = VALUE string_table(
FOR GROUPS grp OF wa IN itab4grp
GROUP BY wa-col1 ASCENDING
LET members = VALUE string_table(
FOR grpd IN GROUP grp ( |{ grpd-col2 }, { grpd-col3 }| ) ) IN
( |{ grp }: { concat_lines_of( table = members sep = ` / ` ) }| ) ).
*a: 1, 2 / 3, 4 / 5, 6
*b: 7, 8 / 9, 10
*c: 11, 12
"Constucting a result using REDUCE
"The example is similar to the previous one by filling a string table.
"The example uses a group key expression specified after GROUP BY.
"In the group key expression, additional components of a structured
"group key are specified which return specific information (group size,
"group index).
DATA(it_reduced) = REDUCE string_table(
INIT li = VALUE string_table( )
FOR GROUPS group OF grt IN itab4grp
GROUP BY ( grpkey = grt-col1
size = GROUP SIZE
index = GROUP INDEX ) ASCENDING
LET mem = VALUE string_table(
FOR grpr IN GROUP group ( |{ grpr-col2 }, { grpr-col3 }| ) ) IN
NEXT li = VALUE string_table( BASE li ( |Group key: "{ group-grpkey }" \| | &&
|group size: { group-size } \| | &&
|group index: { group-index } \| members: | &&
|{ concat_lines_of( table = mem sep = ` / ` ) }| ) ) ).
*Group key: "a" | group size: 3 | group index: 1 | members: 1, 2 / 3, 4 / 5, 6
*Group key: "b" | group size: 2 | group index: 2 | members: 7, 8 / 9, 10
*Group key: "c" | group size: 1 | group index: 3 | members: 11, 12
```
<p align="right"><a href="#top">⬆️ back to top</a></p>