diff --git a/05_Constructor_Expressions.md b/05_Constructor_Expressions.md index 869c7bc..79bc003 100644 --- a/05_Constructor_Expressions.md +++ b/05_Constructor_Expressions.md @@ -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**
-> 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.

⬆️ back to top

@@ -701,6 +703,7 @@ DATA(b) = SWITCH #( a

⬆️ back to top

+ ## FILTER - The @@ -770,76 +773,138 @@ DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num =

⬆️ back to top

-## 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 = 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
  • = it[ sy-index ] + comma = `, ` + IN |{
  • -comp1 }{ comma }{
  • -comp2 }{ comma }{
  • -comp3 }| ). + str_tab = VALUE #( BASE str_tab ( concatenated_tab ) ). +ENDDO. +"Table line content: +"a, 1, 30 +"bb, 2, 10 +"ccc, 3, 20 ``` -> **💡 Note**
    -> - `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. -

    ⬆️ back to top

    -## 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 IN itab INDEX INTO idx + LET idxplus1 = idx + 1 IN + ( col1 = -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 IN itab INDEX INTO idx + LET col1 = |COL1: "{ -col1 }"| + col2 = |COL2: "{ -col2 }"| + col3 = |COL3: "{ -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 ``` -

    ⬆️ back to top

    +### 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 IN itab + NEXT len = len + -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 IN itab + NEXT str = COND #( WHEN strlen( -col1 ) > strlen( str ) + THEN -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 ```

    ⬆️ back to top