From f5f9fbf35f42b12c70e9546cab6912c3c1518b1e Mon Sep 17 00:00:00 2001 From: danrega <16720986+danrega@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:10:37 +0200 Subject: [PATCH] Update --- 01_Internal_Tables.md | 149 ++++++++++++++++++++++++++++++++++++++ 06_Dynamic_Programming.md | 119 ++++++++++++++++++++++++++++-- 07_String_Processing.md | 12 ++- 08_EML_ABAP_for_RAP.md | 3 +- 4 files changed, 270 insertions(+), 13 deletions(-) diff --git a/01_Internal_Tables.md b/01_Internal_Tables.md index 245de63..17ce8e8 100644 --- a/01_Internal_Tables.md +++ b/01_Internal_Tables.md @@ -57,6 +57,7 @@ - [Excursions](#excursions) - [Improving Read Performance with Secondary Table Keys](#improving-read-performance-with-secondary-table-keys) - [Example: Exploring Read Access Performance with Internal Tables](#example-exploring-read-access-performance-with-internal-tables) + - [Generic Table Types with Formal Parameters of Methods and Field Symbols](#generic-table-types-with-formal-parameters-of-methods-and-field-symbols) - [Searching and Replacing Substrings in Internal Tables with Character-Like Data Types](#searching-and-replacing-substrings-in-internal-tables-with-character-like-data-types) - [Ranges Tables](#ranges-tables) - [Comparing Content of Compatible Internal Tables](#comparing-content-of-compatible-internal-tables) @@ -2723,6 +2724,58 @@ DATA(itab) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ( `d` ) ( `e` ) ). "5 DATA(number_of_lines) = lines( itab ). + +"Excursion: Finding out the number of lines in a table by specifying concrete +"component values, e.g. you want to find out how many lines exist in the table +"that have the value 1 for comp2 +TYPES: BEGIN OF struct, + comp1 TYPE c LENGTH 3, + comp2 TYPE i, + END OF struct, + tab_type TYPE TABLE OF struct WITH EMPTY KEY. + +DATA(it) = VALUE tab_type( ( comp1 = 'a' comp2 = 1 ) + ( comp1 = 'b' comp2 = 1 ) + ( comp1 = 'c' comp2 = 1 ) + ( comp1 = 'd' comp2 = 2 ) + ( comp1 = 'e' comp2 = 3 ) + ( comp1 = 'f' comp2 = 4 ) + ( comp1 = 'g' comp2 = 5 ) ). + +"7 +DATA(line_num) = lines( it ). + +"Finding out the number of lines in a table by component value, e.g. +"using constructor expressions and specifying a WHERE clause. +"The example creates an new internal table inline using VALUE and a FOR loop, +"specified with a WHERE clause. The lines function is applied to the +"table created inline. +"3 +DATA(line_num_filtered1) = lines( VALUE tab_type( FOR wa IN it WHERE ( comp2 = 1 ) ( wa ) ) ). + +"Using the REDUCE operator +"The example adds 1 to the resulting integer if the comp2 value of the iterated line is greater than 1. +"The lines function is not relevant in the example. +"4 +DATA(line_num_filtered2) = REDUCE i( INIT var = 0 + FOR IN it + WHERE ( comp2 > 1 ) + NEXT var += 1 ). + +"Using the FILTER operator +"Note: The source table must have at least one sorted key or a hash key for accessing. +"If the table does not have such a primary table key, a secondary table key must be available. +TYPES: tab_type_sorted TYPE TABLE OF struct with NON-UNIQUE SORTED KEY sec_key COMPONENTS comp2. +DATA it_sorted type tab_type_sorted. +it_sorted = it. + +"The example creates an new internal table inline using FILTER, +"specified with a WHERE clause. The lines function is applied to the +"table created inline. +"3 +DATA(line_num_filtered3) = lines( FILTER #( it_sorted USING KEY sec_key WHERE comp2 = 1 ) ). +"4 +DATA(line_num_filtered4) = lines( FILTER #( it_sorted USING KEY sec_key WHERE comp2 > 1 ) ). ```

⬆️ back to top

@@ -3317,6 +3370,7 @@ SELECT SINGLE comp1, comp2, comp3 FROM @itab2 AS it WHERE comp3 = sstring`ABAP` - Explicit specification is the recommended way because it is easier to understand and can prevent unwanted sorting results, especially with tables with standard key. +- You can also sort dynamically. For more information, refer to the [Dynamic Programming](06_Dynamic_Programming.md) cheat sheet. @@ -4500,6 +4554,101 @@ ENDCLASS.

⬆️ back to top

+### Generic Table Types with Formal Parameters of Methods and Field Symbols + + +- [Formal parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm) of methods or [field symbols](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm) can be specified with generic types. +- At runtime, the actual data type is copied from the assigned [actual parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenactual_parameter_glosry.htm) or memory area, i.e. they receive the complete data type only when an actual parameter is passed or a memory area is assigned. +- Among them, there are generic table types. For more information, refer to the [Data Types and Objects](16_Data_Types_and_Objects.md) cheat sheet and the [documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuilt_in_types_generic.htm). +- The following example mainly demonstrates formal parameters of methods that are typed with generic table types. The method calls and the tables passed are only possible if the generic types fits. For example, you cannot pass a hashed table to a method whose importing parameter is typed with the generic type `INDEX TABLE`. Invalid method calls and table passing are commented out. + +```abap +CLASS zcl_some_class DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. + CLASS-METHODS process_any_table IMPORTING itab TYPE ANY TABLE. + CLASS-METHODS process_standard_tables1 IMPORTING itab TYPE STANDARD TABLE. + CLASS-METHODS process_standard_tables2 IMPORTING itab TYPE TABLE. + CLASS-METHODS process_sorted_tables IMPORTING itab TYPE SORTED TABLE. + CLASS-METHODS process_hashed_tables IMPORTING itab TYPE HASHED TABLE. + CLASS-METHODS process_index_tables IMPORTING itab TYPE INDEX TABLE. + +ENDCLASS. + +CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + + DATA standard_tab TYPE TABLE OF string WITH EMPTY KEY. + DATA sorted_tab TYPE SORTED TABLE OF string WITH NON-UNIQUE KEY table_line. + DATA hashed_tab TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line. + + "ANY TABLE + process_any_table( standard_tab ). + process_any_table( sorted_tab ). + process_any_table( hashed_tab ). + + "(STANDARD) TABLE + process_standard_tables1( standard_tab ). + "process_standard_tables1( sorted_tab ). + "process_standard_tables1( hashed_tab ). + process_standard_tables2( standard_tab ). + "process_standard_tables2( sorted_tab ). + "process_standard_tables2( hashed_tab ). + + "SORTED TABLE + "process_sorted_tables( standard_tab ). + process_sorted_tables( sorted_tab ). + "process_sorted_tables( hashed_tab ). + + "HASHED TABLE + "process_hashed_tables( standard_tab ). + "process_hashed_tables( sorted_tab ). + process_hashed_tables( hashed_tab ). + + "INDEX TABLE + process_index_tables( standard_tab ). + process_index_tables( sorted_tab ). + "process_index_tables( hashed_tab ). + + + "Note: Field symbols can also be typed with generic types. + FIELD-SYMBOLS TYPE table. + ASSIGN standard_tab TO . + "ASSIGN sorted_tab TO . + "ASSIGN hashed_tab TO . + + FIELD-SYMBOLS TYPE INDEX TABLE. + ASSIGN standard_tab TO . + ASSIGN sorted_tab TO . + "ASSIGN hashed_tab TO . + + ENDMETHOD. + METHOD process_any_table. + ENDMETHOD. + + METHOD process_hashed_tables. + ENDMETHOD. + + METHOD process_index_tables. + ENDMETHOD. + + METHOD process_sorted_tables. + ENDMETHOD. + + METHOD process_standard_tables1. + ENDMETHOD. + + METHOD process_standard_tables2. + ENDMETHOD. + +ENDCLASS. +``` + +

⬆️ back to top

### Searching and Replacing Substrings in Internal Tables with Character-Like Data Types diff --git a/06_Dynamic_Programming.md b/06_Dynamic_Programming.md index dab8f82..2f7eb24 100644 --- a/06_Dynamic_Programming.md +++ b/06_Dynamic_Programming.md @@ -1580,14 +1580,23 @@ itab_ref = VALUE #( ( NEW demo_struct( col1 = 1 col2 = `aaa` col3 = `zzz` ) ) ). "- Many of the following statements provide similar additions offering dynamic " specifications, such as USING KEY and dynamic component name specifications. -"------- SORT ------ +"---------------------------------------------------------- +"------------------------ SORT (1) ------------------------ +"---------------------------------------------------------- + +"Note: See more dynamic specifications with SORT statements +"further down. + "Named data object specified within parenteses DATA(field_name) = 'COL1'. SORT itab_ek BY (field_name) DESCENDING. "Unnamed data object specified within parenteses SORT itab_ek BY ('COL2') ASCENDING. -"------- READ TABLE ------ +"------------------------------------------------------------- +"------------------------ READ TABLE ------------------------ +"------------------------------------------------------------- + "Reading by specifying keys dynamically "Implicitly specifying the table key values in a work area (USING KEY addition) DATA(wa_read) = VALUE demo_struct( col2 = `aaa` ). @@ -1626,7 +1635,10 @@ IF sy-subrc <> 0. ... ENDIF. -"------- Table expressions ------ +"------------------------------------------------------------- +"------------------------ Table expressions ------------------ +"------------------------------------------------------------- + "Similar to READ TABLE statements, you can specify table lines with 3 alternatives: "index read, read using free key, table key "Also there, dynamic specifications are possible regarding the key specifications. @@ -1652,7 +1664,10 @@ DATA(wa_te4) = itab[ KEY ('PRIMARY_KEY') COMPONENTS ('COL1') = 1 ]. itab[ 1 ]-('COL2') = `jkl`. itab_ref[ 1 ]->('COL2') = `mno`. -"------- LOOP AT ------ +"-------------------------------------------------------- +"------------------------ LOOP AT ----------------------- +"-------------------------------------------------------- + "USING KEY addition: Overriding the standard order determined by the table category LOOP AT itab REFERENCE INTO DATA(ref) USING KEY ('SK'). ... @@ -1676,7 +1691,10 @@ LOOP AT itab REFERENCE INTO ref WHERE (cond_loop). ... ENDLOOP. -"------- INSERT ------ +"-------------------------------------------------------- +"------------------------ INSERT ------------------------ +"-------------------------------------------------------- + "The USING KEY addition (which accepts a dynamic specification) affects the order in which lines are inserted. "Result of the following example when using the ... @@ -1704,7 +1722,10 @@ LOOP AT itab INTO DATA(wa_pk) USING KEY ('PRIMARY_KEY'). APPEND wa_pk TO it_primekey_idx. ENDLOOP. -"------- MODIFY ------ +"-------------------------------------------------------- +"------------------------ MODIFY ------------------------ +"-------------------------------------------------------- + "In the following example, a line is modified based on a work area and a table key. "The component col1 is left out from the work area intentionally. "If the primary table key was used, the value of sy-subrc would be 4, and no modification was done. @@ -1723,7 +1744,10 @@ MODIFY itab INDEX 2 USING KEY ('SK') FROM VALUE #( col3 = `ttt` ) TRANSPORTING ( DATA(cond_mod) = `COL1 < 3`. MODIFY itab FROM VALUE #( col3 = `sss` ) TRANSPORTING ('COL3') WHERE (cond_mod). -"------- DELETE ------ +"-------------------------------------------------------- +"------------------------ DELETE ------------------------ +"-------------------------------------------------------- + "A single line or multipled lines can be deleted. "Note that DELETE ADJACENT DUPLICATES statements can also be specified using "dynamic parts. @@ -1746,6 +1770,87 @@ DATA(condition_tab) = VALUE string_table( ( `COL1 < 3` ) ( `OR` ) ( `COL3 = ``www``` ) ). DELETE itab WHERE (condition_tab). + +"-------------------------------------------------------- +"------------------------ SORT (2) ------------------------ +"-------------------------------------------------------- + +"Sorting by dynamically specified components in a sort table, i. e.an +"internal table of type abap_sortorder_tab. +"Notes: +"- Each line of this sort table specifies a component of the sort key. +"- If this table is initial, there is no sorting. +"- The sort priority is based on the order of the lines in the sort table. + +TYPES: BEGIN OF struct, + comp1 TYPE i, + comp2 TYPE string, + comp3 TYPE c LENGTH 3, + END OF struct. + +DATA it TYPE TABLE OF struct WITH EMPTY KEY. + +it = VALUE #( ( comp1 = 1 comp2 = `B` comp3 = 'a' ) + ( comp1 = 1 comp2 = `A` comp3 = 'b' ) + ( comp1 = 2 comp2 = `D` comp3 = 'c' ) + ( comp1 = 2 comp2 = `C` comp3 = 'd' ) + ( comp1 = 3 comp2 = `F` comp3 = 'e' ) + ( comp1 = 3 comp2 = `E` comp3 = 'f' ) ). + +DATA(it_original) = it. + +"Note: The line type is abap_sortorder. +DATA(sort) = VALUE abap_sortorder_tab( ). + +"No sorting because the sort table is initial. +SORT it BY (sort). + +it = it_original. +"Note: Ascending is the default sort order. The following example flags +"the descending sort order explicitly. +sort = VALUE abap_sortorder_tab( ( name = `COMP1` descending = 'X' ) ). +SORT it BY (sort). + +it = it_original. + +sort = VALUE abap_sortorder_tab( ( name = `COMP1` descending = '' ) + ( name = `COMP2` descending = 'X' ) ). +SORT it BY (sort). + +it = it_original. + +"Sort priority based on the order of lines in the sort table +"In this example, the values of comp3 are set up so that a clear +"sort order is determined. Since the component is specified first in the +"sort table, this sorting has priority. Note the values of comp2 in the +"result table. +sort = VALUE abap_sortorder_tab( ( name = `COMP3` descending = 'X' ) + ( name = `COMP2` descending = 'X' ) ). +SORT it BY (sort). + +"Specifying an invalid component name raises an exception +sort = VALUE abap_sortorder_tab( ( name = `XYZ` descending = 'X' ) ). + +TRY. + SORT it BY (sort). + CATCH cx_sy_dyn_table_ill_comp_val INTO DATA(error). +ENDTRY. +ASSERT error IS NOT INITIAL. + +it = it_original. +"Specifying an expression/functional method call whose result is a sort +"table of type abap_sortorder_tab +"In this case, BY is followed by the expression/functional method call, +"not enclosed in parentheses. + +"The example shows expressions with sort tables created inline +SORT it BY VALUE abap_sortorder_tab( ( name = `COMP1` descending = 'X' ) ). + +it = it_original. + +DATA(comp_names) = VALUE string_table( ( `comp1` ) ( `comp2` ) ). + +SORT it BY VALUE abap_sortorder_tab( FOR wa IN comp_names ( name = condense( to_upper( wa ) ) ) ). ```

⬆️ back to top

diff --git a/07_String_Processing.md b/07_String_Processing.md index ccce485..ea1f4b1 100644 --- a/07_String_Processing.md +++ b/07_String_Processing.md @@ -488,12 +488,16 @@ fixed-length string does not include them. Syntax examples: ``` abap "strlen -DATA(len_c) = strlen( 'abc ' ). "3 -DATA(len_str) = strlen( `abc ` ). "6 +DATA(len_c_a) = strlen( 'abc ' ). "3 +DATA(len_c_b) = strlen( ' abc ' ). "6 +DATA(len_str_a) = strlen( `abc ` ). "6 +DATA(len_str_b) = strlen( ` abc ` ). "9 "numofchar -len_c = numofchar( 'abc ' ). "3 -len_str = numofchar( `abc ` ). "3 +len_c_a = numofchar( 'abc ' ). "3 +len_c_b = numofchar( ' abc ' ). "6 +len_str_a = numofchar( `abc ` ). "3 +len_str_a = numofchar( ` abc ` ). "6 DATA(xstr) = CONV xstring( `480065006C006C006F00200077006F0072006C0064002100` ). DATA(len_xstr) = xstrlen( xstr ). "24 diff --git a/08_EML_ABAP_for_RAP.md b/08_EML_ABAP_for_RAP.md index 40df57f..3e49c45 100644 --- a/08_EML_ABAP_for_RAP.md +++ b/08_EML_ABAP_for_RAP.md @@ -1650,8 +1650,7 @@ instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm? `key` in the underlying [CDS view entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_v2_view_glosry.htm "Glossary Entry") of the RAP BO. - The primary key uniquely identifies each RAP BO entity instance. -- After the creation of an instance including the primary key during a [RAP create operation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_create_operation_glosry.htm "Glossary Entry"), - the primary key can no longer be changed. +- As a general rule, after the creation of an instance including the primary key during a [RAP create operation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_create_operation_glosry.htm "Glossary Entry"), the primary key can no longer be changed. - Note that there are different numbering concepts, such as [early](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_early_numbering_glosry.htm) and [late numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlate_numbering_glosry.htm "Glossary Entry"). In the latter concept, newly created entity instances are given their final key only shortly before saving in the database. Until then, the business logic uses a temporary key that has to be replaced. - If a data set with a particular primary key already exists in the persistent database table, the saving of a RAP BO instance is rejected because of a duplicate primary key.