diff --git a/01_Internal_Tables.md b/01_Internal_Tables.md index e2b8172..e457411 100644 --- a/01_Internal_Tables.md +++ b/01_Internal_Tables.md @@ -9,9 +9,8 @@ - [Creating Internal Tables and Types](#creating-internal-tables-and-types) - [Specifying Keys in Internal Table Declarations](#specifying-keys-in-internal-table-declarations) - [Internal Tables Based on Locally Created Line/Table Types](#internal-tables-based-on-locally-created-linetable-types) - - [Line/Table Type Options of Internal Tables](#linetable-type-options-of-internal-tables) + - [Overview of Line and Table Type Options with Internal Tables](#overview-of-line-and-table-type-options-with-internal-tables) - [Creating Internal Tables By Inline Declaration](#creating-internal-tables-by-inline-declaration) - - [Creating Internal Tables Dynamically](#creating-internal-tables-dynamically) - [Populating Internal Tables](#populating-internal-tables) - [Copying Internal Tables](#copying-internal-tables) - [Using INSERT and APPEND Statements to Populate Internal Tables](#using-insert-and-append-statements-to-populate-internal-tables) @@ -53,6 +52,8 @@ - [Excursion: Joining/Merging Internal Tables into Internal Tables](#excursion-joiningmerging-internal-tables-into-internal-tables) - [Sorting Internal Tables](#sorting-internal-tables) - [Modifying Internal Table Content](#modifying-internal-table-content) + - [Modifying Read Table Lines](#modifying-read-table-lines) + - [Modifying Table Lines Using ABAP MODIFY Statements](#modifying-table-lines-using-abap-modify-statements) - [Deleting Internal Table Content](#deleting-internal-table-content) - [Deleting Adjacent Duplicate Lines](#deleting-adjacent-duplicate-lines) - [Deleting the Entire Internal Table Content](#deleting-the-entire-internal-table-content) @@ -66,6 +67,7 @@ - [Ranges Tables](#ranges-tables) - [Comparing Content of Compatible Internal Tables](#comparing-content-of-compatible-internal-tables) - [BDEF Derived Types (ABAP EML)](#bdef-derived-types-abap-eml) + - [Creating Internal Tables Dynamically](#creating-internal-tables-dynamically) - [More Information](#more-information) - [Executable Example](#executable-example) @@ -243,7 +245,7 @@ DATA itab4 LIKE itab1 ... "Based on an existing in > **💡 Note**
> - If the table category is not specified (`... TYPE TABLE OF ...`), it is automatically `... TYPE STANDARD TABLE OF ...`. -> - Using [Runtime Type Creation (RTTC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_creation_glosry.htm "Glossary Entry"), you can define and create new internal tables and table types as [type description objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_object_glosry.htm) at runtime. For more information, see the [Dynamic Programming](06_Dynamic_Programming.md) ABAP cheat sheet. +> - Using [Runtime Type Creation (RTTC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_creation_glosry.htm "Glossary Entry"), you can define and create new internal tables and table types as [type description objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_object_glosry.htm) at runtime. For more information, see the [Dynamic Programming](06_Dynamic_Programming.md) ABAP cheat sheet. Also find a snippet on creating internal tables dynamically by specifying the type dynamically [below](#creating-internal-tables-dynamically). The following code snippets contain various internal table declarations. It is intended to demonstrate a selection of the rich variety of possible internal tables mentioned in the previous sections, e.g. in *Table Keys in Internal Tables*. In the examples, many of the internal tables are created using the structured type of a demo database table in the DDIC. The line type of the database table is automatically used when defining an internal table. @@ -455,7 +457,7 @@ DATA it27 LIKE TABLE OF it25.

⬆️ back to top

-### Line/Table Type Options of Internal Tables +### Overview of Line and Table Type Options with Internal Tables This section explores various line and table type options when declaring internal tables. Examples have already been covered in the previous sections. Among the options are, for example: - Elementary line types based on elementary built-in ABAP types, locally declared elementary types, globally available elementary types such as DDIC data elements @@ -622,14 +624,12 @@ DATA it_tab_8 LIKE it_tab_7. ``` abap DATA it_ref_1 TYPE TABLE OF REF TO i. DATA it_ref_2 TYPE TABLE OF REF TO string. +DATA it_ref_3 TYPE TABLE OF REF TO zdemo_abap_carr. -"Generic type data -DATA it_ref_3 TYPE TABLE OF REF TO data. +DATA it_ref_4 TYPE TABLE OF REF TO data. "Such a table can hold any data type -"For more details on generic types, see the Data Types and Data Objects -"and Dynamic Programming cheat sheets. -it_ref_3 = VALUE #( ( NEW i( 3 ) ) "Elementary type +it_ref_4 = VALUE #( ( NEW i( 3 ) ) "Elementary type ( NEW string( `hello` ) ) "Elementary type ( NEW zdemo_abap_flsch( carrid = 'XY' connid = '1234' ) ) "Structured type ( NEW string_table( ( `a` ) ( `b` ) ( `c` ) ) ) "Table type @@ -690,34 +690,7 @@ SELECT * FROM zdemo_abap_fli INTO TABLE @FINAL(it_i).

⬆️ back to top

-### Creating Internal Tables Dynamically -Find more information in the [Dynamic Programming cheat sheet](06_Dynamic_Programming.md). - -```abap -DATA(some_type) = 'STRING'. -DATA dataref TYPE REF TO data. - -"Creating an internal table using a CREATE DATA statement -"by specifying the type name dynamically. -"In the example, a standard table with elementary line type -"and standard key is created. -CREATE DATA dataref TYPE TABLE OF (some_type). - -TYPES: BEGIN OF demo_struc, - comp1 TYPE c LENGTH 10, - comp2 TYPE i, - comp3 TYPE i, - END OF demo_struc. - -"Internal table with structured line type and empty key. -CREATE DATA dataref TYPE TABLE OF ('DEMO_STRUC') WITH EMPTY KEY. - -"Using a globally available table type -CREATE DATA dataref TYPE ('STRING_TABLE'). -``` - -

⬆️ back to top

## Populating Internal Tables @@ -905,7 +878,7 @@ INSERT LINES OF itab2 INTO itab INDEX i. The constructor expressions can be specified in/with various positions/statements in ABAP. In most of the following snippets, simple assignments are demonstrated. > **💡 Note**
-> The following sections cover a selection. There are more constructor expressions used in the context of internal tables (e.g. for creating internal tables). Find more details in the [Constructor Expressions](05_Constructor_Expressions.md) ABAP cheat sheet. +> The following sections cover a selection. There are more constructor expressions used in the context of internal tables (e.g. for creating internal tables). Find more details in the [Constructor Expressions](05_Constructor_Expressions.md) cheat sheet. #### VALUE Operator As mentioned above, table lines that are constructed inline as @@ -4728,6 +4701,8 @@ SORT itab BY table_line. As mentioned above, you can modify the content of internal table lines directly in the context of `READ TABLE` and `LOOP AT` statements using field symbols and data reference variables. You can also use table expressions for direct modification (as also covered in section [Table Expressions](#table-expressions)). Note that the key fields of the primary table key of sorted and hashed tables are always read-only. If you try to modify a key field, a runtime error occurs. However, this is not checked until runtime. +### Modifying Read Table Lines + The following examples demonstrate direct modification of recently read table lines: ``` abap "Declaring and populating demo internal tables @@ -4841,9 +4816,11 @@ LOOP AT it_so into data(wa_lo) where comp1 < 4. ENDLOOP. ``` +### Modifying Table Lines Using ABAP MODIFY Statements + [`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_itab.htm) statements provide multiple ways of changing the content of single and multiple table lines by specifying the table key or a table index, -without first reading the lines into a target area. +without first reading the lines into a target area. Do not confuse the ABAP statement `MODIFY` with the ABAP SQL statement [`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPMODIFY_DBTAB.html). ``` abap "Addition FROM ...; specified key values determine the line to be modified @@ -4883,6 +4860,7 @@ MODIFY it FROM line USING KEY sec_key INDEX 1 TRANSPORTING c d. "The additions TRANSPORTING and WHERE are both mandatory; USING KEY is optional. MODIFY it FROM line TRANSPORTING b c WHERE a < 5. ``` + > **💡 Note**
> - The system field `sy-subrc` is set to `0` if at least one line was changed. It is set to `4` if no lines were changed. > - `MODIFY`, `DELETE`, and `INSERT` statements can be specified with and without the `TABLE` addition. With `TABLE` means an index access. Without `TABLE` means an access via the table key. @@ -5000,6 +4978,7 @@ ENDLOOP. ### Deleting Adjacent Duplicate Lines `DELETE ADJACENT DUPLICATES` statements allow you to delete all adjacent lines except for the first line that have the same content in certain components. You usually need to perform some appropriate sorting before using these statements. + ``` abap "Implicitly using the primary table key DELETE ADJACENT DUPLICATES FROM it. @@ -6102,6 +6081,36 @@ Find more information in the [ABAP for RAP: Entity Manipulation Language (ABAP E

⬆️ back to top

+### Creating Internal Tables Dynamically + +Find more information in the [Dynamic Programming cheat sheet](06_Dynamic_Programming.md). + +```abap +DATA(some_type) = 'STRING'. +DATA dataref TYPE REF TO data. + +"Creating an internal table using a CREATE DATA statement +"by specifying the type name dynamically. +"In the example, a standard table with elementary line type +"and standard key is created. +CREATE DATA dataref TYPE TABLE OF (some_type). + +TYPES: BEGIN OF demo_struc, + comp1 TYPE c LENGTH 10, + comp2 TYPE i, + comp3 TYPE i, + END OF demo_struc. + +"Internal table with structured line type and empty key. +CREATE DATA dataref TYPE TABLE OF ('DEMO_STRUC') WITH EMPTY KEY. + +"Using a globally available table type +CREATE DATA dataref TYPE ('STRING_TABLE'). +``` + +

⬆️ back to top

+ + ## More Information Topic [Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenitab.htm) in the ABAP Keyword Documentation. diff --git a/02_Structures.md b/02_Structures.md index eaa1d3e..7718111 100644 --- a/02_Structures.md +++ b/02_Structures.md @@ -616,13 +616,17 @@ diff_deep_struc = CORRESPONDING #( DEEP APPENDING BASE ( diff_struc ) deep_struc ## Clearing Structures You can reset individual components to their initial values and clear the -entire structure using the [`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) keyword. +entire structure using the [`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) keyword. Note that [`FREE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfree_dataobject.htm) statements also deletes the content, but they also release the initially allocated memory. +space. ``` abap CLEAR struc-component. CLEAR struc. +"This statement additionally releases memory space. +FREE struc. + "Note: An assignment using the VALUE operator without entries in the parentheses clears the structure. struc = VALUE #( ). @@ -1389,7 +1393,7 @@ CLASS zcl_some_class IMPLEMENTATION. "the snippets between the sections "---- Comment in/out START ---- "... - "---- Comment in/out END ---- + "---- Comment in/out END ---- DO 100000 TIMES. "------------------------------------------------------------------------ diff --git a/03_ABAP_SQL.md b/03_ABAP_SQL.md index de0c3c0..5b98b71 100644 --- a/03_ABAP_SQL.md +++ b/03_ABAP_SQL.md @@ -38,6 +38,7 @@ - [Using DELETE](#using-delete) - [Using Constructor Expressions in ABAP SQL Statements](#using-constructor-expressions-in-abap-sql-statements) - [Example: Exploring Create, Update, and Delete Operations with ABAP SQL Statements](#example-exploring-create-update-and-delete-operations-with-abap-sql-statements) + - [Dynamic ABAP SQL Statements](#dynamic-abap-sql-statements) - [Excursions](#excursions) - [Evaluating ABAP System Fields after ABAP SQL Statements](#evaluating-abap-system-fields-after-abap-sql-statements) - [Typed Literals](#typed-literals) @@ -199,7 +200,7 @@ SELECT FROM source "What data source read from - Using the `SELECT` list or `FIELDS` clause, you define the structure of the result set. - You can do this by specifying the columns to be read from the data source individually, or by specifying `*` to read all columns. - Syntax variants are possible. -- Note that you can specify the addition `SINGLE` after `SELECT`. With `SINGLE`, it means the result set is a single row result set. Otherwise, it is a multirow result set. An appropriate data object must be specified in the `INTO` clause. +- Note that you can specify the addition `SINGLE` after `SELECT`. With `SINGLE`, it means the result set is a single row result set. Otherwise, it is a multirow result set, or a `SELECT` loop is opened. An appropriate data object must be specified in the `INTO` clause. | Syntax | Notes | |----------|-------------| @@ -2730,6 +2731,24 @@ ENDCLASS.

⬆️ back to top

+## Dynamic ABAP SQL Statements + +- ABAP SQL statements offer syntax options for dynamic programming. +- For example, you can specify the data source to read from dynamically. +- Find more information and code snippets in the ABAP Keyword Documentation or the [ABAP cheat sheet on dynamic programming](06_Dynamic_Programming.md). + +```abap +DATA(dbtab) = 'ZDEMO_ABAP_FLSCH'. + +"Selecting from a dynamically specified database table. +SELECT * + FROM (dbtab) + WHERE ... + INTO ... +``` + +

⬆️ back to top

+ ## Excursions ### Evaluating ABAP System Fields after ABAP SQL Statements @@ -2970,7 +2989,7 @@ SELECT SINGLE - Native SQL is passed directly to the database. - AMDP, which uses Native SQL, also does not support implicit client handling. - While AMDP is permitted in ABAP Cloud, accessing client-dependent data via Native SQL is not supported. -- When using AMDP in ABAP Cloud, it is crucial to access only the current client. Client-safety must be ensured.. +- When using AMDP in ABAP Cloud, it is crucial to access only the current client. Client-safety must be ensured. - AMDP methods in ABAP Cloud must be client-safe, meaning the SQLScript code should access data only in your client. Use only artifacts that limit access to a single client or those that are client-independent. - Consequently, all objects in the `USING` list must be client-safe, including CDS table functions implemented as AMDP methods. - There are additions to cover client-safe aspects, ensuring access only to your client data. @@ -2993,16 +3012,6 @@ There are [RAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index

⬆️ back to top

## More Information -- Note that ABAP SQL statements offer syntax options for dynamic programming. For example, you can specify the data source to read from dynamically. See more information in the ABAP Keyword Documentation or the [ABAP cheat sheet on dynamic programming](06_Dynamic_Programming.md). - ```abap - DATA(dbtab) = 'ZDEMO_ABAP_FLSCH'. - - "Selecting from a dynamically specified database table. - SELECT * - FROM (dbtab) - WHERE ... - INTO ... - ``` - [This topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql.htm) serves as the entry point for topics about ABAP SQL in the ABAP Keyword Documentation. For the full details, check the subtopics there, especially topics not covered in this cheat sheet. - Find more topics in the ABAP Keyword Documentation such as the following: - ABAP SQL statements can contain [SQL path expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_path_expression_glosry.htm). For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_path.htm). The executable example of the CDS view entities cheat sheet includes demo SQL statements. diff --git a/04_ABAP_Object_Orientation.md b/04_ABAP_Object_Orientation.md index 90aad7b..51bdba1 100644 --- a/04_ABAP_Object_Orientation.md +++ b/04_ABAP_Object_Orientation.md @@ -447,8 +447,7 @@ kinds of components are to be distinguished when, for example, looking at declar (`CLASS-DATA`): Their content is independent of instances of a class and, thus, valid for all instances. That means that if you change such a static attribute, the change is visible in all instances. As shown further down, - static attributes can be accessed by using the class name without a - prior creation of an instance. + static attributes can be accessed by both using an object reference variable and using the class name without a prior creation of an instance. > **💡 Note**
@@ -524,6 +523,7 @@ ENDCLASS. can access all of the attributes of a class and trigger all events. You declare them using `METHODS` statements in a visibility section. Note that you must create an instance of a class first before using instance methods. +- `CLASS-METHODS` and `METHODS` can be followed by a colon to list one or more methods, separated by commas, or without a colon to declare a single method.

⬆️ back to top

@@ -1455,6 +1455,13 @@ class_name=>meth( EXPORTING i = j k = l RECEIVING m = DATA(n) ). #### Excursion: Inline Declarations, Returning Parameters +
+ 🟢 Click to expand for more information and example code + + +
+ + - The example code below highlights the convenience of inline declarations when defining target data objects for output parameters. - This approach allows you to create data objects on the spot, eliminating the need for additional helper variables. - It also mitigates the risk of type mismatches. @@ -1535,7 +1542,7 @@ CLASS zcl_some_class IMPLEMENTATION. "IF used with a predicative method call "The result of the relational expression is true if the result of the functional "method call is not initial and false if it is initial. The data type of the result - "of the functional meth1od call, i. e. the return value of the called function method, + "of the functional meth1od call, i. e. the return value of the called functional method, "is arbitrary. A check is made for the type-dependent initial value. IF zcl_some_class=>meth1( i_str = `ABAP` ). ... @@ -1570,30 +1577,63 @@ CLASS zcl_some_class IMPLEMENTATION. ENDCLASS. ``` +
+ +

⬆️ back to top

### Self-Reference me -When implementing instance methods, you can optionally make use of the implicitly available object reference variable [`me`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenme.htm) which is always available at runtime and points to the respective object itself. You can use it to refer to components of the instance of a particular class: +When implementing instance methods, you can optionally make use of the implicitly available object reference variable [`me`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenme.htm) which is always available at runtime and points to the respective object itself. You can use it, for example, to refer to components of the instance of a particular class: ``` abap ... some_method( ... ) ... ... me->some_method( ... ) ... ``` -The following code snippet shows a method implementation. In this case, a local data object from within the method and an instance attribute that is declared in the declaration part of the class in which this method is implemented have identical names. `me` is used to access the non-local data object. +You can also address the entire object, which is illustrated in the example of section [Method Chaining and Chained Attribute Access](#method-chaining-and-chained-attribute-access). +The following code snippet declares a local data object in a method. It has the same name as a data object declared in the private visibility section. shows a method implementation. `me` is used to access the non-local data object. ``` abap -METHOD me_ref. +CLASS zcl_some_class DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . - DATA str TYPE string VALUE `Local string`. + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. + PROTECTED SECTION. + PRIVATE SECTION. + DATA str TYPE string. + METHODS meth RETURNING VALUE(text) TYPE string. +ENDCLASS. - DATA(local_string) = str. +CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. - "Assuming there is a variable str declared in the class declaration part. - DATA(other_string) = me->str. + str = `AP`. + DATA(text) = meth( ). + ASSERT text = `ABAP`. -ENDMETHOD. + ENDMETHOD. + + METHOD meth. + + "Declaring a local data object having the same + "name as a data object declared in a visibility section + DATA str TYPE string VALUE `AB`. + + "Addressing locally declared data object + DATA(local_string) = str. + + "Addressing data object declared in private visibility section + DATA(other_string) = me->str. + + text = local_string && other_string. + + ENDMETHOD. + +ENDCLASS. ```

⬆️ back to top

@@ -1662,7 +1702,7 @@ DATA(json) = xco_cp_json=>data->builder( )->begin_object( )->end_object( )->get_data( )->to_string( ). ``` -Self-contained example class demonstrating chained method calls with a function method call and a standalone statement: +Self-contained example class demonstrating chained method calls with a functional method call and a standalone statement: ```abap CLASS zcl_some_class DEFINITION @@ -1686,7 +1726,7 @@ CLASS zcl_some_class IMPLEMENTATION. METHOD if_oo_adt_classrun~main. "---------------------------------------------------------------- - "-------- Method chaining with a function method call ----------- + "-------- Method chaining with a functional method call --------- "---------------------------------------------------------------- "This example chained method call includes a chained attribute access "at the end so that the target variable contains the content of the @@ -1765,7 +1805,13 @@ ENDCLASS. ### Excursion: Example Class -The commented example class below explores various aspects covered in the previous sections. You can create a demo class called `zcl_demo_test` and copy and paste the following code. Once activated, you can choose *F9* in ADT to run the class. The example is designed to display output in the console that shows the result of calling different methods. +Expand the following collapsible section for an example class. The commented example class explores various aspects covered in the previous sections. You can create a demo class called `zcl_demo_test` and copy and paste the following code. Once activated, you can choose *F9* in ADT to run the class. The example is designed to display output in the console that shows the result of calling different methods. + +
+ 🟢 Click to expand for example code + + +
```abap CLASS zcl_demo_test DEFINITION @@ -2304,6 +2350,11 @@ CLASS zcl_demo_test IMPLEMENTATION. ENDCLASS. ``` +
+ + + +

⬆️ back to top

@@ -2605,9 +2656,16 @@ METHODS another_meth FINAL REDEFINITION. ### Excursion: Inheritance Example -The following example explores inheritance and demonstrates a selection of the inheritance-related syntax described above. The inheritance tree consists of four example classes. The base class includes the implementation of the classrun interface. The example is designed to output information to the console. So, you can execute this class using F9 in ADT. +Expand the following collapsible section for example classes. The example classes explore inheritance and demonstrate a selection of the inheritance-related syntax described above. The inheritance tree consists of four example classes. The base class includes the implementation of the classrun interface. The example is designed to output information to the console. So, you can execute this class using F9 in ADT. The purpose of the example and information output is to visualize and explore concepts and syntax related to inheritance, checking out when and how methods are called, redefining methods, abstract and final classes and methods. + +
+ 🟢 Click to expand for more information and example code + + +
+ The inheritance tree of the example classes is as follows: ``` @@ -2665,7 +2723,7 @@ Notes on the example: - Declares a static method to delegate method calls of this class -Expand the following collapsible section for example classes. To try them out, create four demo classes named +To try the example classes out, create four demo classes named - `ZCL_DEMO_ABAP_OO_INHERITANCE_1` - `ZCL_DEMO_ABAP_OO_INHERITANCE_2` @@ -2674,9 +2732,6 @@ Expand the following collapsible section for example classes. To try them out, c and paste the code into it. After activation, choose *F9* in ADT to execute the class `ZCL_DEMO_ABAP_OO_INHERITANCE_1`. The example is set up to display output in the console. -
- 🟢 Click to expand for example code -
@@ -4014,11 +4069,18 @@ CLASS global_class DEFINITION CREATE PUBLIC FRIENDS other_global_class ... . #### Friendship between Global and Local Classes -The following example demonstrates granting friendship between a global class and a local class (in the CCIMP include, *Local Types* tab in ADT). In the example, friendship is granted in both ways so that the global class can access private components of the local class, and the local class can access private components of the global class. +Expand the following collapsible section for an example class. It demonstrates granting friendship between a global class and a local class (in the CCIMP include, *Local Types* tab in ADT). In the example, friendship is granted in both ways so that the global class can access private components of the local class, and the local class can access private components of the global class. For more information, see the following topics: - [`LOCAL FRIENDS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_local_friends.htm) - [`DEFERRED`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_deferred.htm) +
+ 🟢 Click to expand for more information and example code + + +
+ + **Global class** - Create a new global class (the example uses the name `zcl_some_class`) and copy and paste the following code in the *Global Class* tab in ADT. - The class has a type and method declaration in the private section. They are used in the local class. @@ -4086,6 +4148,11 @@ CLASS local_class IMPLEMENTATION. ENDCLASS. ``` +
+ + + +

⬆️ back to top

### Events diff --git a/05_Constructor_Expressions.md b/05_Constructor_Expressions.md index 62ac963..7e3a726 100644 --- a/05_Constructor_Expressions.md +++ b/05_Constructor_Expressions.md @@ -111,17 +111,28 @@ and [nested structures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en- or [deep tables](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendeep_table_glosry.htm "Glossary Entry"), the use of `VALUE` expressions is handy, too, because you can create corresponding values in place. -The following examples cover: -- Populating structures and internal tables with `VALUE` -- Creating initial values (for all types possible) -- Possible additions, such as `BASE` (retaining existing content) and `LINES OF` (adding all or some lines from other internal tables; more additions are available here) -- Short form of `VALUE` constructor expressions for internal tables with structured line types -- Excursions +The following table illustrates a variety of syntax options and aspects regarding the `VALUE` operator. -```abap -"-------------- Populating structures/internal tables with VALUE -------------- +> **💡 Note**
+> - The examples represent a selection. Check the documentation for all options. +> - Some of the additions and concepts mentioned here are also valid for other constructor expressions further down but not necessarily mentioned explicitly. See the details on the syntax +options of the constructor operators in the ABAP Keyword Documentation. -"Declaring structured data type and structured data object + + + + + + + + + + + + -"Using such a VALUE constructor expression instead of, for example, -"assigning the component values individually using the component -"selector (-). -struc-a = 4. -struc-b = 'ddd'. + + + + + + + + + + + + + + + -"-------------- BASE addition -------------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subject Notes/Code Snippet
Populating an existing structure or a structure created inline + +``` abap +"Declaring structured data type and structured data object +"(also used in the following snippets) TYPES: BEGIN OF struc_type, a TYPE i, b TYPE c LENGTH 3, @@ -129,28 +140,41 @@ TYPES: BEGIN OF struc_type, DATA struc TYPE struc_type. -"Using VALUE constructor expression "Note: The data type can be retrieved from the context. Then, # can "be specified. struc = VALUE #( a = 1 b = 'aaa' ). +"The following syntax is also possible (explicit data type +"specification although the type can be determined). +struc = VALUE struc_type( a = 2 b = 'bbb' ). + +"Using such a VALUE constructor expression instead of, for example, +"assigning the component values individually using the component +"selector (-). +struc-a = 3. +struc-b = 'ccc'. + "Using an inline declaration "In the following example, the type cannot be retrieved from the "context. Therefore, an explicit specification of the type is "required. -DATA(struc2) = VALUE struc_type( a = 2 b = 'bbb' ). +DATA(struc2) = VALUE struc_type( a = 4 b = 'ddd' ). +``` -"The following syntax is also possible (explicit data type -"specification although the type can be determined). -struc = VALUE struc_type( a = 3 b = 'ccc' ). +
-"Internal table +Populating an existing internal table or an internal table created inline + + + + +``` abap "Note the extra pair of parentheses for an individual table line. DATA itab TYPE TABLE OF struc_type WITH EMPTY KEY. @@ -172,9 +196,21 @@ DATA(itab2) = VALUE itab_type( ( a = 7 b = 'ggg' ) "Unstructured line types work without component names. DATA(itab3) = VALUE string_table( ( `Hello` ) ( `world` ) ). +``` -"-------------- Creating initial values -------------- +
+ +Creating initial values for all types + + + +``` abap "Type-specific initial value for data objects by leaving the "VALUE constructor expression empty "Structure (the entire structure is initial) @@ -203,9 +239,21 @@ DATA(int) = VALUE i( ). DATA int2 TYPE i. int2 = VALUE #( ). DATA(xstr) = VALUE xstring( ). +``` -"-------------- VALUE constructor used for nested/deep data objects -------------- +
+ +`VALUE` constructor used for nested/deep data objects + + + +``` abap "Creating a nested structure DATA: BEGIN OF nested_struc, a TYPE i, @@ -228,13 +276,21 @@ TYPES deep_itab_type LIKE TABLE OF nested_struc WITH EMPTY KEY. DATA(deep_itab) = VALUE deep_itab_type( ( nested_struc ) "Adding an existing structure ( a = 3 struct = VALUE #( b = 3 c = 'ccc' ) ) ( a = 4 struct = VALUE #( b = 4 c = 'ddd' ) ) ). +``` -"-------------- Additions to VALUE constructor expressions -------------- -"Note: LET and FOR expressions can be added to VALUE constructor expressions. -"Find more information further down. +
+`BASE` addition + + + +``` abap "A constructor expression without the BASE addition initializes the target variable. "Therefore, you can use the addition if you do not want to construct a structure or "internal table from scratch but keep existing content. @@ -254,9 +310,21 @@ itab = VALUE #( ( a = 1 b = 'aaa' ) itab = VALUE #( BASE itab ( a = 3 b = 'ccc' ) ( a = 4 b = 'ddd' ) ). +``` -"-------------- LINES OF addition ------------- +
+ +`LINES OF` addition + + + +``` abap "All or some lines of another table can be included in the target internal table "(provided that they have appropriate line types). "With the LINES OF addition, more additions can be specified. @@ -270,9 +338,22 @@ itab = VALUE #( ( a = 1 b = 'aaa' ) itab = VALUE #( ( LINES OF itab5 STEP 2 ) "Adding every second line ( LINES OF itab6 USING KEY primary_key ) ). "Specifying a table key +``` + +
+ +Short form for internal tables with structured line types + + -"-------------- Short form for internal tables with structured line types -------------- +``` abap "- Assignments of values to individual structure components are possible outside of inner " parentheses "- In that case, all of the following components in the inner parentheses are assigned that @@ -348,7 +429,110 @@ MODIFY ENTITIES OF zdemo_abap_rap_ro_m MAPPED DATA(m) FAILED DATA(f) REPORTED DATA(r). -``` +``` + +
+ +Assigning incompatible structures + + + +- The example makes use of the `BASE` addition, and includes a `CORRESPONDING` expression. +- The `s1` structure is assigned the identically named components of the `s2` structure. +- Other components are assigned by explicitly specifying them. + +
+ +``` abap +DATA: + BEGIN OF s1, + comp1 TYPE i, + comp2 TYPE i, + comp3 TYPE i, + comp4 TYPE i, + comp5 TYPE i, + END OF s1, + BEGIN OF s2, + comp1 TYPE i VALUE 1, + comp2 TYPE i VALUE 2, + comp3 TYPE i VALUE 3, + END OF s2. + +s1 = VALUE #( BASE CORRESPONDING #( s2 ) comp4 = 4 comp5 = 5 ). +``` + +
+ +Table iterations with `FOR` + + + +- Have the semantics of `LOOP AT` statements +- Find more examples [below](#iteration-expressions-using-for) + +
+ +``` abap +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(it1) = VALUE itab_type( FOR wa IN itab ( col1 = wa-col1 && 'z' + col2 = wa-col2 + 1 ) ). +``` + +
+ +`LET` expressions + + + +- They 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. +- Find more examples [below](#let-expressions) + +
+ +``` abap +DATA(strtab) = VALUE string_table( LET mark = '!' IN + ( |abc{ mark }| ) + ( |def{ mark }| ) + ( |ghi{ mark }| ) ). +``` + +
+ +Using data objects declared inline in various ABAP statements + + Using the inline construction of structures and internal tables, you can avoid the declaration of extra variables in many contexts, for example, @@ -361,7 +545,8 @@ statements like (which is not to be confused with the ABAP statement having the same name) for modifying database tables. -Examples: +
+ ``` abap "ABAP statements "Modifiying individual internal table entries based on a structure created inline @@ -389,11 +574,36 @@ MODIFY zdemo_abap_carr FROM TABLE @( VALUE #( url =  'another_url' ) ) ). ``` -> **💡 Note**
-> Some of the additions and concepts mentioned here are -also valid for other constructor expressions further down but not -necessarily mentioned explicitly. See the details on the syntax -options of the constructor operators in the ABAP Keyword Documentation. +
+ +Grouping lines in internal tables + + + +- Regarding grouping lines in internal tables, find more information in the [Internal Tables: Grouping](11_Internal_Tables_Grouping.md) cheat sheet. +- More code snippets on grouping lines, covering syntax such as `FOR GROUPS` with the `VALUE` and `REDUCE` operators, are available [below](#grouping-lines-in-internal-tables-with-valuereduce). + +
+ +``` abap +... +DATA(it_val_1) = VALUE string_table( FOR GROUPS gr OF wa IN itab4grp + GROUP BY wa-col1 ASCENDING + WITHOUT MEMBERS + ( |{ gr }| ) ). +``` + +
+

⬆️ back to top

@@ -423,6 +633,7 @@ this operator. There are more variants available (also that are not covered. Find more information in [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) of the ABAP Keyword Documentation. + | Addition | Details | |---|---| | `BASE` | Keeps original values. Unlike, for example, the operator `VALUE`, a pair of parentheses must be set around `BASE`. | @@ -431,6 +642,9 @@ topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file | `DISCARDING DUPLICATES` | Relevant for tabular components. Handles duplicate lines and prevents exceptions when dealing with internal tables that have a unique primary or secondary table key. | | `DEEP` | Relevant for deep tabular components. They are resolved at every hierarchy level and identically named components are assigned line by line. | | `[DEEP] APPENDING` | Relevant for (deep) tabular components. It ensures that the nested target tables are not deleted. The effect without `DEEP` is that lines of the nested source table are added using `CORRESPONDING` without addition. The effect with `DEEP` is that lines of the nested source table are added using `CORRESPONDING` with the addition `DEEP`. | +| `DEEP` | Relevant for deep tabular components. They are resolved at every hierarchy level and identically named components are assigned line by line. | +| `FROM tab USING` | Relevant for constructing an internal table by joining an internal table and a lookup table and comparing their components. | + Examples: ``` abap @@ -560,31 +774,15 @@ it2 = CORRESPONDING #( it1 DISCARDING DUPLICATES ). *A B D *4 aaa *5 eee -``` -> **✔️ Hint**
-> `CORRESPONDING` operator versus -[`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) in the context of structures: -Although the functionality is the same, note that, as the name implies, -constructor operators construct and - without the addition -`BASE` - target objects are initialized. Hence, the following -two statements are not the same: ->``` abap ->struc2 = CORRESPONDING #( struc1 ). -> ->"Not matching components are not initialized ->MOVE-CORRESPONDING struc1 TO struc2. ->``` +"-------------- DEFAULT addition when using MAPPING ------------- +"- This addition allows the assignment of values for a target component based +" on an expression (which is evaluated before the CORRESPONDING expression). +"- DEFAULT can be preceded by the source component. In this case, the source +" component's value is assigned to the left-hand side only if the source +" component is not initial. If it is initial, the value of the expression +" following the DEFAULT addition is assigned. - -**`DEFAULT` addition when using `MAPPING`** - -- This addition allows the assignment of values for a target component based on an expression (which is evaluated before the `CORRESPONDING` expression). -- `DEFAULT` can be preceded by the source component. In this case, the source component's value is assigned to the left-hand side only if the source component is not initial. If it is initial, the value of the expression following the `DEFAULT` addition is assigned. - -Examples: - -```abap "Creating and populating data objects to work with DATA: BEGIN OF struc1, id1 TYPE i, @@ -661,6 +859,19 @@ struc2 = CORRESPONDING #( *1 a hallo 2 d 30 ``` +> **✔️ Hint**
+> `CORRESPONDING` operator versus +[`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) in the context of structures: +Although the functionality is the same, note that, as the name implies, +constructor operators construct and - without the addition +`BASE` - target objects are initialized. Hence, the following +two statements are not the same: +>``` abap +>struc2 = CORRESPONDING #( struc1 ). +> +>"Not matching components are not initialized +>MOVE-CORRESPONDING struc1 TO struc2. +>``` **`CORRESPONDING` with lookup table** @@ -1024,7 +1235,22 @@ DATA(oref5) = NEW cl_b( 123 ). - The operator is particularly suitable for avoiding the declaration of helper variables. -Examples: + + + + + + + + + + + + + + + + + + + +
Subject Notes/Code Snippet
+ +Explicit conversion + + + ``` abap "Result: 0.2 DATA(conv_res) = CONV decfloat34( 1 / 5 ). @@ -1047,14 +1273,26 @@ itab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ). "Using CONV to convert the internal table to the required table type. DATA(conv_itab) = CONV inttab_type( itab ). ASSIGN conv_itab TO . -``` +``` -**Constructing data objects with the CONV operator** +
+ +Constructing data objects + + As outlined above, you can construct structures and internal tables using the `VALUE` operator. Using `VALUE` for constructing [elementary data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_object_glosry.htm "Glossary Entry") and providing values is not possible. You can only use it to create a data object with an initial value, for example `DATA(str) = VALUE string( ).`. The `CONV` operator closes this gap. +
+ ``` abap DATA(a) = CONV decfloat34( '0.4' ). @@ -1079,7 +1317,13 @@ DATA e TYPE string. DATA(f) = `hallo`. "Produces a syntax warning "DATA(g) = CONV string( `hallo` ). -``` +``` + +
+

⬆️ back to top

@@ -1102,10 +1346,23 @@ DATA(f) = `hallo`. with the [rules of lossless assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove_exact.htm). -Examples: -``` abap -"-------------- Lossless assignments ------------- + + + + + + + + + + + + + + + + + +
Subject Notes/Code Snippet
+ +Lossless assignments + + + +``` abap "Note: An assignment is made in accordance with conversion rules. Check "the ABAP Keyword Documentation for these rules. An assignment is only "made if no values are lost. Otherwise, an error occurs. Either it is @@ -1120,9 +1377,22 @@ TRY. DATA(as4) = EXACT clen3( 'abcd' ). CATCH cx_sy_conversion_data_loss. ENDTRY. +``` -"-------------- Lossless calculations ------------- +
+ +Lossless calculations + + + + +``` abap "The first statement works, whereas the second statement raises an exception. "A rounding to two decimal places is required. TYPES packednum TYPE p LENGTH 8 DECIMALS 2. @@ -1134,7 +1404,12 @@ TRY. DATA(calc3) = EXACT packednum( 1 / 3 ). CATCH cx_sy_conversion_rounding. ENDTRY. -``` +``` + +

⬆️ back to top

@@ -1287,7 +1562,23 @@ DATA(methods) = CAST cl_abap_objectdescr( specify an `ELSE` clause at the end. If this clause is not specified, the result is the initial value of the specified or derived data type. - Note that all operands specified after `THEN` must be convertible to the specified or derived data type. -Example: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subject Notes/Code Snippet
+ +Creating a result depending on logical expressions + + + ``` abap DATA(day_or_night) = COND #( WHEN cl_abap_context_info=>get_system_time( ) BETWEEN '050000' AND '220000' THEN `day` @@ -1299,15 +1590,41 @@ IF cl_abap_context_info=>get_system_time( ) BETWEEN '050000' AND '220000'. ELSE. day_or_night = `night`. ENDIF. +``` -"Multiple logical expressions initiated by WHEN -"Also LET expressions are possible. See more details further down. +
+ +Multiple logical expressions initiated by `WHEN`, using `LET` + + + +``` abap DATA(time_of_day) = COND #( LET time = cl_abap_context_info=>get_system_time( ) IN WHEN time BETWEEN '050001' AND '120000' THEN |Good morning, it's { time TIME = ISO }.| WHEN time BETWEEN '120001' AND '180000' THEN |Good afternoon, it's { time TIME = ISO }.| WHEN time BETWEEN '180001' AND '220000' THEN |Good evening, it's { time TIME = ISO }.| ELSE |Good night, it's { time TIME = ISO }.| ). +``` +
+ +`THROW` addition to raise an exception + + + + +``` abap "THROW addition to raise an exception (working like RAISE EXCEPTION TYPE statements) "by specifying an exception class "Note: It is possible to ... @@ -1327,14 +1644,35 @@ ENDTRY. "Excursion for the example above: The following statement does not result in an "error in ABAP (zero division 'allowed' if the first operand has also the value 0). div = 0 / 0. +``` +
+ +`THROW SHORTDUMP` addition to raise a runtime error + + + +``` abap "THROW SHORTDUMP addition to raise a runtime error (working like RAISE SHORTDUMP "TYPE statements) by specifying an exception class; a message can be also passed, "and input parameters can be filled -div = COND decfloat34( WHEN num1 <> 0 AND num2 <> 0 THEN num1 / num2 - WHEN num1 = 0 AND num2 <> 0 THEN num1 / num2 - ELSE THROW SHORTDUMP cx_sy_zerodivide( ) ). -``` +DATA(int1) = 0. +DATA(int2) = 0. + +DATA(division) = COND decfloat34( WHEN int1 <> 0 AND int2 <> 0 THEN int1 / int2 + WHEN int1 = 0 AND int2 <> 0 THEN int1 / int2 + ELSE THROW SHORTDUMP cx_sy_zerodivide( ) ). +``` + +

⬆️ back to top

diff --git a/06_Dynamic_Programming.md b/06_Dynamic_Programming.md index ae8b71b..7144f3f 100644 --- a/06_Dynamic_Programming.md +++ b/06_Dynamic_Programming.md @@ -31,6 +31,7 @@ - [Dynamic Invoke](#dynamic-invoke) - [Dynamic ABAP EML Statements](#dynamic-abap-eml-statements) - [Dynamic Formatting Option Specifications in String Templates](#dynamic-formatting-option-specifications-in-string-templates) + - [Dynamic Parameter List in EXPORT and IMPORT Statements](#dynamic-parameter-list-in-export-and-import-statements) - [Security Considerations in Dynamic Programming Using External Input](#security-considerations-in-dynamic-programming-using-external-input) - [Runtime Type Services (RTTS)](#runtime-type-services-rtts) - [Getting Type Information at Runtime (RTTI)](#getting-type-information-at-runtime-rtti) @@ -2527,6 +2528,56 @@ DATA(s6) = |{ some_string CASE = int_tab[ 1 ] }|. "AbAp ``` +

⬆️ back to top

+ +### Dynamic Parameter List in EXPORT and IMPORT Statements + +- Used in the context of exporting and importing data clusters +- Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENDATA_CLUSTER.html) and an executable example, including the code snippet below, in the [Working with XML and JSON in ABAP](21_XML_JSON.md) cheat sheet. + +```abap +DATA buffer TYPE xstring. + +"--------- Dynamic specification of the parameter list --------- +"Note: +"- The parameter list is specified in an index table with two columns. +"- The column names can have random names, but the type must be character-like. +"- The first column represents the parameter name, the second column represents +" the name of the data object. +"- Note that special behavior applies. See the documentation. + +TYPES: BEGIN OF param, + name TYPE string, + dobj TYPE string, + END OF param, + param_tab_type TYPE TABLE OF param WITH EMPTY KEY. + +DATA: txt1 TYPE string VALUE `hello`, + txt2 TYPE string VALUE `world`, + txt3 TYPE string VALUE `ABAP`. + +DATA(param_table) = VALUE param_tab_type( + ( name = `txt1` dobj = `txt1` ) + ( name = `txt2` dobj = `txt2` ) + ( name = `txt3` dobj = `txt3` ) ). + +EXPORT (param_table) TO DATA BUFFER buffer. + +"The example reads the content into structure components. +DATA: BEGIN OF values, + txt1 TYPE string, + txt2 TYPE string, + txt3 TYPE string, + END OF values. + +param_table = VALUE param_tab_type( + ( name = `txt1` dobj = `values-txt1` ) + ( name = `txt2` dobj = `values-txt2` ) + ( name = `txt3` dobj = `values-txt3` ) ). + +IMPORT (param_table) FROM DATA BUFFER buffer. +``` +

⬆️ back to top

## Security Considerations in Dynamic Programming Using External Input diff --git a/07_String_Processing.md b/07_String_Processing.md index e9d1708..b99c318 100644 --- a/07_String_Processing.md +++ b/07_String_Processing.md @@ -556,7 +556,7 @@ s1 = concat_lines_of( table = itab sep = ` ` ). "With separator ### Literal Operator -The [literal operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator_glosry.htm "Glossary Entry") `&` combines [text string literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_string_literal_glosry.htm "Glossary Entry"), however, with [significant differences](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator.htm) to `&&`, which the code snippet demonstrates. +The [literal operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator_glosry.htm "Glossary Entry") `&` combines [text string literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_string_literal_glosry.htm "Glossary Entry"), however, with [significant differences](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator.htm) to `&&`, which the code snippet addresses. ```abap diff --git a/08_EML_ABAP_for_RAP.md b/08_EML_ABAP_for_RAP.md index 105f2ef..5965cfb 100644 --- a/08_EML_ABAP_for_RAP.md +++ b/08_EML_ABAP_for_RAP.md @@ -32,7 +32,7 @@ - [COMMIT ENTITIES: Persisting to the Database](#commit-entities-persisting-to-the-database) - [GET PERMISSIONS: Retrieving Information about RAP BO Permissions](#get-permissions-retrieving-information-about-rap-bo-permissions) - [Raising RAP Business Events](#raising-rap-business-events) - - [Additions to ABAP EML Statements in ABAP Behavior Pools](#additions-to-abap-eml-statements-in-abap-behavior-pools) + - [IN LOCAL MODE Addition to ABAP EML Statements in ABAP Behavior Pools](#in-local-mode-addition-to-abap-eml-statements-in-abap-behavior-pools) - [RAP Excursions](#rap-excursions) - [Using Keys and Identifying RAP BO Instances in a Nutshell](#using-keys-and-identifying-rap-bo-instances-in-a-nutshell) - [RAP Concepts](#rap-concepts) @@ -572,8 +572,8 @@ METHODS some_action FOR MODIFY that have special RAP-related components as covered further down. - The parameters' names can be chosen freely. This is also true for the method names except for some predefined names. -- Each handler method must have at least one importing parameter. The - addition `IMPORTING` is optional since it is used +- Each handler method must have at least one importing parameter. + Specifying the addition `IMPORTING` explicitly is optional since it is used implicitly. In most cases, entire instances or just key values of instances are imported. - All handler methods have changing parameters that are usually not @@ -972,6 +972,24 @@ Bullet points on selected `%` components: `if_abap_behv=>mk-off`, the values of these fields are not returned in the result. + +The following code snippet illustrates the importance of careful component access and value assignment with component groups in BDEF derived types: +- It uses the key component of a demo RAP BO and an internal table of type `FOR CREATE` as an example. +- The type includes the component groups `%data` and `%key`. +- `%data` contains `%key` as a component. +- Component access may be done in various ways. +- Especially in value assignments, make sure that there is only one assignment per component. + +```abap +DATA itab TYPE TABLE FOR CREATE zdemo_abap_rap_ro_m. +APPEND INITIAL LINE TO itab. + +DATA(a) = itab[ 1 ]-key_field. +DATA(b) = itab[ 1 ]-%key-key_field. +DATA(c) = itab[ 1 ]-%data-key_field. +DATA(d) = itab[ 1 ]-%data-%key-key_field. +``` +

⬆️ back to top

### Constants for BDEF Derived Type Components @@ -986,6 +1004,7 @@ Several BDEF derived types contain `%` components, which have a specific type an | `ABP_BEHV_FIELD_CTRL` | `IF_ABAP_BEHV=>FC-F` | For field feature control results, such as a field marked with no restrictions. | | `ABP_BEHV_OP_CTRL` | `IF_ABAP_BEHV=>FC-O` | For operation feature control results, such as a disabled update operation. | | `ABP_BEHV_AUTH` | `IF_ABAP_BEHV=>AUTH` | For authorization results, such as an unauthorized operation. | +| `IF_ABAP_BEHV=>T_CHAR01` | `IF_ABAP_BEHV=>MK` | For dynamic ABAP EML statements; e.g. `if_abap_behv=>op-m-create` for create and `if_abap_behv=>op-r-read` for read operations. |

⬆️ back to top

@@ -1421,7 +1440,7 @@ MODIFY ENTITIES OF root_ent #### Dynamic Form of ABAP EML MODIFY Statements -- The code snippet demonstrate the dynamic form `MODIFY ENTITIES OPERATIONS ...`. +- The code snippet demonstrates the dynamic form `MODIFY ENTITIES OPERATIONS ...`. - Using the statement, you can execute multiple modify operations for multiple RAP BOs in a single statement. - Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPMODIFY_ENTITIES_OPERATIONS_DYN.html). @@ -1979,7 +1998,6 @@ DO 2 TIMES. ... ENDIF. -"Data is not saved SELECT FROM zdemo_abap_rapt1 FIELDS key_field ORDER BY key_field @@ -2096,7 +2114,7 @@ ENDCLASS.

⬆️ back to top

-### Additions to ABAP EML Statements in ABAP Behavior Pools +### IN LOCAL MODE Addition to ABAP EML Statements in ABAP Behavior Pools - There are a [special additions when using EML in behavior pools](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeneml_in_abp.htm). diff --git a/13_Program_Flow_Logic.md b/13_Program_Flow_Logic.md index 9090736..55609ca 100644 --- a/13_Program_Flow_Logic.md +++ b/13_Program_Flow_Logic.md @@ -601,7 +601,7 @@ CALL FUNCTION func params. - `params`: Parameter list or table - Incorrectly provided function module names or parameters are not checked until runtime - Unlike method calls, you cannot specify inline declarations as actual parameters. -- Regarding dynamic function module calls: Static and dynamic function module calls are syntactically identical. In a static call, the function module is specified as a character literal or a constant, with parameters passed statically. Conversely, in a dynamic call, the function module's name is specified in a variable, with parameters passed dynamically. For dynamic calls, you can utilize the `CL_ABAP_DYN_PRG` as shown in the [Released ABAP Classes](22_Released_ABAP_Classes.md). +- Regarding dynamic function module calls: Static and dynamic function module calls are syntactically identical. In a static call, the function module is specified as a character literal or a constant, with parameters passed statically. Conversely, in a dynamic call, the function module's name is specified in a variable, with parameters passed dynamically. For dynamic calls, you can utilize the `CL_ABAP_DYN_PRG` as shown in the [Released ABAP Classes](22_Released_ABAP_Classes.md) cheat sheet. - When a function module call is made, the system field `sy-subrc` is set to 0. If a non-class-based exception is raised and a value is assigned to handle it, this value updates `sy-subrc`. Example function module calls with parameter passing and exception handling: diff --git a/21_XML_JSON.md b/21_XML_JSON.md index 5758273..c9e7c09 100644 --- a/21_XML_JSON.md +++ b/21_XML_JSON.md @@ -19,6 +19,7 @@ - [Serializing and Deserializing Objects](#serializing-and-deserializing-objects) - [Converting string \<-\> xstring](#converting-string---xstring) - [Compressing and Decompressing Binary Data](#compressing-and-decompressing-binary-data) + - [Exporting and Importing Data Clusters](#exporting-and-importing-data-clusters) - [More Information](#more-information) - [Executable Example](#executable-example) @@ -1545,6 +1546,235 @@ DATA(conv_str) = cl_abap_conv_codepage=>create_in( )->convert( xstr_decomp ). DATA(is_equal) = xsdbool( len_xstr = len_xstr_decomp AND str = conv_str ). ``` +### Exporting and Importing Data Clusters + +- A data cluster groups data objects for temporary and persistent storage in a medium, such as an elementary data object of type `xstring`, or an internal table with a specific table type. +- Potential uses include: + - Fast serialization and deserialization of data to and from `xstring` + - Storing the data cluster (in a compressed form) in a DDIC database table field + - Passing data clusters through parameters in procedures for further evaluation, especially with large, complex data +- Related ABAP statements: + - `EXPORT` to write data objects to the memory medium + - `IMPORT` to read from the memory medium and extract the data objects + +> **💡 Note**
+> - The use cases of data clusters go beyond the actual subject of this cheat sheet. Here, the emphasis is on the fast serialization and deserialization of data to and from `xstring`. +> - Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENDATA_CLUSTER.html). +> - More syntax options are available in [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm). +> - Various exceptions can be raised when using these statements; see the related subtopics in the [documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABENDATA_CLUSTER.html). +> - Additions to `IMPORT` statements offer [conversion options](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/ABAPIMPORT_CONVERSION.html). + +The following example covers: +- Exporting a data cluster, storing it in a byte string, and importing it back to a data object +- Activating compression using the `COMPRESSION ON` addition +- Specifying multiple data objects in the parameter list +- Alternative syntax for specifying parameters +- Dynamic specification of the parameter list +- Exporting and importing class objects + +```abap +CLASS zcl_some_class DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. + INTERFACES if_serializable_object. + METHODS constructor IMPORTING text TYPE string OPTIONAL. + PROTECTED SECTION. + PRIVATE SECTION. + DATA timestamp TYPE utclong. + DATA text TYPE string. +ENDCLASS. + +CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + + DATA buffer TYPE xstring. + + + "---- Exporting data cluster, storing it in byte string, ------- + "---- and importing it to a data object again ------------------ + + "The following example exports an internal table to a byte string buffer, and + "imports the content to another internal table. + "The parameter list includes one data object. Compression is deactivated + "by default. + + SELECT * + FROM zdemo_abap_fli + INTO TABLE @DATA(itab1). + + EXPORT flights = itab1 TO DATA BUFFER buffer. + + "Determining the length of the xstring (to compare it with the + "same example that activates compression). + DATA(strlen_export) = xstrlen( buffer ). + + out->write( data = strlen_export name = `strlen_export` ). + out->write( |\n| ). + + DATA itab2 LIKE itab1. + IMPORT flights = itab2 FROM DATA BUFFER buffer. + + ASSERT itab2 = itab1. + + out->write( data = itab2 name = `itab2` ). + out->write( |\n| ). + + "---------------- Activating compression ---------------- + EXPORT flights = itab1 TO DATA BUFFER buffer COMPRESSION ON. + + DATA(strlen_export_compr) = xstrlen( buffer ). + + ASSERT strlen_export_compr < strlen_export. + out->write( data = strlen_export_compr name = `strlen_export_compr` ). + out->write( |\n| ). + + "------ Multiple data objects specified in the parameter list ----- + "The following example writes and reads a byte string of two numbers. + + DATA num1 TYPE i. + DATA num2 TYPE i. + EXPORT int1 = 100 int2 = 200 TO DATA BUFFER buffer. + IMPORT int1 = num1 int2 = num2 FROM DATA BUFFER buffer. + + "----------------- Exceptions ----------------- + "The following example includes a non-compatible data object to read + "to. The example emphasizes that various exceptions can be + "raised when using the statements. Find more details in the ABAP + "Keyword Documentation. + DATA str_table TYPE string_table. + TRY. + IMPORT int1 = num1 int2 = str_table FROM DATA BUFFER buffer. + CATCH cx_sy_import_mismatch_error. + ENDTRY. + + "--------- Alternative syntax for specifying the parameters --------- + "EXPORT: Using ... FROM ... instead of ... = ... + "IMPORT: Using ... TO ... instead of ... = ... + EXPORT flights FROM itab1 TO DATA BUFFER buffer. + IMPORT flights TO itab2 FROM DATA BUFFER buffer. + EXPORT int1 = 100 int2 = 200 TO DATA BUFFER buffer. + IMPORT int1 TO num1 int2 TO num2 FROM DATA BUFFER buffer. + + "--------- Dynamic specification of the parameter list --------- + "Note: + "- The parameter list is specified in an index table with two columns. + "- The column names can have random names, but the type must be character-like. + "- The first column represents the parameter name, the second column represents + " the name of the data object. + "- Note that special behavior applies. See the documentation. + + TYPES: BEGIN OF param, + name TYPE string, + dobj TYPE string, + END OF param, + param_tab_type TYPE TABLE OF param WITH EMPTY KEY. + + DATA: txt1 TYPE string VALUE `hello`, + txt2 TYPE string VALUE `world`, + txt3 TYPE string VALUE `ABAP`. + + DATA(param_table) = VALUE param_tab_type( + ( name = `txt1` dobj = `txt1` ) + ( name = `txt2` dobj = `txt2` ) + ( name = `txt3` dobj = `txt3` ) ). + + EXPORT (param_table) TO DATA BUFFER buffer. + + "The example reads the content into structure components. + DATA: BEGIN OF values, + txt1 TYPE string, + txt2 TYPE string, + txt3 TYPE string, + END OF values. + + param_table = VALUE param_tab_type( + ( name = `txt1` dobj = `values-txt1` ) + ( name = `txt2` dobj = `values-txt2` ) + ( name = `txt3` dobj = `values-txt3` ) ). + + IMPORT (param_table) FROM DATA BUFFER buffer. + + out->write( data = values name = `values` ). + out->write( |\n| ). + + "--------- Exporting and importing objects of classes ---------- + "The following example explores: + "- Objects of the example class are created + "- The objects are serialized using a CALL TRANSFORMATION statement + "- As a prerequisite, the class includes the IF_SERIALIZABLE_OBJECT interface + "- In a DO loop, 3 objects of the class are created. + "- After serializing the objects, the data is exported with compression activated. + "- Then, the data is read and deserialized again. + "- Instance attributes are accessed and added to an internal table for output + " purposes. The class is setup that instance attributes receive different values, + " for example, the current UTC timestamp is set. + + TYPES: BEGIN OF info, + text TYPE string, + timestamp TYPE utclong, + END OF info. + + DATA info_tab TYPE TABLE OF info WITH EMPTY KEY. + + DO 3 TIMES. + DATA(obj_ref) = NEW zcl_some_class( |Instance { sy-index }| ). + CALL TRANSFORMATION id SOURCE oref = obj_ref RESULT XML DATA(xml). + + EXPORT xml_data = xml TO DATA BUFFER buffer COMPRESSION ON. + + CLEAR obj_ref. + + IMPORT xml_data = xml FROM DATA BUFFER buffer. + + CALL TRANSFORMATION id SOURCE XML xml RESULT oref = obj_ref. + DATA(text_deserialized) = obj_ref->text. + DATA(timestamp_deserialized) = obj_ref->timestamp. + APPEND VALUE #( text = text_deserialized timestamp = timestamp_deserialized ) TO info_tab. + ENDDO. + + out->write( info_tab ). + out->write( |\n| ). + + "--------- Exporting and importing data objects to an internal table as storage medium ---------- + "The following example exports an internal table to a data cluster in an internal table, + "and imports it into another internal table. + "Note that there are prerequisites for the internal table as storage medium. See the documentation. + "As the width of the second column is restricted, the data is stored across multiple table lines. + + TYPES: BEGIN OF buffer_line, + id TYPE i, + clstr TYPE x LENGTH 100, + END OF buffer_line. + + DATA tab_buffer TYPE TABLE OF buffer_line WITH EMPTY KEY. + EXPORT itab = itab1 TO INTERNAL TABLE tab_buffer. + + out->write( |Lines in buffer table: { lines( tab_buffer ) }| ). + out->write( |\n| ). + + IMPORT itab = itab2 FROM INTERNAL TABLE tab_buffer. + + ASSERT itab2 = itab1. + + ENDMETHOD. + + METHOD constructor. + me->timestamp = utclong_current( ). + + IF text IS SUPPLIED AND text IS NOT INITIAL. + me->text = text. + ENDIF. + ENDMETHOD. + +ENDCLASS. +``` + +

⬆️ back to top

+ ## More Information - [ABAP and XML (main topic in the ABAP Keyword Documentation)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_xml.htm) diff --git a/27_Exceptions.md b/27_Exceptions.md index b42b766..e42213a 100644 --- a/27_Exceptions.md +++ b/27_Exceptions.md @@ -432,7 +432,7 @@ ENDDO. - Exceptions can be handled locally using a `TRY` structure or be propagated to the caller, making the caller responsible for handling the error. This approach allows for better code structure by managing errors centrally rather than checking each procedure call individually. - If the exception cannot be caught and handled, the program terminates with a runtime error. - If the exception is handled or no exception is raised, processing continues after `ENDTRY`. - - Strategies about how to continue after an exception is raised and caught include ignoring the error, correcting and retrying, evaluating the error situation (see notes on the `INTO` addition to the `CATCH` statement), showing an error message to the user, logging the error, etc. + - Options for how to continue after an exception is raised and caught may include ignoring the error, correcting and retrying, evaluating the error situation (see notes on the `INTO` addition to the `CATCH` statement), showing an error message to the user, logging the error, etc.

⬆️ back to top