From 508e74a1e0399f1e686363bb8a7803d9858a1ae0 Mon Sep 17 00:00:00 2001 From: danrega <16720986+danrega@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:24:35 +0100 Subject: [PATCH] Update --- 01_Internal_Tables.md | 3388 ++++++++++++------------ 02_Structures.md | 1470 ++++++----- 03_ABAP_SQL.md | 3409 ++++++++++++------------ 04_ABAP_Object_Orientation.md | 2658 +++++++++---------- 07_String_Processing.md | 4174 ++++++++++++++++-------------- 08_EML_ABAP_for_RAP.md | 3438 ++++++++++++------------ 13_Program_Flow_Logic.md | 1395 +++++----- 16_Data_Types_and_Objects.md | 2982 +++++++++++---------- 17_SAP_LUW.md | 902 ++++--- 18_Dynpro.md | 1552 +++++------ 19_ABAP_for_Cloud_Development.md | 372 ++- 20_Selection_Screens_Lists.md | 2673 +++++++++---------- 21_XML_JSON.md | 1497 +++++------ 13 files changed, 15028 insertions(+), 14882 deletions(-) diff --git a/01_Internal_Tables.md b/01_Internal_Tables.md index f3722f7..192e83f 100644 --- a/01_Internal_Tables.md +++ b/01_Internal_Tables.md @@ -1,1694 +1,1696 @@ - - -# Internal Tables - -- [Internal Tables](#internal-tables) - - [Introduction](#introduction) - - [Basic Properties of Internal Tables](#basic-properties-of-internal-tables) - - [Table Keys in Internal Tables (Primary, Secondary, Standard, Empty)](#table-keys-in-internal-tables-primary-secondary-standard-empty) - - [Creating Internal Tables and Types](#creating-internal-tables-and-types) - - [Filling and Copying Internal Tables](#filling-and-copying-internal-tables) - - [Excursions with Internal Tables](#excursions-with-internal-tables) - - [Reading from Internal Tables](#reading-from-internal-tables) - - [Processing Multiple Internal Table Lines Sequentially](#processing-multiple-internal-table-lines-sequentially) - - [Iteration Expressions](#iteration-expressions) - - [Sorting Internal Tables](#sorting-internal-tables) - - [Modifying Internal Table Content](#modifying-internal-table-content) - - [Deleting Internal Table Content](#deleting-internal-table-content) - - [Excursions](#excursions) - - [Improving Read Performance with Secondary Table Keys](#improving-read-performance-with-secondary-table-keys) - - [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) - - [More Information](#more-information) - - [Executable Example](#executable-example) - - -## Introduction - -Internal Tables ... - -- are [dynamic data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_data_object_glosry.htm), i.e. all properties apart from the memory consumption are determined statically by the [data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm). -- consist of a variable sequence of lines of the same data type. -- have a [table type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm) as its data type (it is a [complex data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm)), which defines the following properties: - - [line type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrow_type_glosry.htm) - - [table category](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_category_glosry.htm) - - [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm) -- are used when a variable data set of a random data type needs to be processed in a structured way. -- allow access to individual table lines via a [table index](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_index_glosry.htm) or a [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm). - -

⬆️ back to top

- -## Basic Properties of Internal Tables - -
- Expand to view the details - - -**Line Type** - -- Defines how each line of the internal table is set up, i. e. it describes what columns the table has. -- It can be any ABAP data type, e.g. an [elementary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm) or complex data type as well as a [reference type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm). -- In most cases, the line type is [structured](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm). In this case, the individual components of a line are also referred to as the columns of the internal table. -- In a simple case, the line consists of a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm) with elementary data objects; however, it can also be a [deep structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm) whose components can be structures themselves or even internal tables. - -**Table Category** - -- Defines how internal tables are managed and stored internally, and how to access individual table entries. -- Why is it relevant? The use of a suitable table category should meet your requirements, i.e. if the internal tables are large, the different categories can have significant performance differences when accessing table content. -- Note: There are two ways to access internal tables: - - Access by table index: A line of an internal table is accessed by its line number. This kind of access is the fastest way to access table lines. - - Access by table key: A line of an internal table is accessed by searching for specific values in specific columns. Note: The columns in which you search can be key columns, but they can also be non-key columns. - - -| Category | Internally managed by | Access | Primary table key | When to use | Hints | -|---|---|---|---|---|---| -|`STANDARD`|Primary table index (that's why these tables are called [index tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenindex_table_glosry.htm))||||| -|`SORTED`|Primary table index (that's why these tables are called [index tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenindex_table_glosry.htm))||||| -|`HASHED`|Hash algorithm ||Always unique||| - - - -**Key Attributes** - -- There are two types of table keys: a [primary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_table_key_glosry.htm) and [secondary table keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm). -- Table keys ... - - are intended to provide an optimized access to the content of internal tables. - - are either unique or non-unique, i.e. more than one line with the same key (duplicates) can exist in the internal table or not. Regarding the primary table key, the definition depends on the table category. For the secondary table key, the definition depends on the key type. For standard tables, the primary table key can also be defined as empty, i.e. it does not contain any key columns. Note that for standard tables, an optimized access is only possible with secondary table keys. - - Type of keys: - - Sorted keys: - - Are either the primary table keys of sorted tables or the secondary table keys of any table. - - Are managed internally by a table index. In the case of sorted tables, this is the primary table index. In the case of secondary table keys, a secondary table index is added. - - Access via sorted keys means an optimized binary search. - - Hashed keys: - - Are either the primary table key of hashed tables or secondary table keys of any table. - - Internally managed by a hash algorithm. - - There is no table index for a hashed key. - -**Further information** -- [Internal Tables - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenitab_oview.htm) -- [Programming guidelines: Internal Tables (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenadmin_costs_dyn_mem_obj_guidl.htm) -
- -

⬆️ back to top

- -## Table Keys in Internal Tables (Primary, Secondary, Standard, Empty) - -
- Expand to view the details - - -**Primary table key** - -- Each internal table has a primary table key. -- Can be either a self-defined key or the [standard key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_key_glosry.htm). -- The primary table key is ... - - sorted for sorted tables. - - hashed for hashed tables. -- Note that the key fields in sorted and hashed tables are read-only. This is not valid for standard tables. -- The specification of the primary key can be omitted only for standard tables. The primary table key is then automatically defined as a non-unique standard key. -- The primary table key has the predefined name `primary_key`, by which it can also be addressed explicitly. However, its use is optional, and it is usually not necessary to specify it explicitly. You can also specify an alias name for the primary key. -- When accessing internal tables using the table key, the primary key is always used implicitly in processing statements if no secondary key is specified. Note that the primary table key must be specified in table expressions if the primary key is to be used explicitly. - -> **💡 Note**
-> The key can consist of individual key fields or the entire line of the internal table. In this case, the pseudo component `table_line` can be used to denote the primary table key. For non-structured line types, this is the only way to define the key. - -**Standard key** -- The [standard key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_key_glosry.htm) is a special primary table key. -- It can be declared either explicitly or implicitly. -- Standard key of an internal table with a ... - - structured line type: The primary table key consists of all fields with character-like and byte-like data types. - - non-structured/elementary line type: The entire table is the key (`table_line`). -- An internal table with no explicit key specification implicitly has the standard table key as the primary table key. -- Why respecting standard keys is important: - - Sorting of a table can produce unexpected results. - - Since the standard key can consist of many fields, it affects the performance when accessing the internal table via the keys. - - The key fields of the primary table key of sorted and hashed tables are always read-only, i.e. using the standard key with these table categories and then (unintentionally) modifying fields can cause unexpected runtime errors. - - Specifying keys explicitly has the advantage of making the code more readable and preventing the standard key from being set by mistake. - -**Empty key** -- The primary table key of a standard table can be empty, i.e. it does not contain any key fields. -- An empty key is not possible for sorted and hashed tables. -- When used: - - When the definition of a table key is not important. - - To explicitly state that a table key is not required, instead of specifying no key definition. Otherwise, the standard key is used, which can lead to unexpected results as mentioned above. -- Declaration: - - Explicit declaration using the addition `EMPTY KEY`. - - Implicit declaration when using the standard key if a structured - line type does not contain non-numeric elementary components or - if an unstructured line type is tabular. - - Note: When using an [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry") such as `... INTO TABLE @DATA(itab) ...` in `SELECT` statements, the resulting table is a standard table and has an empty key. - -**Secondary table keys** - -- Secondary table keys ... - - are optional for all table categories. - - can be unique/non-unique sorted keys or unique hash keys. - - have a self-defined name. An alias name can also be specified. -- A secondary table index is created internally for each sorted secondary key. This allows index access to hashed tables via the secondary table key. In this case, `sy-tabix` is set. -- When accessing internal tables using the secondary table key, the key name (or the alias if specified) must be specified. They are not selected automatically. If no secondary key is specified in a processing statement, the primary key or primary table index is always used. If you want to make use of this key in ABAP statements, for example, `READ`, `LOOP AT` or `MODIFY` statements, you must specify the key explicitly using the appropriate additions, for example, `WITH ... KEY ... COMPONENTS` or `USING KEY`. -- Use cases: - - To improve read performance. - - For very large internal tables (that are filled once and changed very often) - - Standard tables, whose primary table keys cannot be unique, can be provided with a means of ensuring that unique table entries are read. - - Note that defining secondary table keys involves additional administration costs (additional memory consumption). Therefore, the use of secondary table keys should be reserved for cases where the benefits outweigh the extra costs. -- For more details, see the programming guidelines for secondary keys: [Secondary - Key (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_key_guidl.htm "Guideline"). - -> **💡 Note**
-> - See examples of internal table declarations using the table keys mentioned above in the following section. -> - See an example that uses secondary table keys [below](#improving-read-performance-with-secondary-table-keys). - -
- -

⬆️ back to top

- - -## Creating Internal Tables and Types - -You can declare internal tables and internal table types in [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) using the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) and [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) statements. The relevant syntax elements for internal tables are `TABLE OF` in combination -with the additions [`TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_simple.htm) -or [`LIKE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_referring.htm). - -``` abap -TYPES itab_type1 TYPE STANDARD TABLE OF data_type ... "Standard table type -TYPES itab_type2 LIKE SORTED TABLE OF data_object ... "Sorted table type - -DATA itab1 TYPE TABLE OF data_type ... "Standard table by default -DATA itab2 TYPE HASHED TABLE OF data_type ... "Hashed table -DATA itab3 TYPE itab_type1 ... "Based on an existing internal table type -DATA itab4 LIKE itab1 ... "Based on an existing internal table -``` - -> **💡 Note**
-> If the table category is not specified (`... TYPE TABLE OF ...`), it is automatically `... TYPE STANDARD TABLE OF ...`. - -The following code snippet contains 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, 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. - - -``` abap -"------------------ Standard table key ------------------ - -"Standard table without explicit primary table key specification. Note that STANDARD -"is not explicitly specified. -"Implicitly, the standard key is used; all non-numeric table fields -"make up the primary table key. -DATA it1 TYPE TABLE OF zdemo_abap_fli. - -"Explicitly specifying STANDARD for a standard table. -"Explicitly specifying the standard table key. It is the same as it1. -DATA it2 TYPE STANDARD TABLE OF zdemo_abap_fli WITH DEFAULT KEY. - -"Hashed table with unique standard table key -DATA it3 TYPE HASHED TABLE OF zdemo_abap_fli WITH UNIQUE DEFAULT KEY. - -"Sorted table with non-unique standard table key -DATA it4 TYPE SORTED TABLE OF zdemo_abap_fli WITH NON-UNIQUE DEFAULT KEY. - -"Elementary line type; the whole table line is the standard table key -DATA it5 TYPE TABLE OF i. - -"------------------ Primary table key ------------------ - -"Specifying the primary table key -"Standard tables: only a non-unique key possible -"The following two examples are the same. NON-UNIQUE can be ommitted but is implicitly added. -DATA it6 TYPE TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid. -DATA it7 TYPE TABLE OF zdemo_abap_fli WITH KEY carrid. - -"Sorted tables: both UNIQUE and NON-UNIQUE possible -DATA it8 TYPE SORTED TABLE OF zdemo_abap_fli WITH UNIQUE KEY carrid connid. -DATA it9 TYPE SORTED TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid connid cityfrom. - -"Hashed tables: UNIQUE KEY must be specified -DATA it10 TYPE HASHED TABLE OF zdemo_abap_fli WITH UNIQUE KEY carrid. - -"Explicitly specifying the predefined name primary_key and listing the components. -"The example is the same as it6 and it7. -DATA it11 TYPE TABLE OF zdemo_abap_fli WITH KEY primary_key COMPONENTS carrid. - -"The following example is the same as it9. -DATA it12 TYPE SORTED TABLE OF zdemo_abap_fli - WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid cityfrom. - -"Specifying an alias name for a primary table key. -"Only possible for sorted/hashed tables. -DATA it13 TYPE SORTED TABLE OF zdemo_abap_fli - WITH NON-UNIQUE KEY primary_key - ALIAS p1 COMPONENTS carrid connid cityfrom. - -"Specifying a key that is composed of the entire line using the predefined table_line. -"In the example, an alias name is defined for a primary table key. -DATA it14 TYPE HASHED TABLE OF zdemo_abap_fli - WITH UNIQUE KEY primary_key - ALIAS p2 COMPONENTS table_line. - -"------------------ Empty key ------------------ - -"Empty keys only possible for standard tables -DATA it15 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. - -"Excursion: The inline declaration in a SELECT statement produces a standard table with empty key. -SELECT * FROM zdemo_abap_fli INTO TABLE @DATA(it16). - -"------------------ Secondary table key ------------------ - -"The following examples demonstrate secondary table keys that are possible for all table categories. -DATA it17 TYPE TABLE OF zdemo_abap_fli "standard table - WITH NON-UNIQUE KEY carrid connid "primary table key - WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto. "secondary table key - -DATA it18 TYPE HASHED TABLE OF zdemo_abap_fli "hashed table - WITH UNIQUE KEY carrid connid - WITH NON-UNIQUE SORTED KEY airports COMPONENTS airpfrom airpto. - -DATA it19 TYPE SORTED TABLE OF zdemo_abap_fli "sorted table - WITH UNIQUE KEY carrid connid - WITH UNIQUE HASHED KEY countries COMPONENTS countryfr countryto. - -"Multiple secondary keys are possible -DATA it20 TYPE TABLE OF zdemo_abap_fli - WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid - WITH NON-UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto - WITH UNIQUE HASHED KEY airports COMPONENTS airpfrom airpto. - -"Alias names for secondary table keys (and also for the primary table key in the example) -DATA it21 TYPE SORTED TABLE OF zdemo_abap_fli - WITH NON-UNIQUE KEY primary_key ALIAS k1 COMPONENTS carrid connid city - WITH NON-UNIQUE SORTED KEY cities ALIAS s1 COMPONENTS cityfrom cityto - WITH UNIQUE HASHED KEY airports ALIAS s2 COMPONENTS airpfrom airpto. - -"Example for using table keys and alias names using a LOOP AT statement. -"All of the statements below are possible. -"Note that if the secondary table key is not specified (and if the USING KEY addition is not -"used in the example), the primary table key is respected by default. -"Further ABAP statements, such as READ or MODIFY, are available in which the key can be -"explicitly specified to process internal tables. -LOOP AT it21 INTO DATA(wa) USING KEY primary_key. -"LOOP AT it21 INTO DATA(wa) USING KEY k1. -"LOOP AT it21 INTO DATA(wa) USING KEY cities. -"LOOP AT it21 INTO DATA(wa) USING KEY s1. -"LOOP AT it21 INTO DATA(wa) USING KEY airports. -"LOOP AT it21 INTO DATA(wa) USING KEY s2. - ... -ENDLOOP. -``` - -As mentioned, the examples above demonstrate internal tables that are created using the structured type of a database table in the DDIC. -The following example shows the pattern and various examples of declaring internal tables and types by including the local definition of structured data and internal table types for demonstration purposes. - -Steps: -1. Define a structured data type (locally or globally). - This is not necessary if you use, for example, the name of a database table or [CDS view](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm) in the internal table declaration. In these cases their line type is used automatically. -2. Define an internal table type. -3. Create the internal table, i.e. a data object that uses this type. - -You can also create an internal table by ... -- combining the data object creation and table type definition in one step. -- using an [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry"). Such inline declarations are possible at suitable [declaration -positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_positions.htm) -if the operand type can be fully determined, for example, using a -`DATA` statement (or [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) for immutable variables). - - -``` abap -"1. Defining line type locally - -TYPES: BEGIN OF ls_loc, - key_field TYPE i, - char1 TYPE c LENGTH 10, - char2 TYPE c LENGTH 10, - num1 TYPE i, - num2 TYPE i, - END OF ls_loc. - -"2. Defining internal table types -"All of the examples use the short form: - -TYPES: - "Standard table type based on locally defined structure type. - tt_loc_str TYPE TABLE OF ls_loc WITH NON-UNIQUE KEY key_field, - - "Based on global structure type - tt_gl_str TYPE TABLE OF zsome_global_struc_type WITH NON-UNIQUE KEY key_field, - - "Based on database table (could also be, e. g. a CDS view) - "In this case, the line type of the table is automatically used. - tt_gl_tab TYPE TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid, - - "Based on an elementary type - tt_el_type TYPE TABLE OF i. - -"3. Creating internal tables ... -"... from locally defined table types -DATA: itab_a1 TYPE tt_loc_str, - itab_a2 TYPE tt_gl_str, - itab_a3 TYPE tt_gl_tab, - itab_a4 TYPE tt_el_type. - -"... from global internal table types -DATA itab_a5 TYPE string_table. - -"Combining data object and table type definition -DATA itab_a6 TYPE TABLE OF ls_loc WITH NON-UNIQUE KEY key_field. - -"Internal table based on an already existing internal table using LIKE. -DATA itab_a7 LIKE TABLE OF itab_a6. - -"Creating internal tables by inline declarations - -"Table declared inline in the context of an assignment -"The examples show the copying of a table including the content on the fly -"and creating the table in one step. The data type of the -"declared variable is determined by the right side. -DATA(it_inline1) = itab_a1. -DATA(it_inline2) = it_inline1. - -"Using FINAL for creating immutable variables -FINAL(it_final) = it_inline1. - -"Using the VALUE operator and an internal table type -DATA(it_inline3) = VALUE tt_loc_str( ( ... ) ). - -"Table declared inline in the context of a SELECT statement; -"a prior extra declaration of an internal table is not needed. -SELECT * FROM zdemo_abap_fli INTO TABLE @DATA(it_inline4). - -"Instead of -DATA it_sel TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. -SELECT * FROM zdemo_abap_fli INTO TABLE @it_sel. - -"Using FINAL -SELECT * FROM zdemo_abap_fli INTO TABLE @FINAL(it_inline5). -``` - -

⬆️ back to top

- -## Filling and Copying Internal Tables - -You can use the ABAP keywords -[`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_itab.htm) -and [`APPEND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapappend.htm) -to add lines to internal tables. - -
- Notes on using APPEND and INSERT - - -- `APPEND` ... - - always adds lines at the bottom of the internal table. - - is not a problem for standard tables where lines are managed - by an index. When the statement is used, the system field - `sy-tabix` is set to the index of the recently added - line. `sy-tabix` is always set to the index with respect - to the primary table index. - - cannot be used for hashed tables. For sorted tables, - lines are appended only if they match the sort order, and no - duplicate entries are created if the primary table key is unique. - Therefore, `INSERT` should be used when adding lines to - sorted tables. -- `INSERT` ... - - can be used to add lines at a specific position in tables (by - specifying the target index). In doing so, all the following - lines are moved down one position. - - without specifying the position adds the lines at the bottom of - the table in case of standard tables. However, when using - `INSERT`, `sy-tabix` is not set unlike - `APPEND`. In case of sorted tables, the line is - automatically inserted at the correct position. - - With `INSERT`, you can specify the position in the internal table at which lines are inserted after `INTO`. - - `... INTO TABLE itab ...`: Line is inserted in ... - - standard tables as last line (i.e. appended) - - sorted tables in the sort order in accordance with primary key values - - hashed table by the hash administration in accordance with primary key values - - `... INTO itab INDEX n`: Possible for index tables. The line is inserted before the line with the line number `n` in the primary table index. - - Note: In the case of unique primary table keys, the table cannot have entries with duplicate - keys. If a duplicate is inserted, the insertion fails and the - system field `sy-subrc` is set to 4. -- What to use? The recommendation is the `INSERT` statement. It covers all table and key types. Consider potential issues when you change table/key types, and you use `APPEND` in your code. -
-
- -**Adding a line to an internal table**. The example shows both a structure that is created using the `VALUE` operator as well as an existing structure that is added. - -``` abap -APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab. -APPEND lv_struc TO itab. - -INSERT VALUE #( comp1 = a comp2 = b ... ) INTO TABLE itab. -INSERT lv_struc INTO TABLE itab. -``` - -**Adding an initial line** to an internal table without providing any field values. - -``` abap -APPEND INITIAL LINE TO itab. - -INSERT INITIAL LINE INTO TABLE itab. -``` - -**Adding a line and assigning the added line to a field symbol or data reference variable**. -```abap -"When inserting single lines, you can specify the optional additions -"ASSIGNING and REFERENCE INTO. If the insertion is successful, the -"line is assigned to a field symbol or a data reference variable. -"The targets can also be created inline. -APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab ASSIGNING FIELD-SYMBOL(). -APPEND INITIAL LINE TO itab ASSIGNING . -INSERT INITIAL LINE INTO TABLE itab REFERENCE INTO DATA(dref). -``` - -**Adding all lines** from another internal table. - -``` abap -APPEND LINES OF itab2 TO itab. - -INSERT LINES OF itab2 INTO TABLE itab. -``` - -**Adding multiple lines from another internal table with a specified index range**. -- Both `FROM` and `TO` are not mandatory in one statement. it is possible to use only one of them. -- If you use only ... - - `FROM`, all lines up to the last table entry are respected. - - `TO`, all lines starting with the first table entry are respected. - -``` abap -"i1/i2 represent integer values - -APPEND LINES OF itab2 FROM i1 TO i2 TO itab. - -APPEND LINES OF itab2 FROM i1 TO itab. - -APPEND LINES OF itab2 TO i2 TO itab. - -INSERT LINES OF itab2 FROM i1 TO i2 INTO itab. -``` - -**Inserting one line or multiple lines from another internal table at a specific position**. -`FROM` and `TO` can be used here, too. - -``` abap -INSERT lv_struc INTO itab2 INDEX i. - -INSERT LINES OF itab2 INTO itab INDEX i. -``` - -

⬆️ back to top

- -**Adding lines using constructor expressions** - -As mentioned above, table lines that are constructed inline as -arguments to the `VALUE` operator, for example, can be added to -internal tables. In the following cases, internal tables are populated -using constructor expressions in the context of -[assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_glosry.htm "Glossary Entry"). - -In the example below, the internal table is populated by assigning an -internal table that is constructed inline with the `VALUE` -operator. The inline constructed table has two lines. `line` -represents an existing structure with a compatible line type. The -other line is constructed inline. - - -> **💡 Note**
-> The extra pair of parentheses represents a table line. The `#` character indicates that the line type can be derived from the context. The assignment deletes the existing content of the internal table on the left side. - -``` abap -itab = VALUE #( ( line ) -                ( comp1 = a comp2 = b ...  ) ). -``` - -**Creating an internal table by inline declaration** and adding lines with a constructor expression. -``` abap -"Internal table type -TYPES it_type LIKE itab. - -"Inline declaration -"The # character would not be possible here since the line type -"cannot be derived from the context. -DATA(it_in) = VALUE it_type( ( comp1 = a comp2 = b ... ) - ( comp1 = c comp2 = d ... ) ). -``` - -When you use the above assignments (`itab = ...`), the internal table is initialized and the existing content is deleted. To add new lines **without deleting existing content**, use the [`BASE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvalue_constructor_params_itab.htm) addition. - -``` abap -itab = VALUE #( BASE itab ( comp1 = a comp2 = b ... ) -                          ( comp1 = c comp2 = d ... ) ). -``` - -**Adding lines of other tables** using the `LINES OF` addition to the `VALUE` operator. -> **💡 Note**
-> Without the `BASE` addition, the existing content is deleted. It is assumed that the line type of the source table is compatible with that of the target table. -``` abap -itab = VALUE #( ( comp1 = a comp2 = b ...) -                ( comp1 = a comp2 = b ...) -                ( LINES OF itab2 ) -                ... ). -``` -A simple assignment without a constructor expression that **copies the content of another internal table** (note that the existing content in `itab` are deleted). The example below assumes that the source and target table have compatible line types. -``` abap -itab = itab2. -``` -> **💡 Note**
-> - Internal tables can only be assigned to internal tables. -> - Internal tables can be assigned to each other if their line types are [compatible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencompatible_glosry.htm) or [convertible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconvertible_glosry.htm). -> - An assignment can trigger an uncatchable exception if, for example, the target table is assigned a duplicate of a unique primary table key or secondary table. -> More information: [Conversion Rules for Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_itab.htm) - -**Copying the content of another internal table** using the -[`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator. -- Note that the existing content is deleted. -- As an alternative to the `CORRESPONDING` operator, you can use [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) statements. -- The example assumes that the line types of the source and target table are not compatible. However, if the line types are compatible, the syntax will also work. -- Several additions are possible. They can also be combined. Check the ABAP Keyword Documentation. - -``` abap -itab = CORRESPONDING #( itab3 ). - -MOVE-CORRESPONDING itab3 TO itab. -``` - -**Copying content and retaining existing content** using the `CORRESPONDING` operator. -The `KEEPING TARGET LINES` addition of the `MOVE-CORRESPONDING` statement preserves the table content. - -``` abap -itab = CORRESPONDING #( BASE ( itab ) itab3 ). - -MOVE-CORRESPONDING itab3 TO itab KEEPING TARGET LINES. -``` -**Assigning components using mapping relationships** -- You can use the `MAPPING` addition of the `CORRESPONDING` operator to specify components of a source table that are assigned to the components of a target table in mapping relationships. -- For elementary components, the assignment is made according to the associated assignment rules. - -``` abap -itab = CORRESPONDING #( itab3 MAPPING a = c b = d ). -``` - -**Excluding components from the assignment** using the `EXCEPT` addition to the `CORRESPONDING` operator. -- This is particularly useful if there are identically named components in the source and target tables that are not compatible or convertible. You can avoid syntax errors or runtime errors. -- Instead of a component list, `EXCEPT` can also be followed by `*` to exclude all components that are not mentioned in a previous mapping of components. -- If `EXCEPT *` is used without the `MAPPING` addition, all components remain initial. -``` abap -itab = CORRESPONDING #( itab3 EXCEPT e ). - -itab = CORRESPONDING #( itab3 EXCEPT * ). -``` - -**Preventing runtime errors when duplicate lines are assigned** to the target table that is defined to accept only unique keys using the `DISCARDING DUPLICATES` addition of the `CORRESPONDING` operator. -- In this case, the duplicate line is ignored in the source table. -- The addition can also be specified with `MAPPING ...`. - -``` abap -itab = CORRESPONDING #( itab2 DISCARDING DUPLICATES ). -``` - -**Copying data from deep internal tables**. -- The `BASE` addition does not delete the existing content. -- See also the alternative `MOVE-CORRESPONDING` statements. -``` abap -itab_nested2 = CORRESPONDING #( DEEP itab_nested1 ). - -itab_nested2 = CORRESPONDING #( DEEP BASE ( itab_nested2 ) itab_nested1 ) - -MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES. - -MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES KEEPING TARGET LINES. -``` - -

⬆️ back to top

- -### Excursions with Internal Tables -For more details on ABAP SQL, see the cheat sheet on [ABAP SQL](03_ABAP_SQL.md). - -**Adding multiple lines from a database table to an internal table** using -[`SELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm), -for example, based on a condition. In the case below, the internal table -is created inline. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2 ... - WHERE ... - INTO TABLE @DATA(itab_sel). -``` - -**Sequentially adding multiple rows** from a database table to an internal table using `SELECT ... ENDSELECT.`, for example, based on a condition. In this case, the selected data is first stored in a structure that can be further processed and added to an internal table. - -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2 ... - WHERE ... - INTO @DATA(struc_sel). - - IF sy-subrc = 0. - APPEND struc_sel TO itab. -  ... - ENDIF. -ENDSELECT. -``` - -Adding multiple lines from a database table using `SELECT`, for example, based on a condition when the database table has a line type that is incompatible with the internal table. The `*` character means that all fields are selected. The other examples define specific fields. -The `APPENDING CORRESPONDING FIELDS INTO TABLE` addition appends the selected data to the end of the table without deleting existing -table entries. The `INTO CORRESPONDING FIELDS OF TABLE` addition adds lines and deletes existing table entries. -``` abap -SELECT FROM dbtab2 - FIELDS * - WHERE ... - APPENDING CORRESPONDING FIELDS OF TABLE @itab. - -SELECT FROM dbtab2 - FIELDS * - WHERE ... - INTO CORRESPONDING FIELDS OF TABLE @itab. -``` -Adding multiple lines from an internal table to another internal table using `SELECT`. Note the alias name that must be defined for the -internal table. -``` abap -SELECT comp1, comp2, ... - FROM @itab2 AS it_alias - INTO TABLE @DATA(itab_sel). -``` - -**Combining data from multiple tables into one internal table** using an [inner -join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm "Glossary Entry"). -The following example joins data of an internal and a database table -using a `SELECT` statement and the [`INNER JOIN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) addition. Note that the field list includes fields from both tables. The fields are referred to using `~`. -``` abap -SELECT it_alias~comp1, it_alias~comp2, dbtab~comp3 ... - FROM @itab AS it_alias - INNER JOIN dbtab ON it_alias~comp1 = dbtab~comp1 - INTO TABLE @DATA(it_join_result). -``` - -Filling an internal table from a database table using -[subqueries](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). -The following two examples fill an internal table from a database table. In the first example, a subquery is specified in the -`WHERE` clause with the `NOT IN` addition. It checks whether a value matches a value in a set of values -specified in parentheses. The second example fills an internal table depending on data in another table. A subquery with the `EXISTS` addition is specified in -the `WHERE` clause. In this -case, the result of the subquery, which is another -`SELECT` statement, is checked to see if an entry exists in -a table based on the specified conditions. - -``` abap -SELECT comp1, comp2, ... - FROM dbtab - WHERE comp1 NOT IN ( a, b, c ... ) - INTO TABLE @DATA(it_subquery_result1). - -SELECT comp1, comp2, ... - FROM dbtab - WHERE EXISTS ( SELECT 'X' FROM @itab AS itab_alias - WHERE comp1 = dbtab~comp1 ) - INTO TABLE @DATA(it_subquery_result2). -``` - -Filling internal table from a table based on the existence of data in -another table using the [`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) addition. - -> **💡 Note**
-> Make sure that the internal table you are reading from is not initial. Therefore, it is recommended that you use a subquery as shown above: `... ( SELECT ... FROM @itab AS itab_alias WHERE ...`). - -``` abap -IF itab IS NOT INITIAL. - - SELECT dbtab~comp1, dbtab~comp2, ... - FROM dbtab - FOR ALL ENTRIES IN @itab - WHERE comp1 = @itab-comp1 - INTO TABLE @DATA(it_select_result). - -ENDIF. -``` - -**Using the `FILTER` operator** - -To create an internal table by copying data from another internal table and -filtering out lines that do not meet the `WHERE` condition, you can use the [`FILTER` -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_filter.htm). - -- The - `FILTER` operator constructs an internal table according to a specified type (which can be an explicitly specified, non-generic table type or the `#` character as a symbol for the [operand type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_type_glosry.htm) before the first parenthesis). -- The lines for the new internal table are taken from an - existing internal table based on conditions specified in a `WHERE` clause. Note that the table type of the existing internal table must be convertible into the specified target type. -- The conditions can be based on either single values or a [filter - table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_filter_table.htm). -- Additions: - -|Addition |Details | -|---|---| -|`USING KEY` | Specifies the [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm "Glossary Entry") used to evaluate the `WHERE` condition: either a [sorted key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm "Glossary Entry") or a [hash key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhash_key_glosry.htm "Glossary Entry"). If the internal table does not have either of these, it must have a [secondary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm "Glossary Entry"), which must be specified after `USING KEY`. | -| `EXCEPT` | Specifying `EXCEPT` means that those lines of the existing table are used that do not meet the condition specified in the `WHERE` clause. If `EXCEPT` is not specified, those lines of the existing table that meet the condition are used. | - -Examples: -```abap -"FILTER on conditions based on single values -"Assumption: The component num is of type i. -DATA itab1 TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY num. -DATA itab2 TYPE STANDARD TABLE OF struc WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS num. -DATA itab3 TYPE HASHED TABLE OF struc WITH UNIQUE KEY num. - -"The lines meeting the condition are respected. -"Note: The source table must have at least one sorted or hashed key. -"Here, the primary key is used -DATA(f1) = FILTER #( itab1 WHERE num >= 3 ). - -"USING KEY primary_key explicitly specified; same as above -DATA(f2) = FILTER #( itab1 USING KEY primary_key WHERE num >= 3 ). - -"EXCEPT addition -DATA(f3) = FILTER #( itab1 EXCEPT WHERE num >= 3 ). -DATA(f4) = FILTER #( itab1 EXCEPT USING KEY primary_key WHERE num >= 3 ). - -"Secondary table key specified after USING KEY -DATA(f5) = FILTER #( itab2 USING KEY sec_key WHERE num >= 4 ). -DATA(f6) = FILTER #( itab2 EXCEPT USING KEY sec_key WHERE num >= 3 ). - -"Note: In case of a hash key, exactly one comparison expression for each key component is allowed; -"only = as comparison operator possible. -DATA(f7) = FILTER #( itab3 WHERE num = 3 ). - -"Using a filter table -"In the WHERE condition, the columns of source and filter table are compared. -"Those lines in the source table are used for which at least one line in the filter -"table meets the condition. EXCEPT and USING KEY are also possible. - -DATA filter_tab1 TYPE SORTED TABLE OF i - WITH NON-UNIQUE KEY table_line. - -DATA filter_tab2 TYPE STANDARD TABLE OF i - WITH EMPTY KEY - WITH UNIQUE SORTED KEY line COMPONENTS table_line. - -DATA(f8) = FILTER #( itab1 IN filter_tab1 WHERE num = table_line ). - -"EXCEPT addition -DATA(f9) = FILTER #( itab1 EXCEPT IN filter_tab1 WHERE num = table_line ). - -"USING KEY is specified for the filter table -DATA(f10) = FILTER #( itab2 IN filter_tab2 USING KEY line WHERE num = table_line ). - -"USING KEY is specified for the source table, including EXCEPT -DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num = table_line ). -``` - -**Collecting values** - -Use the -[`COLLECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcollect.htm) -keyword, for example, to add the values of numeric components to the -corresponding values in an internal table. Use it mainly for internal -tables with a unique primary key, especially hashed tables. -``` abap -COLLECT VALUE dtype( comp1 = a comp2 = b ... ) INTO itab. -``` - -

⬆️ back to top

- -## Reading from Internal Tables - -There are three different ways to specify the line to read: - -- by index (only index tables) -- by table keys (only tables for which a key is defined) -- by free key - -The following code snippets include [`READ TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_table.htm) statements and [table expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expressions.htm) to read from internal tables. - -**Reading single lines** - -*Determining the target area* - -- Copying a line to a data object using the addition `INTO`. - After the copying, the line found exists separately in the internal table and - in the data object. If you change the - data object or the table line, the change does not affect the other. - However, you can modify the copied table line and use a - `MODIFY` statement to modify the table based on the modified - table line (see below). The `TRANSPORTING` addition - specifies which components to copy. If - it is not specified, all components are respected. - ``` abap - READ TABLE itab INTO dobj ... "dobj must have the table's structure type - - READ TABLE itab INTO DATA(dobj_inl) ... - - READ TABLE itab INTO ... TRANSPORTING comp1 [comp2 ... ]. - ``` - -- Assigning a line to a [field - symbol](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm "Glossary Entry"), - for example, using an inline declaration (`ASSIGNING `). When you then access the field symbol, it means that you access the found table line. There is no actual copying of - content. Therefore, modifying the field symbol means - modifying the table line directly. Note that you cannot use the - `TRANSPORTING` addition since the entire table is - assigned to the field symbol. - - ``` abap - READ TABLE itab ASSIGNING ... "The field symbol must have an appropriate type. - - READ TABLE itab ASSIGNING FIELD-SYMBOL() ... "The field symbol is created inline. - ``` - -- Reading a line into a [data reference - variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm "Glossary Entry") - using `REFERENCE INTO`. In this case, no copying takes place. If you want to address the line, you must first [dereference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm) the data reference. You cannot use the addition `TRANSPORTING`. - - ``` abap - READ TABLE itab REFERENCE INTO dref ... - - READ TABLE itab REFERENCE INTO DATA(dref_inl) ... - ``` - -**Which to use then?** Since all syntax options provide the same -functionality, your use case, the -performance or readability of the code may play a role. For more information, see -the programming guidelines for the [target -area (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_output_guidl.htm "Guideline"). -A use case for `INTO dobj` is when the table should -not be changed using the copied table line. However, copying comes -at a performance cost. Imagine that your table contains many columns or -nested components. In this case, it is better not to copy at all (although you can use -the `TRANSPORTING` addition to restrict the fields to be copied). - -

⬆️ back to top

- -*Reading a single line by index* - -The following example shows `READ TABLE` statements to read a single line from an internal table by specifying the index. You can use the addition `USING KEY` to specify a table key and thus explicitly determine the table index to use. If the table has a sorted secondary -key, the addition can be specified and the line to be read is then determined from its secondary table index. If the primary table key is -specified by its name `primary_key`, the table must be an index table, and the behavior is the same as if `USING KEY` was -not specified. -Note that the examples only show reading into a work area. Other targets are possible as shown above. -``` abap -READ TABLE itab INTO wa INDEX i. - -READ TABLE itab INTO wa INDEX i USING KEY primary_key. -``` - -Using a [table -expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expressions.htm), -the read result is stored in a variable that can be declared inline. -The number in the square brackets represents the index. A line that is -not found results in an runtime error. To avoid an error, you can -use a [`TRY ... CATCH ... ENDTRY.`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) block. - -``` abap -"In the examples, integer values are specified for the index. -DATA(lv1) = itab[ 1 ]. - -TRY. - DATA(lv2) = itab[ 2 ]. - CATCH cx_sy_itab_line_not_found. - ... -ENDTRY. - -DATA(lv3) = itab[ KEY primary_key INDEX 3 ]. - -"Copying a table line via table expression and embedding in constructor expression -DATA(lv4) = VALUE #( itab[ 4 ] ). - -"Reading into data reference variable using the REF operator -DATA(lv5_ref) = REF #( itab[ 5 ] ). -``` - -When you read a non-existent line using a table expression, you may not want to throw an exception. You can also embed the table expression -in a constructor expression using the `OPTIONAL` addition. This way, an unsuccessful read will not trigger the -exception. The result returned is a line with initial values. -Alternatively, you can use the `DEFAULT` addition to return a -default line in case of an unsuccessful read operation, which can also be another table expression or constructor expression. - -``` abap -DATA(line1) = VALUE #( itab[ 6 ] OPTIONAL ). - -DATA(line2) = VALUE #( itab[ 7 ] DEFAULT itab[ 8 ] ). -``` - -

⬆️ back to top

- -*Reading single lines using table keys* - -Lines can be read by explicitly specifying the table keys or the alias names, if any. -```abap -"Example internal table with primary and secondary table key and alias names -"Assumption: All components are of type i - -DATA it TYPE SORTED TABLE OF struc - WITH NON-UNIQUE KEY primary_key ALIAS pk COMPONENTS a b - WITH NON-UNIQUE SORTED KEY sec_key ALIAS sk COMPONENTS c d. - -"Table expressions - -"Key must be fully specified -line = it[ KEY primary_key COMPONENTS a = 1 b = 2 ]. - -"The addition COMPONENTS is optional; same as above -line = it[ KEY primary_key a = 1 b = 2 ]. - -"Primary key alias -line = it[ KEY pk a = 1 b = 2 ]. - -"Secondary table key -line = it[ KEY sec_key c = 3 d = 4 ]. - -"Secondary table key alias -line = it[ KEY sk c = 3 d = 4 ]. - -"READ TABLE statements -"Primary table key -READ TABLE it INTO wa WITH TABLE KEY primary_key COMPONENTS a = 1 b = 2. - -"Alias -READ TABLE it INTO wa WITH TABLE KEY pk COMPONENTS a = 1 b = 2. - -"Secondary table key -READ TABLE it INTO wa WITH TABLE KEY sec_key COMPONENTS c = 3 d = 4. - -"Alias -READ TABLE it INTO wa WITH TABLE KEY sk COMPONENTS c = 3 d = 4. - -"Reading a line based on keys specified in a work area -"Work area containing primary and secondary table key values; the line type -"must be compatible to the internal table -DATA(pr_keys) = VALUE struc( a = 1 b = 2 ). - -DATA(sec_keys) = VALUE struc( c = 3 d = 4 ). - -READ TABLE it FROM pr_keys INTO wa. - -"If USING KEY is not specified, the primary table key is used. -"If it is used, the specified table key is used. -READ TABLE it FROM pr_keys USING KEY primary_key INTO wa. - -READ TABLE it FROM sec_keys USING KEY sec_key INTO wa. - -"Alias -READ TABLE it FROM sec_keys USING KEY sk INTO wa. -``` - -

⬆️ back to top

- -**Reading a single line using a free key** - -The specified components used as keys need not be part of a table key. -``` abap -line = it[ b = 2 ]. - -READ TABLE it INTO wa WITH KEY b = 2. -``` - -*Addressing individual components* - -When reading single lines in general, you can also address individual -components of the line using the [component -selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_selector_glosry.htm "Glossary Entry") -`-` (or the [dereferencing -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm "Glossary Entry") -`->*` in the case of data reference variables). -``` abap -DATA(comp1) = it[ b = 2 ]-c. - -READ TABLE it INTO DATA(wa) WITH KEY b = 2. -DATA(comp2) = wa-c. - -READ TABLE it ASSIGNING FIELD-SYMBOL() WITH KEY b = 2. -DATA(comp3) = -c. - -READ TABLE it REFERENCE INTO DATA(dref) WITH KEY b = 2. -DATA(comp4) = dref->c. -"Note: The syntax dref->*-c is also possible. -``` - -

⬆️ back to top

- -**Checking the existence and the index of a line in an internal table** - -This is relevant if you are not interested in the content of a table -line, but only want to find out whether a line exists that matches to the -index or key specifications. To do this, use a [`READ TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_table.htm) -statement with the `TRANSPORTING NO FIELDS` addition. The -addition indicates that no actual content is to be read. If the search was -successful and an entry exists, the system field `sy-subrc` is -set to 0. - -A newer way to check the existence of a line is the [predicate -function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_function_glosry.htm "Glossary Entry") -[`line_exists( )`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenline_exists_function.htm). -This function expects a [table -expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expression_glosry.htm "Glossary Entry") as an argument. -See below for more on table expressions. Note that table expressions do not set system fields. -``` abap -"Read using the key -READ TABLE it WITH KEY b = 2 TRANSPORTING NO FIELDS. - -IF sy-subrc = 0. - ... -ENDIF. - -"Read using the index -READ TABLE it INDEX 1 TRANSPORTING NO FIELDS. - -IF sy-subrc = 0. - ... -ENDIF. - -"Read using the key -IF line_exists( it[ b = 2 ] ). - ... -ENDIF. - -"Read using the index -IF line_exists( it[ 1 ] ). - ... -ENDIF. -``` - -If you want to find out about the index of a line in an internal table, you can also make use of the `READ TABLE` statement above. If -the line is found, the system field `sy-tabix` is set to the number of the index. Otherwise, the built-in function -[`line_index( )`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenline_index_function.htm) can be used. It returns the index of the found line or 0 if the line does not exist. - -``` abap -DATA(idx) = line_index( it[ b = 2 ] ). -``` - -`lines( )` is another built-in function that you can use to check how many lines exist in an internal table. It returns an integer value. - -``` abap -DATA(number_of_lines) = lines( it ). -``` - -

⬆️ back to top

- -## Processing Multiple Internal Table Lines Sequentially - -If you are interested not only in single table lines, but in the entire -table content or in specific parts of it, you can use [`LOOP -AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab.htm) -statements to process table lines sequentially. As above, you -can use multiple options for target areas: work area, field -symbol, data reference. There are multiple additions to the `LOOP AT` -statements to further restrict the table content to be processed. - -Simple form: -``` abap -"The target is an existing work area. -DATA wa LIKE LINE OF it. - -LOOP AT it INTO wa. - "No addition of the loop statement; all lines are processed - "Statements in this block are relevant for each individual table line. - ... -ENDLOOP. - -"Work area declared inline -LOOP AT itab INTO DATA(wa_inl). - ... -ENDLOOP. - -"Field symbols -FIELD-SYMBOLS LIKE LINE OF it. - -LOOP AT it ASSIGNING . - ... -ENDLOOP. - -LOOP AT it ASSIGNING FIELD-SYMBOL(). - ... -ENDLOOP. - -"Data reference variables -DATA dref TYPE REF TO dbtab. - -LOOP AT it REFERENCE INTO dref. - ... -ENDLOOP. - -LOOP AT it REFERENCE INTO DATA(dref_inl). - ... -ENDLOOP. -``` - -- The order in which tables are iterated depends on the table category. - - Note the [`STEP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_cond.htm#!ABAP_ADDITION_3@3@) addition, which is also available for other ABAP statements. -- Index tables are looped over in ascending order by the index. -- Hashed tables are looped in the order in which the lines were added to the table. You can also sort the table before the loop. -- During the loop, the system field `sy-tabix` is set to the number of the currently processed table -line. This is not true for hashed tables. There, `sy-tabix` is `0`. -- Note that if you want to work with the value of `sy-tabix`, you -should do so immediately after the `LOOP` statement to avoid possible overwriting in statements contained in the loop block. - -*Restricting the area of the table to be looped over* - -The additions of `LOOP` statements come into play when you want to restrict the table content to be respected by the loop because -you do not want to loop over the entire table. Note that the examples only show work areas as target objects to hold the table line read. -Other options are possible as shown above. - -``` abap -"FROM/TO: Only for index tables - -"Specifying an index range -LOOP AT it INTO wa FROM 2 TO 5. - ... -ENDLOOP. - -"From specified line until the end -LOOP AT it INTO wa FROM 2. - ... -ENDLOOP. - -"From first line until the specified line -LOOP AT it INTO wa TO 5. - ... -ENDLOOP. - -"WHERE clause: Restricting lines based on logical expression - -LOOP AT it INTO wa WHERE a > 1 AND b < 4. - ... -ENDLOOP. - -"No interest in the table content; only relevant system fields are filled - -"Mandatory WHERE clause -LOOP AT it TRANSPORTING NO FIELDS WHERE a < 5. - ... -ENDLOOP. - -"Table key specification (snippet uses example table from above) -"The specified table key affects the order in which the table lines -"are accessed and the evaluation of the other conditions. - -LOOP AT it INTO wa USING KEY primary_key. -"LOOP AT it INTO wa USING KEY pk. "primary key alias -"LOOP AT it INTO wa USING KEY sec_key. "secondary key -"LOOP AT it INTO wa USING KEY sk. "secondary key alias - ... -ENDLOOP. - -"STEP addition for defining the step size and the direction of the loop -"- Step size: Specified by the absolute value of an integer -"- Direction: Specified by a positive (forward loop) or negative -" (loop in reverse order) integer - -"Reversing the loop order using a negative integer -"Each line is read indicated by the absolute value 1 -LOOP AT it INTO wa STEP -1. - ... -ENDLOOP. - -"Forward loop by specifiying a positive integer -"In the example, every second line is read. -"Note: Omitting STEP means STEP 1 by default. -LOOP AT it INTO wa STEP 2. - ... -ENDLOOP. - -"STEP with other additions -"The example uses the additions FROM and TO. -"Note: If the value after STEP is negative, the value -"after FROM must be greater than the value after TO. -LOOP AT it INTO wa FROM 6 TO 3 STEP -2. - ... -ENDLOOP. -``` - -### Iteration Expressions - -Iteration expressions with [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm) as part of certain constructor expressions allow you to create content of an internal table by evaluating one or more source tables. - -The expressions are covered in the cheat sheet [Constructor Expressions](05_Constructor_Expressions.md): -- [Iteration Expressions Using FOR](05_Constructor_Expressions.md#iteration-expressions-using-for) -- Special reduction operator `REDUCE` that is based on iteration expressions: [REDUCE](05_Constructor_Expressions.md#reduce) - -

⬆️ back to top

- -## Sorting Internal Tables - -- Sorted tables are stored in the memory in an automatically sorted - order, hence, they cannot be sorted explicitly with - [`SORT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsort_itab.htm). -- For standard and hashed tables, the order can be changed. -- When using `SORT` statements, the sort order is derived either - by the primary table key (Note: Secondary keys - cannot be used for the sorting.) or by explicitly specifying the - fields to be sorted by. -- Explicit specification is the recommended way because it is - easier to understand and can prevent unwanted sorting results, - especially with tables with standard key. - -*Sorting by primary table key* -``` abap -"Implicit sorting by primary table key and in ascending order by default -SORT itab. - -"Optional additions to determine the sort order -"As mentioned above, ASCENDING is used implicitly. Here, specifying it explicitly. -SORT itab ASCENDING. -SORT itab DESCENDING. -``` - -The effect of sorting can have an unexpected result if you use the simple form of the statement and do not explicitly specify the keys. If an internal table has a structured line type and (perhaps inadvertently) the standard key as the primary table key, that is, all character-like and byte-like components make up the primary table key, all these components are taken into account when the table is sorted. -``` abap -"Is basically the same as it2 -DATA it1 TYPE TABLE OF zdemo_abap_fli. - -DATA it2 TYPE STANDARD TABLE OF zdemo_abap_fli WITH DEFAULT KEY. - -"Respecting the standard key when sorting -SORT it1. -``` -Plus: Suppose there are only elementary numeric components in an internal table with a structured line type. In this case, sorting has no effect because the primary table key is considered empty. This is certainly also true for tables declared with `EMPTY KEY`. - -*Sorting by explicitly specifying components* - -You can sort by any component of the internal table. It is also possible to specify the sort order -(even component-wise). Explicitly specifying the components has the advantage that your code is easier to understand and you can avoid unexpected results if you accidentally use `SORT` without the `BY` addition on empty and standard table keys. - -``` abap -DATA it3 TYPE TABLE OF struc WITH NON-UNIQUE KEY a. - -"Sorting by primary table key a -SORT itab. - -"Specifying the component to sort for; here, it is the same as the key; -"this way, the sorting is easier to understand -SORT itab BY a. - -"Syntax showing multiple component sorting with component-wise sort order -SORT itab BY a b ASCENDING c DESCENDING. - -"Sorting respecting the entire line (e. g. in the context of tables with -"empty or standard keys) -SORT itab BY table_line. -``` - -

⬆️ back to top

- -## Modifying Internal Table Content - -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. 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. - -The following examples demonstrate direct modification of recently read table lines: -``` abap -"Table declarations - -DATA it_st TYPE TABLE OF struc WITH NON-UNIQUE KEY a. - -DATA it_so TYPE SORTED TABLE OF struc WITH UNIQUE KEY a. - -"Reading table line into target area - -READ TABLE it_st ASSIGNING FIELD-SYMBOL() INDEX 1. - -READ TABLE it_so REFERENCE INTO DATA(dref) INDEX 2. - -"Modification examples -"Modifying the entire table line while keeping the values of other components; -"this way is not possible for it_so because of key value change. - - = VALUE #( BASE a = 1 b = 2 ). - -"Modifying a single component via field symbol - --c = 3. - -"Modification via dereferencing - -ref->b = 4. - -"Table expressions - -it_st[ 1 ] = VALUE #( a = 1 b = 2 ). - -it_st[ 2 ]-c = 3. - -"Sorted table: no key field change - -it_so[ 2 ]-d = 4. -``` - -> **💡 Note**
-> If you want to modify recently read lines in a work area, for example, within a loop (`LOOP AT INTO dobj`), you can modify the line and then use a `MODIFY` statement to modify the internal table based on this line. - -[`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. - -``` abap -"Addition FROM ...; specified key values determine the line to be modified - -"line: existing line including key values -MODIFY TABLE it FROM line. - -"line constructed inline -MODIFY TABLE it FROM VALUE #( a = 1 b = 2 ... ). - -"Respecting only specified fields with the addition TRANSPORTING -"In case of sorted/hashed tables, key values cannot be specified. -MODIFY TABLE it FROM line TRANSPORTING b c. - -"Modification via index -"Note that it is only MODIFY, not MODIFY TABLE. -"Example: It modifies the line with number 1 in the primary table index. -MODIFY it FROM line INDEX 1. - -"Without the addition TRANSPORTING, the entire line is changed. -"Example: It modifies specific values. -MODIFY it FROM line INDEX 1 TRANSPORTING b c. - -"USING KEY addition -"If the addition is not specified, the primary table key is used; -"otherwise, it is the explicitly specified table key that is used. -"Example: It is the same as MODIFY it FROM line INDEX 1. -MODIFY it FROM line USING KEY primary_key INDEX 1. - -"The statement below uses a secondary key and an index specification -"for the secondary table index. Only specific fields are modified. -MODIFY it FROM line USING KEY sec_key INDEX 1 TRANSPORTING c d. - -"Modifying multiple lines in internal tables -"All lines matching the logical expression in the WHERE clause are modified -"as specified in line. -"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. - -

⬆️ back to top

- -## Deleting Internal Table Content - -You can use [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdelete_itab.htm) statements to delete single and multiple lines in internal tables. The following additions can be used: `USING KEY` (for specifying a table key), `FROM`/`TO` (for specifying row ranges), `STEP` (for specifying the step size), and `WHERE` (for specifying conditions). - -``` abap -"Deleting via index -"Example: The first line in the table is deleted. -DELETE it INDEX 1. - -"If USING KEY is not used, INDEX can only be used with index tables. -"If doing so, it determines the line from the primary table index. -"If a secondary key is specified, the secondary table index is respected -"Example: same as above -DELETE it INDEX 1 USING KEY primary_key. - -"Deleting an index range; FROM or TO alone can also be specified -DELETE it FROM 2 TO 5. - -"Deleting via keys -"The line must have a compatible type to the tables line type and -"include key values. The first found line with the corresponding keys -"is deleted. -"If the key is empty, no line is deleted. -DELETE TABLE it FROM line. - -"Instead of specifying the keys using a data object ("line" above), -"the keys can be specified separately. All key values must be specified. -"Example: Respects keys from primary table index. -DELETE TABLE it WITH TABLE KEY a = 1. - -"You can also specify secondary keys. -"Example: Same as above -DELETE TABLE it WITH TABLE KEY primary_key COMPONENTS a = 1. - -DELETE TABLE it_sec WITH TABLE KEY sec_key COMPONENTS ... - -"Deleting multiple lines based on a WHERE condition -"Specifying the additions USING KEY, FROM, TO is also possible. -DELETE it WHERE a < 6. - -"Excursion: Deleting in a LIKE-like fashion you may know from -"ABAP SQL statements. -"The LIKE addition is not available for the WHERE clause in DELETE -"statements for internal tables as is the case for ABAP SQL DELETE statements. -DATA(str_table) = VALUE string_table( ( `abcZ` ) ( `Zdef` ) ( `gZhi` ) - ( `Zjkl` ) ( `Zmno` ) ( `pqrZ` ) ). - -"You can, for example, use logical operators such as CP (conforms to pattern) -"All lines that begin with Z are to be deleted. -DELETE str_table WHERE table_line CP `Z*`. -"Result: abcZ / gZhi / pqrZ -``` - -`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. - -"Deletion respecting the values of the entire line -DELETE ADJACENT DUPLICATES FROM it COMPARING ALL FIELDS. - -"Only lines are deleted with matching content in specific fields -DELETE ADJACENT DUPLICATES FROM it COMPARING a c. - -"Deletion respecting a specified table key -"Same as first example above -DELETE ADJACENT DUPLICATES FROM it USING KEY primary_key. - -DELETE ADJACENT DUPLICATES FROM it USING KEY sec_key. -``` - -> **💡 Note**
-> The system field `sy-subrc` is set to `0` if at least one line has been deleted. It is set to `4` if no lines were deleted. - -The -[`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) -and -[`FREE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfree_dataobject.htm) -statements allow you to delete the entire table content. - -The difference between the two is in the handling of the memory space originally allocated to the table. When a table is cleared with `CLEAR`, -the content is removed, but the memory space initially requested remains -allocated. If the table is filled again later, the memory space is still -available, which is a performance advantage over -clearing an internal table with `FREE`. Such a statement also -deletes the table content, but it also releases the memory -space. -Note that an assignment using the `VALUE` operator without entries in the parentheses clears the internal table. - -``` abap -CLEAR it. - -"This statement additionally releases memory space. -FREE it. - -"Assignment using the VALUE operator without entries in the parentheses -it = VALUE #( ). -``` -

⬆️ back to top

- -## Excursions - -### Improving Read Performance with Secondary Table Keys - -The following example creates two demo internal tables. One without a secondary -table key and the other with a secondary table key. Consider a scenario where you -have an internal table without a secondary table key, and you want to add a secondary table key later to improve read performance. The tables are populated with a lot of data. Then, in a DO loop, many reads are performed on the internal tables. One example uses a free key for the read, the other uses a secondary table key. Before and after the reads, the current timestamp is stored in variables, from which the elapsed time is calculated. There should be a significant delta of the elapsed time. - -```abap -CLASS zcl_some_class DEFINITION PUBLIC FINAL CREATE PUBLIC. - PUBLIC SECTION. - INTERFACES if_oo_adt_classrun. - PROTECTED SECTION. - PRIVATE SECTION. -ENDCLASS. -CLASS zcl_some_class IMPLEMENTATION. - METHOD if_oo_adt_classrun~main. - TYPES: BEGIN OF demo_struc, - idx TYPE i, - str TYPE string, - num TYPE i, - END OF demo_struc. - - DATA itab TYPE HASHED TABLE OF demo_struc WITH UNIQUE KEY idx. - DATA itab_sec TYPE HASHED TABLE OF demo_struc - WITH UNIQUE KEY idx - WITH NON-UNIQUE SORTED KEY sk - COMPONENTS str num. - - DO 500 TIMES. - INSERT VALUE #( idx = sy-index - str = |INDEX{ sy-index }| - num = sy-index ) INTO TABLE itab. - ENDDO. - itab_sec = itab. - - DATA(ts1) = utclong_current( ). - DO 500 TIMES. - "Reading into a data reference variable using using a free key. - "This key corresponds to the secondary table key specified for - "the table in the second example. - DATA(dref) = REF #( itab[ str = `INDEX250` num = 250 ] ). - ENDDO. - DATA(ts2) = utclong_current( ). - - cl_abap_utclong=>diff( EXPORTING high = ts2 - low = ts1 - IMPORTING seconds = DATA(seconds) ). - - out->write( `Elapsed time for the reads using a free key:` ). - out->write( seconds ). - out->write( `----------------------------------------------------------` ). - - ts1 = utclong_current( ). - DO 500 TIMES. - "Reading from an internal table using the secondary table key - dref = REF #( itab_sec[ KEY sk str = `INDEX250` num = 250 ] ). - ENDDO. - ts2 = utclong_current( ). - - cl_abap_utclong=>diff( EXPORTING high = ts2 - low = ts1 - IMPORTING seconds = seconds ). - out->write( `Elapsed time for the reads using a secondary table key:` ). - out->write( seconds ). - ENDMETHOD. -ENDCLASS. -``` - -

⬆️ back to top

- -### Searching and Replacing Substrings in Internal Tables with Character-Like Data Types - -You can use [`FIND ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_itab.htm) statements to search for substrings in internal tables (standard tables without secondary table keys; with character-like line type) line by line. - -``` abap -DATA(str_table) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). - -"Finding all occurrences in a table -"Note: res_tab is of type match_result_tab -"You can also restrict the search range in an internal table; see an example in REPLACE ... IN TABLE -FIND ALL OCCURRENCES OF `Z` - IN TABLE str_table - RESULTS DATA(res_tab) - RESPECTING CASE. - -"4 entries in table res_tab (tables in SUBMATCHES are initial since no regular expression is used) -"1. line: 1, offset: 1, length: 1, submatches: (initial) -"2. line: 1, offset: 4, length: 1, ... -"3. line: 2, offset: 2, length: 1, ... -"4. line: 3, offset: 0, length: 1, ... - -"Finding the first occurrence in a table -"Note: res_struc, which is declared inline here, is of type match_result -FIND FIRST OCCURRENCE OF `Z` - IN TABLE str_table - RESULTS DATA(res_struc) - RESPECTING CASE. - -"Entries in structure res_struc -"line: 1, offset: 1, length: 1, submatches: (initial) - -"Alternative to the statement above (storing the information in individual data objects) -FIND FIRST OCCURRENCE OF `Z` - IN TABLE str_table - MATCH LINE DATA(line) "1 - MATCH OFFSET DATA(off) "1 - MATCH LENGTH DATA(len) "1 - RESPECTING CASE. -``` - -Replacements in internal tables with [`REPLACE ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace_itab.htm): - -``` abap -DATA(str_table_original) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). -DATA(str_table) = str_table_original. - -"Replacing all occurrences in a table -"RESULTS addition: Storing information in an internal table of type repl_result_tab -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - WITH `#` - RESULTS DATA(res_table) - RESPECTING CASE. - -"str_table: a#bz# / cd#ze / #zzf / ghz -"res_table: -"LINE OFFSET LENGTH -"1 1 1 -"1 4 1 -"2 2 1 -"3 0 1 - -str_table = str_table_original. - -"Replacing the first occurrence in a table -"RESULTS addition: Storing information in a structure of type repl_result -REPLACE FIRST OCCURRENCE OF `Z` - IN TABLE str_table - WITH `#` - RESULTS DATA(res_structure) - RESPECTING CASE. - -"str_table: a#bzZ / cdZze / Zzzf / ghz -"res_structure: -"LINE OFFSET LENGTH -"1 1 1 - -str_table = str_table_original. - -"Restricting the search range in an internal table -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - FROM 1 TO 2 - WITH `#` - RESPECTING CASE. - -"str_table: a#bz# / cd#ze / Zzzf / ghz - -str_table = str_table_original. - -"Offsets can be optionally specified (also only the offset of start or end line possible) -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - FROM 1 OFFSET 3 TO 2 OFFSET 2 - WITH `#` - RESPECTING CASE. - -"str_table: aZbz# / cdZze / Zzzf / ghz -``` - -

⬆️ back to top

- -### Ranges Tables - -- Internal tables that have the predefined columns `SIGN`, `OPTION`, `LOW`, and `HIGH` -- Declared with the `TYPE RANGE OF` addition in `DATA` and `TYPES` statements -- Used to store range conditions that can be evaluated in expressions using the `IN` operator (each row in the table represents a separate comparison) - -```abap -"Populating an integer table with values from 1 to 20 -TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY. -DATA(inttab) = VALUE int_tab_type( FOR x = 1 WHILE x <= 20 ( x ) ). - -"Declaring a ranges table -DATA rangestab TYPE RANGE OF i. - -"Populating a ranges table using VALUE -rangestab = VALUE #( sign = 'I' - option = 'BT' ( low = 1 high = 3 ) - ( low = 6 high = 8 ) - ( low = 12 high = 15 ) - option = 'GE' ( low = 18 ) ). - -"Using a SELECT statement and the IN addition to retrieve internal table -"content based on the ranges table specifications -SELECT * FROM @inttab AS tab - WHERE table_line IN @rangestab - INTO TABLE @DATA(result). -"result: 1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 18, 19, 20 -``` - -

⬆️ 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. - -## Executable Example -[zcl_demo_abap_internal_tables](./src/zcl_demo_abap_internal_tables.clas.abap) - -> **💡 Note**
-> - The executable example covers the following topics, among others: Creating, populating, reading from, sorting, modifying internal tables -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). + + +# Internal Tables + +- [Internal Tables](#internal-tables) + - [Introduction](#introduction) + - [Basic Properties of Internal Tables](#basic-properties-of-internal-tables) + - [Table Keys in Internal Tables (Primary, Secondary, Standard, Empty)](#table-keys-in-internal-tables-primary-secondary-standard-empty) + - [Creating Internal Tables and Types](#creating-internal-tables-and-types) + - [Filling and Copying Internal Tables](#filling-and-copying-internal-tables) + - [Excursions with Internal Tables](#excursions-with-internal-tables) + - [Reading from Internal Tables](#reading-from-internal-tables) + - [Processing Multiple Internal Table Lines Sequentially](#processing-multiple-internal-table-lines-sequentially) + - [Iteration Expressions](#iteration-expressions) + - [Sorting Internal Tables](#sorting-internal-tables) + - [Modifying Internal Table Content](#modifying-internal-table-content) + - [Deleting Internal Table Content](#deleting-internal-table-content) + - [Excursions](#excursions) + - [Improving Read Performance with Secondary Table Keys](#improving-read-performance-with-secondary-table-keys) + - [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) + - [More Information](#more-information) + - [Executable Example](#executable-example) + + +## Introduction + +Internal Tables ... + +- are [dynamic data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_data_object_glosry.htm), i.e. all properties apart from the memory consumption are determined statically by the [data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm). +- consist of a variable sequence of lines of the same data type. +- have a [table type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm) as its data type (it is a [complex data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm)), which defines the following properties: + - [line type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrow_type_glosry.htm) + - [table category](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_category_glosry.htm) + - [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm) +- are used when a variable data set of a random data type needs to be processed in a structured way. +- allow access to individual table lines via a [table index](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_index_glosry.htm) or a [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm). + +

⬆️ back to top

+ +## Basic Properties of Internal Tables + +
+ Expand to view the details + + +**Line Type** + +- Defines how each line of the internal table is set up, i. e. it describes what columns the table has. +- It can be any ABAP data type, e.g. an [elementary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm) or complex data type as well as a [reference type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm). +- In most cases, the line type is [structured](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm). In this case, the individual components of a line are also referred to as the columns of the internal table. +- In a simple case, the line consists of a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm) with elementary data objects; however, it can also be a [deep structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm) whose components can be structures themselves or even internal tables. + +**Table Category** + +- Defines how internal tables are managed and stored internally, and how to access individual table entries. +- Why is it relevant? The use of a suitable table category should meet your requirements, i.e. if the internal tables are large, the different categories can have significant performance differences when accessing table content. +- Note: There are two ways to access internal tables: + - Access by table index: A line of an internal table is accessed by its line number. This kind of access is the fastest way to access table lines. + - Access by table key: A line of an internal table is accessed by searching for specific values in specific columns. Note: The columns in which you search can be key columns, but they can also be non-key columns. + + +| Category | Internally managed by | Access | Primary table key | When to use | Hints | +|---|---|---|---|---|---| +|`STANDARD`|Primary table index (that's why these tables are called [index tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenindex_table_glosry.htm))|
  • Table index
  • Table key
|
  • Always non-unique, i.e. duplicate entries are always allowed
  • Definition of an empty key is possible if the key is not relevant(`WITH EMPTY KEY`)
|
  • If you primarily access the table content for sequential processing or via the table index.
  • Response time for accessing the table using the primary key: This kind of table access is optimized only for sorted and hashed tables. For standard tables, primary key access uses a linear search across all lines. That means that large standard tables (more than 100 lines) are not ideal if the you primarily access the table using the table key.
|
  • There is no particular sort order, but the tables can be sorted using `SORT`.
  • Filling this kind of table: Lines are either appended at the end of the table or inserted at a specific position.
  • [Secondary table keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm) can be defined to make key access to standard tables more efficient.
  • Standard and sorted tables have the least [administration costs (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenadmin_costs_dyn_mem_obj_guidl.htm).
| +|`SORTED`|Primary table index (that's why these tables are called [index tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenindex_table_glosry.htm))|
  • Table index
  • Table key
|
  • Non-unique
  • Unique

  • ... used to sort the table in ascending order.
|
  • Enables an optimized access to table content using table key and index.
  • If access via table key is the main access method, but no unique key can be defined.
|
  • Sorting is done automatically when lines are inserted or deleted. As a consequence, the table index must usually be reorganized.
  • The response time for accessing the table using the primary key depends logarithmically on the number of table entries, since a binary search is used.
  • Standard and sorted tables have the least administration costs.
| +|`HASHED`|Hash algorithm |
  • Table key
  • [Secondary table index](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_index_glosry.htm)
|Always unique|
  • For large internal tables.
  • Optimized for key access. Access to table content via table key is the main access method and a unique key can be defined.
|
  • The response time for primary key access is constant and independent of the number of entries in the table.
  • Hashed tables have the highest administration costs.
| + + + +**Key Attributes** + +- There are two types of table keys: a [primary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_table_key_glosry.htm) and [secondary table keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm). +- Table keys ... + - are intended to provide an optimized access to the content of internal tables. + - are either unique or non-unique, i.e. more than one line with the same key (duplicates) can exist in the internal table or not. Regarding the primary table key, the definition depends on the table category. For the secondary table key, the definition depends on the key type. For standard tables, the primary table key can also be defined as empty, i.e. it does not contain any key columns. Note that for standard tables, an optimized access is only possible with secondary table keys. + - Type of keys: + - Sorted keys: + - Are either the primary table keys of sorted tables or the secondary table keys of any table. + - Are managed internally by a table index. In the case of sorted tables, this is the primary table index. In the case of secondary table keys, a secondary table index is added. + - Access via sorted keys means an optimized binary search. + - Hashed keys: + - Are either the primary table key of hashed tables or secondary table keys of any table. + - Internally managed by a hash algorithm. + - There is no table index for a hashed key. + +**Further information** +- [Internal Tables - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenitab_oview.htm) +- [Programming guidelines: Internal Tables (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenadmin_costs_dyn_mem_obj_guidl.htm) +
+ +

⬆️ back to top

+ +## Table Keys in Internal Tables (Primary, Secondary, Standard, Empty) + +
+ Expand to view the details + + +**Primary table key** + +- Each internal table has a primary table key. +- Can be either a self-defined key or the [standard key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_key_glosry.htm). +- The primary table key is ... + - sorted for sorted tables. + - hashed for hashed tables. +- Note that the key fields in sorted and hashed tables are read-only. This is not valid for standard tables. +- The specification of the primary key can be omitted only for standard tables. The primary table key is then automatically defined as a non-unique standard key. +- The primary table key has the predefined name `primary_key`, by which it can also be addressed explicitly. However, its use is optional, and it is usually not necessary to specify it explicitly. You can also specify an alias name for the primary key. +- When accessing internal tables using the table key, the primary key is always used implicitly in processing statements if no secondary key is specified. Note that the primary table key must be specified in table expressions if the primary key is to be used explicitly. + +> **💡 Note**
+> The key can consist of individual key fields or the entire line of the internal table. In this case, the pseudo component `table_line` can be used to denote the primary table key. For non-structured line types, this is the only way to define the key. + +**Standard key** +- The [standard key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_key_glosry.htm) is a special primary table key. +- It can be declared either explicitly or implicitly. +- Standard key of an internal table with a ... + - structured line type: The primary table key consists of all fields with character-like and byte-like data types. + - non-structured/elementary line type: The entire table is the key (`table_line`). +- An internal table with no explicit key specification implicitly has the standard table key as the primary table key. +- Why respecting standard keys is important: + - Sorting of a table can produce unexpected results. + - Since the standard key can consist of many fields, it affects the performance when accessing the internal table via the keys. + - The key fields of the primary table key of sorted and hashed tables are always read-only, i.e. using the standard key with these table categories and then (unintentionally) modifying fields can cause unexpected runtime errors. + - Specifying keys explicitly has the advantage of making the code more readable and preventing the standard key from being set by mistake. + +**Empty key** +- The primary table key of a standard table can be empty, i.e. it does not contain any key fields. +- An empty key is not possible for sorted and hashed tables. +- When used: + - When the definition of a table key is not important. + - To explicitly state that a table key is not required, instead of specifying no key definition. Otherwise, the standard key is used, which can lead to unexpected results as mentioned above. +- Declaration: + - Explicit declaration using the addition `EMPTY KEY`. + - Implicit declaration when using the standard key if a structured + line type does not contain non-numeric elementary components or + if an unstructured line type is tabular. + - Note: When using an [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry") such as `... INTO TABLE @DATA(itab) ...` in `SELECT` statements, the resulting table is a standard table and has an empty key. + +**Secondary table keys** + +- Secondary table keys ... + - are optional for all table categories. + - can be unique/non-unique sorted keys or unique hash keys. + - have a self-defined name. An alias name can also be specified. +- A secondary table index is created internally for each sorted secondary key. This allows index access to hashed tables via the secondary table key. In this case, `sy-tabix` is set. +- When accessing internal tables using the secondary table key, the key name (or the alias if specified) must be specified. They are not selected automatically. If no secondary key is specified in a processing statement, the primary key or primary table index is always used. If you want to make use of this key in ABAP statements, for example, `READ`, `LOOP AT` or `MODIFY` statements, you must specify the key explicitly using the appropriate additions, for example, `WITH ... KEY ... COMPONENTS` or `USING KEY`. +- Use cases: + - To improve read performance. + - For very large internal tables (that are filled once and changed very often) + - Standard tables, whose primary table keys cannot be unique, can be provided with a means of ensuring that unique table entries are read. + - Note that defining secondary table keys involves additional administration costs (additional memory consumption). Therefore, the use of secondary table keys should be reserved for cases where the benefits outweigh the extra costs. +- For more details, see the programming guidelines for secondary keys: [Secondary + Key (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_key_guidl.htm "Guideline"). + +> **💡 Note**
+> - See examples of internal table declarations using the table keys mentioned above in the following section. +> - See an example that uses secondary table keys [below](#improving-read-performance-with-secondary-table-keys). + +
+ +

⬆️ back to top

+ + +## Creating Internal Tables and Types + +You can declare internal tables and internal table types in [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) using the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) and [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) statements. The relevant syntax elements for internal tables are `TABLE OF` in combination +with the additions [`TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_simple.htm) +or [`LIKE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_referring.htm). + +``` abap +TYPES itab_type1 TYPE STANDARD TABLE OF data_type ... "Standard table type +TYPES itab_type2 LIKE SORTED TABLE OF data_object ... "Sorted table type + +DATA itab1 TYPE TABLE OF data_type ... "Standard table by default +DATA itab2 TYPE HASHED TABLE OF data_type ... "Hashed table +DATA itab3 TYPE itab_type1 ... "Based on an existing internal table type +DATA itab4 LIKE itab1 ... "Based on an existing internal table +``` + +> **💡 Note**
+> If the table category is not specified (`... TYPE TABLE OF ...`), it is automatically `... TYPE STANDARD TABLE OF ...`. + +The following code snippet contains 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, 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. + + +``` abap +"------------------ Standard table key ------------------ + +"Standard table without explicit primary table key specification. Note that STANDARD +"is not explicitly specified. +"Implicitly, the standard key is used; all non-numeric table fields +"make up the primary table key. +DATA it1 TYPE TABLE OF zdemo_abap_fli. + +"Explicitly specifying STANDARD for a standard table. +"Explicitly specifying the standard table key. It is the same as it1. +DATA it2 TYPE STANDARD TABLE OF zdemo_abap_fli WITH DEFAULT KEY. + +"Hashed table with unique standard table key +DATA it3 TYPE HASHED TABLE OF zdemo_abap_fli WITH UNIQUE DEFAULT KEY. + +"Sorted table with non-unique standard table key +DATA it4 TYPE SORTED TABLE OF zdemo_abap_fli WITH NON-UNIQUE DEFAULT KEY. + +"Elementary line type; the whole table line is the standard table key +DATA it5 TYPE TABLE OF i. + +"------------------ Primary table key ------------------ + +"Specifying the primary table key +"Standard tables: only a non-unique key possible +"The following two examples are the same. NON-UNIQUE can be ommitted but is implicitly added. +DATA it6 TYPE TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid. +DATA it7 TYPE TABLE OF zdemo_abap_fli WITH KEY carrid. + +"Sorted tables: both UNIQUE and NON-UNIQUE possible +DATA it8 TYPE SORTED TABLE OF zdemo_abap_fli WITH UNIQUE KEY carrid connid. +DATA it9 TYPE SORTED TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid connid cityfrom. + +"Hashed tables: UNIQUE KEY must be specified +DATA it10 TYPE HASHED TABLE OF zdemo_abap_fli WITH UNIQUE KEY carrid. + +"Explicitly specifying the predefined name primary_key and listing the components. +"The example is the same as it6 and it7. +DATA it11 TYPE TABLE OF zdemo_abap_fli WITH KEY primary_key COMPONENTS carrid. + +"The following example is the same as it9. +DATA it12 TYPE SORTED TABLE OF zdemo_abap_fli + WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid cityfrom. + +"Specifying an alias name for a primary table key. +"Only possible for sorted/hashed tables. +DATA it13 TYPE SORTED TABLE OF zdemo_abap_fli + WITH NON-UNIQUE KEY primary_key + ALIAS p1 COMPONENTS carrid connid cityfrom. + +"Specifying a key that is composed of the entire line using the predefined table_line. +"In the example, an alias name is defined for a primary table key. +DATA it14 TYPE HASHED TABLE OF zdemo_abap_fli + WITH UNIQUE KEY primary_key + ALIAS p2 COMPONENTS table_line. + +"------------------ Empty key ------------------ + +"Empty keys only possible for standard tables +DATA it15 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. + +"Excursion: The inline declaration in a SELECT statement produces a standard table with empty key. +SELECT * FROM zdemo_abap_fli INTO TABLE @DATA(it16). + +"------------------ Secondary table key ------------------ + +"The following examples demonstrate secondary table keys that are possible for all table categories. +DATA it17 TYPE TABLE OF zdemo_abap_fli "standard table + WITH NON-UNIQUE KEY carrid connid "primary table key + WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto. "secondary table key + +DATA it18 TYPE HASHED TABLE OF zdemo_abap_fli "hashed table + WITH UNIQUE KEY carrid connid + WITH NON-UNIQUE SORTED KEY airports COMPONENTS airpfrom airpto. + +DATA it19 TYPE SORTED TABLE OF zdemo_abap_fli "sorted table + WITH UNIQUE KEY carrid connid + WITH UNIQUE HASHED KEY countries COMPONENTS countryfr countryto. + +"Multiple secondary keys are possible +DATA it20 TYPE TABLE OF zdemo_abap_fli + WITH NON-UNIQUE KEY primary_key COMPONENTS carrid connid + WITH NON-UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto + WITH UNIQUE HASHED KEY airports COMPONENTS airpfrom airpto. + +"Alias names for secondary table keys (and also for the primary table key in the example) +DATA it21 TYPE SORTED TABLE OF zdemo_abap_fli + WITH NON-UNIQUE KEY primary_key ALIAS k1 COMPONENTS carrid connid city + WITH NON-UNIQUE SORTED KEY cities ALIAS s1 COMPONENTS cityfrom cityto + WITH UNIQUE HASHED KEY airports ALIAS s2 COMPONENTS airpfrom airpto. + +"Example for using table keys and alias names using a LOOP AT statement. +"All of the statements below are possible. +"Note that if the secondary table key is not specified (and if the USING KEY addition is not +"used in the example), the primary table key is respected by default. +"Further ABAP statements, such as READ or MODIFY, are available in which the key can be +"explicitly specified to process internal tables. +LOOP AT it21 INTO DATA(wa) USING KEY primary_key. +"LOOP AT it21 INTO DATA(wa) USING KEY k1. +"LOOP AT it21 INTO DATA(wa) USING KEY cities. +"LOOP AT it21 INTO DATA(wa) USING KEY s1. +"LOOP AT it21 INTO DATA(wa) USING KEY airports. +"LOOP AT it21 INTO DATA(wa) USING KEY s2. + ... +ENDLOOP. +``` + +As mentioned, the examples above demonstrate internal tables that are created using the structured type of a database table in the DDIC. +The following example shows the pattern and various examples of declaring internal tables and types by including the local definition of structured data and internal table types for demonstration purposes. + +Steps: +1. Define a structured data type (locally or globally). + This is not necessary if you use, for example, the name of a database table or [CDS view](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm) in the internal table declaration. In these cases their line type is used automatically. +2. Define an internal table type. +3. Create the internal table, i.e. a data object that uses this type. + +You can also create an internal table by ... +- combining the data object creation and table type definition in one step. +- using an [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry"). Such inline declarations are possible at suitable [declaration +positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_positions.htm) +if the operand type can be fully determined, for example, using a +`DATA` statement (or [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) for immutable variables). + + +``` abap +"1. Defining line type locally + +TYPES: BEGIN OF ls_loc, + key_field TYPE i, + char1 TYPE c LENGTH 10, + char2 TYPE c LENGTH 10, + num1 TYPE i, + num2 TYPE i, + END OF ls_loc. + +"2. Defining internal table types +"All of the examples use the short form: + +TYPES: + "Standard table type based on locally defined structure type. + tt_loc_str TYPE TABLE OF ls_loc WITH NON-UNIQUE KEY key_field, + + "Based on global structure type + tt_gl_str TYPE TABLE OF zsome_global_struc_type WITH NON-UNIQUE KEY key_field, + + "Based on database table (could also be, e. g. a CDS view) + "In this case, the line type of the table is automatically used. + tt_gl_tab TYPE TABLE OF zdemo_abap_fli WITH NON-UNIQUE KEY carrid, + + "Based on an elementary type + tt_el_type TYPE TABLE OF i. + +"3. Creating internal tables ... +"... from locally defined table types +DATA: itab_a1 TYPE tt_loc_str, + itab_a2 TYPE tt_gl_str, + itab_a3 TYPE tt_gl_tab, + itab_a4 TYPE tt_el_type. + +"... from global internal table types +DATA itab_a5 TYPE string_table. + +"Combining data object and table type definition +DATA itab_a6 TYPE TABLE OF ls_loc WITH NON-UNIQUE KEY key_field. + +"Internal table based on an already existing internal table using LIKE. +"Here, an internal table is created containing internal tables of the +"type of itab_a6. +DATA itab_a7 LIKE TABLE OF itab_a6. + +"Creating internal tables by inline declarations + +"Table declared inline in the context of an assignment +"The examples show the copying of a table including the content on the fly +"and creating the table in one step. The data type of the +"declared variable is determined by the right side. +DATA(it_inline1) = itab_a1. +DATA(it_inline2) = it_inline1. + +"Using FINAL for creating immutable variables +FINAL(it_final) = it_inline1. + +"Using the VALUE operator and an internal table type +DATA(it_inline3) = VALUE tt_loc_str( ( ... ) ). + +"Table declared inline in the context of a SELECT statement; +"a prior extra declaration of an internal table is not needed. +SELECT * FROM zdemo_abap_fli INTO TABLE @DATA(it_inline4). + +"Instead of +DATA it_sel TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. +SELECT * FROM zdemo_abap_fli INTO TABLE @it_sel. + +"Using FINAL +SELECT * FROM zdemo_abap_fli INTO TABLE @FINAL(it_inline5). +``` + +

⬆️ back to top

+ +## Filling and Copying Internal Tables + +You can use the ABAP keywords +[`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_itab.htm) +and [`APPEND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapappend.htm) +to add lines to internal tables. + +
+ Notes on using APPEND and INSERT + + +- `APPEND` ... + - always adds lines at the bottom of the internal table. + - is not a problem for standard tables where lines are managed + by an index. When the statement is used, the system field + `sy-tabix` is set to the index of the recently added + line. `sy-tabix` is always set to the index with respect + to the primary table index. + - cannot be used for hashed tables. For sorted tables, + lines are appended only if they match the sort order, and no + duplicate entries are created if the primary table key is unique. + Therefore, `INSERT` should be used when adding lines to + sorted tables. +- `INSERT` ... + - can be used to add lines at a specific position in tables (by + specifying the target index). In doing so, all the following + lines are moved down one position. + - without specifying the position adds the lines at the bottom of + the table in case of standard tables. However, when using + `INSERT`, `sy-tabix` is not set unlike + `APPEND`. In case of sorted tables, the line is + automatically inserted at the correct position. + - With `INSERT`, you can specify the position in the internal table at which lines are inserted after `INTO`. + - `... INTO TABLE itab ...`: Line is inserted in ... + - standard tables as last line (i.e. appended) + - sorted tables in the sort order in accordance with primary key values + - hashed table by the hash administration in accordance with primary key values + - `... INTO itab INDEX n`: Possible for index tables. The line is inserted before the line with the line number `n` in the primary table index. + - Note: In the case of unique primary table keys, the table cannot have entries with duplicate + keys. If a duplicate is inserted, the insertion fails and the + system field `sy-subrc` is set to 4. +- What to use? The recommendation is the `INSERT` statement. It covers all table and key types. Consider potential issues when you change table/key types, and you use `APPEND` in your code. +
+
+ +**Adding a line to an internal table**. The example shows both a structure that is created using the `VALUE` operator as well as an existing structure that is added. + +``` abap +APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab. +APPEND lv_struc TO itab. + +INSERT VALUE #( comp1 = a comp2 = b ... ) INTO TABLE itab. +INSERT lv_struc INTO TABLE itab. +``` + +**Adding an initial line** to an internal table without providing any field values. + +``` abap +APPEND INITIAL LINE TO itab. + +INSERT INITIAL LINE INTO TABLE itab. +``` + +**Adding a line and assigning the added line to a field symbol or data reference variable**. +```abap +"When inserting single lines, you can specify the optional additions +"ASSIGNING and REFERENCE INTO. If the insertion is successful, the +"line is assigned to a field symbol or a data reference variable. +"The targets can also be created inline. +APPEND VALUE #( comp1 = a comp2 = b ... ) TO itab ASSIGNING FIELD-SYMBOL(). +APPEND INITIAL LINE TO itab ASSIGNING . +INSERT INITIAL LINE INTO TABLE itab REFERENCE INTO DATA(dref). +``` + +**Adding all lines** from another internal table. + +``` abap +APPEND LINES OF itab2 TO itab. + +INSERT LINES OF itab2 INTO TABLE itab. +``` + +**Adding multiple lines from another internal table with a specified index range**. +- Both `FROM` and `TO` are not mandatory in one statement. it is possible to use only one of them. +- If you use only ... + - `FROM`, all lines up to the last table entry are respected. + - `TO`, all lines starting with the first table entry are respected. + +``` abap +"i1/i2 represent integer values + +APPEND LINES OF itab2 FROM i1 TO i2 TO itab. + +APPEND LINES OF itab2 FROM i1 TO itab. + +APPEND LINES OF itab2 TO i2 TO itab. + +INSERT LINES OF itab2 FROM i1 TO i2 INTO itab. +``` + +**Inserting one line or multiple lines from another internal table at a specific position**. +`FROM` and `TO` can be used here, too. + +``` abap +INSERT lv_struc INTO itab2 INDEX i. + +INSERT LINES OF itab2 INTO itab INDEX i. +``` + +

⬆️ back to top

+ +**Adding lines using constructor expressions** + +As mentioned above, table lines that are constructed inline as +arguments to the `VALUE` operator, for example, can be added to +internal tables. In the following cases, internal tables are populated +using constructor expressions in the context of +[assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_glosry.htm "Glossary Entry"). + +In the example below, the internal table is populated by assigning an +internal table that is constructed inline with the `VALUE` +operator. The inline constructed table has two lines. `line` +represents an existing structure with a compatible line type. The +other line is constructed inline. + + +> **💡 Note**
+> The extra pair of parentheses represents a table line. The `#` character indicates that the line type can be derived from the context. The assignment deletes the existing content of the internal table on the left side. + +``` abap +itab = VALUE #( ( line ) +                ( comp1 = a comp2 = b ...  ) ). +``` + +**Creating an internal table by inline declaration** and adding lines with a constructor expression. +``` abap +"Internal table type +TYPES it_type LIKE itab. + +"Inline declaration +"The # character would not be possible here since the line type +"cannot be derived from the context. +DATA(it_in) = VALUE it_type( ( comp1 = a comp2 = b ... ) + ( comp1 = c comp2 = d ... ) ). +``` + +When you use the above assignments (`itab = ...`), the internal table is initialized and the existing content is deleted. To add new lines **without deleting existing content**, use the [`BASE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvalue_constructor_params_itab.htm) addition. + +``` abap +itab = VALUE #( BASE itab ( comp1 = a comp2 = b ... ) +                          ( comp1 = c comp2 = d ... ) ). +``` + +**Adding lines of other tables** using the `LINES OF` addition to the `VALUE` operator. +> **💡 Note**
+> Without the `BASE` addition, the existing content is deleted. It is assumed that the line type of the source table is compatible with that of the target table. +``` abap +itab = VALUE #( ( comp1 = a comp2 = b ...) +                ( comp1 = a comp2 = b ...) +                ( LINES OF itab2 ) +                ... ). +``` +A simple assignment without a constructor expression that **copies the content of another internal table** (note that the existing content in `itab` are deleted). The example below assumes that the source and target table have compatible line types. +``` abap +itab = itab2. +``` +> **💡 Note**
+> - Internal tables can only be assigned to internal tables. +> - Internal tables can be assigned to each other if their line types are [compatible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencompatible_glosry.htm) or [convertible](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconvertible_glosry.htm). +> - An assignment can trigger an uncatchable exception if, for example, the target table is assigned a duplicate of a unique primary table key or secondary table. +> More information: [Conversion Rules for Internal Tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_itab.htm) + +**Copying the content of another internal table** using the +[`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator. +- Note that the existing content is deleted. +- As an alternative to the `CORRESPONDING` operator, you can use [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) statements. +- The example assumes that the line types of the source and target table are not compatible. However, if the line types are compatible, the syntax will also work. +- Several additions are possible. They can also be combined. Check the ABAP Keyword Documentation. + +``` abap +itab = CORRESPONDING #( itab3 ). + +MOVE-CORRESPONDING itab3 TO itab. +``` + +**Copying content and retaining existing content** using the `CORRESPONDING` operator. +The `KEEPING TARGET LINES` addition of the `MOVE-CORRESPONDING` statement preserves the table content. + +``` abap +itab = CORRESPONDING #( BASE ( itab ) itab3 ). + +MOVE-CORRESPONDING itab3 TO itab KEEPING TARGET LINES. +``` +**Assigning components using mapping relationships** +- You can use the `MAPPING` addition of the `CORRESPONDING` operator to specify components of a source table that are assigned to the components of a target table in mapping relationships. +- For elementary components, the assignment is made according to the associated assignment rules. + +``` abap +itab = CORRESPONDING #( itab3 MAPPING a = c b = d ). +``` + +**Excluding components from the assignment** using the `EXCEPT` addition to the `CORRESPONDING` operator. +- This is particularly useful if there are identically named components in the source and target tables that are not compatible or convertible. You can avoid syntax errors or runtime errors. +- Instead of a component list, `EXCEPT` can also be followed by `*` to exclude all components that are not mentioned in a previous mapping of components. +- If `EXCEPT *` is used without the `MAPPING` addition, all components remain initial. +``` abap +itab = CORRESPONDING #( itab3 EXCEPT e ). + +itab = CORRESPONDING #( itab3 EXCEPT * ). +``` + +**Preventing runtime errors when duplicate lines are assigned** to the target table that is defined to accept only unique keys using the `DISCARDING DUPLICATES` addition of the `CORRESPONDING` operator. +- In this case, the duplicate line is ignored in the source table. +- The addition can also be specified with `MAPPING ...`. + +``` abap +itab = CORRESPONDING #( itab2 DISCARDING DUPLICATES ). +``` + +**Copying data from deep internal tables**. +- The `BASE` addition does not delete the existing content. +- See also the alternative `MOVE-CORRESPONDING` statements. +``` abap +itab_nested2 = CORRESPONDING #( DEEP itab_nested1 ). + +itab_nested2 = CORRESPONDING #( DEEP BASE ( itab_nested2 ) itab_nested1 ) + +MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES. + +MOVE-CORRESPONDING itab_nested1 TO itab_nested2 EXPANDING NESTED TABLES KEEPING TARGET LINES. +``` + +

⬆️ back to top

+ +### Excursions with Internal Tables +For more details on ABAP SQL, see the cheat sheet on [ABAP SQL](03_ABAP_SQL.md). + +**Adding multiple lines from a database table to an internal table** using +[`SELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm), +for example, based on a condition. In the case below, the internal table +is created inline. +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2 ... + WHERE ... + INTO TABLE @DATA(itab_sel). +``` + +**Sequentially adding multiple rows** from a database table to an internal table using `SELECT ... ENDSELECT.`, for example, based on a condition. In this case, the selected data is first stored in a structure that can be further processed and added to an internal table. + +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2 ... + WHERE ... + INTO @DATA(struc_sel). + + IF sy-subrc = 0. + APPEND struc_sel TO itab. +  ... + ENDIF. +ENDSELECT. +``` + +Adding multiple lines from a database table using `SELECT`, for example, based on a condition when the database table has a line type that is incompatible with the internal table. The `*` character means that all fields are selected. The other examples define specific fields. +The `APPENDING CORRESPONDING FIELDS INTO TABLE` addition appends the selected data to the end of the table without deleting existing +table entries. The `INTO CORRESPONDING FIELDS OF TABLE` addition adds lines and deletes existing table entries. +``` abap +SELECT FROM dbtab2 + FIELDS * + WHERE ... + APPENDING CORRESPONDING FIELDS OF TABLE @itab. + +SELECT FROM dbtab2 + FIELDS * + WHERE ... + INTO CORRESPONDING FIELDS OF TABLE @itab. +``` +Adding multiple lines from an internal table to another internal table using `SELECT`. Note the alias name that must be defined for the +internal table. +``` abap +SELECT comp1, comp2, ... + FROM @itab2 AS it_alias + INTO TABLE @DATA(itab_sel). +``` + +**Combining data from multiple tables into one internal table** using an [inner +join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm "Glossary Entry"). +The following example joins data of an internal and a database table +using a `SELECT` statement and the [`INNER JOIN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) addition. Note that the field list includes fields from both tables. The fields are referred to using `~`. +``` abap +SELECT it_alias~comp1, it_alias~comp2, dbtab~comp3 ... + FROM @itab AS it_alias + INNER JOIN dbtab ON it_alias~comp1 = dbtab~comp1 + INTO TABLE @DATA(it_join_result). +``` + +Filling an internal table from a database table using +[subqueries](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). +The following two examples fill an internal table from a database table. In the first example, a subquery is specified in the +`WHERE` clause with the `NOT IN` addition. It checks whether a value matches a value in a set of values +specified in parentheses. The second example fills an internal table depending on data in another table. A subquery with the `EXISTS` addition is specified in +the `WHERE` clause. In this +case, the result of the subquery, which is another +`SELECT` statement, is checked to see if an entry exists in +a table based on the specified conditions. + +``` abap +SELECT comp1, comp2, ... + FROM dbtab + WHERE comp1 NOT IN ( a, b, c ... ) + INTO TABLE @DATA(it_subquery_result1). + +SELECT comp1, comp2, ... + FROM dbtab + WHERE EXISTS ( SELECT 'X' FROM @itab AS itab_alias + WHERE comp1 = dbtab~comp1 ) + INTO TABLE @DATA(it_subquery_result2). +``` + +Filling internal table from a table based on the existence of data in +another table using the [`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) addition. + +> **💡 Note**
+> Make sure that the internal table you are reading from is not initial. Therefore, it is recommended that you use a subquery as shown above: `... ( SELECT ... FROM @itab AS itab_alias WHERE ...`). + +``` abap +IF itab IS NOT INITIAL. + + SELECT dbtab~comp1, dbtab~comp2, ... + FROM dbtab + FOR ALL ENTRIES IN @itab + WHERE comp1 = @itab-comp1 + INTO TABLE @DATA(it_select_result). + +ENDIF. +``` + +**Using the `FILTER` operator** + +To create an internal table by copying data from another internal table and +filtering out lines that do not meet the `WHERE` condition, you can use the [`FILTER` +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_filter.htm). + +- The + `FILTER` operator constructs an internal table according to a specified type (which can be an explicitly specified, non-generic table type or the `#` character as a symbol for the [operand type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_type_glosry.htm) before the first parenthesis). +- The lines for the new internal table are taken from an + existing internal table based on conditions specified in a `WHERE` clause. Note that the table type of the existing internal table must be convertible into the specified target type. +- The conditions can be based on either single values or a [filter + table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_filter_table.htm). +- Additions: + +|Addition |Details | +|---|---| +|`USING KEY` | Specifies the [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm "Glossary Entry") used to evaluate the `WHERE` condition: either a [sorted key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm "Glossary Entry") or a [hash key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhash_key_glosry.htm "Glossary Entry"). If the internal table does not have either of these, it must have a [secondary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm "Glossary Entry"), which must be specified after `USING KEY`. | +| `EXCEPT` | Specifying `EXCEPT` means that those lines of the existing table are used that do not meet the condition specified in the `WHERE` clause. If `EXCEPT` is not specified, those lines of the existing table that meet the condition are used. | + +Examples: +```abap +"FILTER on conditions based on single values +"Assumption: The component num is of type i. +DATA itab1 TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY num. +DATA itab2 TYPE STANDARD TABLE OF struc WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS num. +DATA itab3 TYPE HASHED TABLE OF struc WITH UNIQUE KEY num. + +"The lines meeting the condition are respected. +"Note: The source table must have at least one sorted or hashed key. +"Here, the primary key is used +DATA(f1) = FILTER #( itab1 WHERE num >= 3 ). + +"USING KEY primary_key explicitly specified; same as above +DATA(f2) = FILTER #( itab1 USING KEY primary_key WHERE num >= 3 ). + +"EXCEPT addition +DATA(f3) = FILTER #( itab1 EXCEPT WHERE num >= 3 ). +DATA(f4) = FILTER #( itab1 EXCEPT USING KEY primary_key WHERE num >= 3 ). + +"Secondary table key specified after USING KEY +DATA(f5) = FILTER #( itab2 USING KEY sec_key WHERE num >= 4 ). +DATA(f6) = FILTER #( itab2 EXCEPT USING KEY sec_key WHERE num >= 3 ). + +"Note: In case of a hash key, exactly one comparison expression for each key component is allowed; +"only = as comparison operator possible. +DATA(f7) = FILTER #( itab3 WHERE num = 3 ). + +"Using a filter table +"In the WHERE condition, the columns of source and filter table are compared. +"Those lines in the source table are used for which at least one line in the filter +"table meets the condition. EXCEPT and USING KEY are also possible. + +DATA filter_tab1 TYPE SORTED TABLE OF i + WITH NON-UNIQUE KEY table_line. + +DATA filter_tab2 TYPE STANDARD TABLE OF i + WITH EMPTY KEY + WITH UNIQUE SORTED KEY line COMPONENTS table_line. + +DATA(f8) = FILTER #( itab1 IN filter_tab1 WHERE num = table_line ). + +"EXCEPT addition +DATA(f9) = FILTER #( itab1 EXCEPT IN filter_tab1 WHERE num = table_line ). + +"USING KEY is specified for the filter table +DATA(f10) = FILTER #( itab2 IN filter_tab2 USING KEY line WHERE num = table_line ). + +"USING KEY is specified for the source table, including EXCEPT +DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num = table_line ). +``` + +**Collecting values** + +Use the +[`COLLECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcollect.htm) +keyword, for example, to add the values of numeric components to the +corresponding values in an internal table. Use it mainly for internal +tables with a unique primary key, especially hashed tables. +``` abap +COLLECT VALUE dtype( comp1 = a comp2 = b ... ) INTO itab. +``` + +

⬆️ back to top

+ +## Reading from Internal Tables + +There are three different ways to specify the line to read: + +- by index (only index tables) +- by table keys (only tables for which a key is defined) +- by free key + +The following code snippets include [`READ TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_table.htm) statements and [table expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expressions.htm) to read from internal tables. + +**Reading single lines** + +*Determining the target area* + +- Copying a line to a data object using the addition `INTO`. + After the copying, the line found exists separately in the internal table and + in the data object. If you change the + data object or the table line, the change does not affect the other. + However, you can modify the copied table line and use a + `MODIFY` statement to modify the table based on the modified + table line (see below). The `TRANSPORTING` addition + specifies which components to copy. If + it is not specified, all components are respected. + ``` abap + READ TABLE itab INTO dobj ... "dobj must have the table's structure type + + READ TABLE itab INTO DATA(dobj_inl) ... + + READ TABLE itab INTO ... TRANSPORTING comp1 [comp2 ... ]. + ``` + +- Assigning a line to a [field + symbol](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm "Glossary Entry"), + for example, using an inline declaration (`ASSIGNING `). When you then access the field symbol, it means that you access the found table line. There is no actual copying of + content. Therefore, modifying the field symbol means + modifying the table line directly. Note that you cannot use the + `TRANSPORTING` addition since the entire table is + assigned to the field symbol. + + ``` abap + READ TABLE itab ASSIGNING ... "The field symbol must have an appropriate type. + + READ TABLE itab ASSIGNING FIELD-SYMBOL() ... "The field symbol is created inline. + ``` + +- Reading a line into a [data reference + variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm "Glossary Entry") + using `REFERENCE INTO`. In this case, no copying takes place. If you want to address the line, you must first [dereference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm) the data reference. You cannot use the addition `TRANSPORTING`. + + ``` abap + READ TABLE itab REFERENCE INTO dref ... + + READ TABLE itab REFERENCE INTO DATA(dref_inl) ... + ``` + +**Which to use then?** Since all syntax options provide the same +functionality, your use case, the +performance or readability of the code may play a role. For more information, see +the programming guidelines for the [target +area (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_output_guidl.htm "Guideline"). +A use case for `INTO dobj` is when the table should +not be changed using the copied table line. However, copying comes +at a performance cost. Imagine that your table contains many columns or +nested components. In this case, it is better not to copy at all (although you can use +the `TRANSPORTING` addition to restrict the fields to be copied). + +

⬆️ back to top

+ +*Reading a single line by index* + +The following example shows `READ TABLE` statements to read a single line from an internal table by specifying the index. You can use the addition `USING KEY` to specify a table key and thus explicitly determine the table index to use. If the table has a sorted secondary +key, the addition can be specified and the line to be read is then determined from its secondary table index. If the primary table key is +specified by its name `primary_key`, the table must be an index table, and the behavior is the same as if `USING KEY` was +not specified. +Note that the examples only show reading into a work area. Other targets are possible as shown above. +``` abap +READ TABLE itab INTO wa INDEX i. + +READ TABLE itab INTO wa INDEX i USING KEY primary_key. +``` + +Using a [table +expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expressions.htm), +the read result is stored in a variable that can be declared inline. +The number in the square brackets represents the index. A line that is +not found results in an runtime error. To avoid an error, you can +use a [`TRY ... CATCH ... ENDTRY.`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) block. + +``` abap +"In the examples, integer values are specified for the index. +DATA(lv1) = itab[ 1 ]. + +TRY. + DATA(lv2) = itab[ 2 ]. + CATCH cx_sy_itab_line_not_found. + ... +ENDTRY. + +DATA(lv3) = itab[ KEY primary_key INDEX 3 ]. + +"Copying a table line via table expression and embedding in constructor expression +DATA(lv4) = VALUE #( itab[ 4 ] ). + +"Reading into data reference variable using the REF operator +DATA(lv5_ref) = REF #( itab[ 5 ] ). +``` + +When you read a non-existent line using a table expression, you may not want to throw an exception. You can also embed the table expression +in a constructor expression using the `OPTIONAL` addition. This way, an unsuccessful read will not trigger the +exception. The result returned is a line with initial values. +Alternatively, you can use the `DEFAULT` addition to return a +default line in case of an unsuccessful read operation, which can also be another table expression or constructor expression. + +``` abap +DATA(line1) = VALUE #( itab[ 6 ] OPTIONAL ). + +DATA(line2) = VALUE #( itab[ 7 ] DEFAULT itab[ 8 ] ). +``` + +

⬆️ back to top

+ +*Reading single lines using table keys* + +Lines can be read by explicitly specifying the table keys or the alias names, if any. +```abap +"Example internal table with primary and secondary table key and alias names +"Assumption: All components are of type i + +DATA it TYPE SORTED TABLE OF struc + WITH NON-UNIQUE KEY primary_key ALIAS pk COMPONENTS a b + WITH NON-UNIQUE SORTED KEY sec_key ALIAS sk COMPONENTS c d. + +"Table expressions + +"Key must be fully specified +line = it[ KEY primary_key COMPONENTS a = 1 b = 2 ]. + +"The addition COMPONENTS is optional; same as above +line = it[ KEY primary_key a = 1 b = 2 ]. + +"Primary key alias +line = it[ KEY pk a = 1 b = 2 ]. + +"Secondary table key +line = it[ KEY sec_key c = 3 d = 4 ]. + +"Secondary table key alias +line = it[ KEY sk c = 3 d = 4 ]. + +"READ TABLE statements +"Primary table key +READ TABLE it INTO wa WITH TABLE KEY primary_key COMPONENTS a = 1 b = 2. + +"Alias +READ TABLE it INTO wa WITH TABLE KEY pk COMPONENTS a = 1 b = 2. + +"Secondary table key +READ TABLE it INTO wa WITH TABLE KEY sec_key COMPONENTS c = 3 d = 4. + +"Alias +READ TABLE it INTO wa WITH TABLE KEY sk COMPONENTS c = 3 d = 4. + +"Reading a line based on keys specified in a work area +"Work area containing primary and secondary table key values; the line type +"must be compatible to the internal table +DATA(pr_keys) = VALUE struc( a = 1 b = 2 ). + +DATA(sec_keys) = VALUE struc( c = 3 d = 4 ). + +READ TABLE it FROM pr_keys INTO wa. + +"If USING KEY is not specified, the primary table key is used. +"If it is used, the specified table key is used. +READ TABLE it FROM pr_keys USING KEY primary_key INTO wa. + +READ TABLE it FROM sec_keys USING KEY sec_key INTO wa. + +"Alias +READ TABLE it FROM sec_keys USING KEY sk INTO wa. +``` + +

⬆️ back to top

+ +**Reading a single line using a free key** + +The specified components used as keys need not be part of a table key. +``` abap +line = it[ b = 2 ]. + +READ TABLE it INTO wa WITH KEY b = 2. +``` + +*Addressing individual components* + +When reading single lines in general, you can also address individual +components of the line using the [component +selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_selector_glosry.htm "Glossary Entry") +`-` (or the [dereferencing +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm "Glossary Entry") +`->*` in the case of data reference variables). +``` abap +DATA(comp1) = it[ b = 2 ]-c. + +READ TABLE it INTO DATA(wa) WITH KEY b = 2. +DATA(comp2) = wa-c. + +READ TABLE it ASSIGNING FIELD-SYMBOL() WITH KEY b = 2. +DATA(comp3) = -c. + +READ TABLE it REFERENCE INTO DATA(dref) WITH KEY b = 2. +DATA(comp4) = dref->c. +"Note: The syntax dref->*-c is also possible. +``` + +

⬆️ back to top

+ +**Checking the existence and the index of a line in an internal table** + +This is relevant if you are not interested in the content of a table +line, but only want to find out whether a line exists that matches to the +index or key specifications. To do this, use a [`READ TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_table.htm) +statement with the `TRANSPORTING NO FIELDS` addition. The +addition indicates that no actual content is to be read. If the search was +successful and an entry exists, the system field `sy-subrc` is +set to 0. + +A newer way to check the existence of a line is the [predicate +function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_function_glosry.htm "Glossary Entry") +[`line_exists( )`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenline_exists_function.htm). +This function expects a [table +expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expression_glosry.htm "Glossary Entry") as an argument. +See below for more on table expressions. Note that table expressions do not set system fields. +``` abap +"Read using the key +READ TABLE it WITH KEY b = 2 TRANSPORTING NO FIELDS. + +IF sy-subrc = 0. + ... +ENDIF. + +"Read using the index +READ TABLE it INDEX 1 TRANSPORTING NO FIELDS. + +IF sy-subrc = 0. + ... +ENDIF. + +"Read using the key +IF line_exists( it[ b = 2 ] ). + ... +ENDIF. + +"Read using the index +IF line_exists( it[ 1 ] ). + ... +ENDIF. +``` + +If you want to find out about the index of a line in an internal table, you can also make use of the `READ TABLE` statement above. If +the line is found, the system field `sy-tabix` is set to the number of the index. Otherwise, the built-in function +[`line_index( )`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenline_index_function.htm) can be used. It returns the index of the found line or 0 if the line does not exist. + +``` abap +DATA(idx) = line_index( it[ b = 2 ] ). +``` + +`lines( )` is another built-in function that you can use to check how many lines exist in an internal table. It returns an integer value. + +``` abap +DATA(number_of_lines) = lines( it ). +``` + +

⬆️ back to top

+ +## Processing Multiple Internal Table Lines Sequentially + +If you are interested not only in single table lines, but in the entire +table content or in specific parts of it, you can use [`LOOP +AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab.htm) +statements to process table lines sequentially. As above, you +can use multiple options for target areas: work area, field +symbol, data reference. There are multiple additions to the `LOOP AT` +statements to further restrict the table content to be processed. + +Simple form: +``` abap +"The target is an existing work area. +DATA wa LIKE LINE OF it. + +LOOP AT it INTO wa. + "No addition of the loop statement; all lines are processed + "Statements in this block are relevant for each individual table line. + ... +ENDLOOP. + +"Work area declared inline +LOOP AT itab INTO DATA(wa_inl). + ... +ENDLOOP. + +"Field symbols +FIELD-SYMBOLS LIKE LINE OF it. + +LOOP AT it ASSIGNING . + ... +ENDLOOP. + +LOOP AT it ASSIGNING FIELD-SYMBOL(). + ... +ENDLOOP. + +"Data reference variables +DATA dref TYPE REF TO dbtab. + +LOOP AT it REFERENCE INTO dref. + ... +ENDLOOP. + +LOOP AT it REFERENCE INTO DATA(dref_inl). + ... +ENDLOOP. +``` + +- The order in which tables are iterated depends on the table category. + - Note the [`STEP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_cond.htm#!ABAP_ADDITION_3@3@) addition, which is also available for other ABAP statements. +- Index tables are looped over in ascending order by the index. +- Hashed tables are looped in the order in which the lines were added to the table. You can also sort the table before the loop. +- During the loop, the system field `sy-tabix` is set to the number of the currently processed table +line. This is not true for hashed tables. There, `sy-tabix` is `0`. +- Note that if you want to work with the value of `sy-tabix`, you +should do so immediately after the `LOOP` statement to avoid possible overwriting in statements contained in the loop block. + +*Restricting the area of the table to be looped over* + +The additions of `LOOP` statements come into play when you want to restrict the table content to be respected by the loop because +you do not want to loop over the entire table. Note that the examples only show work areas as target objects to hold the table line read. +Other options are possible as shown above. + +``` abap +"FROM/TO: Only for index tables + +"Specifying an index range +LOOP AT it INTO wa FROM 2 TO 5. + ... +ENDLOOP. + +"From specified line until the end +LOOP AT it INTO wa FROM 2. + ... +ENDLOOP. + +"From first line until the specified line +LOOP AT it INTO wa TO 5. + ... +ENDLOOP. + +"WHERE clause: Restricting lines based on logical expression + +LOOP AT it INTO wa WHERE a > 1 AND b < 4. + ... +ENDLOOP. + +"No interest in the table content; only relevant system fields are filled + +"Mandatory WHERE clause +LOOP AT it TRANSPORTING NO FIELDS WHERE a < 5. + ... +ENDLOOP. + +"Table key specification (snippet uses example table from above) +"The specified table key affects the order in which the table lines +"are accessed and the evaluation of the other conditions. + +LOOP AT it INTO wa USING KEY primary_key. +"LOOP AT it INTO wa USING KEY pk. "primary key alias +"LOOP AT it INTO wa USING KEY sec_key. "secondary key +"LOOP AT it INTO wa USING KEY sk. "secondary key alias + ... +ENDLOOP. + +"STEP addition for defining the step size and the direction of the loop +"- Step size: Specified by the absolute value of an integer +"- Direction: Specified by a positive (forward loop) or negative +" (loop in reverse order) integer + +"Reversing the loop order using a negative integer +"Each line is read indicated by the absolute value 1 +LOOP AT it INTO wa STEP -1. + ... +ENDLOOP. + +"Forward loop by specifiying a positive integer +"In the example, every second line is read. +"Note: Omitting STEP means STEP 1 by default. +LOOP AT it INTO wa STEP 2. + ... +ENDLOOP. + +"STEP with other additions +"The example uses the additions FROM and TO. +"Note: If the value after STEP is negative, the value +"after FROM must be greater than the value after TO. +LOOP AT it INTO wa FROM 6 TO 3 STEP -2. + ... +ENDLOOP. +``` + +### Iteration Expressions + +Iteration expressions with [`FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfor.htm) as part of certain constructor expressions allow you to create content of an internal table by evaluating one or more source tables. + +The expressions are covered in the cheat sheet [Constructor Expressions](05_Constructor_Expressions.md): +- [Iteration Expressions Using FOR](05_Constructor_Expressions.md#iteration-expressions-using-for) +- Special reduction operator `REDUCE` that is based on iteration expressions: [REDUCE](05_Constructor_Expressions.md#reduce) + +

⬆️ back to top

+ +## Sorting Internal Tables + +- Sorted tables are stored in the memory in an automatically sorted + order, hence, they cannot be sorted explicitly with + [`SORT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsort_itab.htm). +- For standard and hashed tables, the order can be changed. +- When using `SORT` statements, the sort order is derived either + by the primary table key (Note: Secondary keys + cannot be used for the sorting.) or by explicitly specifying the + fields to be sorted by. +- Explicit specification is the recommended way because it is + easier to understand and can prevent unwanted sorting results, + especially with tables with standard key. + +*Sorting by primary table key* +``` abap +"Implicit sorting by primary table key and in ascending order by default +SORT itab. + +"Optional additions to determine the sort order +"As mentioned above, ASCENDING is used implicitly. Here, specifying it explicitly. +SORT itab ASCENDING. +SORT itab DESCENDING. +``` + +The effect of sorting can have an unexpected result if you use the simple form of the statement and do not explicitly specify the keys. If an internal table has a structured line type and (perhaps inadvertently) the standard key as the primary table key, that is, all character-like and byte-like components make up the primary table key, all these components are taken into account when the table is sorted. +``` abap +"Is basically the same as it2 +DATA it1 TYPE TABLE OF zdemo_abap_fli. + +DATA it2 TYPE STANDARD TABLE OF zdemo_abap_fli WITH DEFAULT KEY. + +"Respecting the standard key when sorting +SORT it1. +``` +Plus: Suppose there are only elementary numeric components in an internal table with a structured line type. In this case, sorting has no effect because the primary table key is considered empty. This is certainly also true for tables declared with `EMPTY KEY`. + +*Sorting by explicitly specifying components* + +You can sort by any component of the internal table. It is also possible to specify the sort order +(even component-wise). Explicitly specifying the components has the advantage that your code is easier to understand and you can avoid unexpected results if you accidentally use `SORT` without the `BY` addition on empty and standard table keys. + +``` abap +DATA it3 TYPE TABLE OF struc WITH NON-UNIQUE KEY a. + +"Sorting by primary table key a +SORT itab. + +"Specifying the component to sort for; here, it is the same as the key; +"this way, the sorting is easier to understand +SORT itab BY a. + +"Syntax showing multiple component sorting with component-wise sort order +SORT itab BY a b ASCENDING c DESCENDING. + +"Sorting respecting the entire line (e. g. in the context of tables with +"empty or standard keys) +SORT itab BY table_line. +``` + +

⬆️ back to top

+ +## Modifying Internal Table Content + +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. 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. + +The following examples demonstrate direct modification of recently read table lines: +``` abap +"Table declarations + +DATA it_st TYPE TABLE OF struc WITH NON-UNIQUE KEY a. + +DATA it_so TYPE SORTED TABLE OF struc WITH UNIQUE KEY a. + +"Reading table line into target area + +READ TABLE it_st ASSIGNING FIELD-SYMBOL() INDEX 1. + +READ TABLE it_so REFERENCE INTO DATA(dref) INDEX 2. + +"Modification examples +"Modifying the entire table line while keeping the values of other components; +"this way is not possible for it_so because of key value change. + + = VALUE #( BASE a = 1 b = 2 ). + +"Modifying a single component via field symbol + +-c = 3. + +"Modification via dereferencing + +ref->b = 4. + +"Table expressions + +it_st[ 1 ] = VALUE #( a = 1 b = 2 ). + +it_st[ 2 ]-c = 3. + +"Sorted table: no key field change + +it_so[ 2 ]-d = 4. +``` + +> **💡 Note**
+> If you want to modify recently read lines in a work area, for example, within a loop (`LOOP AT INTO dobj`), you can modify the line and then use a `MODIFY` statement to modify the internal table based on this line. + +[`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. + +``` abap +"Addition FROM ...; specified key values determine the line to be modified + +"line: existing line including key values +MODIFY TABLE it FROM line. + +"line constructed inline +MODIFY TABLE it FROM VALUE #( a = 1 b = 2 ... ). + +"Respecting only specified fields with the addition TRANSPORTING +"In case of sorted/hashed tables, key values cannot be specified. +MODIFY TABLE it FROM line TRANSPORTING b c. + +"Modification via index +"Note that it is only MODIFY, not MODIFY TABLE. +"Example: It modifies the line with number 1 in the primary table index. +MODIFY it FROM line INDEX 1. + +"Without the addition TRANSPORTING, the entire line is changed. +"Example: It modifies specific values. +MODIFY it FROM line INDEX 1 TRANSPORTING b c. + +"USING KEY addition +"If the addition is not specified, the primary table key is used; +"otherwise, it is the explicitly specified table key that is used. +"Example: It is the same as MODIFY it FROM line INDEX 1. +MODIFY it FROM line USING KEY primary_key INDEX 1. + +"The statement below uses a secondary key and an index specification +"for the secondary table index. Only specific fields are modified. +MODIFY it FROM line USING KEY sec_key INDEX 1 TRANSPORTING c d. + +"Modifying multiple lines in internal tables +"All lines matching the logical expression in the WHERE clause are modified +"as specified in line. +"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. + +

⬆️ back to top

+ +## Deleting Internal Table Content + +You can use [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdelete_itab.htm) statements to delete single and multiple lines in internal tables. The following additions can be used: `USING KEY` (for specifying a table key), `FROM`/`TO` (for specifying row ranges), `STEP` (for specifying the step size), and `WHERE` (for specifying conditions). + +``` abap +"Deleting via index +"Example: The first line in the table is deleted. +DELETE it INDEX 1. + +"If USING KEY is not used, INDEX can only be used with index tables. +"If doing so, it determines the line from the primary table index. +"If a secondary key is specified, the secondary table index is respected +"Example: same as above +DELETE it INDEX 1 USING KEY primary_key. + +"Deleting an index range; FROM or TO alone can also be specified +DELETE it FROM 2 TO 5. + +"Deleting via keys +"The line must have a compatible type to the tables line type and +"include key values. The first found line with the corresponding keys +"is deleted. +"If the key is empty, no line is deleted. +DELETE TABLE it FROM line. + +"Instead of specifying the keys using a data object ("line" above), +"the keys can be specified separately. All key values must be specified. +"Example: Respects keys from primary table index. +DELETE TABLE it WITH TABLE KEY a = 1. + +"You can also specify secondary keys. +"Example: Same as above +DELETE TABLE it WITH TABLE KEY primary_key COMPONENTS a = 1. + +DELETE TABLE it_sec WITH TABLE KEY sec_key COMPONENTS ... + +"Deleting multiple lines based on a WHERE condition +"Specifying the additions USING KEY, FROM, TO is also possible. +DELETE it WHERE a < 6. + +"Excursion: Deleting in a LIKE-like fashion you may know from +"ABAP SQL statements. +"The LIKE addition is not available for the WHERE clause in DELETE +"statements for internal tables as is the case for ABAP SQL DELETE statements. +DATA(str_table) = VALUE string_table( ( `abcZ` ) ( `Zdef` ) ( `gZhi` ) + ( `Zjkl` ) ( `Zmno` ) ( `pqrZ` ) ). + +"You can, for example, use logical operators such as CP (conforms to pattern) +"All lines that begin with Z are to be deleted. +DELETE str_table WHERE table_line CP `Z*`. +"Result: abcZ / gZhi / pqrZ +``` + +`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. + +"Deletion respecting the values of the entire line +DELETE ADJACENT DUPLICATES FROM it COMPARING ALL FIELDS. + +"Only lines are deleted with matching content in specific fields +DELETE ADJACENT DUPLICATES FROM it COMPARING a c. + +"Deletion respecting a specified table key +"Same as first example above +DELETE ADJACENT DUPLICATES FROM it USING KEY primary_key. + +DELETE ADJACENT DUPLICATES FROM it USING KEY sec_key. +``` + +> **💡 Note**
+> The system field `sy-subrc` is set to `0` if at least one line has been deleted. It is set to `4` if no lines were deleted. + +The +[`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) +and +[`FREE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfree_dataobject.htm) +statements allow you to delete the entire table content. + +The difference between the two is in the handling of the memory space originally allocated to the table. When a table is cleared with `CLEAR`, +the content is removed, but the memory space initially requested remains +allocated. If the table is filled again later, the memory space is still +available, which is a performance advantage over +clearing an internal table with `FREE`. Such a statement also +deletes the table content, but it also releases the memory +space. +Note that an assignment using the `VALUE` operator without entries in the parentheses clears the internal table. + +``` abap +CLEAR it. + +"This statement additionally releases memory space. +FREE it. + +"Assignment using the VALUE operator without entries in the parentheses +it = VALUE #( ). +``` +

⬆️ back to top

+ +## Excursions + +### Improving Read Performance with Secondary Table Keys + +The following example creates two demo internal tables. One without a secondary +table key and the other with a secondary table key. Consider a scenario where you +have an internal table without a secondary table key, and you want to add a secondary table key later to improve read performance. The tables are populated with a lot of data. Then, in a DO loop, many reads are performed on the internal tables. One example uses a free key for the read, the other uses a secondary table key. Before and after the reads, the current timestamp is stored in variables, from which the elapsed time is calculated. There should be a significant delta of the elapsed time. + +```abap +CLASS zcl_some_class DEFINITION PUBLIC FINAL CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. + PROTECTED SECTION. + PRIVATE SECTION. +ENDCLASS. +CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + TYPES: BEGIN OF demo_struc, + idx TYPE i, + str TYPE string, + num TYPE i, + END OF demo_struc. + + DATA itab TYPE HASHED TABLE OF demo_struc WITH UNIQUE KEY idx. + DATA itab_sec TYPE HASHED TABLE OF demo_struc + WITH UNIQUE KEY idx + WITH NON-UNIQUE SORTED KEY sk + COMPONENTS str num. + + DO 500 TIMES. + INSERT VALUE #( idx = sy-index + str = |INDEX{ sy-index }| + num = sy-index ) INTO TABLE itab. + ENDDO. + itab_sec = itab. + + DATA(ts1) = utclong_current( ). + DO 500 TIMES. + "Reading into a data reference variable using using a free key. + "This key corresponds to the secondary table key specified for + "the table in the second example. + DATA(dref) = REF #( itab[ str = `INDEX250` num = 250 ] ). + ENDDO. + DATA(ts2) = utclong_current( ). + + cl_abap_utclong=>diff( EXPORTING high = ts2 + low = ts1 + IMPORTING seconds = DATA(seconds) ). + + out->write( `Elapsed time for the reads using a free key:` ). + out->write( seconds ). + out->write( `----------------------------------------------------------` ). + + ts1 = utclong_current( ). + DO 500 TIMES. + "Reading from an internal table using the secondary table key + dref = REF #( itab_sec[ KEY sk str = `INDEX250` num = 250 ] ). + ENDDO. + ts2 = utclong_current( ). + + cl_abap_utclong=>diff( EXPORTING high = ts2 + low = ts1 + IMPORTING seconds = seconds ). + out->write( `Elapsed time for the reads using a secondary table key:` ). + out->write( seconds ). + ENDMETHOD. +ENDCLASS. +``` + +

⬆️ back to top

+ +### Searching and Replacing Substrings in Internal Tables with Character-Like Data Types + +You can use [`FIND ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_itab.htm) statements to search for substrings in internal tables (standard tables without secondary table keys; with character-like line type) line by line. + +``` abap +DATA(str_table) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). + +"Finding all occurrences in a table +"Note: res_tab is of type match_result_tab +"You can also restrict the search range in an internal table; see an example in REPLACE ... IN TABLE +FIND ALL OCCURRENCES OF `Z` + IN TABLE str_table + RESULTS DATA(res_tab) + RESPECTING CASE. + +"4 entries in table res_tab (tables in SUBMATCHES are initial since no regular expression is used) +"1. line: 1, offset: 1, length: 1, submatches: (initial) +"2. line: 1, offset: 4, length: 1, ... +"3. line: 2, offset: 2, length: 1, ... +"4. line: 3, offset: 0, length: 1, ... + +"Finding the first occurrence in a table +"Note: res_struc, which is declared inline here, is of type match_result +FIND FIRST OCCURRENCE OF `Z` + IN TABLE str_table + RESULTS DATA(res_struc) + RESPECTING CASE. + +"Entries in structure res_struc +"line: 1, offset: 1, length: 1, submatches: (initial) + +"Alternative to the statement above (storing the information in individual data objects) +FIND FIRST OCCURRENCE OF `Z` + IN TABLE str_table + MATCH LINE DATA(line) "1 + MATCH OFFSET DATA(off) "1 + MATCH LENGTH DATA(len) "1 + RESPECTING CASE. +``` + +Replacements in internal tables with [`REPLACE ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace_itab.htm): + +``` abap +DATA(str_table_original) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). +DATA(str_table) = str_table_original. + +"Replacing all occurrences in a table +"RESULTS addition: Storing information in an internal table of type repl_result_tab +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + WITH `#` + RESULTS DATA(res_table) + RESPECTING CASE. + +"str_table: a#bz# / cd#ze / #zzf / ghz +"res_table: +"LINE OFFSET LENGTH +"1 1 1 +"1 4 1 +"2 2 1 +"3 0 1 + +str_table = str_table_original. + +"Replacing the first occurrence in a table +"RESULTS addition: Storing information in a structure of type repl_result +REPLACE FIRST OCCURRENCE OF `Z` + IN TABLE str_table + WITH `#` + RESULTS DATA(res_structure) + RESPECTING CASE. + +"str_table: a#bzZ / cdZze / Zzzf / ghz +"res_structure: +"LINE OFFSET LENGTH +"1 1 1 + +str_table = str_table_original. + +"Restricting the search range in an internal table +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + FROM 1 TO 2 + WITH `#` + RESPECTING CASE. + +"str_table: a#bz# / cd#ze / Zzzf / ghz + +str_table = str_table_original. + +"Offsets can be optionally specified (also only the offset of start or end line possible) +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + FROM 1 OFFSET 3 TO 2 OFFSET 2 + WITH `#` + RESPECTING CASE. + +"str_table: aZbz# / cdZze / Zzzf / ghz +``` + +

⬆️ back to top

+ +### Ranges Tables + +- Internal tables that have the predefined columns `SIGN`, `OPTION`, `LOW`, and `HIGH` +- Declared with the `TYPE RANGE OF` addition in `DATA` and `TYPES` statements +- Used to store range conditions that can be evaluated in expressions using the `IN` operator (each row in the table represents a separate comparison) + +```abap +"Populating an integer table with values from 1 to 20 +TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY. +DATA(inttab) = VALUE int_tab_type( FOR x = 1 WHILE x <= 20 ( x ) ). + +"Declaring a ranges table +DATA rangestab TYPE RANGE OF i. + +"Populating a ranges table using VALUE +rangestab = VALUE #( sign = 'I' + option = 'BT' ( low = 1 high = 3 ) + ( low = 6 high = 8 ) + ( low = 12 high = 15 ) + option = 'GE' ( low = 18 ) ). + +"Using a SELECT statement and the IN addition to retrieve internal table +"content based on the ranges table specifications +SELECT * FROM @inttab AS tab + WHERE table_line IN @rangestab + INTO TABLE @DATA(result). +"result: 1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 18, 19, 20 +``` + +

⬆️ 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. + +## Executable Example +[zcl_demo_abap_internal_tables](./src/zcl_demo_abap_internal_tables.clas.abap) + +> **💡 Note**
+> - The executable example covers the following topics, among others: Creating, populating, reading from, sorting, modifying internal tables +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). > - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file diff --git a/02_Structures.md b/02_Structures.md index f19a991..10deaa2 100644 --- a/02_Structures.md +++ b/02_Structures.md @@ -1,745 +1,727 @@ - - -# Structures - -- [Structures](#structures) - - [Introduction](#introduction) - - [Creating Structures and Structured Types](#creating-structures-and-structured-types) - - [Variants of Structures](#variants-of-structures) - - [Accessing (Components of) Structures](#accessing-components-of-structures) - - [Populating Structures](#populating-structures) - - [Using the VALUE Operator](#using-the-value-operator) - - [Using the NEW Operator](#using-the-new-operator) - - [Using the CORRESPONDING Operator and MOVE-CORRESPONDING Statements](#using-the-corresponding-operator-and-move-corresponding-statements) - - [Clearing Structures](#clearing-structures) - - [Processing Structures](#processing-structures) - - [Excursion: Including Structures](#excursion-including-structures) - - [Executable Example](#executable-example) - -## Introduction -Structures ... - -- are [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry") - with [structured data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm "Glossary Entry") (which is a [complex data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm "Glossary Entry") because it is composed of other data types). -- consist of a sequence of [components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_glosry.htm "Glossary Entry") of any data type, that is, the components of a structure can be, for example, [elementary data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_object_glosry.htm), structures themselves, [internal tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninternal_table_glosry.htm "Glossary Entry") or [references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm). -- are used to combine different data objects that belong together. A typical example is an address. It has several components, such as name, street, city, and so on, that belong together. -- play an important role in the context of internal tables and [database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_table_glosry.htm "Glossary Entry"). Structured types serve as [line types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrow_type_glosry.htm) for these tables. Most internal tables across [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) may have structured line types. For database tables, there is no alternative to structured line types. -- can be created locally in an ABAP program. You can also create them as global [DDIC structures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_structure_glosry.htm) in the [ABAP Dictionary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm). Such a DDIC structure defines a globally available structured type ([DDIC type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_type_glosry.htm)). - - Note: There are other structured types available globally, which may be the structured types most commonly used in ABAP programs: - - [Database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_db_table_glosry.htm) defined in the ABAP Dictionary can be used as data types just like DDIC structures in an ABAP program. This means that when you create a structure in your ABAP program, for example, you can simply use the name of a database table to address the line type of the table. The structure you created will then have the same structured type as the database table. Typically, you use the database tables to create structures of such a type, or internal tables of such a structured line type, to process data read from the database table in structures or internal tables. - - A [CDS entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm) such as a [CDS view](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm) also represents a structured data type and can be used as such in ABAP programs (but not in the ABAP Dictionary). The same applies to [DDIC views](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_view_glosry.htm) that are only available in [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm). - - Structures and structured data types can also be defined in the public [visibility section](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvisibility_section_glosry.htm) of [global classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_class_glosry.htm) or in [global interfaces](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_interface_glosry.htm) and then used globally. - -

⬆️ back to top

- -## Creating Structures and Structured Types - -The typical language elements for creating structures and structured types locally in an ABAP program are [`BEGIN OF ... END OF ...`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes_struc.htm). They are used in combination with the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) keyword to create a structured type and the [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) keyword to create a structure. - -> **💡 Note**
-> This cheat sheet focuses on locally defined structures and structured types. - -**Creating structured types** - -- The following statement defines a structured type introduced by `TYPES`. The type name is preceded by `BEGIN OF` (which marks the beginning of the structured type definition) and `END OF` (the end of the definition). -- The components - at least one must be defined - are listed in between. -- Such structured type definitions are usually grouped together in a [chained statement](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenchained_statement_glosry.htm), i.e. `TYPES` is followed by a colon, and the components are separated by commas. - - -``` abap -TYPES: BEGIN OF struc_type, -         comp1 TYPE ..., -         comp2 TYPE ..., -         comp3 TYPE ..., -         ..., -       END OF struc_type. -``` - -Alternatively, you can also use the following syntax. However, a chained statement provides better readability. -``` abap -TYPES BEGIN OF struc_type. - TYPES comp1 TYPE ... . - TYPES comp2 TYPE ... . - TYPES comp3 TYPE ... . - ... . -TYPES END OF struc_type. -``` - - -- The simplest structures and structured types have [elementary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm "Glossary Entry") -components. -- As mentioned above, the components can be of any type, i.e. they can be of structured types themselves, internal table types, or [reference types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm). -- You can use the [`TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_simple.htm) -and [`LIKE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_referring.htm) additions for the types of the components. -You can use the `LINE OF` addition to refer to a table type or an internal table. - - -``` abap -TYPES: BEGIN OF struc_type, -         comp1 TYPE i,             "elementary type     -         comp2 TYPE c LENGTH 5, "elementary type -         comp3 TYPE structured_type,   "structured type -         comp4 TYPE itab_type,         "internal table type -         comp5 TYPE ddic_type,         "DDIC type -         comp6 TYPE REF TO i,          "data reference -         comp7 LIKE data_object,       "deriving type from a data object - comp8 TYPE LINE OF itab_type, "component has structured type, type derived from internal table type - comp9 LIKE LINE OF itab, "component has structured type, type derived from internal table - comp10, "no TYPE/LIKE specification: component is of type c length 1 -         ..., -       END OF struc_type. -``` - - -> **💡 Note**
-> Outside of classes, you can also refer to DDIC types using `LIKE` (`... comp11 LIKE ddic_type, ...`). If you actually want to refer to an existing data object, but due to typing errors you inadvertently specify a name that exists as DDIC type, errors may be unavoidable. - - -**Creating structures** - -- To create a structure in an ABAP program, you can use the `DATA` keyword. - It works in the same way as the `TYPES` statement above. -- Unlike the `TYPES` statement, you can use the [`VALUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_options.htm) addition to set default values. - -``` abap -DATA: BEGIN OF struc, -        comp1 TYPE ..., -        comp2 TYPE ... VALUE ..., -        comp3 TYPE i VALUE 99, -        comp4 TYPE i VALUE IS INITIAL, "Without the addition VALUE, or if IS INITIAL is specified, - "the content is initial. -        comp5 TYPE local_structured_type, -        ..., - END OF struc. -``` - -Alternatively, you can use the following syntax. Similar to above, a chained statement provides better readability. - -``` abap -DATA BEGIN OF struc. - DATA comp1 TYPE ... . - DATA comp2 TYPE ... VALUE ... . -... . -DATA END OF struc. -``` - -> **💡 Note**
->- The keywords [`CLASS-DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass-data.htm) and [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) can also be used to create structures. In principle, they represent special cases of the general statement shown above. See the ABAP Keyword Documentation for more information. ->- Structures can also be created [inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm) using [`DATA(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm) or [`FINAL(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm), as shown below. - -Creating structures using existing structured types: - -``` abap -"Local structured type -TYPES: BEGIN OF struc_type, -         comp1 TYPE i,                  -         comp2 TYPE c LENGTH 5, - END OF struc_type. - -"Creating a structure using a local structured type -DATA struc_1 TYPE struc_type. - -"Creating structures based on globally available types from the DDIC -"Note: When referring to such types, you cannot provide start values for the individual components. -DATA: struc_2 TYPE some_ddic_structure, - struc_3 TYPE some_ddic_table, - struc_4 TYPE some_cds_view. - -"Structure based on a structured type that is available in the public -"visibility section of a global class -DATA struc_5 TYPE cl_some_class=>struc_type. - -"Creating structures by referring to local data objects and internal table types -DATA: struc_6 LIKE struc_1, - struc_7 LIKE LINE OF some_itab, - struc_8 TYPE LINE OF some_itab_type. -``` - - -Creating structures by inline declaration using `DATA(...)` -- This is particularly useful for declaring data objects at the [operand positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm) where you actually need them. -- In this way, you can avoid an extra declaration of the structure in different contexts. -- You can also use the [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm). - -``` abap -"Structures created inline instead of an extra declared variable -DATA struc_9 LIKE struc_1. -struc_9 = struc_1 - -"Type is derived from the right-hand structure; the content of struc is assigned, too. -DATA(struc_10) = struc_1. -FINAL(struc_11) = struc_9. - -"Structures declared inline instead of an extra declared variable - -"Example: SELECT statement -"Extra declaration -DATA struc_12 TYPE zdemo_abap_fli. - -SELECT SINGLE * - FROM zdemo_abap_fli - WHERE carrid = 'LH' - INTO @struc_12. - -"Inline declaration -SELECT SINGLE * - FROM zdemo_abap_fli - WHERE carrid = 'LH' - INTO @DATA(struc_13). - -"Example: Loop over an internal table -DATA itab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. -... "itab is filled - -"Extra declaration -DATA wa_1 LIKE LINE OF itab. - -LOOP AT itab INTO wa_1. -  ... -ENDLOOP. - -"Inline declaration -LOOP AT itab INTO DATA(wa_2). -  ... -ENDLOOP. -``` - -

⬆️ back to top

- -## Variants of Structures - -Depending on the component type, the structure can be a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm "Glossary Entry"), -a [nested structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennested_structure_glosry.htm "Glossary Entry"), -or a [deep structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm "Glossary Entry"). - -- **Flat structures** contain only elementary types that have a fixed length, that is, there are no internal tables, reference types or strings as components. Nesting does not matter in this context. Even a nested structure is considered flat unless a substructure contains a deep component. - ``` abap - DATA: BEGIN OF struc, -         comp1 TYPE i, -         comp2 TYPE c LENGTH 15, -         comp3 TYPE p LENGTH 8 DECIMALS 2, -         ..., - END OF struc. - ``` - -- **Nested structures**: At least one component of a structure is a [substructure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstructure_glosry.htm "Glossary Entry"), -that is, it refers to another structure. The following example has multiple substructures. - ``` abap - DATA: BEGIN OF address_n, - BEGIN OF name, - title   TYPE string VALUE `Mr.`, - prename TYPE string VALUE `Duncan`, - surname TYPE string VALUE `Pea`, - END OF name, - BEGIN OF street, - name TYPE string VALUE `Vegetable Lane`, - num TYPE string VALUE `11`, - END OF street, - BEGIN OF city, - zipcode TYPE string VALUE `349875`, - name    TYPE string VALUE `Botanica`, - END OF city, - END OF address_n. - ``` - -- **Deep structures**: Contains at least one internal table, reference type, or string as a component. - ``` abap - DATA: BEGIN OF address_d, - name    TYPE string VALUE `Mr. Duncan Pea`, - street  TYPE string VALUE `Vegetable Lane 11`, - city   TYPE string VALUE `349875 Botanica`, - details TYPE TABLE OF some_table WITH EMPTY KEY, - END OF address_d. - ``` - Although the following structure looks quite simple, it is not a flat structure, but a deep structure, because it contains strings. - ``` abap - DATA: BEGIN OF address, - name   TYPE string VALUE `Mr. Duncan Pea`, - street TYPE string VALUE `Vegetable Lane 11`, - city   TYPE string VALUE `349875 Botanica`, - END OF address. - ``` - -> **💡 Note**
->- The data types of DDIC types are all flat (not nested) structures. Exception: Components of type `string` can be contained. ->- [Work areas](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm) of ABAP SQL statements cannot contain any deep components other than strings among others. ->- Especially for assignments and comparisons of deep structures, the compatibility of the source and target structure must be taken into account. - -

⬆️ back to top

- -## Accessing (Components of) Structures - -- Structures can be accessed as a whole. You can also address the individual components of structures at the appropriate operand positions. -- To address the components, use the [structure component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructure_component_sel_glosry.htm "Glossary Entry") -`-`. -- For variables with reference to a structured data object, the [object component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_component_select_glosry.htm) `->` can be used: `...dref->comp ...`. The following syntax also works, but is less *convenient*: `... dref->*-comp ...`. -- ADT and the ABAP Editor provide code completion for structure components after the component selectors. -``` abap -"Addressing components via the structure component selector -... struc-comp1 ... -... struc-comp2 ... -... struc-comp3 ... - -"Examples for addressing the whole structure and individual components -IF struc IS INITIAL. - ... -ENDIF. - -IF struc-comp1 = 1. - ... -ENDIF. - -DATA(complete_struc) = struc. -DATA(comp_value) = struc-comp2. - -"Type and data declarations -TYPES: type_1 TYPE structured_type-comp1, -      type_2 LIKE struc-comp1. - -DATA: var_1 TYPE structured_type-comp1, -      var_2 LIKE struc-comp1. - -"Variables with reference to a structured data object -DATA ref_struc_1 TYPE REF TO structured_type. -ref_struc_1 = NEW #( ). -"Excursion: Creating a reference variable using inline declaration -DATA(ref_struc_2) = NEW structured_type( ). - -... ref_struc_1->comp1 ... -... ref_struc_1->*-comp1 ... "Using the dereferencing operator -... ref_struc_2->-comp2 ... -... ref_struc_2->*-comp2 ... "Using the dereferencing operator -``` - -Nested components can be addressed using chaining: -``` abap -... struc-substructure-comp1 ... -... address_n-name-title ... -``` - -> **💡 Note**
-> There are syntax options for dynamically accessing structure components. See the [Dynamic Porgramming](06_Dynamic_Programming.md) cheat sheet. - -

⬆️ back to top

- -## Populating Structures - -You can copy the content of a structure to another using the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm) `=`. -In the following example, it is assumed that the target and source structures are of compatible types. In general, note that special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) apply to value assignments involving structures. -``` abap -some_struc = another_struc. - -"When creating a new structure by inline declaration, the type of -"the right-hand structure is derived and the content is assigned. - -DATA(struc_inl) = some_struc. -``` - -To assign values to individual structure components, use the component selector. -``` abap -TYPES: BEGIN OF addr_struc, -        name   TYPE string, -        street TYPE string, -        city   TYPE string, -    END OF addr_struc. - -DATA address TYPE addr_struc. - -address-name   = `Mr. Duncan Pea`. - -address-street = `Vegetable Lane 11`. - -address-city   = `349875 Botanica`. -``` - -

⬆️ back to top

- -### Using the VALUE Operator - -- The [`VALUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_value.htm) operator can be used to construct the content of complex data objects such as structures or internal tables. -- It is particularly useful because assigning values by addressing the structure components individually can be very cumbersome, especially when assigning values to structure components at the [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry"). -- If the type of the operand can be inferred implicitly, the `#` character can be used used before the parentheses. Otherwise, the type must be specified explicitly. -- The `VALUE` operator and inline declarations can be used to create and populate structures in one go. -- Note that there are special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) rules for structures. See the ABAP Keyword Documentation for more details. - - -``` abap -"# used: type of the operand can be implicitly derived -address = VALUE #( name   = `Mr. Duncan Pea` -                  street = `Vegetable Lane 11` -                  city   = `349875 Botanica` ). - -"Declaring a structure inline -"Type used explicitly: type of the operand cannot be implicitly derived -DATA(addr) = VALUE addr_struc( name   = `Mr. Duncan Pea` -                    street = `Vegetable Lane 11` -                    city   = `349875 Botanica` ). - -"Nesting value operators -TYPES: BEGIN OF struc_nested, - a TYPE i, - BEGIN OF nested_1, - b TYPE i, - c TYPE i, - END OF nested_1, - BEGIN OF nested_2, - d TYPE i, - e TYPE i, - END OF nested_2, - END OF struc_nested. - -DATA str_1 TYPE struc_nested. - -str_1 = VALUE #( a = 1 - nested_1 = VALUE #( b = 2 c = 3 ) - nested_2 = VALUE #( d = 4 e = 5 ) ). - -"Inline declaration -"Component a is not specified here, i.e. its value remains initial. -DATA(str_2) = VALUE struc_nested( nested_1 = VALUE #( b = 2 c = 3 ) - nested_2 = VALUE #( d = 4 e = 5 ) ). - -"Apart from the VALUE operator, the NEW operator can be used to create -"a data reference variable (and populate the structure) -DATA(str_ref) = NEW struc_nested( a = 1 - nested_1 = VALUE #( b = 2 c = 3 ) - nested_2 = VALUE #( d = 4 e = 5 ) ). -``` - -

⬆️ back to top

- -### Using the NEW Operator - -Using the instance operator [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm), you can create [anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm "Glossary Entry"), such as anonymous structures. You can access the components or the entire data objects by [dereferencing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm). For more information, refer to the [Dynamic Programming](06_Dynamic_Programming.md) and [Constructor Expressions](05_Constructor_Expressions.md) cheat sheets. - -```abap -"Creating a data reference variable -DATA addr_ref1 TYPE REF TO addr_struc. - -"Populating the anonymous structure -addr_ref1 = NEW #( name = `Mr. Duncan Pea` - street = `Vegetable Lane 11` - city = `349875 Botanica` ). - -addr_ref1->name = `Mrs. Jane Doe`. - -"Declaring an anonymous structure/a data reference variable inline -DATA(addr_ref2) = NEW addr_struc( name = `Mr. Duncan Pea` - street = `Vegetable Lane 11` - city = `349875 Botanica` ). - -addr_ref2->* = VALUE #( BASE addr_ref2->* name = `Mr. John Doe` ). -``` - -

⬆️ back to top

- -### Using the CORRESPONDING Operator and MOVE-CORRESPONDING Statements - -- You can use statements with [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) -and the [`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator to assign values to structure components, especially when assigning values from a source structure to a target structure which have incompatible types and/or differently named components. -- Both are used to assign identically named components of structures to each other. -- The syntax also works for structures of the same type. -- Also note the special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) rules for structures in this context. - -> **💡 Note**
->- The [`CL_ABAP_CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencl_abap_corresponding.htm) system class is available for making assignments. See the ABAP Keyword Documentation for the details. ->- The `INTO` clause of ABAP SQL statements has the `CORRESPONDING` addition. There, the following basic rule applies, which affects the value assignment: Without the `CORRESPONDING ...` addition, column names do not matter, only the position. With the `CORRESPONDING ...` addition, the position of the columns does not matter, only the name. See examples in the ABAP SQL cheat sheet. - -The following examples demonstrate the value assignment using `MOVE-CORRESPONDING` statements and the `CORRESPONDING` operator with various additions. -The focus is on flat structures only. - -``` abap -"Moves identically named components; content in other components -"of the targets structure are kept. - -MOVE-CORRESPONDING struc TO diff_struc. - -"Initializes target structure; moves identically named components - -diff_struc = CORRESPONDING #( struc ). - -"Same effect as the first MOVE-CORRESPONDING statement; -"addition BASE keeps existing content - -diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc ). - -"MAPPING addition: Specifying components of a source structure that are -"assigned to the components of a target structure in mapping -"relationships. - -diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc MAPPING comp1 = compa ). - -"EXCEPT addition: Excluding components from the assignment. - -diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc EXCEPT comp1 ). -``` - -Value assignments in deep structures -- In the context of deep structures, there are additional syntax variants available for [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) statements and the [`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator. -- The following examples focus on internal tables as structure components. Check out the syntax in action in the executable example. - -``` abap -"Nonidentical elementary component types are kept in target -"structure which is true for the below MOVE-CORRESPONDING statements; -"existing internal table content is replaced by content of -"the source table irrespective of identically named components - -MOVE-CORRESPONDING deep_struc TO diff_deep_struc. - -"Existing internal table content is replaced but the value -"assignment happens for identically named components only. - -MOVE-CORRESPONDING deep_struc TO diff_deep_struc EXPANDING NESTED TABLES. - -"Existing internal table content is kept; table content of the source -"structure are added but the value assignment happens like the first -"MOVE-CORRESPONDING statement without further syntax additions. - -MOVE-CORRESPONDING deep_struc TO diff_deep_struc KEEPING TARGET LINES. - -"Existing internal table content is kept; table content of the source -"structure are added; the value assignment happens like the statement -"MOVE-CORRESPONDING ... EXPANDING NESTED TABLES. - -MOVE-CORRESPONDING deep_struc TO diff_deep_struc EXPANDING NESTED TABLES KEEPING TARGET LINES. - -"Target structure is initialized; the value assignment for an internal -"table happens irrespective of identically named components. - -diff_deep_struc = CORRESPONDING #( deep_struc ). - -"Target structure is initialized; the value assignment for an internal -"table happens for identically named components only. - -diff_deep_struc = CORRESPONDING #( DEEP deep_struc ). - -"Nonidentical elementary component types are kept in target structure; -"internal table content is replaced; there, the value assignment -"happens like using the CORRESPONDING operator without addition. - -diff_deep_struc = CORRESPONDING #( BASE ( diff_struc ) deep_struc ). - -"Nonidentical elementary component types are kept in target structure; -"internal table content is replaced; there, the value assignment -"happens like using the CORRESPONDING operator with the addition DEEP. - -diff_deep_struc = CORRESPONDING #( DEEP BASE ( diff_struc ) deep_struc ). - -"Nonidentical elementary component types are kept in target structure; -"internal table content is kept, too, and table content of the -"source structure are added; there, the value assignment -"happens like using the CORRESPONDING operator without addition. - -diff_deep_struc = CORRESPONDING #( APPENDING BASE ( diff_struc ) deep_struc ). - -"Nonidentical elementary component types are kept in target structure; -"internal table content is kept, too, and table content of the -"source structure are added; there, the value assignment -"happens like using the CORRESPONDING operator with the addition DEEP. - -diff_deep_struc = CORRESPONDING #( DEEP APPENDING BASE ( diff_struc ) deep_struc ). -``` - -

⬆️ back to top

- -## 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. - -``` abap -CLEAR struc-component. - -CLEAR struc. - -"Note: An assignment using the VALUE operator without entries in the parentheses clears the structure. -struc = VALUE #( ). -``` - -

⬆️ back to top

- -## Processing Structures -Structures are primarily used to process data from tables. In this context, structures often take on the role of a [work area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry"). -The following code snippets cover only a selection. For more examples, see the cheat sheets about internal tables and ABAP SQL. - -**Reading a row from a database table into a structure that has a compatible type**. Note that, since database tables are flat, the -target structure must also be flat. In the example below, the [`SINGLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_single.htm) -addition reads only a single row into the structure. It returns the first entry that matches the `WHERE` condition. - -``` abap -"Creating a structure with a compatible type -DATA ls_fli1 TYPE zdemo_abap_fli. - -SELECT SINGLE FROM zdemo_abap_fli - FIELDS * - WHERE carrid = 'LH' - INTO @ls_fli1. - -"Target structure declared inline -SELECT SINGLE FROM zdemo_abap_fli - FIELDS * - WHERE carrid = 'LH' - INTO @DATA(ls_fli2). -``` -**Reading a row from a database table into a structure that has an incompatible type**. -Components in the structure with identical names are filled. - -``` abap -SELECT SINGLE FROM zdemo_abap_fli - FIELDS * - WHERE carrid = 'AA' - INTO CORRESPONDING FIELDS OF @ls_fli_diff. -``` -**Reading a line from an internal table into a structure** ... - -... using a `SELECT` statement. Note the specified alias name and that ABAP variables like internal tables must be escaped with `@`. The addition `INTO CORRESPONDING FIELDS OF` also applies here. -``` abap -SELECT SINGLE FROM @itab AS itab_alias - FIELDS * - WHERE ... - INTO @DATA(ls_struc). - "INTO CORRESPONDING FIELDS OF @some_existing_struc. -``` -... using a `READ TABLE` statement. The code snippet below shows the reading of a line into a [work area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry"), a [field symbol](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm "Glossary Entry"), and a [data reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm "Glossary Entry"), all of which -represent structured data objects that are declared inline. In the following example, a line is read based on the line number by -specifying `INDEX`. For more details, see the section *Determining the target area* in the cheat sheet [Internal Tables](01_Internal_Tables.md#). -``` abap -READ TABLE itab INTO DATA(wa) INDEX 1. - -READ TABLE itab ASSIGNING FIELD-SYMBOL() INDEX 2. - -READ TABLE itab REFERENCE INTO DATA(dref) INDEX 3. -``` -... using a [table expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expression_glosry.htm "Glossary Entry"). -The code snippet shows how to read a line into a structure declared inline. The index is given in square brackets. -``` abap -DATA(ls_table_exp) = itab[ 3 ]. -``` - -**Sequentially reading** ... - -... a row from a database table into a structure. A `SELECT` loop can be specified with the syntax `SELECT ... ENDSELECT.`. -In the following example, the row found and returned in a structure declared inline can be processed further. -``` abap -SELECT FROM zdemo_abap_fli - FIELDS * - WHERE carrid = 'AZ' - INTO @DATA(ls_sel_loop). -       - IF sy-subrc = 0. - ... - ENDIF. -ENDSELECT. -``` -... a line from an internal table into a structure using a [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm) statement. There are many ways to specify the condition on which the loop is based. The following example covers the option of reading all lines sequentially into a field symbol declared inline. When using a field symbol, you can, for example, directly modify components. -``` abap -LOOP AT itab ASSIGNING FIELD-SYMBOL(). - -comp1 = ... - ... -ENDLOOP. -``` - -**Inserting a single row into a database table from a structure** using ABAP SQL statements with -[`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_dbtab.htm). The following statements can be considered as alternatives. The third statement shows that instead of inserting a row from an existing structure, you can create and fill a structure directly. -Note that you should avoid inserting a row with a particular key into the database table if a row with the same key already exists. -``` abap -INSERT INTO dbtab VALUES @struc. - -INSERT dbtab FROM @struc. - -INSERT dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). -``` -**Updating a single row in a database table from a structure** using ABAP SQL statements with [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapupdate.htm). Note that this syntax changes the entire row and all of its components. -``` abap -UPDATE dbtab FROM @struc. - -UPDATE dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). -``` -If you want to update a database table row from a structure by specifying components to be changed without overwriting other components, you can use the following method. First, read the desired row from the database table into a structure. Then, use the `VALUE` operator with the `BASE` addition and specify the components to be changed. -``` abap -SELECT SINGLE * - FROM dbtab - WHERE ... - INTO @DATA(wa). - -UPDATE dbtab FROM @( VALUE #( BASE wa comp2 = ... comp4 = ... ) ). -``` -**Updating or creating a single row in a database table from a structure** using ABAP SQL statements with -[`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_dbtab.htm). If a row with the same key as specified in the structure already exists in the database table, the row is updated. If no row with the keys specified in the structure exists, a new row is created in the database table. -``` abap -MODIFY dbtab FROM @struc. - -MODIFY dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). -``` -**Adding lines to and updating single lines in an internal table from a structure** using `INSERT`, -`APPEND`, and `MODIFY` statements. -- Note that all statements, including `INSERT` and `MODIFY`, are ABAP statements in this context, not ABAP SQL statements. -- Both `INSERT` and `APPEND` add one or more lines to an internal table. While `APPEND` adds at the bottom of the -internal table, `INSERT` can be used to add lines at a specific position in the table. If you do not specify the position, the lines are also added at the bottom of the table. However, unlike `APPEND`, `INSERT` does not set `sy-tabix`. -- `MODIFY` changes the content of an internal table entry. -- Statements using the `VALUE` operator to directly create and populate the structures are also possible. For more information and code -snippets, see the [Internal Tables](01_Internal_Tables.md#) cheat sheet. -``` abap -INSERT struc INTO TABLE itab. - -APPEND struc TO itab. - -MODIFY TABLE itab FROM struc. -``` - -

⬆️ back to top

- -## Excursion: Including Structures - -- [`INCLUDE TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinclude_type.htm) -and [`INCLUDE STRUCTURE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinclude_type.htm) statements -are used in the context of local structures. -- Structured data objects and types created with `... BEGIN OF... END OF ...` can use this syntax to include components of another structure, whether it is a locally defined or global structure, without creating substructures. -- `INCLUDE TYPE` can be used to include a structured type. -- You can use `INCLUDE STRUCTURE` to include a structure. - -> **💡 Note**
-> - They are not additions of `... BEGIN OF ... END OF ...` but individual ABAP statements. -> - If you use a chained statement with a colon to declare the structure, the inclusion of other structures with these statements interrupts the chained statement, that is, the components of the included structures are included as direct components of the [superstructure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperstructure_glosry.htm "Glossary Entry"). ->- By using the optional `AS` addition and specifying a name, the included components can be addressed by this common name as if they were actually components of a substructure. ->- The optional `RENAMING WITH SUFFIX` addition, followed by a name, gives the included components a suffix name to avoid naming conflicts with other components. - -The following example shows how structured types and data objects are included in another structure. First, three structured types and a structured data object based on one of these types are created. Then, the types and the structure are included in the structured type `address_type`. The executable example demonstrates a structure that includes other structures in this way. -``` abap -TYPES: BEGIN OF name_type, - title   TYPE string, - prename TYPE string, - surname TYPE string, - END OF name_type, - BEGIN OF street_type, - name TYPE string, - num TYPE string, - END OF street_type, - BEGIN OF city_type, - zipcode TYPE string, - name    TYPE string, - END OF city_type. - -DATA city_struc TYPE city_type. - -TYPES BEGIN OF address_type. - INCLUDE TYPE name_type AS name. - INCLUDE TYPE street_type AS street RENAMING WITH SUFFIX _street. - INCLUDE STRUCTURE city_struc AS city RENAMING WITH SUFFIX _city. -TYPES END OF address_type. -``` - - -

⬆️ back to top

- -## Executable Example -[zcl_demo_abap_structures](./src/zcl_demo_abap_structures.clas.abap) - -> **💡 Note**
-> - The executable example covers the following topics, among others: -> - Creating structures and structured types -> - Variants of structures -> - Accessing, populating, and clearing structures -> - Structures in the context of tables -> - Including structures -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). + + +# Structures + +- [Structures](#structures) + - [Introduction](#introduction) + - [Creating Structures and Structured Types](#creating-structures-and-structured-types) + - [Variants of Structures](#variants-of-structures) + - [Accessing (Components of) Structures](#accessing-components-of-structures) + - [Populating Structures](#populating-structures) + - [Using the VALUE Operator](#using-the-value-operator) + - [Using the NEW Operator](#using-the-new-operator) + - [Using the CORRESPONDING Operator and MOVE-CORRESPONDING Statements](#using-the-corresponding-operator-and-move-corresponding-statements) + - [Clearing Structures](#clearing-structures) + - [Processing Structures](#processing-structures) + - [Excursion: Including Structures](#excursion-including-structures) + - [Executable Example](#executable-example) + +## Introduction +Structures ... + +- are [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry") + with [structured data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm "Glossary Entry") (which is a [complex data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm "Glossary Entry") because it is composed of other data types). +- consist of a sequence of [components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_glosry.htm "Glossary Entry") of any data type, that is, the components of a structure can be, for example, [elementary data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_object_glosry.htm), structures themselves, [internal tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninternal_table_glosry.htm "Glossary Entry") or [references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm). +- are used to combine different data objects that belong together. A typical example is an address. It has several components, such as name, street, city, and so on, that belong together. +- play an important role in the context of internal tables and [database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_table_glosry.htm "Glossary Entry"). Structured types serve as [line types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrow_type_glosry.htm) for these tables. Most internal tables across [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) may have structured line types. For database tables, there is no alternative to structured line types. +- can be created locally in an ABAP program. You can also create them as global [DDIC structures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_structure_glosry.htm) in the [ABAP Dictionary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm). Such a DDIC structure defines a globally available structured type ([DDIC type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_type_glosry.htm)). + - Note: There are other structured types available globally, which may be the structured types most commonly used in ABAP programs: + - [Database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_db_table_glosry.htm) defined in the ABAP Dictionary can be used as data types just like DDIC structures in an ABAP program. This means that when you create a structure in your ABAP program, for example, you can simply use the name of a database table to address the line type of the table. The structure you created will then have the same structured type as the database table. Typically, you use the database tables to create structures of such a type, or internal tables of such a structured line type, to process data read from the database table in structures or internal tables. + - A [CDS entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm) such as a [CDS view](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm) also represents a structured data type and can be used as such in ABAP programs (but not in the ABAP Dictionary). The same applies to [DDIC views](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_view_glosry.htm) that are only available in [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm). + - Structures and structured data types can also be defined in the public [visibility section](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvisibility_section_glosry.htm) of [global classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_class_glosry.htm) or in [global interfaces](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_interface_glosry.htm) and then used globally. + +

⬆️ back to top

+ +## Creating Structures and Structured Types + +The typical language elements for creating structures and structured types locally in an ABAP program are [`BEGIN OF ... END OF ...`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes_struc.htm). They are used in combination with the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) keyword to create a structured type and the [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) keyword to create a structure. + +> **💡 Note**
+> This cheat sheet focuses on locally defined structures and structured types. + +**Creating structured types** + +- The following statement defines a structured type introduced by `TYPES`. The type name is preceded by `BEGIN OF` (which marks the beginning of the structured type definition) and `END OF` (the end of the definition). +- The components - at least one must be defined - are listed in between. +- Such structured type definitions are usually grouped together in a [chained statement](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenchained_statement_glosry.htm), i.e. `TYPES` is followed by a colon, and the components are separated by commas. + + +``` abap +TYPES: BEGIN OF struc_type, +         comp1 TYPE ..., +         comp2 TYPE ..., +         comp3 TYPE ..., +         ..., +       END OF struc_type. +``` + +Alternatively, you can also use the following syntax. However, a chained statement provides better readability. +``` abap +TYPES BEGIN OF struc_type. + TYPES comp1 TYPE ... . + TYPES comp2 TYPE ... . + TYPES comp3 TYPE ... . + ... . +TYPES END OF struc_type. +``` + +- The simplest structures and structured types have [elementary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm "Glossary Entry") +components. +- As mentioned above, the components can be of any type, i.e. they can be of structured types themselves, internal table types, or [reference types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm). +- You can use the [`TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_simple.htm) +and [`LIKE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_referring.htm) additions for the types of the components. +You can use the `LINE OF` addition to refer to a table type or an internal table. + + +``` abap +TYPES: BEGIN OF struc_type, +         comp1 TYPE i,             "elementary type     +         comp2 TYPE c LENGTH 5, "elementary type +         comp3 TYPE structured_type,   "structured type +         comp4 TYPE itab_type,         "internal table type +         comp5 TYPE ddic_type,         "DDIC type +         comp6 TYPE REF TO i,          "data reference +         comp7 LIKE data_object,       "deriving type from a data object + comp8 TYPE LINE OF itab_type, "component has structured type, type derived from internal table type + comp9 LIKE LINE OF itab, "component has structured type, type derived from internal table + comp10, "no TYPE/LIKE specification: component is of type c length 1 +         ..., +       END OF struc_type. +``` + + +> **💡 Note**
+> Outside of classes, you can also refer to DDIC types using `LIKE` (`... comp11 LIKE ddic_type, ...`). If you actually want to refer to an existing data object, but due to typing errors you inadvertently specify a name that exists as DDIC type, errors may be unavoidable. + + +**Creating structures** + +- To create a structure in an ABAP program, you can use the `DATA` keyword. - It works in the same way as the `TYPES` statement above. +- Unlike the `TYPES` statement, you can use the [`VALUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_options.htm) addition to set default values. + +``` abap +DATA: BEGIN OF struc, +        comp1 TYPE ..., +        comp2 TYPE ... VALUE ..., +        comp3 TYPE i VALUE 99, +        comp4 TYPE i VALUE IS INITIAL, "Without the addition VALUE, or if IS INITIAL is specified, + "the content is initial. +        comp5 TYPE local_structured_type, +        ..., + END OF struc. +``` + +Alternatively, you can use the following syntax. Similar to above, a chained statement provides better readability. + +``` abap +DATA BEGIN OF struc. + DATA comp1 TYPE ... . + DATA comp2 TYPE ... VALUE ... . +... . +DATA END OF struc. +``` + +> **💡 Note**
+>- The keywords [`CLASS-DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass-data.htm) and [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) can also be used to create structures. In principle, they represent special cases of the general statement shown above. See the ABAP Keyword Documentation for more information. +>- Structures can also be created [inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm) using [`DATA(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm) or [`FINAL(...)`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm), as shown below. + +Creating structures using existing structured types: + +``` abap +"Local structured type +TYPES: BEGIN OF struc_type, +         comp1 TYPE i,                  +         comp2 TYPE c LENGTH 5, + END OF struc_type. + +"Creating a structure using a local structured type +DATA struc_1 TYPE struc_type. + +"Creating structures based on globally available types from the DDIC +"Note: When referring to such types, you cannot provide start values for the individual components. +DATA: struc_2 TYPE some_ddic_structure, + struc_3 TYPE some_ddic_table, + struc_4 TYPE some_cds_view. + +"Structure based on a structured type that is available in the public +"visibility section of a global class +DATA struc_5 TYPE cl_some_class=>struc_type. + +"Creating structures by referring to local data objects and internal table types +DATA: struc_6 LIKE struc_1, + struc_7 LIKE LINE OF some_itab, + struc_8 TYPE LINE OF some_itab_type. +``` + + +Creating structures by inline declaration using `DATA(...)` +- This is particularly useful for declaring data objects at the [operand positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm) where you actually need them. +- In this way, you can avoid an extra declaration of the structure in different contexts. +- You can also use the [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm). + +``` abap +"Structures created inline instead of an extra declared variable +DATA struc_9 LIKE struc_1. +struc_9 = struc_1 + +"Type is derived from the right-hand structure; the content of struc is assigned, too. +DATA(struc_10) = struc_1. +FINAL(struc_11) = struc_9. + +"Structures declared inline instead of an extra declared variable + +"Example: SELECT statement +"Extra declaration +DATA struc_12 TYPE zdemo_abap_fli. + +SELECT SINGLE * + FROM zdemo_abap_fli + WHERE carrid = 'LH' + INTO @struc_12. + +"Inline declaration +SELECT SINGLE * + FROM zdemo_abap_fli + WHERE carrid = 'LH' + INTO @DATA(struc_13). + +"Example: Loop over an internal table +DATA itab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. +... "itab is filled + +"Extra declaration +DATA wa_1 LIKE LINE OF itab. + +LOOP AT itab INTO wa_1. +  ... +ENDLOOP. + +"Inline declaration +LOOP AT itab INTO DATA(wa_2). +  ... +ENDLOOP. +``` + +

⬆️ back to top

+ +## Variants of Structures + +Depending on the component type, the structure can be a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm "Glossary Entry"), +a [nested structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennested_structure_glosry.htm "Glossary Entry"), +or a [deep structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm "Glossary Entry"). + +- **Flat structures** contain only elementary types that have a fixed length, that is, there are no internal tables, reference types or strings as components. Nesting does not matter in this context. Even a nested structure is considered flat unless a substructure contains a deep component. + ``` abap + DATA: BEGIN OF struc, +         comp1 TYPE i, +         comp2 TYPE c LENGTH 15, +         comp3 TYPE p LENGTH 8 DECIMALS 2, +         ..., + END OF struc. + ``` + +- **Nested structures**: At least one component of a structure is a [substructure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstructure_glosry.htm "Glossary Entry"), +that is, it refers to another structure. The following example has multiple substructures. + ``` abap + DATA: BEGIN OF address_n, + BEGIN OF name, + title   TYPE string VALUE `Mr.`, + prename TYPE string VALUE `Duncan`, + surname TYPE string VALUE `Pea`, + END OF name, + BEGIN OF street, + name TYPE string VALUE `Vegetable Lane`, + num TYPE string VALUE `11`, + END OF street, + BEGIN OF city, + zipcode TYPE string VALUE `349875`, + name    TYPE string VALUE `Botanica`, + END OF city, + END OF address_n. + ``` + +- **Deep structures**: Contains at least one internal table, reference type, or string as a component. + ``` abap + DATA: BEGIN OF address_d, + name    TYPE string VALUE `Mr. Duncan Pea`, + street  TYPE string VALUE `Vegetable Lane 11`, + city   TYPE string VALUE `349875 Botanica`, + details TYPE TABLE OF some_table WITH EMPTY KEY, + END OF address_d. + ``` + Although the following structure looks quite simple, it is not a flat structure, but a deep structure, because it contains strings. + ``` abap + DATA: BEGIN OF address, + name   TYPE string VALUE `Mr. Duncan Pea`, + street TYPE string VALUE `Vegetable Lane 11`, + city   TYPE string VALUE `349875 Botanica`, + END OF address. + ``` + +> **💡 Note**
+>- The data types of DDIC types are all flat (not nested) structures. Exception: Components of type `string` can be contained. +>- [Work areas](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm) of ABAP SQL statements cannot contain any deep components other than strings among others. +>- Especially for assignments and comparisons of deep structures, the compatibility of the source and target structure must be taken into account. + +

⬆️ back to top

+ +## Accessing (Components of) Structures + +- Structures can be accessed as a whole. You can also address the individual components of structures at the appropriate operand positions. +- To address the components, use the [structure component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructure_component_sel_glosry.htm "Glossary Entry") +`-`. +- For variables with reference to a structured data object, the [object component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_component_select_glosry.htm) `->` can be used: `...dref->comp ...`. The following syntax also works, but is less *convenient*: `... dref->*-comp ...`. +- ADT and the ABAP Editor provide code completion for structure components after the component selectors. +``` abap +"Addressing components via the structure component selector +... struc-comp1 ... +... struc-comp2 ... +... struc-comp3 ... + +"Examples for addressing the whole structure and individual components +IF struc IS INITIAL. + ... +ENDIF. + +IF struc-comp1 = 1. + ... +ENDIF. + +DATA(complete_struc) = struc. +DATA(comp_value) = struc-comp2. + +"Type and data declarations +TYPES: type_1 TYPE structured_type-comp1, +      type_2 LIKE struc-comp1. + +DATA: var_1 TYPE structured_type-comp1, +      var_2 LIKE struc-comp1. + +"Variables with reference to a structured data object +DATA ref_struc_1 TYPE REF TO structured_type. +ref_struc_1 = NEW #( ). +"Excursion: Creating a reference variable using inline declaration +DATA(ref_struc_2) = NEW structured_type( ). + +... ref_struc_1->comp1 ... +... ref_struc_1->*-comp1 ... "Using the dereferencing operator +... ref_struc_2->-comp2 ... +... ref_struc_2->*-comp2 ... "Using the dereferencing operator +``` + +Nested components can be addressed using chaining: +``` abap +... struc-substructure-comp1 ... +... address_n-name-title ... +``` + +> **💡 Note**
+> There are syntax options for dynamically accessing structure components. See the [Dynamic Porgramming](06_Dynamic_Programming.md) cheat sheet. + +

⬆️ back to top

+ +## Populating Structures + +You can copy the content of a structure to another using the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm) `=`. +In the following example, it is assumed that the target and source structures are of compatible types. In general, note that special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) apply to value assignments involving structures. +``` abap +some_struc = another_struc. + +"When creating a new structure by inline declaration, the type of +"the right-hand structure is derived and the content is assigned. + +DATA(struc_inl) = some_struc. +``` + +To assign values to individual structure components, use the component selector. +``` abap +TYPES: BEGIN OF addr_struc, +        name   TYPE string, +        street TYPE string, +        city   TYPE string, +    END OF addr_struc. + +DATA address TYPE addr_struc. + +address-name   = `Mr. Duncan Pea`. +address-street = `Vegetable Lane 11`. +address-city   = `349875 Botanica`. +``` + +

⬆️ back to top

+ +### Using the VALUE Operator + +- The [`VALUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_value.htm) operator can be used to construct the content of complex data objects such as structures or internal tables. +- It is particularly useful because assigning values by addressing the structure components individually can be very cumbersome, especially when assigning values to structure components at the [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry"). +- If the type of the operand can be inferred implicitly, the `#` character can be used used before the parentheses. Otherwise, the type must be specified explicitly. +- The `VALUE` operator and inline declarations can be used to create and populate structures in one go. +- Note that there are special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) rules for structures. See the ABAP Keyword Documentation for more details. + + +``` abap +"# used: type of the operand can be implicitly derived +address = VALUE #( name   = `Mr. Duncan Pea` +                  street = `Vegetable Lane 11` +                  city   = `349875 Botanica` ). + +"Declaring a structure inline +"Type used explicitly: type of the operand cannot be implicitly derived +DATA(addr) = VALUE addr_struc( name   = `Mr. Duncan Pea` +                    street = `Vegetable Lane 11` +                    city   = `349875 Botanica` ). + +"Nesting value operators +TYPES: BEGIN OF struc_nested, + a TYPE i, + BEGIN OF nested_1, + b TYPE i, + c TYPE i, + END OF nested_1, + BEGIN OF nested_2, + d TYPE i, + e TYPE i, + END OF nested_2, + END OF struc_nested. + +DATA str_1 TYPE struc_nested. + +str_1 = VALUE #( a = 1 + nested_1 = VALUE #( b = 2 c = 3 ) + nested_2 = VALUE #( d = 4 e = 5 ) ). + +"Inline declaration +"Component a is not specified here, i.e. its value remains initial. +DATA(str_2) = VALUE struc_nested( nested_1 = VALUE #( b = 2 c = 3 ) + nested_2 = VALUE #( d = 4 e = 5 ) ). + +"Apart from the VALUE operator, the NEW operator can be used to create +"a data reference variable (and populate the structure) +DATA(str_ref) = NEW struc_nested( a = 1 + nested_1 = VALUE #( b = 2 c = 3 ) + nested_2 = VALUE #( d = 4 e = 5 ) ). +``` + +

⬆️ back to top

+ +### Using the NEW Operator + +Using the instance operator [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm), you can create [anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm "Glossary Entry"), such as anonymous structures. You can access the components or the entire data objects by [dereferencing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendereferencing_operat_glosry.htm). For more information, refer to the [Dynamic Programming](06_Dynamic_Programming.md) and [Constructor Expressions](05_Constructor_Expressions.md) cheat sheets. + +```abap +"Creating a data reference variable +DATA addr_ref1 TYPE REF TO addr_struc. + +"Populating the anonymous structure +addr_ref1 = NEW #( name = `Mr. Duncan Pea` + street = `Vegetable Lane 11` + city = `349875 Botanica` ). + +addr_ref1->name = `Mrs. Jane Doe`. + +"Declaring an anonymous structure/a data reference variable inline +DATA(addr_ref2) = NEW addr_struc( name = `Mr. Duncan Pea` + street = `Vegetable Lane 11` + city = `349875 Botanica` ). + +addr_ref2->* = VALUE #( BASE addr_ref2->* name = `Mr. John Doe` ). +``` + +

⬆️ back to top

+ +### Using the CORRESPONDING Operator and MOVE-CORRESPONDING Statements + +- You can use statements with [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) +and the [`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator to assign values to structure components, especially when assigning values from a source structure to a target structure which have incompatible types and/or differently named components. +- Both are used to assign identically named components of structures to each other. +- The syntax also works for structures of the same type. +- Also note the special [conversion](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_struc.htm) and [comparison](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules_operands_struc.htm) rules for structures in this context. + +> **💡 Note**
+>- The [`CL_ABAP_CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencl_abap_corresponding.htm) system class is available for making assignments. See the ABAP Keyword Documentation for the details. +>- The `INTO` clause of ABAP SQL statements has the `CORRESPONDING` addition. There, the following basic rule applies, which affects the value assignment: Without the `CORRESPONDING ...` addition, column names do not matter, only the position. With the `CORRESPONDING ...` addition, the position of the columns does not matter, only the name. See examples in the ABAP SQL cheat sheet. + +The following examples demonstrate the value assignment using `MOVE-CORRESPONDING` statements and the `CORRESPONDING` operator with various additions. +The focus is on flat structures only. + +``` abap +"Moves identically named components; content in other components +"of the targets structure are kept. +MOVE-CORRESPONDING struc TO diff_struc. + +"Initializes target structure; moves identically named components +diff_struc = CORRESPONDING #( struc ). + +"Same effect as the first MOVE-CORRESPONDING statement; +"addition BASE keeps existing content +diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc ). + +"MAPPING addition: Specifying components of a source structure that are +"assigned to the components of a target structure in mapping +"relationships. +diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc MAPPING comp1 = compa ). + +"EXCEPT addition: Excluding components from the assignment. +diff_struc = CORRESPONDING #( BASE ( diff_struc ) struc EXCEPT comp1 ). +``` + +Value assignments in deep structures +- In the context of deep structures, there are additional syntax variants available for [`MOVE-CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove-corresponding.htm) statements and the [`CORRESPONDING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_corresponding.htm) operator. +- The following examples focus on internal tables as structure components. Check out the syntax in action in the executable example. + +``` abap +"Nonidentical elementary component types are kept in target +"structure which is true for the below MOVE-CORRESPONDING statements; +"existing internal table content is replaced by content of +"the source table irrespective of identically named components +MOVE-CORRESPONDING deep_struc TO diff_deep_struc. + +"Existing internal table content is replaced but the value +"assignment happens for identically named components only. +MOVE-CORRESPONDING deep_struc TO diff_deep_struc EXPANDING NESTED TABLES. + +"Existing internal table content is kept; table content of the source +"structure are added but the value assignment happens like the first +"MOVE-CORRESPONDING statement without further syntax additions. +MOVE-CORRESPONDING deep_struc TO diff_deep_struc KEEPING TARGET LINES. + +"Existing internal table content is kept; table content of the source +"structure are added; the value assignment happens like the statement +"MOVE-CORRESPONDING ... EXPANDING NESTED TABLES. +MOVE-CORRESPONDING deep_struc TO diff_deep_struc EXPANDING NESTED TABLES KEEPING TARGET LINES. + +"Target structure is initialized; the value assignment for an internal +"table happens irrespective of identically named components. +diff_deep_struc = CORRESPONDING #( deep_struc ). + +"Target structure is initialized; the value assignment for an internal +"table happens for identically named components only. +diff_deep_struc = CORRESPONDING #( DEEP deep_struc ). + +"Nonidentical elementary component types are kept in target structure; +"internal table content is replaced; there, the value assignment +"happens like using the CORRESPONDING operator without addition. +diff_deep_struc = CORRESPONDING #( BASE ( diff_struc ) deep_struc ). + +"Nonidentical elementary component types are kept in target structure; +"internal table content is replaced; there, the value assignment +"happens like using the CORRESPONDING operator with the addition DEEP. +diff_deep_struc = CORRESPONDING #( DEEP BASE ( diff_struc ) deep_struc ). + +"Nonidentical elementary component types are kept in target structure; +"internal table content is kept, too, and table content of the +"source structure are added; there, the value assignment +"happens like using the CORRESPONDING operator without addition. +diff_deep_struc = CORRESPONDING #( APPENDING BASE ( diff_struc ) deep_struc ). + +"Nonidentical elementary component types are kept in target structure; +"internal table content is kept, too, and table content of the +"source structure are added; there, the value assignment +"happens like using the CORRESPONDING operator with the addition DEEP. +diff_deep_struc = CORRESPONDING #( DEEP APPENDING BASE ( diff_struc ) deep_struc ). +``` + +

⬆️ back to top

+ +## 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. + +``` abap +CLEAR struc-component. + +CLEAR struc. + +"Note: An assignment using the VALUE operator without entries in the parentheses clears the structure. +struc = VALUE #( ). +``` + +

⬆️ back to top

+ +## Processing Structures +Structures are primarily used to process data from tables. In this context, structures often take on the role of a [work area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry"). +The following code snippets cover only a selection. For more examples, see the cheat sheets about internal tables and ABAP SQL. + +**Reading a row from a database table into a structure that has a compatible type**. Note that, since database tables are flat, the +target structure must also be flat. In the example below, the [`SINGLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_single.htm) +addition reads only a single row into the structure. It returns the first entry that matches the `WHERE` condition. + +``` abap +"Creating a structure with a compatible type +DATA ls_fli1 TYPE zdemo_abap_fli. + +SELECT SINGLE FROM zdemo_abap_fli + FIELDS * + WHERE carrid = 'LH' + INTO @ls_fli1. + +"Target structure declared inline +SELECT SINGLE FROM zdemo_abap_fli + FIELDS * + WHERE carrid = 'LH' + INTO @DATA(ls_fli2). +``` +**Reading a row from a database table into a structure that has an incompatible type**. +Components in the structure with identical names are filled. + +``` abap +SELECT SINGLE FROM zdemo_abap_fli + FIELDS * + WHERE carrid = 'AA' + INTO CORRESPONDING FIELDS OF @ls_fli_diff. +``` +**Reading a line from an internal table into a structure** ... + +... using a `SELECT` statement. Note the specified alias name and that ABAP variables like internal tables must be escaped with `@`. The addition `INTO CORRESPONDING FIELDS OF` also applies here. +``` abap +SELECT SINGLE FROM @itab AS itab_alias + FIELDS * + WHERE ... + INTO @DATA(ls_struc). + "INTO CORRESPONDING FIELDS OF @some_existing_struc. +``` +... using a `READ TABLE` statement. The code snippet below shows the reading of a line into a [work area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry"), a [field symbol](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm "Glossary Entry"), and a [data reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm "Glossary Entry"), all of which +represent structured data objects that are declared inline. In the following example, a line is read based on the line number by +specifying `INDEX`. For more details, see the section *Determining the target area* in the cheat sheet [Internal Tables](01_Internal_Tables.md#). +``` abap +READ TABLE itab INTO DATA(wa) INDEX 1. + +READ TABLE itab ASSIGNING FIELD-SYMBOL() INDEX 2. + +READ TABLE itab REFERENCE INTO DATA(dref) INDEX 3. +``` +... using a [table expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_expression_glosry.htm "Glossary Entry"). +The code snippet shows how to read a line into a structure declared inline. The index is given in square brackets. +``` abap +DATA(ls_table_exp) = itab[ 3 ]. +``` + +**Sequentially reading** ... + +... a row from a database table into a structure. A `SELECT` loop can be specified with the syntax `SELECT ... ENDSELECT.`. +In the following example, the row found and returned in a structure declared inline can be processed further. +``` abap +SELECT FROM zdemo_abap_fli + FIELDS * + WHERE carrid = 'AZ' + INTO @DATA(ls_sel_loop). +       + IF sy-subrc = 0. + ... + ENDIF. +ENDSELECT. +``` +... a line from an internal table into a structure using a [`LOOP AT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab_variants.htm) statement. There are many ways to specify the condition on which the loop is based. The following example covers the option of reading all lines sequentially into a field symbol declared inline. When using a field symbol, you can, for example, directly modify components. +``` abap +LOOP AT itab ASSIGNING FIELD-SYMBOL(). + -comp1 = ... + ... +ENDLOOP. +``` + +**Inserting a single row into a database table from a structure** using ABAP SQL statements with +[`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_dbtab.htm). The following statements can be considered as alternatives. The third statement shows that instead of inserting a row from an existing structure, you can create and fill a structure directly. +Note that you should avoid inserting a row with a particular key into the database table if a row with the same key already exists. +``` abap +INSERT INTO dbtab VALUES @struc. + +INSERT dbtab FROM @struc. + +INSERT dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). +``` +**Updating a single row in a database table from a structure** using ABAP SQL statements with [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapupdate.htm). Note that this syntax changes the entire row and all of its components. +``` abap +UPDATE dbtab FROM @struc. + +UPDATE dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). +``` +If you want to update a database table row from a structure by specifying components to be changed without overwriting other components, you can use the following method. First, read the desired row from the database table into a structure. Then, use the `VALUE` operator with the `BASE` addition and specify the components to be changed. +``` abap +SELECT SINGLE * + FROM dbtab + WHERE ... + INTO @DATA(wa). + +UPDATE dbtab FROM @( VALUE #( BASE wa comp2 = ... comp4 = ... ) ). +``` +**Updating or creating a single row in a database table from a structure** using ABAP SQL statements with +[`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_dbtab.htm). If a row with the same key as specified in the structure already exists in the database table, the row is updated. If no row with the keys specified in the structure exists, a new row is created in the database table. +``` abap +MODIFY dbtab FROM @struc. + +MODIFY dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). +``` +**Adding lines to and updating single lines in an internal table from a structure** using `INSERT`, +`APPEND`, and `MODIFY` statements. +- Note that all statements, including `INSERT` and `MODIFY`, are ABAP statements in this context, not ABAP SQL statements. +- Both `INSERT` and `APPEND` add one or more lines to an internal table. While `APPEND` adds at the bottom of the +internal table, `INSERT` can be used to add lines at a specific position in the table. If you do not specify the position, the lines are also added at the bottom of the table. However, unlike `APPEND`, `INSERT` does not set `sy-tabix`. +- `MODIFY` changes the content of an internal table entry. +- Statements using the `VALUE` operator to directly create and populate the structures are also possible. For more information and code +snippets, see the [Internal Tables](01_Internal_Tables.md#) cheat sheet. +``` abap +INSERT struc INTO TABLE itab. + +APPEND struc TO itab. + +MODIFY TABLE itab FROM struc. +``` + +

⬆️ back to top

+ +## Excursion: Including Structures + +- [`INCLUDE TYPE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinclude_type.htm) +and [`INCLUDE STRUCTURE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinclude_type.htm) statements +are used in the context of local structures. +- Structured data objects and types created with `... BEGIN OF... END OF ...` can use this syntax to include components of another structure, whether it is a locally defined or global structure, without creating substructures. +- `INCLUDE TYPE` can be used to include a structured type. +- You can use `INCLUDE STRUCTURE` to include a structure. + +> **💡 Note**
+> - They are not additions of `... BEGIN OF ... END OF ...` but individual ABAP statements. +> - If you use a chained statement with a colon to declare the structure, the inclusion of other structures with these statements interrupts the chained statement, that is, the components of the included structures are included as direct components of the [superstructure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperstructure_glosry.htm "Glossary Entry"). +>- By using the optional `AS` addition and specifying a name, the included components can be addressed by this common name as if they were actually components of a substructure. +>- The optional `RENAMING WITH SUFFIX` addition, followed by a name, gives the included components a suffix name to avoid naming conflicts with other components. + +The following example shows how structured types and data objects are included in another structure. First, three structured types and a structured data object based on one of these types are created. Then, the types and the structure are included in the structured type `address_type`. The executable example demonstrates a structure that includes other structures in this way. +``` abap +TYPES: BEGIN OF name_type, + title   TYPE string, + prename TYPE string, + surname TYPE string, + END OF name_type, + BEGIN OF street_type, + name TYPE string, + num TYPE string, + END OF street_type, + BEGIN OF city_type, + zipcode TYPE string, + name    TYPE string, + END OF city_type. + +DATA city_struc TYPE city_type. + +TYPES BEGIN OF address_type. + INCLUDE TYPE name_type AS name. + INCLUDE TYPE street_type AS street RENAMING WITH SUFFIX _street. + INCLUDE STRUCTURE city_struc AS city RENAMING WITH SUFFIX _city. +TYPES END OF address_type. +``` + + +

⬆️ back to top

+ +## Executable Example +[zcl_demo_abap_structures](./src/zcl_demo_abap_structures.clas.abap) + +> **💡 Note**
+> - The executable example covers the following topics, among others: +> - Creating structures and structured types +> - Variants of structures +> - Accessing, populating, and clearing structures +> - Structures in the context of tables +> - Including structures +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). > - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file diff --git a/03_ABAP_SQL.md b/03_ABAP_SQL.md index 677771c..49a49e0 100644 --- a/03_ABAP_SQL.md +++ b/03_ABAP_SQL.md @@ -1,1720 +1,1689 @@ - - -# ABAP SQL - -- [ABAP SQL](#abap-sql) - - [Introduction](#introduction) - - [Excursion: Database Tables and Views](#excursion-database-tables-and-views) - - [Reading Data Using SELECT](#reading-data-using-select) - - [Basic Syntax](#basic-syntax) - - [Using SELECT for Multiple Purposes](#using-select-for-multiple-purposes) - - [Clause Variations and Additions in SELECT Statements](#clause-variations-and-additions-in-select-statements) - - [More Clauses](#more-clauses) - - [Operands and Expressions in ABAP SQL Statements](#operands-and-expressions-in-abap-sql-statements) - - [SQL operands](#sql-operands) - - [SQL Expressions](#sql-expressions) - - [Elementary Expressions](#elementary-expressions) - - [SQL Functions](#sql-functions) - - [More SQL Expressions](#more-sql-expressions) - - [Window Expressions](#window-expressions) - - [SQL Conditions](#sql-conditions) - - [Selecting Data by Evaluating the Content of Other Tables](#selecting-data-by-evaluating-the-content-of-other-tables) - - [Combining Data of Multiple Database Tables](#combining-data-of-multiple-database-tables) - - [Common Table Expressions (CTE)](#common-table-expressions-cte) - - [Changing Data in Database Tables](#changing-data-in-database-tables) - - [Using `INSERT`](#using-insert) - - [Using `UPDATE`](#using-update) - - [Using `MODIFY`](#using-modify) - - [Using `DELETE`](#using-delete) - - [More Information](#more-information) - - [Executable Example](#executable-example) - -## Introduction - -- [ABAP SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_glosry.htm) is a subset of [SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_glosry.htm "Glossary Entry") - which is the standardized language for accessing databases. -- The main ABAP SQL keywords to read and change data are the - following: - - | Keyword | Purpose | - | -------- | ------------------------------------------------------------------------- | - | `SELECT` | Reads data from database tables | - | `INSERT` | Adds rows to database tables | - | `UPDATE` | Changes the content of rows of database tables | - | `MODIFY` | Inserts rows into database tables or changes the content of existing rows | - | `DELETE` | Deletes rows from database tables | - -- ABAP SQL statements use the ABAP SQL interface. This interface transforms all ABAP SQL statements that access the standard database of an AS ABAP to platform-dependent SQL and forwards the results to the database system. -- Generally bear in mind the [performance notes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_perfo.htm) when using - ABAP SQL. The considerations there are not relevant for this cheat sheet since - the focus is on syntax options. - -## Excursion: Database Tables and Views - -
- Expand to view the details -
- -This section provides bullet points on database tables and views which contain persisted data. Note that the code snippets in this cheat sheet focus on database tables as [data source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry") for ABAP SQL statements. - -**Database tables in [AS ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenas_abap_glosry.htm "Glossary Entry") ...** - -- are objects of the [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm "Glossary Entry"). The term *database table* describes a physical database table in the current [standard database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_db_glosry.htm). -- are two-dimensional matrices consisting of rows and columns. -- contain a [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm), i. e. a field or a combination of fields uniquely identifies every row in a table. A [primary key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_key_glosry.htm) must exist for every database table. - - Note the concept of [foreign keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenforeign_key_glosry.htm) in which one or more columns of a database table can be primary keys of another table. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_forkey.htm). -- have a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm "Glossary Entry") - type. Plus, the definition of database tables consists of [technical](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_techstruc.htm) and [semantic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_semastruc.htm) properties. -- can be referenced as a data type and can be accessed using ABAP SQL. - -Find more information in the respective (sub)topics in the ABAP Keyword Documentation [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables.htm). - - -**Views ...** - -- are further ABAP Dictionary objects for grouping columns from one or more database tables, among others. -- usually realize a - [join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenjoin_glosry.htm "Glossary Entry") - with defined [join - conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenjoin_condition_glosry.htm "Glossary Entry"). -- Note: - - Similar to database tables, the columns of such a view form a - flat structure. The view's name can be used, for example, as [data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm) to declare - [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm), too. - - The views can be accessed by ABAP SQL, especially for reading - purposes using `SELECT`. - -**"Classic"** [DDIC -Views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenddic_view_glosry.htm "Glossary Entry") ... - -- are the oldest form of views and are not available in [ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_cloud_glosry.htm). -- can be accessed by ABAP SQL for read and write operations, however, writing is only supported if the view is created with only one database table. -- can only be created in the [ABAP Workbench](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_workbench_glosry.htm). - -**"Modern" Views (since release 7.40)** - -- [External - views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexternal_view_glosry.htm "Glossary Entry") - as proxies for [SAP HANA - views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenhana_view_glosry.htm "Glossary Entry") - (attribute view, analytic view, calculation view) - - SAP HANA Views are entities of the SAP HANA database that are - defined using the [SAP HANA - Studio](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenhana_studio_glosry.htm "Glossary Entry"). - - They are based on HANA-specific data types. - - Using external views of the ABAP dictionary, you can make those - SAP HANA views "known" to the ABAP program. In doing so, the - external views can be used like classic DDIC views as structured - data types and as a source for reading operations with ABAP SQL. - - To be used only if the central database of the AS ABAP is an - [SAP HANA - database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhana_database_glosry.htm "Glossary Entry"). -- [ABAP Core Data Services (ABAP - CDS)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm "Glossary Entry") - ... - - serve the purpose of defining semantically rich data models. - - have a lot more options than classic views, for example, they - support [annotations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_annotation_glosry.htm). Data sources can be combined using [associations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_association_glosry.htm), views can be defined with input parameters, and more. - - are used like a classic database view as structured data types - and used as a source for reading operations with ABAP SQL (using - [`SELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm)). - - are created using [Data Definition - Language (DDL)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddl_glosry.htm "Glossary Entry") - in the - [ADT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry") - (that is, a source code editor, in contrast to a form-based - editor). - - are, in contrast to external views, supported by all database - systems (that support the ABAP CDS characteristics). -
- -

⬆️ back to top

- -## Reading Data Using SELECT - -### Basic Syntax - -You use ABAP SQL `SELECT` statements to read data from one or more database tables (or views). This can be done to create a multirow or single row result set by assigning the result set to a suitable data object, i. e. you can store the multirow read result in an internal table or the single row result in a structure. -The `SELECT` statement includes several clauses that serve -different purposes. The following code snippet shows the basic syntax: -``` abap -SELECT FROM source "What database table or view to read from - FIELDS field_list "What columns should be read - WHERE condition "Specifies conditions on which a row/rows should be read - INTO @target. "Data object to which the result set is assigned (preceded by @) -``` -> **💡 Note**
->- There are further clauses available of which some are dealt with - further down. In general, the recommendation is to hit `F1` for the keywords and additions to get all the details in the ABAP Keyword Documentation. ->- Especially in older ABAP programs, you will see other forms of the - `SELECT` syntax that you should no longer use. Strict syntax check modes might enforce the use - of specific ABAP SQL syntax. For example, the `INTO` clause should be placed after the other clauses. Furthermore, [host variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") or [host expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") are required for data objects and expressions, i. e. they must be preceded by `@` or `@( ... )`. Further information: [Release-Dependent Syntax Check Modes (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_sql_strict_modes.htm). ->- Regarding host variables as in `SELECT ... INTO @target.` and since they are used in most examples below: A host variable is a data object that is -> - declared in the ABAP program -> - prefixed with the `@` character and -> - specified in an [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm) of an ABAP SQL statement. -> See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm). ->- The `SELECT` list, i. e. the fields that are specified, can also be specified following the `SELECT` - keyword before the `FROM` clause - without `FIELDS`. The - following two `SELECT` statements are basically the same but differently arranged: -> ``` abap -> SELECT FROM dbtab -> FIELDS comp1, comp2, comp3 ->    ... -> -> SELECT comp1, comp2, comp3 -> FROM dbtab ->    ... -> ``` ->- Regarding the target into which data is read: Instead of using a - variable that is (extra) declared beforehand, you can also make use - of [inline - declarations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry"), - for example `... INTO TABLE @DATA(itab).`, to comfortably - create an appropriate variable in place. Note that in case of - internal tables as targets, the resulting table is a standard table - and has an empty key which might have an impact when further - processing the internal table entries. Find more information in the - ABAP cheat sheet [Internal Tables](01_Internal_Tables.md). In newer ABAP releases, the declaration operator [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) can be used to declare immutable variables. - -

⬆️ back to top

- -### Using SELECT for Multiple Purposes - -**Reading a single row into a structure** -``` abap -"SINGLE addition -"Here, all fields of a single row a read. Specifying an -"asterisk * indicates that all fields are to be read. -"Alternatively, you can list all the fields separated by comma. -"Note that if the selection covers more than one row, e. g. in case -"of a non-unique WHERE clause, one of these rows is included in -"the result. - -SELECT SINGLE FROM dbtab - FIELDS * - WHERE ... - INTO @struc. "Existing structure of dbtab's row type - -"Reading a selected set of fields of a single row - -SELECT SINGLE FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - INTO @DATA(struc2). "Structure declared inline - -"Alternative syntax without the FIELDS addition -"Here, the CORRESPONDING FIELDS OF addition is used. Only the content of -"columns that have identically named components in the target data object -"is assigned. - -SELECT SINGLE comp1, comp2, comp3   "Selected set of fields - FROM dbtab - WHERE ... - INTO CORRESPONDING FIELDS OF @struc. "Existing structure -``` -> **💡 Note**
->- Although its use is optional, a `WHERE` clause should be specified to further restrict the read result. ->- Regarding the addition `CORRESPONDING FIELDS OF` in the `INTO` - clause: As mentioned, only the content of columns for which there are identically named components in the target are assigned. However, if you want to read data into an existing data object and particular fields are specified in the `SELECT` list and if the addition is **not** specified, you might stumble on undesired results. The target data object must contain enough components and the content of the columns are assigned to the components of the target from left to right in the order specified after `SELECT`. The content of surplus components of the target is not changed. Plus, pay attention to [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm). Basic rule: Without `CORRESPONDING ...`, column names do not play a role but only the position. With `CORRESPONDING ...`, the position of the columns does not play a role but only the name. ->- Find more information regarding the addition `INTO` [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm). - -**Reading multiple rows into an internal table**. -``` abap -SELECT FROM dbtab - FIELDS *   "All fields - WHERE ... - INTO TABLE @itab. "itab has an appropriate row type - -"Alternative syntax without the FIELDS addition - -SELECT comp1, comp2, comp3   "Selected set of fields - FROM dbtab - WHERE ... - INTO TABLE @DATA(lv_itab). "Internal table declared inline - -"Selected set of fields, existing variable -"See the note on CORRESPONDING FIELDS OF above - -SELECT FROM dbtab - FIELDS comp1, comp2, comp3   "Selected set of fields - WHERE ... - INTO CORRESPONDING FIELDS OF TABLE @itab. -``` - -**`SELECT` loop: Sequentially reading multiple rows**. -- A `SELECT` loop can be opened if the assignment is made to a structure and the addition `SINGLE` is not used. -- If the row is found, the system field `sy-subrc` is set to `0`. -- The loop must be closed using `ENDSELECT`. -- To terminate the loop completely, you can use the statement [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm). -- Note: As covered further down, when using the addition `PACKAGE SIZE` and storing the result in a table, a loop is opened, too. - -``` abap -SELECT FROM dbtab - FIELDS * - WHERE ... - INTO @struc. - - IF sy-subrc = 0. -      ...  "For example, making changes on data and adding the row to an internal table. - - ENDIF. - -ENDSELECT. -``` -

⬆️ back to top

- -### Clause Variations and Additions in SELECT Statements - -`SELECT`/`FROM` clauses: - -**Checking the existence of a row in a database table** -``` abap -"Instead of @abap_true, you could also use 'X'. - -SELECT SINGLE @abap_true - FROM dbtab - WHERE ... - INTO @DATA(exists). - -IF exists = abap_true. - ... -ENDIF. -``` - -**Removing rows that occur more than once in a multirow result set** using the `DISTINCT` addition. -- Cannot be used with the addition `SINGLE`. -- See more information here [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm). -``` abap -SELECT DISTINCT comp1 - FROM dbtab - WHERE ... - INTO TABLE @itab. -``` - -**SELECT list variants** (some of them are already outlined above) - -The following specifications can also be combined: -- `SELECT * ...`: As outlined above, the `*` character defines all columns to be read from a data source (in the order specified there). -- `SELECT col1, col2, col3 ...`: A comma-separated list of individual column names. -- `SELECT data_source~col1, data_source~col2, data_source~col3 ...`: A comma-separated list of individual column names. Here, the name of the data source is explicitly specified and precedes the column name, separated by a tilde. -- `SELECT data_source~* ...`: In this case, the name of the data source is followed by a tilde and the `*` character to specify all columns. Note that there are [special conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_list.htm#!ABAP_VARIANT_1@1@) when using this variant. -- `SELECT col1 AS al1, col2 AS al2, col3 AS al3 ...`: - - Defining alias names for individual columns of the result set with [`AS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_list.htm). - - Make sure that you use an alias name only once here. In the statement, the alias name can only be used after an `ORDER BY` clause. - - As shown further down, in some cases (e. g. when using SQL expressions) the specification of an alias name is required. Setting an alias name for the data source is also possible (`SELECT FROM dbtab AS alias_name ...`). See the section on joins further down. - -> **💡 Note**
-> You have plenty of options regarding the specification of the columns in the `SELECT` list, among them, the outlined direct specification of the column name. SQL expressions can be specified, too. See more details [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause_col_spec.htm) and in the sections on SQL expressions further down. - - -``` abap -"All fields -SELECT * FROM dbtab - WHERE ... - INTO ... - -"Comma-separated list -SELECT col1, col2, col3 - FROM dbtab - WHERE ... - INTO ... - -"Comma-separated list, data source explicitly specified -SELECT dbtab~col1, dbtab~col2, col3 - FROM dbtab - WHERE ... - INTO ... - -"Data source explicitly specified, all fields -SELECT dbtab~* - FROM dbtab - WHERE ... - INTO ... - -"Alias names -"Consider the following: You want to read data from a database table into a target data -"object but, for example, a name in the target is different. Provided that there will -"not be an issue regarding the type (conversion) when the values are assigned, you might -"specify an alias name for the database column to match a component's name in the target data object. - -SELECT FROM dbtab - FIELDS comp1 AS comp_a, comp2 AS comp_b, comp3 AS comp_c - WHERE ... - INTO CORRESPONDING FIELDS OF TABLE @itab. - -"Alias name also possible for the data source -SELECT ds~col1, ds~col2, ds~col3 - FROM dbtab AS ds - WHERE ... - INTO ... -``` - -

⬆️ back to top

- -**Reading data from a database table in another client** ([classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm) only). Note that there are several variants of the `USING ...` addition for switching the [implicit client handling (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_sql_client_handling.htm) from the current client to other clients. See more information [here (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect_client.htm). -``` abap -"Some examples; not available in ABAP for Cloud Development - -"Replaces the current client with the specified client -SELECT * - FROM dbtab USING CLIENT '000'             - WHERE ... - INTO TABLE @itab. - -"Selects data of any number of clients -SELECT * - FROM dbtab USING ALL CLIENTS - WHERE ... - INTO TABLE @itab. -``` - -**Reading data from an internal table as data source** using `SELECT`. Note that an alias name must be specified for the internal table used as data source. -Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_itab.htm). - -``` abap -SELECT * - FROM @itab1 AS tab - WHERE ... - INTO TABLE @DATA(itab2). -``` - -

⬆️ back to top

- -`INTO` **clause**: - -**Limiting the number of returned table rows** using the optional addition [`UP TO n -ROWS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm). - -``` abap -"A maximum of five rows are to be returned -"If the INTO clause is the last clause, the UP TO clause must be positioned after it. -SELECT * FROM dbtab - WHERE ... - INTO TABLE @DATA(itab_upto) - UP TO 5 ROWS. -``` - -**Returning only the table rows after a row with a specified count from the result set** using the optional addition [`OFFSET n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm#!ABAP_ADDITION_2@2@). You can only use the addition, if an `ORDER BY` clause is specified. - -``` abap -"In the example, data of all flights are retrieved, except for the 2 flights -"with the shortest flight time. -SELECT * - FROM ztest_abap_flsch - WHERE carrid = 'LH' - ORDER BY fltime ASCENDING - INTO TABLE @DATA(itab) - OFFSET 2. -``` - -**Reading into individual elementary data objects**. -Apart from reading into structures and internal tables outlined above, you can also read into individual elementary data objects. -Here, the individual elementary data objects as target objects are specified in a comma-separated list (e. g. as existing host variables or declared inline with `@DATA(...)`) and put between a pair of parentheses. -Note: -- The comma-separated list must have the same number of elements as columns in the result set. -- The content of the columns in the result set is assigned to the data objects specified in the list from left to right in accordance with the order specified in the `SELECT` list. -- Note the [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm) also in this context. -- More information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ALTERNATIVE_1@1@). - - -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - INTO (@res1,@res2,@res3). - "INTO (@DATA(res1),@DATA(res2),@DATA(res3)). "Using inline declarations -``` - -**Appending the result set to an existing internal table**. -The addition `INTO` initializes the target object. When using the addition `APPENDING`, you can retain existing lines in internal tables. `APPENDING` is also possible with the addition `CORRESPONDING FIELDS OF TABLE`. - -``` abap -SELECT * FROM dbtab - WHERE ... - APPENDING TABLE @itab. - -SELECT * FROM dbtab - WHERE ... - APPENDING CORRESPONDING FIELDS OF TABLE @diff_itab. -``` - -**Reading into packages of a specified number of rows** when reading into internal tables. The addition [`PACKAGE SIZE n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ONE_ADD@1@) can be specified after `INTO TABLE` and `APPENDING TABLE`. A `SELECT` loop ist opened. After `PACKAGE SIZE`, the number of rows is specified (which can be a host variable, host expression or a literal of type `i`) denoting the number of rows to be inserted in the target object per iteration. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - INTO TABLE @DATA(itab_pack) PACKAGE SIZE n. -... -ENDSELECT. -``` - -**Specifying an [anonymous data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) as target object** using the addition [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm#!ABAP_ALTERNATIVE_3@3@). Only to be used after `INTO` and not `APPENDING`. - -``` abap -"Here, the target object is an anonymous data object declared inline. -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - INTO TABLE NEW @DATA(dref). -``` - -

⬆️ back to top

- -### More Clauses - -[`GROUP BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapgroupby_clause.htm) -clause: Combining groups of table rows in the result set. You -might also use [SQL expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") -here. Multiple clause elements are separated by a comma. Find more -information on SQL expressions further down. - -Note that the `GROUP BY` clause requires all columns that are -directly specified in the `SELECT` list or specified there as an -argument of an SQL expression to be specified. An exception to this is -[aggregate -functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") -in [aggregate -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_expression_glosry.htm "Glossary Entry") -(except [grouping -functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengrouping_glosry.htm "Glossary Entry")) -as shown in the following example. - -In the example below, the database table rows that have the same content in column `comp1` are combined. The lowest and highest values in column `comp2` are determined for each of these groups and placed into the combined row. -``` abap -SELECT FROM dbtab - FIELDS comp1, MIN( comp2 ) AS min, MAX( comp2 ) AS max - WHERE ... - GROUP BY comp1 - INTO ... -``` - -[`HAVING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaphaving_clause.htm) -clause: Limiting the number of table rows in groups in the -result by setting conditions on these rows. The rows for which a -logical expression is true are inserted in the target variable. Note -that `HAVING` can only be used together with `GROUP BY`. -``` abap -SELECT FROM dbtab - FIELDS comp1, MIN( comp2 ) AS min, MAX( comp3 ) AS max - WHERE ... - GROUP BY comp1 - HAVING comp1 LIKE '%XYZ%' AND SUM( comp4 ) > 100 - INTO ... -``` - -[`ORDER BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaporderby_clause.htm) -clause: Sorting the result set by specified columns. - -The following example shows the ordering of the result set based on the -content of the primary key of the [data -source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry"). -You can also order by any columns and by explicitly specifying the sort -order. There are more ordering options, for example, by using SQL -expressions. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE ... - ORDER BY PRIMARY KEY - "comp2 ASCENDING - "comp2 DESCENDING - INTO ... -``` - -> **💡 Note**
->- Not specifying `ORDER BY` means that the order of entries in the result set is undefined. ->- If `ORDER BY` and `GROUP BY` clauses are used, all columns specified after `ORDER BY` must also be specified after `GROUP BY`. ->- If aggregate functions are specified after `SELECT`, all columns that are specified after `ORDER BY` and that do not have an alias name for an aggregate function must also be specified after `SELECT` and after the `GROUP BY` clause which is required in this case, too. - -[`WHERE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhere.htm) clause: Restricts the number of rows that are included in the result set using logical expressions. See further information on them in the following sections. -``` abap -SELECT FROM dbtab - FIELDS comp1, comp2, comp3 - WHERE comp1 = 'abc' - AND comp2 < 123    - INTO ... -``` - -

⬆️ back to top

- -### Operands and Expressions in ABAP SQL Statements - -ABAP offers plenty of [SQL -operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_glosry.htm "Glossary Entry") -and -[expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") -that are possible in ABAP SQL statements, not only in the context of -`SELECT` statements and the `SELECT` lists which are -mainly used for the following demonstration examples. Questions about -when to use what, what is possible in which contexts and positions, is -beyond the scope of this cheat sheet. Check the details in the -respective topics in the ABAP Keyword Documentation. Find a general -overview of important operand positions in ABAP SQL -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_positions_oview.htm). -Due to the rich variety of options, the cheat sheet covers a selection. - -#### SQL operands - -- Are elementary operands in an ABAP SQL statement -- Can be database table or view columns, a - [literal](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_glosry.htm "Glossary Entry"), - [host - variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") - (i. e. global or local data objects escaped using `@`: - `@dobj`) or [host - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") - (`@( ... )`) - - Regarding literals: They are not prefixed with the escape - character `@`. The literals can be - [typed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm "Glossary Entry") - (using the type name and content within a pair of backquotes: - char\`abc\`) with [built-in ABAP Dictionary - types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_builtin_types.htm) - or untyped. Typed literals are preferable for the following - reasons: Using untyped literals means extra cost in terms of - performance since they must be converted by the compiler. Plus, - their use can result in errors at runtime whereas typed literals - guarantee type compatibility at once. - - Regarding host expressions: Structures and internal tables are - possible as host expressions for statements modifying the - content of database tables as shown further down. -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operands.htm). - -Example demonstrating possible operands: -``` abap -DATA upto TYPE i VALUE 3. - -SELECT FROM zdemo_abap_flsch - FIELDS -  "Specifies a column of a data source directly using its name - cityfrom, - -  "Column selector ~ can be used to prefix every specified column. -  "Here, it is optional. It is non-optional, e. g., if multiple data -  "sources in an ABAP SQL statement are edited and the column name -  "is not unique. - zdemo_abap_flsch~cityto, - - 'Lufthansa' AS name, "Untyped literal - - char`X` AS flag, "Typed literal - - @upto AS num, "Host variable - - @( cl_abap_context_info=>get_system_date( ) ) as date "Host expression - - WHERE carrid = 'LH'         "Untyped literal - AND countryfr = char`DE` "Typed literal - -  "Data object created inline and escaped with @ - INTO TABLE @DATA(it) - -  "The following clause shows all options having the same effect - UP TO 3 ROWS.         "Untyped numeric literal - "UP TO int4`3` ROWS.   "Typed numeric literal - "UP TO @upto ROWS.     "Host variable - "UP TO @( 10 - 7 ) ROWS. "Host expression -``` - -

⬆️ back to top

- -#### SQL Expressions - -- Expressions in an ABAP SQL statement that are passed to the database - system for evaluation. -- For example, SQL expressions can be specified as columns in the - `SELECT` list as demonstrated in most of the following examples. - Find information on more possible positions and general information - on SQL expressions - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm) - and the subtopics there. - -##### Elementary Expressions - -- An elementary expression represents one of the four mentioned - operands above: A value from the database (the column name) or - values from an ABAP program passed to the database (literal, host - variable or host expression). -- As an example, see the `SELECT` list in the example above. -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_elem.htm). - -##### SQL Functions - -- You can use built-in functions in ABAP SQL. -- Result: Value with the associated dictionary type. -- Arguments of the functions: Cover one or more SQL expressions. -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_builtin_functions.htm). - -Example: [Numeric functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith_func.htm) -``` abap -SELECT SINGLE - carrname, - - "Division, result rounded to an integer - "Result: 2 - div( 4, 2 ) AS div, - - "Division, 3rd argument: result is rounded to the specified - "number of decimals - "Result: 0.33 - division( 1, 3, 2 ) AS division, - - "Result is rounded to first greater integer - "Result: 2 - ceil( decfloat34`1.333` ) AS ceil, - - "Result is the remainder of division - "Result: 1 - mod( 3, 2 ) AS mod, - - "Result: Largest integer value not greater than the specified value - "Result: 1 - floor( decfloat34`1.333` ) AS floor, - - "Returns the absolute number - "Result: 2 - abs( int4`-2` ) AS abs, - - "Result is rounded to the specified position after the decimal separator - "Result: 1.34 - round( decfloat34`1.337`, 2 ) AS round - - FROM zdemo_abap_carr - WHERE carrid = 'AA' - INTO @DATA(numeric_functions). -``` - -

⬆️ back to top

- -Example: [String functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string_func.htm) - -``` abap -SELECT SINGLE - carrid,   "LH - carrname, "Lufthansa - url, "http://www.lufthansa.com - - "Concatenates strings, ignores trailing blanks - "Result: LHLufthansa - concat( carrid, carrname ) AS concat, - - "Concatenates strings, number denotes the blanks that are inserted - "Result: LH Lufthansa - concat_with_space( carrid, carrname, 1 ) AS concat_with_space, - - "First letter of a word -> uppercase, all other letters -> lowercase; - "note that a space and other special characters means a new word. - "Result: Http://Www.Lufthansa.Com - initcap( url ) AS initcap, - - "Position of the first occurrence of the substring specified - "Result: 6 - instr( carrname,'a' ) AS instr, - - "String of length n starting from the left of an expression; - "trailing blanks are ignored - "Result: Luft - left( carrname, 4 ) AS left, - - "Number of characters in an expression, trailing blanks are ignored - "Result: 24 - length( url ) AS length, - - "Checks if expression contains a PCRE expression; - "case-sensitive by default (case_sensitive parameter can be specified) - "Notes on the result: 1 = found, 0 = not found - "Result: 1 - like_regexpr( pcre  = '\..', "Period that is followed by any character -                value = url ) AS like_regex, - - "Returns position of a substring in an expression, - "3rd parameter = specifies offset (optional) - "4th parameter = determines the number of occurrences (optional) - "Result: 9 - locate( carrname, 'a', 0, 2 ) AS locate, - - "Searches a PCRE pattern, returns offset of match; - "many optional parameters: occurrence, case_sensitive, start, group - "Result: 21 - locate_regexpr( pcre = '\..', "Period followed by any character -                  value = url, -                  occurrence = 2 ) "2nd occurrence in the string - AS locate_regexpr, - - "Searches a PCRE pattern, returns offset of match + 1; - "many optional parameters: occurrence, case_sensitive, start, group - "Result: 2 - locate_regexpr_after( pcre = '.',  "Any character -                        value = url, -                        occurrence = 1 ) AS locate_regexpr_after, - - "Removes leading characters as specified in the 2nd argument, - "trailing blanks are removed - "Result: ufthansa - ltrim( carrname, 'L' ) AS ltrim, - - "Counts all occurrences of found PCRE patterns - "Result: 2 - occurrences_regexpr( pcre = '\..', "Period that is followed by any character -                       value = url ) AS occ_regex, - - "Replaces the 2nd argument with the 3rd in an expression - "Result: Lufth#ns# - replace( carrname, 'a', '#' ) AS replace, - - "Replaces a found PCRE expression; - "more parameters possible: occurrence, case_sensitive, start - "Result: http://www#ufthansa#om - replace_regexpr( pcre = '\..', "Period that is followed by any character -                   value = url, -                   with = '#' ) AS replace_regex, - - "Extracts a string with the length specified starting from the right - "Result: hansa - right( carrname, 5 ) AS right, - - "Expands string to length n (2nd argument); trailing blanks produced - "are replaced by the characters from the (3rd) argument - "Note that if n is less than the string, the expression is truncated - "on the right. - "Result: Lufthansa### - rpad( carrname, 12, '#' ) AS rpad, - - "All trailing characters that match the character of the 2nd argument - "are removed; trailing blanks are removed, too - "Result: Lufthans - rtrim( carrname, 'a' ) AS rtrim, - - "Returns a substring; 2nd argument = position from where to start; - "3rd argument: length of the extracted substring - "Result: fth - substring( carrname, 3, 3 ) AS substring, - - "Searches for a PCRE expression and returns the matched substring - "More parameters possible: occurrence, case_sensitive, start, group - "Result: .lu - substring_regexpr( pcre = '\...', "Period that is followed by any two characters -                     value = url ) AS substring_regexpr, - - "All lower case letters are transformed to upper case letters - "Result: LUFTHANSA - upper( carrname ) AS upper - - FROM zdemo_abap_carr - WHERE carrid = 'LH' - INTO @DATA(string_functions). -``` - -

⬆️ back to top

- -Example: [Special functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_special_functions.htm) - -``` abap -SELECT SINGLE - carrid, - -  "Conversion functions -  "When used: Special conversions that cannot be handled in a general -  "CAST expression - -  "Type conversion: string of fixed length (e.g. of type c) to variable -  "length string of type string - to_clob( carrid ) AS clob, - -  "Byte string -> character string - bintohex( raw`3599421128650F4EE00008000978B976` ) AS bintohex, - -  "Character string -> byte string - hextobin( char`3599421128650F4EE00008000978B976` ) AS hextobin, - -  "Byte field of type RAW to a byte string (BLOB) of type RAWSTRING - to_blob( raw`3599421128650F4EE00008000978B976` ) AS blob, - -  "Unit and currency conversion functions -  "More parameters are available. - -  "Converts miles to kilometers - unit_conversion( quantity = d34n`1`, -                   source_unit = unit`MI`, -                   target_unit = unit`KM` ) AS miles_to_km, - -  "Converts Euro to US dollars using today's rate - currency_conversion( -    amount = d34n`1`, -    source_currency = char`EUR`, -    target_currency = char`USD`, -    exchange_rate_date = @( cl_abap_context_info=>get_system_date( ) ) -                     ) AS eur_to_usd, - -  "Date and time functions - add_days( @( cl_abap_context_info=>get_system_date( ) ), 4 ) AS add_days, - add_months( @( cl_abap_context_info=>get_system_date( ) ), 2 ) AS add_months, - is_valid( @( cl_abap_context_info=>get_system_date( ) ) ) AS date_is_valid, - is_valid( @( cl_abap_context_info=>get_system_time( ) ) ) AS time_is_valid - -FROM zdemo_abap_carr -INTO @DATA(special_functions). -``` - -

⬆️ back to top

- -[Aggregate expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm) - -- Consist of [aggregate - functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") - and aggregate the values of multiple rows of the result set of a - [query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenquery_glosry.htm "Glossary Entry") - into a single value -- See more information - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm). - -Example: -``` abap -"The example shows a selection of available functions -SELECT - carrid, - - "Average value of the content of a column in a row set - AVG( fltime ) AS fltime1, - - "AVG with data type specification for the result - AVG( fltime AS DEC( 14,4 ) ) AS fltime2, - - "Maximum value of the results in a row set - MAX( fltime ) AS max, - - "Minimum value - MIN( fltime ) AS min, - - "Sum of the results in a row set. - SUM( fltime ) AS sum, - - "Returns the number of rows in a row set. - "The following two have the same meaning. - COUNT( * ) AS count2, - COUNT(*) AS count3, - - "Chains the results in a row set. - "An optional separator can be specified - STRING_AGG( airpfrom, ', ' ) AS string_agg - - FROM zdemo_abap_flsch - WHERE carrid = 'LH' - GROUP BY carrid - INTO TABLE @DATA(agg_exp). -``` - -

⬆️ back to top

- -##### More SQL Expressions - -- [Arithmetic - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith.htm) - to perform arithmetic calculations using the operators `+`, - `-`, `*`, `/`, -- [Cast - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast.htm) - to convert the value of operands to a dedicated dictionary type. - Note that there are special [conversion - rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast_rules.htm). -- [String - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string.htm) - using the operator `&&` to concatenate character strings. -- [Case - distinctions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_case.htm) - to carry out either a simple (comparison of the values of a - dedicated operand) or complex (searched case; evaluation of multiple - logical expressions) case distinction. - -The following example demonstrates the expressions mentioned above: -``` abap -SELECT SINGLE -  carrid, - -  "Arithmethic expressions -  "operators + - * -  "Note that / is not allowed in integer expressions as the one below -  ( 1 + 2 ) * 3 AS calc, - -  "/ used in an expression using type adjustment in ABAP SQL. -  "A cast expression converts the value of the operands to the -  "specified dictionary type. The result is a representation of the -  "source value in the specified type. - CAST( 1 AS D34N ) / CAST( 2 AS D34N ) AS ratio, - -  "String expression using && to concatenate two character strings; -  "the result of the concatenation must not be longer than -  "255 characters. -  carrid && carrname AS concat, - -  "Case distinction -  "Simple case distinction -  "The expression compares the values of an operand with other -  "operands. Result: The first operand after THEN for which the -  "comparison is true. If no matches are found, the result specified -  "after ELSE is selected. - CASE currcode - WHEN 'EUR' THEN 'A' - WHEN 'USD' THEN 'B' - ELSE 'C' - END AS case_simple, - -  "Complex case distinction -  "The expression evaluates logical expressions. Result: The first -  "operand after THEN for which the logical expression is true. If no -  "logical expressions are true, the result specified after ELSE is -  "selected. - CASE WHEN length( carrname ) <= 5 THEN 'small' - WHEN length( carrname ) BETWEEN 6 AND 10 THEN 'mid' - WHEN length( carrname ) BETWEEN 11 AND 15 THEN 'large' - ELSE 'huge' - END AS case_complex - -FROM zdemo_abap_carr -WHERE carrid = 'AA' -INTO @DATA(more_sql_expr). -``` - -

⬆️ back to top

- -##### Window Expressions - -How [window expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_expression_glosry.htm "Glossary Entry") work: - -- Define a subset of the result set (i. e. the - "[window](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_glosry.htm "Glossary Entry")") - of a database query that implements ABAP SQL -- Apply a [window - function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_function_glosry.htm "Glossary Entry") - - which evaluates the rows of the window and which can, for example, - be an [aggregate - function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") - like - [`AVG`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_agg_func&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_VARIANT_1@1@&tree=X) - to determine the average value - to the result set -- I. e. a window is constructed by the rows of the result set for - which all the window functions have the same result; a value is then - determined for the rows of a window - -Setup of a statement with window expressions: - -- Window function, e. g. an aggregate function like `AVG`, - followed by `OVER( ... )` (the content in the parentheses - defines the "window") -- The content in the parentheses can contain the following additions: - - Optional `PARTITION BY`: Defines the windows using a - comma-separated list of [SQL - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm); - the window function is calculated for the rows of this window; - note that if the addition is not specified, the window comprises - all rows of the result set - - Optional `ORDER BY`: Introduces both an order (you can - use `ASCENDING` and `DESCENDING`) and a frame - (as outlined below) within the current window, which further - restricts the rows for which the window function is calculated - - A window frame, which stands for a subset of rows inside a - window, can optionally be defined if `ORDER BY` is - specified; there are 3 options to define the starting and ending - frame boundaries (see the example) - -See more information on window expressions and the syntax -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_over.htm). - -Examples: -``` abap -"Example 1: A simple window is constructed in the OVER clause; -"window functions - here aggregate functions - are applied -SELECT carrid, currency, - SUM( paymentsum ) OVER( PARTITION BY carrid ) AS sum, - AVG( price AS DEC( 14,2 ) ) OVER( PARTITION BY carrid ) AS avg, - MAX( price ) OVER( PARTITION BY carrid ) AS max - FROM zdemo_abap_fli - ORDER BY carrid - INTO TABLE @DATA(win). - -"Example 2: -SELECT carrid, currency, fldate, -  "Sorts the rows by some columns and counts the number of rows from -  "the first row of the window to the current row. - COUNT( * ) OVER( ORDER BY currency, fldate - ROWS BETWEEN - "UNBOUNDED PRECEDING: frame starts at the first row of the window - UNBOUNDED PRECEDING -                   "CURRENT ROW: determines starting or ending at the current row; here, it ends - AND CURRENT ROW ) AS count1, - -  "If no window frame is used, the default window frame is -  "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, -  "i. e. the result of count1 equals the result of count2. - COUNT( * ) OVER( ORDER BY currency, fldate ) AS count2, - -  "Sorts the rows by some columns and counts the number of rows from -  "the current row to the last row of the window. -  "The result is reverse numbering. - COUNT( * ) OVER( ORDER BY currency, fldate - ROWS BETWEEN CURRENT ROW -                   UNBOUND FOLLOWING: -                   "Determines the ending frame boundary, this addition specifies the last row of the window - AND UNBOUNDED FOLLOWING ) AS count_reverse, - -  "Sorts the rows by some columns and calculates the rolling averages -  "of a subset of rows from column price. The subset consists of the -  "current row plus one preceding and one following row. Another use -  "case as below example that uses prices would be that, for example, -  "you can calculate the 3-day-average temperature for every day from -  "a list of temperature data. - AVG( price AS DEC( 14,2 ) ) OVER( ORDER BY currency, fldate - ROWS BETWEEN -       "n PRECEDING: for both start and end of frame; frame to start/end n rows above the current row - 1 PRECEDING -       "n FOLLOWING: for both start and end of frame; frame to start/end n rows beneath the current row - AND 1 FOLLOWING ) AS avg - - FROM zdemo_abap_fli - INTO TABLE @DATA(result). -``` - -

⬆️ back to top

- -### SQL Conditions - -You can formulate conditions in ABAP SQL statements, i. e. [logical -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogical_expression_glosry.htm "Glossary Entry"), -especially in the `WHERE` clause to restrict the result. Note -that without a `WHERE` clause, all rows are respected for the -operation. - -See below a selection of the operators that are possible when specifying -conditions. For more information, see the subtopics of the [SQL -Conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenasql_cond.htm) -topic. - -| Operator | Meaning | -|----------|:-------------:| -| `=`, `EQ` | The content of two operands is equal.| -| `<>`, `NE` | The content of two operands is not equal.| -| `<`, `LT` | The content of one operand is less than the content of the other operand.| -| `>`, `GT` | The content of one operand is greater than the content of the other operand.| -| `<=`, `LE` | The content of one operand is less than or equal to the content of the other operand.| -| `>=`, `GE` | The content of one operand is greater than or equal to the content of the other operand.| -| `... [NOT] BETWEEN ... AND ...` | The value of an operand is (not) between the value of the two other operands.| -| `... [NOT] LIKE ...` | The content of an operand matches (does not match) a specified pattern. The pattern can be specified by using wildcard characters. `%` stands for any character string, including an empty string. `_` stands for any character.| -| `... IS [NOT] INITIAL ...` | The value of an operand is (not) the initial value of its built-in dictionary type.| -| `... EXISTS ...` | Checks the result set of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). The expression is true if the result set contains at least one row. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm).| -| `... [NOT] IN ...` | Checks whether the operands on the left side match a value from a set of values specified in parentheses. On the left side, a single operand or an operand list are possible. On the right side, a comma-separated lists or subqueries can be specified. It is also possible to specify a [ranges table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenranges_table_glosry.htm) to evaluate [ranges conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenranges_condition_glosry.htm).| -| `... IS [NOT] NULL ...` | Checks whether the value of an operand is (not) the [null value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). Find more information in the code snippet and in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_null.htm). | - -> **💡 Note**
->You can combine multiple logical expressions into one -logical expression using `AND` or `OR`. To further -detail out the desired condition, expressions within parentheses are -possible. - -Examples: - -``` abap -"---- SQL conditions demonstrated with the WHERE clause ---- -"Note: -"- For most of the self-contained examples, an internal table is used as the -" data source of SELECT statements to work with simple data. -"- For some examples that are covered, such as subqueries, demo database tables -" from the cheat sheet repository are used in addition. -"- Dynamic specifications are also possible. They are not covered here. See -" the Dynamic Programming cheat sheet. - -"---- Types and internal table to work with in the examples ---- -"Note: You cannot use type string columns in WHERE conditions. -TYPES: BEGIN OF demo_struc, - id TYPE i, - name TYPE c LENGTH 15, - "name TYPE string, - END OF demo_struc. -DATA itab TYPE SORTED TABLE OF demo_struc WITH UNIQUE KEY id. -"Populating internal table with data to work with in the examples -itab = VALUE #( ( id = 1 name = 'bear' ) - ( id = 2 name = 'camel' ) - ( id = 3 name = 'rabbit' ) - ( id = 4 name = 'zebra' ) - ( id = 5 name = 'dog' ) - ( id = 6 name = 'deer' ) - ( id = 7 name = 'squirrel' ) - ( id = 8 name = 'cheetah' ) - ( id = 9 name = 'elephant' ) - ( id = 10 name = 'donkey' ) - ( id = 11 name = 'fish' ) - ( id = 12 name = 'sheep' ) ). - -"---- =, <>, >, >= (as a selection of possible comparison operators) ---- -SELECT id FROM @itab AS tab WHERE name = 'bear' INTO TABLE @DATA(it). "1 -SELECT id FROM @itab AS tab WHERE name <> 'bear' INTO TABLE @it. "2-12 -SELECT id FROM @itab AS tab WHERE id > 10 INTO TABLE @it. "11,12 -SELECT id FROM @itab AS tab WHERE id >= 10 INTO TABLE @it. "10,11,12 - -"---- Combining logical expressions using AND, OR and parentheses ---- -SELECT id FROM @itab AS tab WHERE id = 1 AND name = 'bear' INTO TABLE @it. "1 -SELECT id FROM @itab AS tab WHERE name = 'bear' OR name = 'sheep' INTO TABLE @it. "1,12 - -"In the following example, the resulting table is initial. One of the expressions -"in parentheses is false (AND is used between the expressions in parentheses). -"In contrast, the example below returns an entry because of using OR. -SELECT id FROM @itab AS tab - WHERE ( id = 1 AND name = 'bear' ) - AND ( id = 20 AND name = 'camel' ) - INTO TABLE @it. - -SELECT id FROM @itab AS tab - WHERE ( id = 1 AND name = 'bear' ) - OR ( id = 20 AND name = 'camel' ) - INTO TABLE @it. "1 - -"------------------------ [NOT] BETWEEN ------------------------ -SELECT id FROM @itab AS tab WHERE id BETWEEN 1 AND 4 INTO TABLE @it. "1,2,3,4 -"The condition with BETWEEN above corresponds to the following condition. -"The example makes use of a condition specified in parentheses to combine multiple -"expressions. -SELECT id FROM @itab AS tab WHERE ( id >= 1 AND id <= 4 ) INTO TABLE @it. "1,2,3,4 -"Negation with NOT -SELECT id FROM @itab AS tab WHERE id NOT BETWEEN 1 AND 4 INTO TABLE @it. "5-12 - -"------------------------ IS [NOT] INITIAL ------------------------ -SELECT id FROM @itab AS tab WHERE id IS NOT INITIAL INTO TABLE @it. "1-12 - -"------------------------ [NOT] LIKE ------------------------ -"For (not) matching a specified pattern -"Note: % (any character string), _ (any character). -SELECT name FROM @itab AS tab - WHERE name LIKE '%ee%' - OR name LIKE '_o%' - INTO TABLE @DATA(names). "dog,deer,cheetah,donkey,sheep - -"ESCAPE addition for defining a single-character escape character -"In the following example, this character is #. It is placed before -"the % character in the specification after LIKE. In this case, % -"is escaped and does then not stand for any character string in the -"evaluation. -"Adding a table entry for this syntax example. -itab = VALUE #( BASE itab ( id = 13 name = '100%' ) ). -"Any character sequence followed by the % character -SELECT name FROM @itab AS tab - WHERE name LIKE '%#%' ESCAPE '#' - INTO TABLE @names. "100% - -"Deleting the entry because it is not relevant for the further examples. -DELETE itab INDEX 13. - -"------------------------ [NOT] IN (using a value set) ------------------------ -"For (not) matching a value in a set of values specified in parentheses. - -"Single operands on the left side of IN -SELECT id FROM @itab AS tab - WHERE name IN ( 'camel', 'rabbit', 'dog', 'snake' ) - INTO TABLE @it. "2,3,5 - -"Negation NOT IN; note to use host variables/expressions for local/global data objects -DATA(animal) = 'sheep'. -SELECT id FROM @itab AS tab - WHERE name NOT IN ( 'fish', @animal ) - INTO TABLE @it. "1-10 - -"Operand list (a parenthesized comma-separated list) on the left side of IN -"For (not) matching value tuples from a set of value tuples specified in parentheses on the right side. -"In the following example, two values are specified in the operand list on the left. Consequently, -"two values with appropriate types must be specified in parentheses on the right. -SELECT id FROM @itab AS tab - WHERE ( id, name ) IN ( ( 1, 'bear' ), ( 3, 'rabbit' ), ( 8, 'zebra' ), ( 20, 'dog' ) ) - INTO TABLE @it. "1,3 - - -"------------------------ [NOT] IN (using a subquery) ------------------------ -"[NOT] IN for matching a value contained in the result set of a subquery - -"In the following example, the subquery reads data from a demo database table. -"For a representative result, the table is cleared, and then filled with 'suitable' -"data sets. -DELETE FROM zdemo_abap_tab1. -MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #( ( key_field = 11 num1 = 11 ) - ( key_field = 12 num1 = 12 ) - ( key_field = 13 num1 = 13 ) - ( key_field = 14 num1 = 14 ) ) ). - -SELECT id FROM @itab AS tab - WHERE id IN ( SELECT key_field FROM zdemo_abap_tab1 ) INTO TABLE @it. "11,12 - -"------------------------ [NOT] IN (using a ranges table) ------------------------ -"[NOT] IN for checking whether the operands on the left side match a ranges condition in a ranges table - -"Declaring a ranges table -DATA rangestab TYPE RANGE OF i. -"Populating a ranges table using the VALUE operator -rangestab = VALUE #( ( sign = 'I' option = 'BT' low = 1 high = 3 ) - ( sign = 'I' option = 'GE' low = 10 ) ). - -SELECT id FROM @itab AS tab WHERE id IN @rangestab INTO TABLE @it. "1,2,3,10,11,12 - - -"You cannot use logical operators such as CP (conforms to pattern) in the WHERE clause. -"In a ranges table, they are possible. -"Note: -"- Regarding CP: * (any character sequence), + (any character), # (escape character) -"- An equivalent example above uses the LIKE addition. -DATA rt TYPE RANGE OF demo_struc-name. -rt = VALUE #( ( sign = 'I' option = 'CP' low = '*ee*' ) "ee in a string - ( sign = 'I' option = 'CP' low = '+o*' ) ). "o in second position -SELECT name FROM @itab AS tab - WHERE name IN @rt - INTO TABLE @names. "dog,deer,cheetah,donkey,sheep - -"------------------------ EXISTS ------------------------ -"For checking the result set of a subquery. -"The following example reads all entries from the internal table if entries having -"the same key also exist in the database table. -"Note: The SELECT list in the subquery only contains a literal to determine that -"the entry exists. Specifying explicit column names is not relevant. -SELECT id FROM @itab AS tab WHERE - EXISTS ( SELECT @abap_true FROM zdemo_abap_tab1 WHERE key_field = tab~id ) - INTO TABLE @it. "11,12 - -"------------------------ IS [NOT] NULL ------------------------ -"The null value is a special value that is returned by a database. It indicates an -"undefined value or result. Note that, in ABAP, there are no special null values. Do -"not confuse the null value with a type-dependent initial value. When using SELECT -"statements to read data, null values can be produced by, for example, outer joins. -"When the null values are passed to a data object, they are transformed to the -"type-dependent initial values. For more information, refer to the ABAP Keyword Documentation. -"The following example uses a left outer join to intentionally create null values. For -"this purpose, two demo database tables of the cheat sheet repository are cleared and -"populated with specific values to visulaize null values. -DELETE FROM zdemo_abap_tab1. -DELETE FROM zdemo_abap_tab2. -MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' char2 = 'y' ) - ( key_field = 2 char1 = 'b' char2 = 'z' ) ) ). -MODIFY zdemo_abap_tab2 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' ) - ( key_field = 2 char1 = 'a' ) - ( key_field = 3 char1 = 'b' ) - ( key_field = 4 ) ) ). -"Note that for the entry 'key_field = 4' no char1 value was passed. -"char1 is a shared column of the two database tables, and which is used in -"the ON condition of the join. Since there is no entry in char1 for 'key_field = 4', -"the joined values are null in that case. The WHERE clause uses the addition IS NULL. -"Therefore, the result only contains this entry. char2 is assigned the type-initial -"value in the result. -SELECT tab2~key_field, tab1~char2 - FROM zdemo_abap_tab2 AS tab2 - LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 - WHERE tab1~char1 IS NULL - INTO TABLE @DATA(joined_tab). -*KEY_FIELD CHAR2 -*4 - -"The following example visualizes the null values. The INDICATORS addition of the -"INTO clause is used to specify indicators such as the null indicator. In the -"example, an appropriate target table is defined to also store information about -"which columns of the result set contain the null value and which do not. -"For more information on the syntax, refer to the ABAP Keyword Documentation. -TYPES: BEGIN OF st4null, - BEGIN OF s2, - key_field TYPE zdemo_abap_tab2-key_field, - char2 TYPE zdemo_abap_tab1-char2, - END OF s2, - BEGIN OF nulls, - key_field TYPE c LENGTH 1, - char2 TYPE c LENGTH 1, - END OF nulls, - END OF st4null. -DATA joined_tab_w_null_ind TYPE TABLE OF st4null WITH EMPTY KEY. - -SELECT tab2~key_field, tab1~char2 - FROM zdemo_abap_tab2 AS tab2 - LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 - INTO TABLE @joined_tab_w_null_ind INDICATORS NULL STRUCTURE nulls. -*S2 NULLS -*KEY_FIELD CHAR2 KEY_FIELD CHAR2 -*1 y -*KEY_FIELD CHAR2 KEY_FIELD CHAR2 -*2 y -*KEY_FIELD CHAR2 KEY_FIELD CHAR2 -*3 z -*KEY_FIELD CHAR2 KEY_FIELD CHAR2 -*4 X - -"Negation IS NOT NULL -SELECT tab2~key_field, tab1~char2 - FROM zdemo_abap_tab2 AS tab2 - LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 - WHERE tab1~char1 IS NOT NULL - INTO TABLE @joined_tab. -*KEY_FIELD CHAR2 -*1 y -*2 y -*3 z -``` - -

⬆️ back to top

- -### Selecting Data by Evaluating the Content of Other Tables - -[`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) -addition: -- Components of an internal table can be used in the `WHERE` clause in logical expressions for comparisons with a column of the data source. -- The logical expression is evaluated for each individual row of the internal table. -- The result set of the `SELECT` statement is the union set of the result sets produced by the individual evaluations. Rows that occur more than once are removed from the result set automatically. The entire content of a row is respected. -- If `FOR ALL ENTRIES` is specified, there must be at least one comparison with a column of the internal table. -- For more information, especially restricitions and things to pay attention to (e. g. making sure that the internal table is not initial), see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm). - -``` abap -"Checking that table is not initial -IF ( 0 < lines( itab2 ) ). - - SELECT comp1, comp2, comp3 - FROM dbtab - FOR ALL ENTRIES IN @itab2   "Host variable before internal table - WHERE comp1 = @itab2-comp1 ... "Relational expression on the right side of a comparison - INTO TABLE @itab1 - -ENDIF. -``` - -**Checking the result set of a subquery** with the addition [`EXISTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_exists.htm) - -See possible clauses and additions of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm) in a condition in ABAP SQL [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm). - -The following code snippet includes a parenthesized subquery following `EXISTS`. Data is only selected from `dbtab1` if the relational expression (`WHERE EXISTS ...`) is true, i. e. if the result set of the subquery contains at least one row. Note the components of the table that are referenced using a tilde. - -``` abap -SELECT comp1, comp2, comp3 - FROM dbtab1 AS tab1 - WHERE EXISTS - ( SELECT comp1 FROM dbtab2 - WHERE comp1 = tab1~comp1 AND comp2 = tab1~comp2 ) - INTO ... -``` - -

⬆️ back to top

- -### Combining Data of Multiple Database Tables - -**Using an [inner join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm)**: -- Columns of two or more data sources in a result set can be joined. -- Result set: - - Columns of the rows in the result set of the left side with the columns of the rows in the result set of the right side are joined into a single result set. - - Contains all combinations of rows for whose columns the join condition is true. -- If there are identical column names in multiple data sources, use the [column -selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_comp_selector_glosry.htm "Glossary Entry") -`~`. -``` abap -SELECT a~comp1, a~comp2, b~comp3, c~comp4 - FROM dbtab1 AS a - INNER JOIN dbtab2 AS b ON a~comp1 = b~comp1 AND a~comp2 = b~comp2 - INNER JOIN dbtab3 AS c ON a~comp1 = c~comp1 - WHERE ... - INTO ... -``` - -**Using an [outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenouter_join_glosry.htm)**: -- Realized by either a [left outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenleft_outer_join_glosry.htm) or -a [right outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenright_outer_join_glosry.htm). -- Result set: - - Same result set as the inner join. - - Difference: For each selected row on the left side as `LEFT OUTER JOIN` or on the right side as `RIGHT OUTER JOIN`, at least one row is created in the result set even if no rows on the other side meet the condition. The columns on the other side that do not meet the condition are filled with [null values](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). - -``` abap -"Example for a left outer join -SELECT a~comp1, a~comp2, b~comp3, - FROM dbtab1 AS a - LEFT OUTER JOIN dbtab2 AS b ON a~comp1 = b~comp1 - WHERE ... - INTO ... -``` -> **💡 Note**
-> There are more join variants available. See the ABAP -Keyword Documentation on -[joins](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) -for more information. - -**Merging the result sets of multiple queries into a single result set** using the [set operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_set_operators_glosry.htm) [`UNION`](http://ldcialx.wdf.sap.corp:50018/sap/public/bc/abap/docu?object=abapunion&sap-language=EN&sap-client=000&version=A&tree=X). In this case, the rows of the result set of the query after `UNION` are inserted into the result set of the query in front of `UNION`. - -``` abap -SELECT FROM dbtab1 - FIELDS ... - WHERE ... -UNION - SELECT FROM dbtab2 - FIELDS ... - WHERE ... - INTO ... -``` - -

⬆️ back to top

- -#### Common Table Expressions (CTE) - -When to use [Common Table Expressions (CTE)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencommon_table_expression_glosry.htm): - -- Whenever you need intermediate results in a `SELECT` - statement and especially if you need them more than once. -- You get the option of selecting directly from a subquery (`SELECT FROM subquery`), which is not possible in ABAP SQL. - -How it works: - -- The ABAP SQL keyword - [`WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) - introduces the definition of CTEs. -- Each CTE creates a tabular result set in a - [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). -- The result set of such a CTE can then be used in subsequent queries - as data source; CTEs can be considered as temporary views, which - only exist for the duration of the database access. -- The CTEs (at least one) are then used in a final [main - query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmainquery_glosry.htm "Glossary Entry"), i. - e. a `SELECT` statement accesses the result of the - expressions. - -Setup of a statement with CTE: - -- Introductory keyword `WITH` -- A comma-separated list with at least one definition of a CTE - - Each CTE has a unique name with an initial `+` character - - An optional list of column names, which should be used in the - result set, within parentheses - - `AS` followed by a subquery with `SELECT` which - creates the tabular result set of the CTE -- A closing main query with `SELECT` in which the previous - CTEs are to be used as data source -- If a `SELECT` loop is opened and data is written into a work - area in the closing main query, the loop must be closed with - `ENDWITH.` (which fulfills the same task as - `ENDSELECT.`). - -> **💡 Note**
->- Each CTE must be used at least once, either in another CTE or in the - main query. The main query must access at least one CTE. ->- The result set of a CTE never has a [client - column](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclient_column_glosry.htm "Glossary Entry"). ->- See more information in [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) -and further options and additions when using CTEs in the subtopics. - -Example: The result sets of both common table expressions -`+connections` and `+sum_seats` are merged in the -subquery of the CTE `+result` in a join expression. An explicit -name list assigns names to the resulting columns. These names are used -in the main query to sort the results. For each flight connection of the -selected airline, the total number of occupied seats is stored in the -internal table. -``` abap -WITH -+connections AS ( - SELECT zdemo_abap_flsch~carrid, carrname, connid, cityfrom, cityto - FROM zdemo_abap_flsch - INNER JOIN zdemo_abap_carr - ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid - WHERE zdemo_abap_flsch~carrid BETWEEN 'AA' AND 'JL' ), -+sum_seats AS ( - SELECT carrid, connid, SUM( seatsocc ) AS sum_seats - FROM zdemo_abap_fli - WHERE carrid BETWEEN 'AA' AND 'JL' - GROUP BY carrid, connid ), -+result( name, connection, departure, arrival, occupied ) AS ( - SELECT carrname, c~connid, cityfrom, cityto, sum_seats - FROM +connections AS c - INNER JOIN +sum_seats AS s - ON c~carrid = s~carrid AND c~connid = s~connid ) -SELECT * - FROM +result - ORDER BY name, connection - INTO TABLE @DATA(result). -``` - -

⬆️ back to top

- -## Changing Data in Database Tables - -### Using [`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_dbtab.htm) - -- Inserts one or more rows into a database table specified. -- The rows to be inserted are taken from a structure, an internal table, or the result set of an embedded subquery. -- As mentioned above, structures and internal tables from which to insert content should be specified as host variables (with `@`) or host -expressions (with `@( ... )`). -- The system fields `sy-subrc` (0 = single row or all rows inserted successfully, 4 = row not or not all rows inserted) and `sy-dbcnt` (number of rows that are inserted) are set. - -``` abap -"Inserting a single row into a database table - -INSERT dbtab FROM @row. - -"Alternative syntax, same effect -INSERT INTO dbtab VALUES @row. - -"Line is created inline using the VALUE operator as part of a host expression - -INSERT dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). - -"Inserting multiple lines from an internal table into a database table. -"Make sure that the internal table does not contain a line having the same key -"as an existing row in the database table. Otherwise, a runtime error occurs. - -INSERT dbtab FROM TABLE @itab. - -"Inserting lines from a table declared inline using the VALUE operator -"as part of a host expression - -INSERT dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). - -"ACCEPTING DUPLICATE KEYS addition: To avoid the runtime error mentioned above, -"all lines that would produce duplicate entries in the database table -"regarding the keys are discarded and sy-subrc is set to 4. - -INSERT dbtab FROM TABLE @itab ACCEPTING DUPLICATE KEYS. - -"Inserting the result set of an embedded subquery -"Here, multiple result sets can be joined, e. g. using UNION. - -INSERT dbtab FROM ( SELECT ... ). -``` - -

⬆️ back to top

- -### Using [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapupdate.htm) -- Changes the content of one or more rows of a database table specified. -- Similar to `INSERT`, `sy-subrc` and `sy-dbcnt` are set. - -``` abap -"Changing content by overwriting entire rows based on a structure - -UPDATE dbtab FROM @row. -UPDATE dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). "Using a host expression - -"Changing content by overwriting entire rows based on rows in an internal table - -UPDATE dbtab FROM TABLE @itab. - -"Using a host expression - -UPDATE dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). - -"INDICATORS addition: Changing content of specific fields without overwriting -"existing values of other fields -"Example: -"- Structured type is created with WITH INDICATORS addition -"- Internal table from which to update dbtab is created; -" it includes the indicator structure comp_ind -"- Internal table is filled; only one component is flagged as to be updated -"- Other fields remain unchanged; note that key fields must be included -" in ind_tab (indicator setting for key fields has no effect) - -TYPES ind_wa TYPE dbtab WITH INDICATORS comp_ind TYPE abap_bool. - -DATA ind_tab TYPE TABLE OF ind_wa. - -ind_tab = VALUE #( -       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) -       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) ). - -UPDATE dbtab FROM TABLE @ind_tab INDICATORS SET STRUCTURE comp_ind. - -"Reverses the logic - -UPDATE dbtab FROM TABLE @ind_tab INDICATORS NOT SET STRUCTURE comp_ind. - -"SET addition: Changing values of specific fields in all table rows -"There are mutliple options for the value assignment. E. g. you can use -"a literal, host variable/expression, SQL function, and so on. - -UPDATE dbtab SET comp2 = ... . -``` - -

⬆️ back to top

- -### Using [`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_dbtab.htm) -- Inserts one or more rows into a database table specified or overwrites existing ones. -- As above, `sy-subrc` and `sy-dbcnt` are set. - -``` abap -"Inserting a single row into a database table or changing an existing row - -MODIFY dbtab FROM @row. - -"Using a host expression - -MODIFY dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). - -"Inserting/Changing multiple rows - -MODIFY dbtab FROM TABLE @itab. - -"Using a host expression - -MODIFY dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) -                                    ( comp1 = ... comp2 = ... ) ) ). - -"Inserting/Changing multiple rows based on a result set of an embedded subquery - -MODIFY dbtab FROM ( SELECT ... ). -``` - -

⬆️ back to top

- -### Using [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdelete_dbtab.htm) -- Deletes one or more rows from a database table specified. -- As above, `sy-subrc` and `sy-dbcnt` are set. - -``` abap -"Variant DELETE FROM ...: Either all rows are deleted or restricted - -"All rows are deleted - -DELETE FROM dbtab. - -"Rows are deleted based on a condition - -DELETE FROM dbtab WHERE .... - -"Note that there are further options available, e. g. ORDER BY, UP TO -"Variant DELETE ... FROM ...: Deleting a single row or multiple row - -DELETE dbtab FROM @row. - -"Using a host expression - -DELETE dbtab FROM @( VALUE #( comp1 = ... ) ). - -DELETE dbtab FROM TABLE @itab. - -"Using a host expression - -DELETE dbtab FROM TABLE @( VALUE #( ( comp1 = ... ) -                                    ( comp1 = ... ) ) ). -``` - -

⬆️ 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. -- There are [RAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm)-specific variants of ABAP SQL statements that use the `MAPPING FROM ENTITY` addition. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmapping_from_entity.htm). - -## Executable Example -[zcl_demo_abap_sql](./src/zcl_demo_abap_sql.clas.abap) - -> **💡 Note**
-> - The executable example covers the following topics, among others: -> - Reading from database tables using `SELECT` -> - Various additions to `SELECT` statements -> - Changing data in database tables using `INSERT`, `UPDATE`, `MODIFY` and `DELETE` -> - Excursions: Operands and expressions in ABAP SQL statements -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + +# ABAP SQL + +- [ABAP SQL](#abap-sql) + - [Introduction](#introduction) + - [Excursion: Database Tables and Views](#excursion-database-tables-and-views) + - [Reading Data Using SELECT](#reading-data-using-select) + - [Basic Syntax](#basic-syntax) + - [Using SELECT for Multiple Purposes](#using-select-for-multiple-purposes) + - [Clause Variations and Additions in SELECT Statements](#clause-variations-and-additions-in-select-statements) + - [More Clauses](#more-clauses) + - [Operands and Expressions in ABAP SQL Statements](#operands-and-expressions-in-abap-sql-statements) + - [SQL operands](#sql-operands) + - [SQL Expressions](#sql-expressions) + - [Elementary Expressions](#elementary-expressions) + - [SQL Functions](#sql-functions) + - [More SQL Expressions](#more-sql-expressions) + - [Window Expressions](#window-expressions) + - [SQL Conditions](#sql-conditions) + - [Selecting Data by Evaluating the Content of Other Tables](#selecting-data-by-evaluating-the-content-of-other-tables) + - [Combining Data of Multiple Database Tables](#combining-data-of-multiple-database-tables) + - [Common Table Expressions (CTE)](#common-table-expressions-cte) + - [Changing Data in Database Tables](#changing-data-in-database-tables) + - [Using `INSERT`](#using-insert) + - [Using `UPDATE`](#using-update) + - [Using `MODIFY`](#using-modify) + - [Using `DELETE`](#using-delete) + - [More Information](#more-information) + - [Executable Example](#executable-example) + +## Introduction + +- [ABAP SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_glosry.htm) is a subset of [SQL](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_glosry.htm "Glossary Entry") + which is the standardized language for accessing databases. +- The main ABAP SQL keywords to read and change data are the + following: + + | Keyword | Purpose | + | -------- | ------------------------------------------------------------------------- | + | `SELECT` | Reads data from database tables | + | `INSERT` | Adds rows to database tables | + | `UPDATE` | Changes the content of rows of database tables | + | `MODIFY` | Inserts rows into database tables or changes the content of existing rows | + | `DELETE` | Deletes rows from database tables | + +- ABAP SQL statements use the ABAP SQL interface. This interface transforms all ABAP SQL statements that access the standard database of an AS ABAP to platform-dependent SQL and forwards the results to the database system. +- Generally bear in mind the [performance notes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_perfo.htm) when using + ABAP SQL. The considerations there are not relevant for this cheat sheet since + the focus is on syntax options. + +## Excursion: Database Tables and Views + +
+ Expand to view the details +
+ +This section provides bullet points on database tables and views which contain persisted data. Note that the code snippets in this cheat sheet focus on database tables as [data source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry") for ABAP SQL statements. + +**Database tables in [AS ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenas_abap_glosry.htm "Glossary Entry") ...** + +- are objects of the [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm "Glossary Entry"). The term *database table* describes a physical database table in the current [standard database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_db_glosry.htm). +- are two-dimensional matrices consisting of rows and columns. +- contain a [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm), i. e. a field or a combination of fields uniquely identifies every row in a table. A [primary key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_key_glosry.htm) must exist for every database table. + - Note the concept of [foreign keys](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenforeign_key_glosry.htm) in which one or more columns of a database table can be primary keys of another table. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_forkey.htm). +- have a [flat structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenflat_structure_glosry.htm "Glossary Entry") + type. Plus, the definition of database tables consists of [technical](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_techstruc.htm) and [semantic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables_semastruc.htm) properties. +- can be referenced as a data type and can be accessed using ABAP SQL. + +Find more information in the respective (sub)topics in the ABAP Keyword Documentation [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_database_tables.htm). + + +**Views ...** + +- are further ABAP Dictionary objects for grouping columns from one or more database tables, among others. +- usually realize a + [join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenjoin_glosry.htm "Glossary Entry") + with defined [join + conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenjoin_condition_glosry.htm "Glossary Entry"). +- Note: + - Similar to database tables, the columns of such a view form a + flat structure. The view's name can be used, for example, as [data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm) to declare + [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm), too. + - The views can be accessed by ABAP SQL, especially for reading + purposes using `SELECT`. + +**"Classic"** [DDIC +Views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenddic_view_glosry.htm "Glossary Entry") ... + +- are the oldest form of views and are not available in [ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_cloud_glosry.htm). +- can be accessed by ABAP SQL for read and write operations, however, writing is only supported if the view is created with only one database table. +- can only be created in the [ABAP Workbench](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_workbench_glosry.htm). + +**"Modern" Views (since release 7.40)** + +- [External + views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexternal_view_glosry.htm "Glossary Entry") + as proxies for [SAP HANA + views](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenhana_view_glosry.htm "Glossary Entry") + (attribute view, analytic view, calculation view) + - SAP HANA Views are entities of the SAP HANA database that are + defined using the [SAP HANA + Studio](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenhana_studio_glosry.htm "Glossary Entry"). + - They are based on HANA-specific data types. + - Using external views of the ABAP dictionary, you can make those + SAP HANA views "known" to the ABAP program. In doing so, the + external views can be used like classic DDIC views as structured + data types and as a source for reading operations with ABAP SQL. + - To be used only if the central database of the AS ABAP is an + [SAP HANA + database](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhana_database_glosry.htm "Glossary Entry"). +- [ABAP Core Data Services (ABAP + CDS)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_view_glosry.htm "Glossary Entry") + ... + - serve the purpose of defining semantically rich data models. + - have a lot more options than classic views, for example, they + support [annotations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_annotation_glosry.htm). Data sources can be combined using [associations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_association_glosry.htm), views can be defined with input parameters, and more. + - are used like a classic database view as structured data types + and used as a source for reading operations with ABAP SQL (using + [`SELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm)). + - are created using [Data Definition + Language (DDL)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddl_glosry.htm "Glossary Entry") + in the + [ADT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry") + (that is, a source code editor, in contrast to a form-based + editor). + - are, in contrast to external views, supported by all database + systems (that support the ABAP CDS characteristics). +
+ +

⬆️ back to top

+ +## Reading Data Using SELECT + +### Basic Syntax + +You use ABAP SQL `SELECT` statements to read data from one or more database tables (or views). This can be done to create a multirow or single row result set by assigning the result set to a suitable data object, i. e. you can store the multirow read result in an internal table or the single row result in a structure. +The `SELECT` statement includes several clauses that serve +different purposes. The following code snippet shows the basic syntax: +``` abap +SELECT FROM source "What database table or view to read from + FIELDS field_list "What columns should be read + WHERE condition "Specifies conditions on which a row/rows should be read + INTO @target. "Data object to which the result set is assigned (preceded by @) +``` +> **💡 Note**
+>- There are further clauses available of which some are dealt with + further down. In general, the recommendation is to hit `F1` for the keywords and additions to get all the details in the ABAP Keyword Documentation. +>- Especially in older ABAP programs, you will see other forms of the + `SELECT` syntax that you should no longer use. Strict syntax check modes might enforce the use + of specific ABAP SQL syntax. For example, the `INTO` clause should be placed after the other clauses. Furthermore, [host variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") or [host expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") are required for data objects and expressions, i. e. they must be preceded by `@` or `@( ... )`. Further information: [Release-Dependent Syntax Check Modes (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_sql_strict_modes.htm). +>- Regarding host variables as in `SELECT ... INTO @target.` and since they are used in most examples below: A host variable is a data object that is +> - declared in the ABAP program +> - prefixed with the `@` character and +> - specified in an [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm) of an ABAP SQL statement. +> See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm). +>- The `SELECT` list, i. e. the fields that are specified, can also be specified following the `SELECT` + keyword before the `FROM` clause - without `FIELDS`. The + following two `SELECT` statements are basically the same but differently arranged: +> ``` abap +> SELECT FROM dbtab +> FIELDS comp1, comp2, comp3 +>    ... +> +> SELECT comp1, comp2, comp3 +> FROM dbtab +>    ... +> ``` +>- Regarding the target into which data is read: Instead of using a + variable that is (extra) declared beforehand, you can also make use + of [inline + declarations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm "Glossary Entry"), + for example `... INTO TABLE @DATA(itab).`, to comfortably + create an appropriate variable in place. Note that in case of + internal tables as targets, the resulting table is a standard table + and has an empty key which might have an impact when further + processing the internal table entries. Find more information in the + ABAP cheat sheet [Internal Tables](01_Internal_Tables.md). In newer ABAP releases, the declaration operator [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) can be used to declare immutable variables. + +

⬆️ back to top

+ +### Using SELECT for Multiple Purposes + +**Reading a single row into a structure** +``` abap +"SINGLE addition +"Here, all fields of a single row a read. Specifying an +"asterisk * indicates that all fields are to be read. +"Alternatively, you can list all the fields separated by comma. +"Note that if the selection covers more than one row, e. g. in case +"of a non-unique WHERE clause, one of these rows is included in +"the result. +SELECT SINGLE FROM dbtab + FIELDS * + WHERE ... + INTO @struc. "Existing structure of dbtab's row type + +"Reading a selected set of fields of a single row +SELECT SINGLE FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + INTO @DATA(struc2). "Structure declared inline + +"Alternative syntax without the FIELDS addition +"Here, the CORRESPONDING FIELDS OF addition is used. Only the content of +"columns that have identically named components in the target data object +"is assigned. +SELECT SINGLE comp1, comp2, comp3   "Selected set of fields + FROM dbtab + WHERE ... + INTO CORRESPONDING FIELDS OF @struc. "Existing structure +``` +> **💡 Note**
+>- Although its use is optional, a `WHERE` clause should be specified to further restrict the read result. +>- Regarding the addition `CORRESPONDING FIELDS OF` in the `INTO` + clause: As mentioned, only the content of columns for which there are identically named components in the target are assigned. However, if you want to read data into an existing data object and particular fields are specified in the `SELECT` list and if the addition is **not** specified, you might stumble on undesired results. The target data object must contain enough components and the content of the columns are assigned to the components of the target from left to right in the order specified after `SELECT`. The content of surplus components of the target is not changed. Plus, pay attention to [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm). Basic rule: Without `CORRESPONDING ...`, column names do not play a role but only the position. With `CORRESPONDING ...`, the position of the columns does not play a role but only the name. +>- Find more information regarding the addition `INTO` [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm). + +**Reading multiple rows into an internal table**. +``` abap +SELECT FROM dbtab + FIELDS *   "All fields + WHERE ... + INTO TABLE @itab. "itab has an appropriate row type + +"Alternative syntax without the FIELDS addition +SELECT comp1, comp2, comp3   "Selected set of fields + FROM dbtab + WHERE ... + INTO TABLE @DATA(lv_itab). "Internal table declared inline + +"Selected set of fields, existing variable +"See the note on CORRESPONDING FIELDS OF above +SELECT FROM dbtab + FIELDS comp1, comp2, comp3   "Selected set of fields + WHERE ... + INTO CORRESPONDING FIELDS OF TABLE @itab. +``` + +**`SELECT` loop: Sequentially reading multiple rows**. +- A `SELECT` loop can be opened if the assignment is made to a structure and the addition `SINGLE` is not used. +- If the row is found, the system field `sy-subrc` is set to `0`. +- The loop must be closed using `ENDSELECT`. +- To terminate the loop completely, you can use the statement [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm). +- Note: As covered further down, when using the addition `PACKAGE SIZE` and storing the result in a table, a loop is opened, too. + +``` abap +SELECT FROM dbtab + FIELDS * + WHERE ... + INTO @struc. + + IF sy-subrc = 0. +      ...  "For example, making changes on data and adding the row to an internal table. + + ENDIF. + +ENDSELECT. +``` +

⬆️ back to top

+ +### Clause Variations and Additions in SELECT Statements + +`SELECT`/`FROM` clauses: + +**Checking the existence of a row in a database table** +``` abap +"Instead of @abap_true, you could also use 'X'. +SELECT SINGLE @abap_true + FROM dbtab + WHERE ... + INTO @DATA(exists). + +IF exists = abap_true. + ... +ENDIF. +``` + +**Removing rows that occur more than once in a multirow result set** using the `DISTINCT` addition. +- Cannot be used with the addition `SINGLE`. +- See more information here [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause.htm). +``` abap +SELECT DISTINCT comp1 + FROM dbtab + WHERE ... + INTO TABLE @itab. +``` + +**SELECT list variants** (some of them are already outlined above) + +The following specifications can also be combined: +- `SELECT * ...`: As outlined above, the `*` character defines all columns to be read from a data source (in the order specified there). +- `SELECT col1, col2, col3 ...`: A comma-separated list of individual column names. +- `SELECT data_source~col1, data_source~col2, data_source~col3 ...`: A comma-separated list of individual column names. Here, the name of the data source is explicitly specified and precedes the column name, separated by a tilde. +- `SELECT data_source~* ...`: In this case, the name of the data source is followed by a tilde and the `*` character to specify all columns. Note that there are [special conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_list.htm#!ABAP_VARIANT_1@1@) when using this variant. +- `SELECT col1 AS al1, col2 AS al2, col3 AS al3 ...`: + - Defining alias names for individual columns of the result set with [`AS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_list.htm). + - Make sure that you use an alias name only once here. In the statement, the alias name can only be used after an `ORDER BY` clause. + - As shown further down, in some cases (e. g. when using SQL expressions) the specification of an alias name is required. Setting an alias name for the data source is also possible (`SELECT FROM dbtab AS alias_name ...`). See the section on joins further down. + +> **💡 Note**
+> You have plenty of options regarding the specification of the columns in the `SELECT` list, among them, the outlined direct specification of the column name. SQL expressions can be specified, too. See more details [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_clause_col_spec.htm) and in the sections on SQL expressions further down. + + +``` abap +"All fields +SELECT * FROM dbtab + WHERE ... + INTO ... + +"Comma-separated list +SELECT col1, col2, col3 + FROM dbtab + WHERE ... + INTO ... + +"Comma-separated list, data source explicitly specified +SELECT dbtab~col1, dbtab~col2, col3 + FROM dbtab + WHERE ... + INTO ... + +"Data source explicitly specified, all fields +SELECT dbtab~* + FROM dbtab + WHERE ... + INTO ... + +"Alias names +"Consider the following: You want to read data from a database table into a target data +"object but, for example, a name in the target is different. Provided that there will +"not be an issue regarding the type (conversion) when the values are assigned, you might +"specify an alias name for the database column to match a component's name in the target data object. +SELECT FROM dbtab + FIELDS comp1 AS comp_a, comp2 AS comp_b, comp3 AS comp_c + WHERE ... + INTO CORRESPONDING FIELDS OF TABLE @itab. + +"Alias name also possible for the data source +SELECT ds~col1, ds~col2, ds~col3 + FROM dbtab AS ds + WHERE ... + INTO ... +``` + +

⬆️ back to top

+ +**Reading data from a database table in another client** ([classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm) only). Note that there are several variants of the `USING ...` addition for switching the [implicit client handling (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_sql_client_handling.htm) from the current client to other clients. See more information [here (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect_client.htm). +``` abap +"Some examples; not available in ABAP for Cloud Development + +"Replaces the current client with the specified client +SELECT * + FROM dbtab USING CLIENT '000'             + WHERE ... + INTO TABLE @itab. + +"Selects data of any number of clients +SELECT * + FROM dbtab USING ALL CLIENTS + WHERE ... + INTO TABLE @itab. +``` + +**Reading data from an internal table as data source** using `SELECT`. Note that an alias name must be specified for the internal table used as data source. +Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_itab.htm). + +``` abap +SELECT * + FROM @itab1 AS tab + WHERE ... + INTO TABLE @DATA(itab2). +``` + +

⬆️ back to top

+ +`INTO` **clause**: + +**Limiting the number of returned table rows** using the optional addition [`UP TO n ROWS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm). + +``` abap +"A maximum of five rows are to be returned +"If the INTO clause is the last clause, the UP TO clause must be positioned after it. +SELECT * FROM dbtab + WHERE ... + INTO TABLE @DATA(itab_upto) + UP TO 5 ROWS. +``` + +**Returning only the table rows after a row with a specified count from the result set** using the optional addition [`OFFSET n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_up_to_offset.htm#!ABAP_ADDITION_2@2@). You can only use the addition, if an `ORDER BY` clause is specified. + +``` abap +"In the example, data of all flights are retrieved, except for the 2 flights +"with the shortest flight time. +SELECT * + FROM ztest_abap_flsch + WHERE carrid = 'LH' + ORDER BY fltime ASCENDING + INTO TABLE @DATA(itab) + OFFSET 2. +``` + +**Reading into individual elementary data objects**. +Apart from reading into structures and internal tables outlined above, you can also read into individual elementary data objects. +Here, the individual elementary data objects as target objects are specified in a comma-separated list (e. g. as existing host variables or declared inline with `@DATA(...)`) and put between a pair of parentheses. +Note: +- The comma-separated list must have the same number of elements as columns in the result set. +- The content of the columns in the result set is assigned to the data objects specified in the list from left to right in accordance with the order specified in the `SELECT` list. +- Note the [assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenselect_into_conversion.htm) also in this context. +- More information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ALTERNATIVE_1@1@). + + +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + INTO (@res1,@res2,@res3). + "INTO (@DATA(res1),@DATA(res2),@DATA(res3)). "Using inline declarations +``` + +**Appending the result set to an existing internal table**. +The addition `INTO` initializes the target object. When using the addition `APPENDING`, you can retain existing lines in internal tables. `APPENDING` is also possible with the addition `CORRESPONDING FIELDS OF TABLE`. + +``` abap +SELECT * FROM dbtab + WHERE ... + APPENDING TABLE @itab. + +SELECT * FROM dbtab + WHERE ... + APPENDING CORRESPONDING FIELDS OF TABLE @diff_itab. +``` + +**Reading into packages of a specified number of rows** when reading into internal tables. The addition [`PACKAGE SIZE n`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinto_clause.htm#!ABAP_ONE_ADD@1@) can be specified after `INTO TABLE` and `APPENDING TABLE`. A `SELECT` loop ist opened. After `PACKAGE SIZE`, the number of rows is specified (which can be a host variable, host expression or a literal of type `i`) denoting the number of rows to be inserted in the target object per iteration. +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + INTO TABLE @DATA(itab_pack) PACKAGE SIZE n. +... +ENDSELECT. +``` + +**Specifying an [anonymous data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) as target object** using the addition [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm#!ABAP_ALTERNATIVE_3@3@). Only to be used after `INTO` and not `APPENDING`. + +``` abap +"Here, the target object is an anonymous data object declared inline. +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + INTO TABLE NEW @DATA(dref). +``` + +

⬆️ back to top

+ +### More Clauses + +[`GROUP BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapgroupby_clause.htm) +clause: Combining groups of table rows in the result set. You +might also use [SQL expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") +here. Multiple clause elements are separated by a comma. Find more +information on SQL expressions further down. + +Note that the `GROUP BY` clause requires all columns that are +directly specified in the `SELECT` list or specified there as an +argument of an SQL expression to be specified. An exception to this is +[aggregate +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") +in [aggregate +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_expression_glosry.htm "Glossary Entry") +(except [grouping +functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengrouping_glosry.htm "Glossary Entry")) +as shown in the following example. + +In the example below, the database table rows that have the same content in column `comp1` are combined. The lowest and highest values in column `comp2` are determined for each of these groups and placed into the combined row. +``` abap +SELECT FROM dbtab + FIELDS comp1, MIN( comp2 ) AS min, MAX( comp2 ) AS max + WHERE ... + GROUP BY comp1 + INTO ... +``` + +[`HAVING`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaphaving_clause.htm) +clause: Limiting the number of table rows in groups in the +result by setting conditions on these rows. The rows for which a +logical expression is true are inserted in the target variable. Note +that `HAVING` can only be used together with `GROUP BY`. +``` abap +SELECT FROM dbtab + FIELDS comp1, MIN( comp2 ) AS min, MAX( comp3 ) AS max + WHERE ... + GROUP BY comp1 + HAVING comp1 LIKE '%XYZ%' AND SUM( comp4 ) > 100 + INTO ... +``` + +[`ORDER BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaporderby_clause.htm) +clause: Sorting the result set by specified columns. + +The following example shows the ordering of the result set based on the +content of the primary key of the [data +source](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_source_glosry.htm "Glossary Entry"). +You can also order by any columns and by explicitly specifying the sort +order. There are more ordering options, for example, by using SQL +expressions. +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE ... + ORDER BY PRIMARY KEY + "comp2 ASCENDING + "comp2 DESCENDING + INTO ... +``` + +> **💡 Note**
+>- Not specifying `ORDER BY` means that the order of entries in the result set is undefined. +>- If `ORDER BY` and `GROUP BY` clauses are used, all columns specified after `ORDER BY` must also be specified after `GROUP BY`. +>- If aggregate functions are specified after `SELECT`, all columns that are specified after `ORDER BY` and that do not have an alias name for an aggregate function must also be specified after `SELECT` and after the `GROUP BY` clause which is required in this case, too. + +[`WHERE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwhere.htm) clause: Restricts the number of rows that are included in the result set using logical expressions. See further information on them in the following sections. +``` abap +SELECT FROM dbtab + FIELDS comp1, comp2, comp3 + WHERE comp1 = 'abc' + AND comp2 < 123    + INTO ... +``` + +

⬆️ back to top

+ +### Operands and Expressions in ABAP SQL Statements + +ABAP offers plenty of [SQL +operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_glosry.htm "Glossary Entry") +and +[expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_expression_glosry.htm "Glossary Entry") +that are possible in ABAP SQL statements, not only in the context of +`SELECT` statements and the `SELECT` lists which are +mainly used for the following demonstration examples. Questions about +when to use what, what is possible in which contexts and positions, is +beyond the scope of this cheat sheet. Check the details in the +respective topics in the ABAP Keyword Documentation. Find a general +overview of important operand positions in ABAP SQL +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operand_positions_oview.htm). +Due to the rich variety of options, the cheat sheet covers a selection. + +#### SQL operands + +- Are elementary operands in an ABAP SQL statement +- Can be database table or view columns, a + [literal](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_glosry.htm "Glossary Entry"), + [host + variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_variable_glosry.htm "Glossary Entry") + (i. e. global or local data objects escaped using `@`: + `@dobj`) or [host + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhost_expression_glosry.htm "Glossary Entry") + (`@( ... )`) + - Regarding literals: They are not prefixed with the escape + character `@`. The literals can be + [typed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentyped_literal_glosry.htm "Glossary Entry") + (using the type name and content within a pair of backquotes: + char\`abc\`) with [built-in ABAP Dictionary + types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_builtin_types.htm) + or untyped. Typed literals are preferable for the following + reasons: Using untyped literals means extra cost in terms of + performance since they must be converted by the compiler. Plus, + their use can result in errors at runtime whereas typed literals + guarantee type compatibility at once. + - Regarding host expressions: Structures and internal tables are + possible as host expressions for statements modifying the + content of database tables as shown further down. +- See more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_operands.htm). + +Example demonstrating possible operands: +``` abap +DATA upto TYPE i VALUE 3. + +SELECT FROM zdemo_abap_flsch + FIELDS +  "Specifies a column of a data source directly using its name + cityfrom, + +  "Column selector ~ can be used to prefix every specified column. +  "Here, it is optional. It is non-optional, e. g., if multiple data +  "sources in an ABAP SQL statement are edited and the column name +  "is not unique. + zdemo_abap_flsch~cityto, + + 'Lufthansa' AS name, "Untyped literal + + char`X` AS flag, "Typed literal + + @upto AS num, "Host variable + + @( cl_abap_context_info=>get_system_date( ) ) as date "Host expression + + WHERE carrid = 'LH'         "Untyped literal + AND countryfr = char`DE` "Typed literal + +  "Data object created inline and escaped with @ + INTO TABLE @DATA(it) + +  "The following clause shows all options having the same effect + UP TO 3 ROWS.         "Untyped numeric literal + "UP TO int4`3` ROWS.   "Typed numeric literal + "UP TO @upto ROWS.     "Host variable + "UP TO @( 10 - 7 ) ROWS. "Host expression +``` + +

⬆️ back to top

+ +#### SQL Expressions + +- Expressions in an ABAP SQL statement that are passed to the database + system for evaluation. +- For example, SQL expressions can be specified as columns in the + `SELECT` list as demonstrated in most of the following examples. + Find information on more possible positions and general information + on SQL expressions + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm) + and the subtopics there. + +##### Elementary Expressions + +- An elementary expression represents one of the four mentioned + operands above: A value from the database (the column name) or + values from an ABAP program passed to the database (literal, host + variable or host expression). +- As an example, see the `SELECT` list in the example above. +- See more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_elem.htm). + +##### SQL Functions + +- You can use built-in functions in ABAP SQL. +- Result: Value with the associated dictionary type. +- Arguments of the functions: Cover one or more SQL expressions. +- See more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_builtin_functions.htm). + +Example: [Numeric functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith_func.htm) +``` abap +SELECT SINGLE + carrname, + + "Division, result rounded to an integer + "Result: 2 + div( 4, 2 ) AS div, + + "Division, 3rd argument: result is rounded to the specified + "number of decimals + "Result: 0.33 + division( 1, 3, 2 ) AS division, + + "Result is rounded to first greater integer + "Result: 2 + ceil( decfloat34`1.333` ) AS ceil, + + "Result is the remainder of division + "Result: 1 + mod( 3, 2 ) AS mod, + + "Result: Largest integer value not greater than the specified value + "Result: 1 + floor( decfloat34`1.333` ) AS floor, + + "Returns the absolute number + "Result: 2 + abs( int4`-2` ) AS abs, + + "Result is rounded to the specified position after the decimal separator + "Result: 1.34 + round( decfloat34`1.337`, 2 ) AS round + + FROM zdemo_abap_carr + WHERE carrid = 'AA' + INTO @DATA(numeric_functions). +``` + +

⬆️ back to top

+ +Example: [String functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string_func.htm) + +``` abap +SELECT SINGLE + carrid,   "LH + carrname, "Lufthansa + url, "http://www.lufthansa.com + + "Concatenates strings, ignores trailing blanks + "Result: LHLufthansa + concat( carrid, carrname ) AS concat, + + "Concatenates strings, number denotes the blanks that are inserted + "Result: LH Lufthansa + concat_with_space( carrid, carrname, 1 ) AS concat_with_space, + + "First letter of a word -> uppercase, all other letters -> lowercase; + "note that a space and other special characters means a new word. + "Result: Http://Www.Lufthansa.Com + initcap( url ) AS initcap, + + "Position of the first occurrence of the substring specified + "Result: 6 + instr( carrname,'a' ) AS instr, + + "String of length n starting from the left of an expression; + "trailing blanks are ignored + "Result: Luft + left( carrname, 4 ) AS left, + + "Number of characters in an expression, trailing blanks are ignored + "Result: 24 + length( url ) AS length, + + "Checks if expression contains a PCRE expression; + "case-sensitive by default (case_sensitive parameter can be specified) + "Notes on the result: 1 = found, 0 = not found + "Result: 1 + like_regexpr( pcre  = '\..', "Period that is followed by any character +                value = url ) AS like_regex, + + "Returns position of a substring in an expression, + "3rd parameter = specifies offset (optional) + "4th parameter = determines the number of occurrences (optional) + "Result: 9 + locate( carrname, 'a', 0, 2 ) AS locate, + + "Searches a PCRE pattern, returns offset of match; + "many optional parameters: occurrence, case_sensitive, start, group + "Result: 21 + locate_regexpr( pcre = '\..', "Period followed by any character +                  value = url, +                  occurrence = 2 ) "2nd occurrence in the string + AS locate_regexpr, + + "Searches a PCRE pattern, returns offset of match + 1; + "many optional parameters: occurrence, case_sensitive, start, group + "Result: 2 + locate_regexpr_after( pcre = '.',  "Any character +                        value = url, +                        occurrence = 1 ) AS locate_regexpr_after, + + "Removes leading characters as specified in the 2nd argument, + "trailing blanks are removed + "Result: ufthansa + ltrim( carrname, 'L' ) AS ltrim, + + "Counts all occurrences of found PCRE patterns + "Result: 2 + occurrences_regexpr( pcre = '\..', "Period that is followed by any character +                       value = url ) AS occ_regex, + + "Replaces the 2nd argument with the 3rd in an expression + "Result: Lufth#ns# + replace( carrname, 'a', '#' ) AS replace, + + "Replaces a found PCRE expression; + "more parameters possible: occurrence, case_sensitive, start + "Result: http://www#ufthansa#om + replace_regexpr( pcre = '\..', "Period that is followed by any character +                   value = url, +                   with = '#' ) AS replace_regex, + + "Extracts a string with the length specified starting from the right + "Result: hansa + right( carrname, 5 ) AS right, + + "Expands string to length n (2nd argument); trailing blanks produced + "are replaced by the characters from the (3rd) argument + "Note that if n is less than the string, the expression is truncated + "on the right. + "Result: Lufthansa### + rpad( carrname, 12, '#' ) AS rpad, + + "All trailing characters that match the character of the 2nd argument + "are removed; trailing blanks are removed, too + "Result: Lufthans + rtrim( carrname, 'a' ) AS rtrim, + + "Returns a substring; 2nd argument = position from where to start; + "3rd argument: length of the extracted substring + "Result: fth + substring( carrname, 3, 3 ) AS substring, + + "Searches for a PCRE expression and returns the matched substring + "More parameters possible: occurrence, case_sensitive, start, group + "Result: .lu + substring_regexpr( pcre = '\...', "Period that is followed by any two characters +                     value = url ) AS substring_regexpr, + + "All lower case letters are transformed to upper case letters + "Result: LUFTHANSA + upper( carrname ) AS upper + + FROM zdemo_abap_carr + WHERE carrid = 'LH' + INTO @DATA(string_functions). +``` + +

⬆️ back to top

+ +Example: [Special functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sql_special_functions.htm) + +``` abap +SELECT SINGLE + carrid, + +  "Conversion functions +  "When used: Special conversions that cannot be handled in a general +  "CAST expression + +  "Type conversion: string of fixed length (e.g. of type c) to variable +  "length string of type string + to_clob( carrid ) AS clob, + +  "Byte string -> character string + bintohex( raw`3599421128650F4EE00008000978B976` ) AS bintohex, + +  "Character string -> byte string + hextobin( char`3599421128650F4EE00008000978B976` ) AS hextobin, + +  "Byte field of type RAW to a byte string (BLOB) of type RAWSTRING + to_blob( raw`3599421128650F4EE00008000978B976` ) AS blob, + +  "Unit and currency conversion functions +  "More parameters are available. + +  "Converts miles to kilometers + unit_conversion( quantity = d34n`1`, +                   source_unit = unit`MI`, +                   target_unit = unit`KM` ) AS miles_to_km, + +  "Converts Euro to US dollars using today's rate + currency_conversion( +    amount = d34n`1`, +    source_currency = char`EUR`, +    target_currency = char`USD`, +    exchange_rate_date = @( cl_abap_context_info=>get_system_date( ) ) +                     ) AS eur_to_usd, + +  "Date and time functions + add_days( @( cl_abap_context_info=>get_system_date( ) ), 4 ) AS add_days, + add_months( @( cl_abap_context_info=>get_system_date( ) ), 2 ) AS add_months, + is_valid( @( cl_abap_context_info=>get_system_date( ) ) ) AS date_is_valid, + is_valid( @( cl_abap_context_info=>get_system_time( ) ) ) AS time_is_valid + +FROM zdemo_abap_carr +INTO @DATA(special_functions). +``` + +

⬆️ back to top

+ +[Aggregate expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm) + +- Consist of [aggregate + functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") + and aggregate the values of multiple rows of the result set of a + [query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenquery_glosry.htm "Glossary Entry") + into a single value +- See more information + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_aggregate.htm). + +Example: +``` abap +"The example shows a selection of available functions +SELECT + carrid, + + "Average value of the content of a column in a row set + AVG( fltime ) AS fltime1, + + "AVG with data type specification for the result + AVG( fltime AS DEC( 14,4 ) ) AS fltime2, + + "Maximum value of the results in a row set + MAX( fltime ) AS max, + + "Minimum value + MIN( fltime ) AS min, + + "Sum of the results in a row set. + SUM( fltime ) AS sum, + + "Returns the number of rows in a row set. + "The following two have the same meaning. + COUNT( * ) AS count2, + COUNT(*) AS count3, + + "Chains the results in a row set. + "An optional separator can be specified + STRING_AGG( airpfrom, ', ' ) AS string_agg + + FROM zdemo_abap_flsch + WHERE carrid = 'LH' + GROUP BY carrid + INTO TABLE @DATA(agg_exp). +``` + +

⬆️ back to top

+ +##### More SQL Expressions + +- [Arithmetic + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_arith.htm) + to perform arithmetic calculations using the operators `+`, + `-`, `*`, `/`, +- [Cast + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast.htm) + to convert the value of operands to a dedicated dictionary type. + Note that there are special [conversion + rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_cast_rules.htm). +- [String + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_string.htm) + using the operator `&&` to concatenate character strings. +- [Case + distinctions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_case.htm) + to carry out either a simple (comparison of the values of a + dedicated operand) or complex (searched case; evaluation of multiple + logical expressions) case distinction. + +The following example demonstrates the expressions mentioned above: +``` abap +SELECT SINGLE +  carrid, + +  "Arithmethic expressions +  "operators + - * +  "Note that / is not allowed in integer expressions as the one below +  ( 1 + 2 ) * 3 AS calc, + +  "/ used in an expression using type adjustment in ABAP SQL. +  "A cast expression converts the value of the operands to the +  "specified dictionary type. The result is a representation of the +  "source value in the specified type. + CAST( 1 AS D34N ) / CAST( 2 AS D34N ) AS ratio, + +  "String expression using && to concatenate two character strings; +  "the result of the concatenation must not be longer than +  "255 characters. +  carrid && carrname AS concat, + +  "Case distinction +  "Simple case distinction +  "The expression compares the values of an operand with other +  "operands. Result: The first operand after THEN for which the +  "comparison is true. If no matches are found, the result specified +  "after ELSE is selected. + CASE currcode + WHEN 'EUR' THEN 'A' + WHEN 'USD' THEN 'B' + ELSE 'C' + END AS case_simple, + +  "Complex case distinction +  "The expression evaluates logical expressions. Result: The first +  "operand after THEN for which the logical expression is true. If no +  "logical expressions are true, the result specified after ELSE is +  "selected. + CASE WHEN length( carrname ) <= 5 THEN 'small' + WHEN length( carrname ) BETWEEN 6 AND 10 THEN 'mid' + WHEN length( carrname ) BETWEEN 11 AND 15 THEN 'large' + ELSE 'huge' + END AS case_complex + +FROM zdemo_abap_carr +WHERE carrid = 'AA' +INTO @DATA(more_sql_expr). +``` + +

⬆️ back to top

+ +##### Window Expressions + +How [window expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_expression_glosry.htm "Glossary Entry") work: + +- Define a subset of the result set (i. e. the + "[window](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_glosry.htm "Glossary Entry")") + of a database query that implements ABAP SQL +- Apply a [window + function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwindow_function_glosry.htm "Glossary Entry") - + which evaluates the rows of the window and which can, for example, + be an [aggregate + function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenaggregate_function_glosry.htm "Glossary Entry") + like + [`AVG`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensql_agg_func&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_VARIANT_1@1@&tree=X) + to determine the average value - to the result set +- I. e. a window is constructed by the rows of the result set for + which all the window functions have the same result; a value is then + determined for the rows of a window + +Setup of a statement with window expressions: + +- Window function, e. g. an aggregate function like `AVG`, + followed by `OVER( ... )` (the content in the parentheses + defines the "window") +- The content in the parentheses can contain the following additions: + - Optional `PARTITION BY`: Defines the windows using a + comma-separated list of [SQL + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsql_expr.htm); + the window function is calculated for the rows of this window; + note that if the addition is not specified, the window comprises + all rows of the result set + - Optional `ORDER BY`: Introduces both an order (you can + use `ASCENDING` and `DESCENDING`) and a frame + (as outlined below) within the current window, which further + restricts the rows for which the window function is calculated + - A window frame, which stands for a subset of rows inside a + window, can optionally be defined if `ORDER BY` is + specified; there are 3 options to define the starting and ending + frame boundaries (see the example) + +See more information on window expressions and the syntax +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_over.htm). + +Examples: +``` abap +"Example 1: A simple window is constructed in the OVER clause; +"window functions - here aggregate functions - are applied +SELECT carrid, currency, + SUM( paymentsum ) OVER( PARTITION BY carrid ) AS sum, + AVG( price AS DEC( 14,2 ) ) OVER( PARTITION BY carrid ) AS avg, + MAX( price ) OVER( PARTITION BY carrid ) AS max + FROM zdemo_abap_fli + ORDER BY carrid + INTO TABLE @DATA(win). + +"Example 2: +SELECT carrid, currency, fldate, +  "Sorts the rows by some columns and counts the number of rows from +  "the first row of the window to the current row. + COUNT( * ) OVER( ORDER BY currency, fldate + ROWS BETWEEN + "UNBOUNDED PRECEDING: frame starts at the first row of the window + UNBOUNDED PRECEDING +                   "CURRENT ROW: determines starting or ending at the current row; here, it ends + AND CURRENT ROW ) AS count1, + +  "If no window frame is used, the default window frame is +  "BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, +  "i. e. the result of count1 equals the result of count2. + COUNT( * ) OVER( ORDER BY currency, fldate ) AS count2, + +  "Sorts the rows by some columns and counts the number of rows from +  "the current row to the last row of the window. +  "The result is reverse numbering. + COUNT( * ) OVER( ORDER BY currency, fldate + ROWS BETWEEN CURRENT ROW +                   UNBOUND FOLLOWING: +                   "Determines the ending frame boundary, this addition specifies the last row of the window + AND UNBOUNDED FOLLOWING ) AS count_reverse, + +  "Sorts the rows by some columns and calculates the rolling averages +  "of a subset of rows from column price. The subset consists of the +  "current row plus one preceding and one following row. Another use +  "case as below example that uses prices would be that, for example, +  "you can calculate the 3-day-average temperature for every day from +  "a list of temperature data. + AVG( price AS DEC( 14,2 ) ) OVER( ORDER BY currency, fldate + ROWS BETWEEN +       "n PRECEDING: for both start and end of frame; frame to start/end n rows above the current row + 1 PRECEDING +       "n FOLLOWING: for both start and end of frame; frame to start/end n rows beneath the current row + AND 1 FOLLOWING ) AS avg + + FROM zdemo_abap_fli + INTO TABLE @DATA(result). +``` + +

⬆️ back to top

+ +### SQL Conditions + +You can formulate conditions in ABAP SQL statements, i. e. [logical +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogical_expression_glosry.htm "Glossary Entry"), +especially in the `WHERE` clause to restrict the result. Note +that without a `WHERE` clause, all rows are respected for the +operation. + +See below a selection of the operators that are possible when specifying +conditions. For more information, see the subtopics of the [SQL +Conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenasql_cond.htm) +topic. + +| Operator | Meaning | +|----------|:-------------:| +| `=`, `EQ` | The content of two operands is equal.| +| `<>`, `NE` | The content of two operands is not equal.| +| `<`, `LT` | The content of one operand is less than the content of the other operand.| +| `>`, `GT` | The content of one operand is greater than the content of the other operand.| +| `<=`, `LE` | The content of one operand is less than or equal to the content of the other operand.| +| `>=`, `GE` | The content of one operand is greater than or equal to the content of the other operand.| +| `... [NOT] BETWEEN ... AND ...` | The value of an operand is (not) between the value of the two other operands.| +| `... [NOT] LIKE ...` | The content of an operand matches (does not match) a specified pattern. The pattern can be specified by using wildcard characters. `%` stands for any character string, including an empty string. `_` stands for any character.| +| `... IS [NOT] INITIAL ...` | The value of an operand is (not) the initial value of its built-in dictionary type.| +| `... EXISTS ...` | Checks the result set of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). The expression is true if the result set contains at least one row. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm).| +| `... [NOT] IN ...` | Checks whether the operands on the left side match a value from a set of values specified in parentheses. On the left side, a single operand or an operand list are possible. On the right side, a comma-separated lists or subqueries can be specified. It is also possible to specify a [ranges table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenranges_table_glosry.htm) to evaluate [ranges conditions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenranges_condition_glosry.htm).| +| `... IS [NOT] NULL ...` | Checks whether the value of an operand is (not) the [null value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). Find more information in the code snippet and in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_null.htm). | + +> **💡 Note**
+>You can combine multiple logical expressions into one +logical expression using `AND` or `OR`. To further +detail out the desired condition, expressions within parentheses are +possible. + +Examples: + +``` abap +"---- SQL conditions demonstrated with the WHERE clause ---- +"Note: +"- For most of the self-contained examples, an internal table is used as the +" data source of SELECT statements to work with simple data. +"- For some examples that are covered, such as subqueries, demo database tables +" from the cheat sheet repository are used in addition. +"- Dynamic specifications are also possible. They are not covered here. See +" the Dynamic Programming cheat sheet. + +"---- Types and internal table to work with in the examples ---- +"Note: You cannot use type string columns in WHERE conditions. +TYPES: BEGIN OF demo_struc, + id TYPE i, + name TYPE c LENGTH 15, + "name TYPE string, + END OF demo_struc. +DATA itab TYPE SORTED TABLE OF demo_struc WITH UNIQUE KEY id. +"Populating internal table with data to work with in the examples +itab = VALUE #( ( id = 1 name = 'bear' ) + ( id = 2 name = 'camel' ) + ( id = 3 name = 'rabbit' ) + ( id = 4 name = 'zebra' ) + ( id = 5 name = 'dog' ) + ( id = 6 name = 'deer' ) + ( id = 7 name = 'squirrel' ) + ( id = 8 name = 'cheetah' ) + ( id = 9 name = 'elephant' ) + ( id = 10 name = 'donkey' ) + ( id = 11 name = 'fish' ) + ( id = 12 name = 'sheep' ) ). + +"---- =, <>, >, >= (as a selection of possible comparison operators) ---- +SELECT id FROM @itab AS tab WHERE name = 'bear' INTO TABLE @DATA(it). "1 +SELECT id FROM @itab AS tab WHERE name <> 'bear' INTO TABLE @it. "2-12 +SELECT id FROM @itab AS tab WHERE id > 10 INTO TABLE @it. "11,12 +SELECT id FROM @itab AS tab WHERE id >= 10 INTO TABLE @it. "10,11,12 + +"---- Combining logical expressions using AND, OR and parentheses ---- +SELECT id FROM @itab AS tab WHERE id = 1 AND name = 'bear' INTO TABLE @it. "1 +SELECT id FROM @itab AS tab WHERE name = 'bear' OR name = 'sheep' INTO TABLE @it. "1,12 + +"In the following example, the resulting table is initial. One of the expressions +"in parentheses is false (AND is used between the expressions in parentheses). +"In contrast, the example below returns an entry because of using OR. +SELECT id FROM @itab AS tab + WHERE ( id = 1 AND name = 'bear' ) + AND ( id = 20 AND name = 'camel' ) + INTO TABLE @it. + +SELECT id FROM @itab AS tab + WHERE ( id = 1 AND name = 'bear' ) + OR ( id = 20 AND name = 'camel' ) + INTO TABLE @it. "1 + +"------------------------ [NOT] BETWEEN ------------------------ +SELECT id FROM @itab AS tab WHERE id BETWEEN 1 AND 4 INTO TABLE @it. "1,2,3,4 +"The condition with BETWEEN above corresponds to the following condition. +"The example makes use of a condition specified in parentheses to combine multiple +"expressions. +SELECT id FROM @itab AS tab WHERE ( id >= 1 AND id <= 4 ) INTO TABLE @it. "1,2,3,4 +"Negation with NOT +SELECT id FROM @itab AS tab WHERE id NOT BETWEEN 1 AND 4 INTO TABLE @it. "5-12 + +"------------------------ IS [NOT] INITIAL ------------------------ +SELECT id FROM @itab AS tab WHERE id IS NOT INITIAL INTO TABLE @it. "1-12 + +"------------------------ [NOT] LIKE ------------------------ +"For (not) matching a specified pattern +"Note: % (any character string), _ (any character). +SELECT name FROM @itab AS tab + WHERE name LIKE '%ee%' + OR name LIKE '_o%' + INTO TABLE @DATA(names). "dog,deer,cheetah,donkey,sheep + +"ESCAPE addition for defining a single-character escape character +"In the following example, this character is #. It is placed before +"the % character in the specification after LIKE. In this case, % +"is escaped and does then not stand for any character string in the +"evaluation. +"Adding a table entry for this syntax example. +itab = VALUE #( BASE itab ( id = 13 name = '100%' ) ). +"Any character sequence followed by the % character +SELECT name FROM @itab AS tab + WHERE name LIKE '%#%' ESCAPE '#' + INTO TABLE @names. "100% + +"Deleting the entry because it is not relevant for the further examples. +DELETE itab INDEX 13. + +"------------------------ [NOT] IN (using a value set) ------------------------ +"For (not) matching a value in a set of values specified in parentheses. + +"Single operands on the left side of IN +SELECT id FROM @itab AS tab + WHERE name IN ( 'camel', 'rabbit', 'dog', 'snake' ) + INTO TABLE @it. "2,3,5 + +"Negation NOT IN; note to use host variables/expressions for local/global data objects +DATA(animal) = 'sheep'. +SELECT id FROM @itab AS tab + WHERE name NOT IN ( 'fish', @animal ) + INTO TABLE @it. "1-10 + +"Operand list (a parenthesized comma-separated list) on the left side of IN +"For (not) matching value tuples from a set of value tuples specified in parentheses on the right side. +"In the following example, two values are specified in the operand list on the left. Consequently, +"two values with appropriate types must be specified in parentheses on the right. +SELECT id FROM @itab AS tab + WHERE ( id, name ) IN ( ( 1, 'bear' ), ( 3, 'rabbit' ), ( 8, 'zebra' ), ( 20, 'dog' ) ) + INTO TABLE @it. "1,3 + + +"------------------------ [NOT] IN (using a subquery) ------------------------ +"[NOT] IN for matching a value contained in the result set of a subquery + +"In the following example, the subquery reads data from a demo database table. +"For a representative result, the table is cleared, and then filled with 'suitable' +"data sets. +DELETE FROM zdemo_abap_tab1. +MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #( ( key_field = 11 num1 = 11 ) + ( key_field = 12 num1 = 12 ) + ( key_field = 13 num1 = 13 ) + ( key_field = 14 num1 = 14 ) ) ). + +SELECT id FROM @itab AS tab + WHERE id IN ( SELECT key_field FROM zdemo_abap_tab1 ) INTO TABLE @it. "11,12 + +"------------------------ [NOT] IN (using a ranges table) ------------------------ +"[NOT] IN for checking whether the operands on the left side match a ranges condition in a ranges table + +"Declaring a ranges table +DATA rangestab TYPE RANGE OF i. +"Populating a ranges table using the VALUE operator +rangestab = VALUE #( ( sign = 'I' option = 'BT' low = 1 high = 3 ) + ( sign = 'I' option = 'GE' low = 10 ) ). + +SELECT id FROM @itab AS tab WHERE id IN @rangestab INTO TABLE @it. "1,2,3,10,11,12 + + +"You cannot use logical operators such as CP (conforms to pattern) in the WHERE clause. +"In a ranges table, they are possible. +"Note: +"- Regarding CP: * (any character sequence), + (any character), # (escape character) +"- An equivalent example above uses the LIKE addition. +DATA rt TYPE RANGE OF demo_struc-name. +rt = VALUE #( ( sign = 'I' option = 'CP' low = '*ee*' ) "ee in a string + ( sign = 'I' option = 'CP' low = '+o*' ) ). "o in second position +SELECT name FROM @itab AS tab + WHERE name IN @rt + INTO TABLE @names. "dog,deer,cheetah,donkey,sheep + +"------------------------ EXISTS ------------------------ +"For checking the result set of a subquery. +"The following example reads all entries from the internal table if entries having +"the same key also exist in the database table. +"Note: The SELECT list in the subquery only contains a literal to determine that +"the entry exists. Specifying explicit column names is not relevant. +SELECT id FROM @itab AS tab WHERE + EXISTS ( SELECT @abap_true FROM zdemo_abap_tab1 WHERE key_field = tab~id ) + INTO TABLE @it. "11,12 + +"------------------------ IS [NOT] NULL ------------------------ +"The null value is a special value that is returned by a database. It indicates an +"undefined value or result. Note that, in ABAP, there are no special null values. Do +"not confuse the null value with a type-dependent initial value. When using SELECT +"statements to read data, null values can be produced by, for example, outer joins. +"When the null values are passed to a data object, they are transformed to the +"type-dependent initial values. For more information, refer to the ABAP Keyword Documentation. +"The following example uses a left outer join to intentionally create null values. For +"this purpose, two demo database tables of the cheat sheet repository are cleared and +"populated with specific values to visulaize null values. +DELETE FROM zdemo_abap_tab1. +DELETE FROM zdemo_abap_tab2. +MODIFY zdemo_abap_tab1 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' char2 = 'y' ) + ( key_field = 2 char1 = 'b' char2 = 'z' ) ) ). +MODIFY zdemo_abap_tab2 FROM TABLE @( VALUE #( ( key_field = 1 char1 = 'a' ) + ( key_field = 2 char1 = 'a' ) + ( key_field = 3 char1 = 'b' ) + ( key_field = 4 ) ) ). +"Note that for the entry 'key_field = 4' no char1 value was passed. +"char1 is a shared column of the two database tables, and which is used in +"the ON condition of the join. Since there is no entry in char1 for 'key_field = 4', +"the joined values are null in that case. The WHERE clause uses the addition IS NULL. +"Therefore, the result only contains this entry. char2 is assigned the type-initial +"value in the result. +SELECT tab2~key_field, tab1~char2 + FROM zdemo_abap_tab2 AS tab2 + LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 + WHERE tab1~char1 IS NULL + INTO TABLE @DATA(joined_tab). +*KEY_FIELD CHAR2 +*4 + +"The following example visualizes the null values. The INDICATORS addition of the +"INTO clause is used to specify indicators such as the null indicator. In the +"example, an appropriate target table is defined to also store information about +"which columns of the result set contain the null value and which do not. +"For more information on the syntax, refer to the ABAP Keyword Documentation. +TYPES: BEGIN OF st4null, + BEGIN OF s2, + key_field TYPE zdemo_abap_tab2-key_field, + char2 TYPE zdemo_abap_tab1-char2, + END OF s2, + BEGIN OF nulls, + key_field TYPE c LENGTH 1, + char2 TYPE c LENGTH 1, + END OF nulls, + END OF st4null. +DATA joined_tab_w_null_ind TYPE TABLE OF st4null WITH EMPTY KEY. + +SELECT tab2~key_field, tab1~char2 + FROM zdemo_abap_tab2 AS tab2 + LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 + INTO TABLE @joined_tab_w_null_ind INDICATORS NULL STRUCTURE nulls. +*S2 NULLS +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*1 y +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*2 y +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*3 z +*KEY_FIELD CHAR2 KEY_FIELD CHAR2 +*4 X + +"Negation IS NOT NULL +SELECT tab2~key_field, tab1~char2 + FROM zdemo_abap_tab2 AS tab2 + LEFT OUTER JOIN zdemo_abap_tab1 AS tab1 ON tab1~char1 = tab2~char1 + WHERE tab1~char1 IS NOT NULL + INTO TABLE @joined_tab. +*KEY_FIELD CHAR2 +*1 y +*2 y +*3 z +``` + +

⬆️ back to top

+ +### Selecting Data by Evaluating the Content of Other Tables + +[`FOR ALL ENTRIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm) +addition: +- Components of an internal table can be used in the `WHERE` clause in logical expressions for comparisons with a column of the data source. +- The logical expression is evaluated for each individual row of the internal table. +- The result set of the `SELECT` statement is the union set of the result sets produced by the individual evaluations. Rows that occur more than once are removed from the result set automatically. The entire content of a row is respected. +- If `FOR ALL ENTRIES` is specified, there must be at least one comparison with a column of the internal table. +- For more information, especially restricitions and things to pay attention to (e. g. making sure that the internal table is not initial), see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_all_entries.htm). + +``` abap +"Checking that table is not initial +IF ( 0 < lines( itab2 ) ). + + SELECT comp1, comp2, comp3 + FROM dbtab + FOR ALL ENTRIES IN @itab2   "Host variable before internal table + WHERE comp1 = @itab2-comp1 ... "Relational expression on the right side of a comparison + INTO TABLE @itab1 + +ENDIF. +``` + +**Checking the result set of a subquery** with the addition [`EXISTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_exists.htm) + +See possible clauses and additions of a [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm) in a condition in ABAP SQL [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwhere_logexp_subquery.htm). + +The following code snippet includes a parenthesized subquery following `EXISTS`. Data is only selected from `dbtab1` if the relational expression (`WHERE EXISTS ...`) is true, i. e. if the result set of the subquery contains at least one row. Note the components of the table that are referenced using a tilde. + +``` abap +SELECT comp1, comp2, comp3 + FROM dbtab1 AS tab1 + WHERE EXISTS + ( SELECT comp1 FROM dbtab2 + WHERE comp1 = tab1~comp1 AND comp2 = tab1~comp2 ) + INTO ... +``` + +

⬆️ back to top

+ +### Combining Data of Multiple Database Tables + +**Using an [inner join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninner_join_glosry.htm)**: +- Columns of two or more data sources in a result set can be joined. +- Result set: + - Columns of the rows in the result set of the left side with the columns of the rows in the result set of the right side are joined into a single result set. + - Contains all combinations of rows for whose columns the join condition is true. +- If there are identical column names in multiple data sources, use the [column +selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_comp_selector_glosry.htm "Glossary Entry") +`~`. +``` abap +SELECT a~comp1, a~comp2, b~comp3, c~comp4 + FROM dbtab1 AS a + INNER JOIN dbtab2 AS b ON a~comp1 = b~comp1 AND a~comp2 = b~comp2 + INNER JOIN dbtab3 AS c ON a~comp1 = c~comp1 + WHERE ... + INTO ... +``` + +**Using an [outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenouter_join_glosry.htm)**: +- Realized by either a [left outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenleft_outer_join_glosry.htm) or +a [right outer join](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenright_outer_join_glosry.htm). +- Result set: + - Same result set as the inner join. + - Difference: For each selected row on the left side as `LEFT OUTER JOIN` or on the right side as `RIGHT OUTER JOIN`, at least one row is created in the result set even if no rows on the other side meet the condition. The columns on the other side that do not meet the condition are filled with [null values](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_value_glosry.htm). + +``` abap +"Example for a left outer join +SELECT a~comp1, a~comp2, b~comp3, + FROM dbtab1 AS a + LEFT OUTER JOIN dbtab2 AS b ON a~comp1 = b~comp1 + WHERE ... + INTO ... +``` +> **💡 Note**
+> There are more join variants available. See the ABAP +Keyword Documentation on +[joins](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_join.htm) +for more information. + +**Merging the result sets of multiple queries into a single result set** using the [set operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_set_operators_glosry.htm) [`UNION`](http://ldcialx.wdf.sap.corp:50018/sap/public/bc/abap/docu?object=abapunion&sap-language=EN&sap-client=000&version=A&tree=X). In this case, the rows of the result set of the query after `UNION` are inserted into the result set of the query in front of `UNION`. + +``` abap +SELECT FROM dbtab1 + FIELDS ... + WHERE ... +UNION + SELECT FROM dbtab2 + FIELDS ... + WHERE ... + INTO ... +``` + +

⬆️ back to top

+ +#### Common Table Expressions (CTE) + +When to use [Common Table Expressions (CTE)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencommon_table_expression_glosry.htm): + +- Whenever you need intermediate results in a `SELECT` + statement and especially if you need them more than once. +- You get the option of selecting directly from a subquery (`SELECT FROM subquery`), which is not possible in ABAP SQL. + +How it works: + +- The ABAP SQL keyword + [`WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) + introduces the definition of CTEs. +- Each CTE creates a tabular result set in a + [subquery](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubquery_glosry.htm "Glossary Entry"). +- The result set of such a CTE can then be used in subsequent queries + as data source; CTEs can be considered as temporary views, which + only exist for the duration of the database access. +- The CTEs (at least one) are then used in a final [main + query](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmainquery_glosry.htm "Glossary Entry"), i. + e. a `SELECT` statement accesses the result of the + expressions. + +Setup of a statement with CTE: + +- Introductory keyword `WITH` +- A comma-separated list with at least one definition of a CTE + - Each CTE has a unique name with an initial `+` character + - An optional list of column names, which should be used in the + result set, within parentheses + - `AS` followed by a subquery with `SELECT` which + creates the tabular result set of the CTE +- A closing main query with `SELECT` in which the previous + CTEs are to be used as data source +- If a `SELECT` loop is opened and data is written into a work + area in the closing main query, the loop must be closed with + `ENDWITH.` (which fulfills the same task as + `ENDSELECT.`). + +> **💡 Note**
+>- Each CTE must be used at least once, either in another CTE or in the + main query. The main query must access at least one CTE. +>- The result set of a CTE never has a [client + column](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclient_column_glosry.htm "Glossary Entry"). +>- See more information in [this topic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapwith.htm) +and further options and additions when using CTEs in the subtopics. + +Example: The result sets of both common table expressions +`+connections` and `+sum_seats` are merged in the +subquery of the CTE `+result` in a join expression. An explicit +name list assigns names to the resulting columns. These names are used +in the main query to sort the results. For each flight connection of the +selected airline, the total number of occupied seats is stored in the +internal table. +``` abap +WITH ++connections AS ( + SELECT zdemo_abap_flsch~carrid, carrname, connid, cityfrom, cityto + FROM zdemo_abap_flsch + INNER JOIN zdemo_abap_carr + ON zdemo_abap_carr~carrid = zdemo_abap_flsch~carrid + WHERE zdemo_abap_flsch~carrid BETWEEN 'AA' AND 'JL' ), ++sum_seats AS ( + SELECT carrid, connid, SUM( seatsocc ) AS sum_seats + FROM zdemo_abap_fli + WHERE carrid BETWEEN 'AA' AND 'JL' + GROUP BY carrid, connid ), ++result( name, connection, departure, arrival, occupied ) AS ( + SELECT carrname, c~connid, cityfrom, cityto, sum_seats + FROM +connections AS c + INNER JOIN +sum_seats AS s + ON c~carrid = s~carrid AND c~connid = s~connid ) +SELECT * + FROM +result + ORDER BY name, connection + INTO TABLE @DATA(result). +``` + +

⬆️ back to top

+ +## Changing Data in Database Tables + +### Using [`INSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinsert_dbtab.htm) + +- Inserts one or more rows into a database table specified. +- The rows to be inserted are taken from a structure, an internal table, or the result set of an embedded subquery. +- As mentioned above, structures and internal tables from which to insert content should be specified as host variables (with `@`) or host +expressions (with `@( ... )`). +- The system fields `sy-subrc` (0 = single row or all rows inserted successfully, 4 = row not or not all rows inserted) and `sy-dbcnt` (number of rows that are inserted) are set. + +``` abap +"Inserting a single row into a database table +INSERT dbtab FROM @row. + +"Alternative syntax, same effect +INSERT INTO dbtab VALUES @row. + +"Line is created inline using the VALUE operator as part of a host expression +INSERT dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). + +"Inserting multiple lines from an internal table into a database table. +"Make sure that the internal table does not contain a line having the same key +"as an existing row in the database table. Otherwise, a runtime error occurs. +INSERT dbtab FROM TABLE @itab. + +"Inserting lines from a table declared inline using the VALUE operator +"as part of a host expression +INSERT dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) +                                    ( comp1 = ... comp2 = ... ) ) ). + +"ACCEPTING DUPLICATE KEYS addition: To avoid the runtime error mentioned above, +"all lines that would produce duplicate entries in the database table +"regarding the keys are discarded and sy-subrc is set to 4. +INSERT dbtab FROM TABLE @itab ACCEPTING DUPLICATE KEYS. + +"Inserting the result set of an embedded subquery +"Here, multiple result sets can be joined, e. g. using UNION. +INSERT dbtab FROM ( SELECT ... ). +``` + +

⬆️ back to top

+ +### Using [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapupdate.htm) +- Changes the content of one or more rows of a database table specified. +- Similar to `INSERT`, `sy-subrc` and `sy-dbcnt` are set. + +``` abap +"Changing content by overwriting entire rows based on a structure +UPDATE dbtab FROM @row. +UPDATE dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). "Using a host expression + +"Changing content by overwriting entire rows based on rows in an internal table +UPDATE dbtab FROM TABLE @itab. + +"Using a host expression +UPDATE dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) +                                    ( comp1 = ... comp2 = ... ) ) ). + +"INDICATORS addition: Changing content of specific fields without overwriting +"existing values of other fields +"Example: +"- Structured type is created with WITH INDICATORS addition +"- Internal table from which to update dbtab is created; +" it includes the indicator structure comp_ind +"- Internal table is filled; only one component is flagged as to be updated +"- Other fields remain unchanged; note that key fields must be included +" in ind_tab (indicator setting for key fields has no effect) +TYPES ind_wa TYPE dbtab WITH INDICATORS comp_ind TYPE abap_bool. + +DATA ind_tab TYPE TABLE OF ind_wa. + +ind_tab = VALUE #( +       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) +       ( comp1 = ... comp2 = ... comp_ind-comp2 = abap_true ) ). + +UPDATE dbtab FROM TABLE @ind_tab INDICATORS SET STRUCTURE comp_ind. + +"In the following example, the logic is reversed using NOT. +UPDATE dbtab FROM TABLE @ind_tab INDICATORS NOT SET STRUCTURE comp_ind. + +"SET addition: Changing values of specific fields in all table rows +"There are mutliple options for the value assignment. E.g. you can use +"a literal, host variable/expression, SQL function, and so on. +UPDATE dbtab SET comp2 = ... . +``` + +

⬆️ back to top

+ +### Using [`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_dbtab.htm) +- Inserts one or more rows into a database table specified or overwrites existing ones. +- As above, `sy-subrc` and `sy-dbcnt` are set. + +``` abap +"Inserting a single row into a database table or changing an existing row +MODIFY dbtab FROM @row. + +"Using a host expression +MODIFY dbtab FROM @( VALUE #( comp1 = ... comp2 = ... ) ). + +"Inserting/Changing multiple rows +MODIFY dbtab FROM TABLE @itab. + +"Using a host expression +MODIFY dbtab FROM TABLE @( VALUE #( ( comp1 = ... comp2 = ... ) +                                    ( comp1 = ... comp2 = ... ) ) ). + +"Inserting/Changing multiple rows based on a result set of an embedded subquery +MODIFY dbtab FROM ( SELECT ... ). +``` + +

⬆️ back to top

+ +### Using [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdelete_dbtab.htm) +- Deletes one or more rows from a database table specified. +- As above, `sy-subrc` and `sy-dbcnt` are set. + +``` abap +"Variant DELETE FROM ...: Either all rows are deleted or restricted + +"All rows are deleted +DELETE FROM dbtab. + +"Rows are deleted based on a condition +DELETE FROM dbtab WHERE .... + +"Note that there are further options available, e. g. ORDER BY, UP TO +"Variant DELETE ... FROM ...: Deleting a single row or multiple row +DELETE dbtab FROM @row. + +"Using a host expression +DELETE dbtab FROM @( VALUE #( comp1 = ... ) ). +DELETE dbtab FROM TABLE @itab. + +"Using a host expression +DELETE dbtab FROM TABLE @( VALUE #( ( comp1 = ... ) +                                    ( comp1 = ... ) ) ). +``` + +

⬆️ 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. +- There are [RAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm)-specific variants of ABAP SQL statements that use the `MAPPING FROM ENTITY` addition. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmapping_from_entity.htm). + +## Executable Example +[zcl_demo_abap_sql](./src/zcl_demo_abap_sql.clas.abap) + +> **💡 Note**
+> - The executable example covers the following topics, among others: +> - Reading from database tables using `SELECT` +> - Various additions to `SELECT` statements +> - Changing data in database tables using `INSERT`, `UPDATE`, `MODIFY` and `DELETE` +> - Excursions: Operands and expressions in ABAP SQL statements +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) diff --git a/04_ABAP_Object_Orientation.md b/04_ABAP_Object_Orientation.md index 54a5e73..86320b0 100644 --- a/04_ABAP_Object_Orientation.md +++ b/04_ABAP_Object_Orientation.md @@ -1,1329 +1,1329 @@ - - -# ABAP Object Orientation - -> **💡 Note**
-> This ABAP cheat sheet provides an overview on selected syntax options and concepts related to ABAP object orientation. It is supported by code snippets and an executable example. They are **not** suitable as role models for object-oriented design. Their primary focus is on the syntax and functionality. For more details, refer to the respective topics in the ABAP Keyword Documentation. Find an overview in the topic [ABAP Objects - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_oview.htm). - -- [ABAP Object Orientation](#abap-object-orientation) - - [Classes and Objects](#classes-and-objects) - - [Creating Classes](#creating-classes) - - [Creating a Local Class](#creating-a-local-class) - - [Creating a Global Class](#creating-a-global-class) - - [Visibility of Components](#visibility-of-components) - - [Creating the Visibility Sections](#creating-the-visibility-sections) - - [Defining Components](#defining-components) - - [Working with Objects and Components](#working-with-objects-and-components) - - [Declaring Reference Variables](#declaring-reference-variables) - - [Creating Objects](#creating-objects) - - [Assigning Reference Variables](#assigning-reference-variables) - - [Accessing Attributes](#accessing-attributes) - - [Calling Methods](#calling-methods) - - [Method Chaining](#method-chaining) - - [Self-Reference me](#self-reference-me) - - [Notes on Inheritance](#notes-on-inheritance) - - [Notes on Polymorphism and Casting](#notes-on-polymorphism-and-casting) - - [Notes on Interfaces](#notes-on-interfaces) - - [Excursions](#excursions) - - [Friendship](#friendship) - - [Events](#events) - - [Factory Methods and Singletons as Design Patterns](#factory-methods-and-singletons-as-design-patterns) - - [More Information](#more-information) - - [Executable Example](#executable-example) - -## Classes and Objects - -Object-oriented programming in ABAP means dealing with -[classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_glosry.htm "Glossary Entry") -and -[objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_glosry.htm "Glossary Entry"). - -Objects ... - -- are - [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm "Glossary Entry") - of a - [type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_glosry.htm "Glossary Entry"). - In this context, they are instances of a - [class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_glosry.htm "Glossary Entry"). - The terms *object* and *instance* are used synonymously. -- exist in the [internal - session](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninternal_session_glosry.htm "Glossary Entry") - of an [ABAP - program](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm "Glossary Entry"). - - -Classes ... -- are templates for objects, i. e. they determine how - all instances of a class are set up. All instances are created (i.e they are [instantiated](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstantiation_glosry.htm "Glossary Entry")) based on this template and, thus, have the same setup. - - To give an example: If, for example, a vehicle represents a class, then the - instances of the class `vehicle` have the same setup. - That means they all share the same kind of components like a brand, model and color or the same functionality like the acceleration or braking distance. - However, the values of these components are different from instance to instance. For example, one - instance is a red sedan of brand A having a certain - acceleration; another instance is a black SUV of brand B and so on. You can create an object (or instance respectively) that stands - for an actual vehicle with which you can work with. You might create any number of objects that are based on such a class - if instantiation is allowed. -- contain - [components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_glosry.htm "Glossary Entry"): - - [Attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenattribute_glosry.htm "Glossary Entry") - of the objects (the data object declarations) - - [Methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmethod_glosry.htm "Glossary Entry") - that determine the behavior of an object - - [Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_glosry.htm "Glossary Entry") to trigger the processing of ABAP code - -

⬆️ back to top

- - -### Creating Classes - -You can either create local or global classes: - - - - - - - - - - -
Local classes
  • can be defined within an ABAP program
  • can only be used in the ABAP program in which the class is defined
Global -classes
  • are defined as - global types, i. e. they are visible as a repository object - in contrast to local classes. As a global type, they can be used - as the name implies - globally in other ABAP programs or global classes
  • are declared in class pools that can contain a CCIMP include and other include programs
- -> **💡 Note**
-> - If a class is only used in one ABAP program, creating a local class is enough. However, if you choose to create a global class, you must bear in mind that such a class can be used everywhere. Consider the impact on the users of the global class when you change, for example, the visibility section of a component or you delete it. -> - Apart from ADT, global classes can also be created in the ABAP Workbench (`SE80`) or with transaction `SE24` in [classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm). - -Basic structure of classes: -- [Declaration part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry") that includes declarations of the class components. -- [Implementation part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimplementation_part_glosry.htm "Glossary Entry") that includes method implementations. -- Both are introduced by `CLASS` and ended by `ENDCLASS`. - -#### Creating a Local Class - -``` abap -"Declaration part -CLASS local_class DEFINITION. - - ... "Here go the declarations for all components and visibility sections. - "You should place the declarations at the beginning of the program. - -ENDCLASS. - -"Implementation part -CLASS local_class IMPLEMENTATION. - - ... "Here go the method implementations. - "Only required if you declare methods in the declaration part. - -ENDCLASS. -``` - -#### Creating a Global Class -The code snippet shows a basic skeleton of a global class. There are [further -additions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_options.htm) -possible for the declaration part. - -``` abap -"Declaration part -CLASS global_class DEFINITION - PUBLIC "Makes the class a global class in the class library. - FINAL "Means that no subclasses can be derived from this class. - CREATE PUBLIC. "This class can be instantiated anywhere it is visible. - - ... "Here go the declarations for all components and visibility sections. - -ENDCLASS. - -"Implementation part -CLASS global_class IMPLEMENTATION. - - ... "Here go the method implementations. - "Only required if you declare methods in the DEFINITION part. - -ENDCLASS. -``` -> **💡 Note**
-> - Addition `... CREATE PROTECTED.`: The class can only be instantiated in methods of its -[subclasses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry"), -of the class itself, and of its -[friends](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm "Glossary Entry"). -> - Addition `... CREATE PRIVATE`: The class can only -be instantiated in methods of the class itself or of its friends. Hence, -it cannot be instantiated as an inherited component of subclasses. - -

⬆️ back to top

- -### Visibility of Components - -In the class declaration part, you must specify (at least one of the) three -[visibility -sections](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvisibility_section_glosry.htm "Glossary Entry") -and include class components to define their visibility. These visibility sections serve the purpose of encapsulation in ABAP Objects. For example, you do not want to make certain components publicly available for all users. The visibility sections are as follows: - - - - - - - - - - - - - - -
PUBLIC SECTION.
Components declared in this section can be accessed from within the class and from all users of the class.
PROTECTED SECTION.
Components declared in this section can be - accessed from within the class and subclasses as well as friends - - concepts related to inheritance.
PRIVATE SECTION.
Components declared in this section can only be accessed from within the class in which they are declared and its friends.
- -Summary: - -| Visible for | PUBLIC SECTION | PROTECTED SECTION | PRIVATE SECTION | -|---|---|---|---| -| Same class and its friends | X | X | X | -| Any subclasses | X | X | - | -| Any repository objects | X | - | - | - - -#### Creating the Visibility Sections -At least one section must be specified. -``` abap -CLASS local_class DEFINITION. - PUBLIC SECTION. - "Here go the components. - PROTECTED SECTION. - "Here go the components. - PRIVATE SECTION. - "Here go the components. -ENDCLASS. -``` - -

⬆️ back to top

- -### Defining Components - -All components, i. e. -- attributes (using `TYPES`, `DATA`, `CLASS-DATA`, and `CONSTANTS` for data types and data -objects), -- methods (using `METHODS` and `CLASS-METHODS`), -- events (using `EVENTS` and `CLASS-EVENTS`) as well as -- interfaces, - -are declared in the declaration part of the class. There, they must be -assigned to a visibility section. - -Two -kinds of components are to be distinguished when, for example, looking at declarations using `DATA` and `CLASS-DATA` having a preceding `CLASS-`: - -- [Instance components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_component_glosry.htm "Glossary Entry"): - Components that exist separately for each instance and can only be accessed in instances of a class. -- [Static components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_component_glosry.htm "Glossary Entry") (the declarations with `CLASS-`): - Components that exist only once per class. They do no not exclusively exist for specific instances. They can be addressed using the name of the class. - -**Attributes** - -- The attributes of a class (or interface) mean the data objects declared within a - class (or interface). -- [Instance - attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_attribute_glosry.htm "Glossary Entry") - (`DATA`): Determine the state of a objects of a class. The data - is only valid in the context of an instance. As shown further down, - instance attributes can only be accessed via an [object reference - variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry"). -- [Static - attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_attribute_glosry.htm "Glossary Entry") - (`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. - - -> **💡 Note**
-> - You can declare constant data objects that should not be -changed using -[`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) -statements. You specify the values for the constants (which are also static attributes) when you declare -them in the declaration part of a class. -> - The addition -[`READ-ONLY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_options.htm#!ABAP_ADDITION_2@2@) -can be used in the public visibility section. Effect: -> - Can be read from outside of the class -> - Cannot be changed from outside -> - Can only be changed using methods of the class or its subclasses - -Declaring attributes in visibility sections. In the code snippet below, all attributes are declared in the public section of a local class. -``` abap -CLASS local_class DEFINITION. - - PUBLIC SECTION. - TYPES some_type TYPE c LENGTH 3. "Type declaration - - DATA: inst_number TYPE i, "Instance attributes - inst_string TYPE string, - dobj_r_only TYPE c LENGTH 5 READ-ONLY. "Read-only attribute - - CLASS-DATA: stat_number TYPE i, "Static attributes - stat_char TYPE c LENGTH 3. - - CONSTANTS const_num TYPE i VALUE 123. "Non-changeable constant - - PROTECTED SECTION. - "Here go more attributes if needed. - - PRIVATE SECTION. - "Here go more attributes if needed. - -ENDCLASS. - -CLASS local_class IMPLEMENTATION. - - ... "Here go all method implementations. - -ENDCLASS. -``` - -

⬆️ back to top

- -**Methods** - -- Are internal - [procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") - determining the behavior of the class. -- Can access all of the attributes of a class and, if not defined - otherwise, change their content. -- Have a [parameter - interface](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparameter_interface_glosry.htm "Glossary Entry") - (also known as - [signature](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensignature_glosry.htm "Glossary Entry")) - with which methods can get values to work with when being called and pass values - back to the caller (see the notes on formal and actual parameters below). -- [Static - methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_method_glosry.htm "Glossary Entry") - can only access static attributes of a class and trigger static - events. You declare them using `CLASS-METHODS` statements in - a visibility section. -- [Instance - methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_method_glosry.htm "Glossary Entry") - 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. - -**Parameter Interface** - -In the simplest form, methods can have no parameter at all. Apart from that, methods can be defined with the following parameters: - -| Addition | Details | -|---|---| -|`IMPORTING`|Defines one or more input parameters to be imported by the method. | -|`EXPORTING`|Defines one or more output parameters to be exported by the method. | -|`CHANGING`|Defines one or more input or output parameters, i. e. that can be both imported and exported. | -|`RETURNING`|For [functional methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfunctional_method_glosry.htm "Glossary Entry"), i. e. such methods have only one `RETURNING` parameter that can be defined. As an output parameter like the `EXPORTING` parameter, `RETURNING` parameters pass back values (note that the formal parameters of returning parameters must be passed by value as covered below). In contrast to `EXPORTING` for which multiple parameters can be specified, only one `RETURNING` parameter can be specified in a method. If you only need one output parameter, you can benefit from using a `RETURNING` parameter by shortening the method call and enabling method chaining. Another big plus is that such functional methods can, for example, be used in expressions. In case of standalone method calls, the returned value can be accessed using the addition `RECEIVING`. | -|`RAISING` | Used to declare the [class-based exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_based_exception_glosry.htm "Glossary Entry") that can be propagated from the method to the caller. | - - -> **💡 Note**
-> - You may find the addition `EXCEPTIONS` especially in definitions of older classes. They are for non-class-based exceptions. This addition should not be used in ABAP for Cloud Development. -> - Notes on [formal - parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm "Glossary Entry") - versus [actual - parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenactual_parameter_glosry.htm "Glossary Entry"): -> - You define method parameters by specifying a name with a type which - can be a - [generic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_data_type_glosry.htm "Glossary Entry") - or - [complete](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplete_data_type_glosry.htm "Glossary Entry") - type. Examples: -> - `fp` is the formal parameter that has a complete type: `... meth IMPORTING fp TYPE string ...` -> - `gen` is the formal parameter that has a generic type: `... meth IMPORTING gen TYPE any ...` -> - Find more information about generic types also in the [Data Types and Data Objects](16_Data_Types_and_Objects.md#generic-types) cheat sheet. -> - This formal parameter includes the specification of how the - value passing should happen. Parameters can be [passed by - reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_reference_glosry.htm "Glossary Entry") - (`... REFERENCE(param) ...`; note that just specifying the - parameter name `... param ...` - as a shorter syntax - - means passing by reference by default) or [by - value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_value_glosry.htm "Glossary Entry") - (`... VALUE(param) ...`). -> - The actual parameter represents - the data object whose content is passed to or copied from a formal - parameter as an argument when a procedure is called. If - passing by reference is used, a local data object is not created for - the actual parameter. Instead, the procedure is given a - [reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm "Glossary Entry") - to the actual parameter during the call and works with the actual - parameter itself. Note that parameters that are input and passed by - reference cannot be modified in the procedure. However, the use of a - reference is beneficial regarding the performance compared to - creating a local data object. ->- Parameters can be defined as optional using the - [`OPTIONAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_parameters.htm#!ABAP_ONE_ADD@1@) - addition. In doing so, it is not mandatory to pass an actual - parameter. The - [`DEFAULT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_parameters.htm#!ABAP_ONE_ADD@1@) - addition also makes the passing of an actual parameter optional. - However, when using this addition, as the name implies, a default - value is set. - -

⬆️ back to top

- -**Constructors** - -- [Constructors](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_glosry.htm "Glossary Entry") - are special methods that are usually used for setting a defined - initial value for attributes of the class or its objects. -- A class has exactly one [instance - constructor](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_constructor_glosry.htm "Glossary Entry") - and one [static - constructor](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_constructor_glosry.htm "Glossary Entry"). -- The declaration and use of constructors is optional. -- Static constructor: - - Declared using the predefined name `class_constructor` as part of a - `CLASS-METHODS` statement in the public visibility section. - - Has no parameters. - - Automatically and immediately called once for each class when calling a class for - the first time in an internal session, i. e. when, for example, an instance of a class is created or a component is used. Note: If it is not explicitly declared and implemented, it is merely an empty method. -- Instance constructor: - - Declared using the predefined name `constructor` as part of a - `METHODS` statement. In case of global classes, it can only be declared in the public visibility section. - - Automatically called when a class is - instantiated and an instance is created. - - Can have `IMPORTING` parameters and raise exceptions. - -Example for method definitions: The following snippet shows -multiple method definitions in the public section of a local class. Most of the formal -parameters of the demo methods below are defined by just using the -parameter name. This means passing by reference (returning parameters -require to be passed by value). -``` abap -CLASS local_class DEFINITION. - PUBLIC. - METHODS: inst_meth1, "instance methods - - inst_meth2 IMPORTING a TYPE string, - - inst_meth3 IMPORTING b TYPE i - EXPORTING c TYPE i, - - inst_meth4 IMPORTING d TYPE string - RETURNING VALUE(e) TYPE string, - - inst_meth5 IMPORTING f TYPE i - EXPORTING g TYPE i - CHANGING h TYPE string - RETURNING VALUE(i) TYPE i - RAISING cx_sy_zerodivide, - - constructor IMPORTING j TYPE i. "instance constructor with importing parameter - - CLASS-METHODS: stat_meth1, "static methods - - stat_meth2 IMPORTING k TYPE i - EXPORTING l TYPE i, - - class_constructor, "static constructor - - "Options of formal parameter definitions - stat_meth3 IMPORTING VALUE(m) TYPE i, "pass by value - stat_meth4 IMPORTING REFERENCE(n) TYPE i, "pass by reference - stat_meth5 IMPORTING o TYPE i, "same as n; the specification of REFERENCE(...) is optional - stat_meth6 RETURNING VALUE(p) TYPE i, "pass by value once more (note: it's the only option for returning parameters) - - "OPTIONAL/DEFAULT additions - stat_meth7 IMPORTING q TYPE i DEFAULT 123 - r TYPE i OPTIONAL, - - "The examples above use a complete type for - "the parameter specification. Generic types - "are possible. - stat_meth8 IMPORTING s TYPE any "Any data type - t TYPE any table "Any internal table type - u TYPE clike. "Character-like types (c, n, string, d, t and character-like flat structures) - -ENDCLASS. - -CLASS local_class IMPLEMENTATION. - METHOD inst_meth1. - ... - ENDMETHOD. - - ... "Further method implementations. Note that all declared methods must go here. -ENDCLASS. -``` - -

⬆️ back to top

- -## Working with Objects and Components - -### Declaring Reference Variables -- To create an object, a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry") -must be declared. -- Such an [object reference -variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry") -is also necessary for accessing objects and their components. That means objects are not directly accessed but only via references that point to -those objects. This object reference variable contains the reference to the object - after assigning the reference to the object (see further down). -``` abap -"Declaring object reference variables -DATA: ref1 TYPE REF TO local_class, - ref2 TYPE REF TO global_class, - ref3 LIKE ref1. -``` - -

⬆️ back to top

- -### Creating Objects - -- Using the instance operator - [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm), - you can create objects of a class (and [anonymous data - objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm "Glossary Entry"), too, that are not dealt with here). As a result, - you get a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry") - that points to the created object. -- Regarding the type specifications before and parameters within the - parentheses: - - Right before the first parenthesis after `NEW`, the type, i. e. the class, must be specified. The `#` character - instead of the class name - -means that the type (`TYPE REF TO ...`) can be derived from the context (in this case from the type of the reference variable). You can -also omit the explicit declaration of a reference variable by declaring a new reference variable -[inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm), -for example, using `DATA`. In this case, the name of the class must be placed after `NEW` and before the first parenthesis. - - No parameter specified within the parentheses: No values are - passed to the instance constructor of an object. However, non-optional input parameters of the - instance constructor of the instantiated class must be filled. - No parameters are passed for a class without an explicitly declared - instance constructor. See more information: - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennew_constructor_params_class.htm). -- The operator - basically replaces the syntax [`CREATE OBJECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object.htm) you might stumble on. - -``` abap -"Declaring object reference variable -DATA: ref1 TYPE REF TO some_class. - -"Creating objects -ref1 = NEW #( ). "Type derived from already declared ref1 - -DATA(ref2) = NEW some_class( ). "Reference variable declared inline, explicit type - "(class) specification - -"Old syntax. Do not use. -"CREATE OBJECT ref3. "Type derived from already declared ref3 -"CREATE OBJECT ref4 TYPE some_class. "Corresponds to the result of the expression above -``` - -

⬆️ back to top

- -### Assigning Reference Variables -To assign or copy -reference variables, use the [assignment -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") -`=`. In the example below, both object reference variables have the same -type. - -``` abap -DATA: ref1 TYPE REF TO some_class, - ref2 TYPE REF TO some_class. - -ref1 = NEW #( ). - -"Assigning existing reference -ref2 = ref1. -``` - -More examples for dealing with object reference variables: - -**Overwriting reference variables**: An [object -reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm "Glossary Entry") -is overwritten when a new object is created with a reference variable -already pointing to an instance. -``` abap -ref1 = NEW #( ). - -"Existing reference is overwritten -ref1 = NEW #( ). -``` - -**Retaining object references**: -- If your use case is to retain the object references, for example, if you create multiple objects using the same object reference variable, you can put the reference variables in internal tables that are declared using `... TYPE TABLE OF REF TO ...`. -- The following code snippet just visualizes that the object references are not overwritten. Three objects are created with the same reference variable. The internal table includes all object references and, thus, their values are retained. -``` abap -DATA: ref TYPE REF TO some_class, - itab TYPE TABLE OF REF TO some_class. - -DO 3 TIMES. - ref = NEW #( ). - itab = VALUE #( BASE itab ( ref ) ). "Adding the reference to itab -ENDDO. -``` - -**Clearing object references**: You can use -[`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) -statements to explicitly clear a reference variable. -```abap -CLEAR ref. -``` - -> **💡 Note**
-> Objects use up space in the memory and should therefore be -cleared if they are no longer needed. However, the [garbage collector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengarbage_collector_glosry.htm "Glossary Entry") is called periodically and automatically by the [ABAP runtime framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm "Glossary Entry") and clears all objects without any reference. - -

⬆️ back to top

- -### Accessing Attributes -- Instance attributes: Accessed using -the [object component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_component_select_glosry.htm "Glossary Entry") -`->` via a reference variable. -- Static attributes: Accessed (if the attributes are visible) using the [class component -selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_component_select_glosry.htm "Glossary Entry") -`=>` via the class name. You can also declare data objects and -types by referring to static attributes. -``` abap -"Accessing instance attribute via an object reference variable - -... ref->some_attribute ... - -"Accessing static attributes via the class name - -... some_class=>static_attribute ... - -"Without the class name only within the class itself -... static_attribute ... - -"Type and data object declarations - -TYPES some_type LIKE some_class=>some_static_attribute. -DATA dobj1 TYPE some_class=>some_type. -DATA dobj2 LIKE some_class=>some_static_attribute. -``` - -

⬆️ back to top

- -### Calling Methods -- Similar to accessing attributes, instance -methods are called using `->` via a reference variable. -- Static -methods are called using `=>` via the class name. When used -within the class in which it is declared, the static method can also be -called without `class_name=>...`. -- When methods are called, the (non-optional) parameters must be specified within parentheses. -- You might also stumble on method calls with [`CALL METHOD`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_method_static.htm) -statements. These statements should no longer be used. Note that `CALL METHOD` statements are the only option in the context of [dynamic programming](06_Dynamic_Programming.md). Therefore, `CALL METHOD` statements should be reserved for dynamic method calls. - - -Examples for instance method calls and static method calls: -``` abap -"Calling instance methods via reference variable; -"within the parentheses, the parameters must be specified and assigned - if required - -ref->inst_meth( ... ). - -"Calling static methods via/without the class name - -class_name=>stat_meth( ... ). - -"Only within the program in which it is declared. -stat_meth( ... ). - -"Calling (static) method having no parameter - -class_name=>stat_meth( ). - -"Calling (static) methods having a single importing parameter: - -"Note that in the method call, the caller exports values to the -"method having importing parameters defined; hence, the addition -"EXPORTING is relevant for the caller. The following three method calls are the same - -"Explicit use of EXPORTING. -class_name=>meth( EXPORTING a = b ). - -"Only importing parameters in the method signature: explicit EXPORTING not needed - -class_name=>meth( a = b ). - -"If only a single value must be passed: -"the formal parameter name (a) and EXPORTING not needed - -stat_meth( b ). - -"Calling (static) methods having importing/exporting parameters -"Parameters must be specified if they are not marked as optional - -class_name=>meth( EXPORTING a = b c = d "a/c: importing parameters in the method signature - IMPORTING e = f ). "e: exporting parameter in the method signature - -"To store the value of the parameter, you may also declare it inline. - -class_name=>meth( EXPORTING a = b c = d - IMPORTING e = DATA(z) ). - -"Calling (static) methods having a changing parameter; -"should be reserved for changing an existing local variable and value - -DATA h TYPE i VALUE 123. -class_name=>meth( CHANGING g = h ). - -"Calling (static) methods having a returning parameter. -"Basically, they do the same as methods with exporting parameters -"but they are way more versatile, and you can save lines of code. - -"They do not need temporary variables. -"In the example, the return value is stored in a variable declared inline. - -"i and k are importing parameters -DATA(result) = class_name=>meth( i = j k = l ). - -"They can be used with other statements, e. g. logical expressions. -"In the example below, the assumption is that the returning parameter is of type i. -IF class_name=>meth( i = j k = l ) > 100. - ... -ENDIF. - -"They enable method chaining. -"The example shows a method to create random integer values. -"The methods have a returning parameter. -DATA(random_no) = cl_abap_random_int=>create( )->get_next( ). - -"RECEIVING parameter: Available in methods defined with a returning parameter; -"used in standalone method calls only. -"In the snippet, m is the returning parameter; n stores the result. -class_name=>meth( EXPORTING i = j k = l RECEIVING m = DATA(n) ). -``` - -

⬆️ back to top

- -### Method Chaining - -As shown in the previous example, method chaining is possible for functional method calls (i.e. methods that have exactly one return value declared with `RETURNING`) at appropriate read positions. In this case, the method's return value is used as an ABAP operand. -A chained method call can consist of multipled functional methods that are linked using component selectors `->`. The return values of each method are references to the next method. - -```abap -"The following example demonstrates method chaining -"The following class creates random integers. Find more information in the -"class documentation. -"Both methods have returning parameters specified. -DATA(some_int1) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) - min = 1 - max = 10 )->get_next( ). - -"Getting to the result as above - not using method chaining and inline declarations. -DATA some_int2 TYPE i. -DATA dref TYPE REF TO cl_abap_random_int. - -dref = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) - min = 1 - max = 10 ). - -some_int2 = dref->get_next( ). - -"Using the RECEIVING parameter in a standalone method call -DATA some_int3 TYPE i. -dref->get_next( RECEIVING value = some_int3 ). - -"IF statement that uses the return value in a read position -IF cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) - min = 1 - max = 10 )->get_next( ) < 5. - ... "The random number is lower than 5. -ELSE. - ... "The random number is greater than 5. -ENDIF. - -"Examples using classes of the XCO library (see more information in the -"ABAP for Cloud Development and Misc ABAP Classes cheat sheets), in which -"multiple chained method calls can be specified. Each of the methods -"has a returning parameter specified. - -"In the following example, 1 hour is added to the current time. -DATA(add1hour) = xco_cp=>sy->time( xco_cp_time=>time_zone->user )->add( iv_hour = 1 )->as( xco_cp_time=>format->iso_8601_extended )->value. - -"In the following example, a string is converted to xstring using a codepage -DATA(xstr) = xco_cp=>string( `Some string` )->as_xstring( xco_cp_character=>code_page->utf_8 )->value. - -"In the following example, JSON data is created. First, a JSON data builder -"is created. Then, using different methods, JSON data is added. Finally, -"the JSON data is turned to a string. -DATA(json) = xco_cp_json=>data->builder( )->begin_object( - )->add_member( 'CarrierId' )->add_string( 'DL' - )->add_member( 'ConnectionId' )->add_string( '1984' - )->add_member( 'CityFrom' )->add_string( 'San Francisco' - )->add_member( 'CityTo' )->add_string( 'New York' - )->end_object( )->get_data( )->to_string( ). -``` - -

⬆️ 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: -``` 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. - -``` abap -METHOD me_ref. - - DATA str TYPE string VALUE `Local string`. - - DATA(local_string) = str. - - "Assuming there is a variable str declared in the class declaration part. - DATA(other_string) = me->str. - -ENDMETHOD. -``` - -

⬆️ back to top

- -## Notes on Inheritance - -- Concept: Deriving a new class (i. e. - [subclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry")) - from an existing one - ([superclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperclass_glosry.htm "Glossary Entry")). -- In doing so, you create a hierarchical relationship between superclasses and subclasses - (an [inheritance hierarchy](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_hierarchy_glosry.htm "Glossary Entry")) to form an [inheritance - tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_tree_glosry.htm "Glossary Entry"). This is relevant for a class that can have multiple subclasses and one direct superclass. -- Subclasses ... - - inherit and thus adopt all components from superclasses. - - can be made more specific by declaring new components and - redefining instance methods (i. e. you can alter the implementation of inherited methods). In case a subclass has no further components, it contains exactly the components of the superclass - but the ones of the private visibility section are not visible there. - - can redefine the public and protected instance methods of all preceding superclasses. Note: Regarding the static components of superclasses, accessing them is possible but not redefining them. - - can themselves have multiple direct subclasses but only one direct superclass. -- Components that are changed or added to subclasses are not visible to superclasses, hence, these changes are only relevant for the class itself and its subclasses. -- Classes can rule out derivation: classes cannot inherit from classes that are specified with the addition - [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_abstract_final.htm#!ABAP_ADDITION_2@2@) - (e. g. `CLASS global_class DEFINITION PUBLIC FINAL CREATE PUBLIC. ...`). - -

⬆️ back to top

- -**Excursion: Additions `ABSTRACT` and `FINAL`** -- Both classes and methods can be defined with the additions `ABSTRACT` and `FINAL`. -- `FINAL` with ...: - - Classes: These classes cannot be inherited. All methods are automatically and implicitly `FINAL`. In this case, the addition `FINAL` cannot be used for methods. - - Methods: These methods cannot be redefined in subclasses. -- `ABSTRACT` with ...: - - Classes: Defines abstract classes. You cannot create an instance of an abstract class. To use instance components of an abstract class, you must create an instance of a subclass of such classes. - - Methods: Defines abstract methods. The addition is only allowed in abstract classes (and not for private methods). These methods cannot be implemented in the implementation part of the class where they are declared. They must be redefined in subclasses. Note that you can also have non-abstract methods in abstract classes. -- See [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_options.htm) more information on class options. - -``` abap -"Declaration of an abstract method of an abstract superclass -"and its implementation in a concrete subclass. -CLASS cls1 DEFINITION ABSTRACT. - PROTECTED SECTION. - METHODS meth ABSTRACT. -ENDCLASS. - -CLASS cls2 DEFINITION INHERITING FROM cls1. - PROTECTED SECTION. - METHODS meth REDEFINITION. -ENDCLASS. - -CLASS cls2 IMPLEMENTATION. - METHOD meth. - ... - ENDMETHOD. -ENDCLASS. -``` - -

⬆️ back to top

- -**Redefining Methods** - -- Redefining methods is possible for the public and protected instance (not the static) methods of all preceding superclasses in a subclass (but only if the methods are not specified with `FINAL`). -- In the declaration part of the subclass, you must specify the method as follows (and using the same method name): - `METHODS meth REDEFINITION.` -- This must be done in the same - visibility section of the subclass as in the superclass. -- You cannot change the parameters of the method. -- Redefined methods work with private attributes of the subclass and cannot access private attributes of the superclass with the same name. -- If you want to access the identically named method implementation in a superclass from within - the method implementation of the subclass, use the [pseudo - reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpseudo_reference_glosry.htm "Glossary Entry") - [`super->meth`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_method_meth_super.htm). - -> **💡 Note**
-> Inheritance and constructors: -> - Constructors cannot be redefined. -> - If the instance constructor is implemented in a subclass, the instance constructor of the superclass must be called explicitly using `super->constructor`, even if the latter is not explicitly declared. An exception to this: Direct subclasses of the root node `OBJECT`. -> - Regarding the static constructor: When calling a subclass for the first time, the preceding static constructors of all of the entire inheritance tree must have been called first. -> - More information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_constructors.htm). - -

⬆️ back to top

- -## Notes on Polymorphism and Casting - -The object orientation concept -[polymorphism](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpolymorphism_glosry.htm "Glossary Entry") -means you can address differently implemented methods belonging to different objects of different classes using one and the -same reference variable, for example, -object reference variables pointing to a superclass can point to objects of a subclass. - -Note the concept of static and dynamic type in this context: - -- Object reference variables (and also interface reference variables) have both a - [static](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_type_glosry.htm "Glossary Entry") - and a [dynamic - type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm "Glossary Entry"). -- When declaring an object reference variable, e. g. `DATA oref TYPE REF TO cl`, you determine the static type, i. e. - `cl` - a class - is used to declare the reference variable that is statically defined in the code. This is the class of an object to which the reference variable points to. -- Similarly, the dynamic type also defines the class of an object which the reference variable points to. However, the dynamic type is determined at runtime, i. e. the class of an object which the reference variable points to can change. -- Relevant for? This differentiation enters the picture in polymorphism when a reference variable typed with reference to a subclass can always be assigned to reference variables typed with reference to one of its superclasses or their interfaces. That's what is called [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm "Glossary Entry") (or widening cast). Or the assignment is done the other way round. That's what is called [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry") (or narrowing cast). - -> **✔️ Hints**
-> - The following basic rule applies: The static type is always more general than or the same as the dynamic type. The other way round: The dynamic type is always more special than or equal to the static type. ->- That means: -> - If the static type is a class, the dynamic type must be the same class or one of its subclasses. -> - If the static type is an interface, the dynamic type must implement the interface. - -- Regarding assignments: If it can be statically checked that an assignment is possible - although the types are different, the assignment is done using the - [assignment - operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") - `=` that triggers an upcast automatically. -- Otherwise, it is a - [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry"). - Here, the assignability is not checked until runtime. The downcast - in contrast to upcasts - - must be triggered explicitly using the [casting - operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencasting_operator_glosry.htm "Glossary Entry") - [`CAST`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_cast.htm). You might see code using the older - operator [`?=`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove_cast.htm). -- See more information in the topic [Assignment Rules for Reference - Variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_references.htm). - -As an example, assume there is an inheritance tree with `lcl_super` as the superclass and `lcl_sub` as a direct subclass. `lcl_sub2` is a direct subclass of `lcl_sub`. - -In the following code snippet, the rule is met since the superclass is either the same as or more generic than the subclass (the subclass has, for example, redefined methods and is, thus, more specific). Hence, the assignment of an object reference variable pointing to the subclass to a variable pointing to a superclass works. An upcast is triggered. After this casting, the type of `oref_super` has changed and the methods of `lcl_sub` can be accessed via `oref_super`. - -``` abap -"Creating object references -DATA(oref_super) = NEW lcl_super( ). - -DATA(oref_sub) = NEW lcl_sub( ). - -"Upcast -oref_super = oref_sub. - -"The casting might be done when creating the object. -DATA super_ref TYPE REF TO lcl_super. - -super_ref = NEW lcl_sub( ). -``` - -- As mentioned above, a downcast must be triggered -manually. Just an assignment like `oref_sub = oref_super.` -does not work. A syntax error occurs saying the right-hand variable's type cannot be converted to the left-hand variable's type. -- If you indeed want to carry out this casting, you must use -`CAST` (or you might see code using the older operator `?=`) to overcome this syntax error (but just the syntax error!). Note: You might also use these casting operators for the upcasts. That means `oref_super = oref_sub.` has the same effect as `oref_super = CAST #( oref_sub ).`. Using the casting operator for upcasts is usually not necessary. -- At runtime, the assignment is checked and if the conversion does not work, you face a (catchable) exception. Even more so, the assignment `oref_sub = CAST #( oref_super ).` does not throw a syntax error but it does not work in this example either because it violates the rule mentioned above (`oref_sub` is more specific than `oref_super`). -- To check whether such an assignment is possible -on specific classes, you can use the predicate expression [`IS INSTANCE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_instance_of.htm) -or the case distinction [`CASE TYPE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase_type.htm). Carrying out an upcast before the downcast ensures that the left-hand variable's type is compatible to the right-hand variable's type. - -``` abap -DATA(oref_super) = NEW lcl_super( ). -DATA(oref_sub) = NEW lcl_sub( ). -DATA(oref_sub2) = NEW lcl_sub2( ). - -"Downcast impossible (oref_sub is more specific than oref_super); -"the exception is caught here - -TRY. - oref_sub = CAST #( oref_super ). - CATCH CX_SY_MOVE_CAST_ERROR INTO DATA(e). - ... -ENDTRY. - -"Working downcast with a prior upcast - -oref_super = oref_sub2. - -"Due to the prior upcast, the following check is actually not necessary. - -IF oref_super IS INSTANCE OF lcl_sub. - oref_sub = CAST #( oref_super ). - ... -ENDIF. - -"Excursion RTTI: Downcasts, CAST and method chaining -"Downcasts particularly play, for example, a role in the context of -"retrieving type information using RTTI. Method chaining is handy -"because it reduces the lines of code in this case. -"The example below shows the retrieval of type information -"regarding the components of a structure. -"Due to the method chaining in the second example, the three -"statements in the first example are reduced to one statement. - -DATA struct4cast TYPE zdemo_abap_carr. - -DATA(rtti_a) = cl_abap_typedescr=>describe_by_data( struct4cast ). -DATA(rtti_b) = CAST cl_abap_structdescr( rtti_a ). -DATA(rtti_c) = rtti_b->components. - -DATA(rtti_d) = CAST cl_abap_structdescr( - cl_abap_typedescr=>describe_by_data( struct4cast ) - )->components. -``` - -

⬆️ back to top

- -## Notes on Interfaces - -Interfaces ... - -- represent a template for the components in the public visibility - section of classes. -- enhance classes by adding interface components. -- are possible as both - [local](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlocal_interface_glosry.htm "Glossary Entry") - and [global - interfaces](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_interface_glosry.htm "Glossary Entry"). -- support - [polymorphism](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpolymorphism_glosry.htm "Glossary Entry") in classes. Each class that implements an interface can implement its methods differently. [Interface reference variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninterface_ref_variable_glosry.htm "Glossary Entry") can point to objects of all classes that implement the associated interface. -- can be implemented by classes of an inheritance tree. It can be any number of interfaces. However, each interface can be implemented only once in an inheritance tree. -- are different from classes in the following ways: - - They only consist of a part declaring the components without an - implementation part. The implementation is done in classes that use the interface. - - There are no visibility sections. All components of an interface are visible. - - No instances can be created from interfaces. - - Declarations as mentioned for classes, e. g. `DATA`, - `CLASS-DATA`, `METHODS`, - `CLASS-METHODS`, are possible. Constructors are not - possible. - -

⬆️ back to top

- -Defining interfaces: -- Can be done either globally in the repository or locally in an ABAP program. - -``` abap -INTERFACE intf. -"The addition PUBLIC is for global interfaces: -"INTERFACE intf_g PUBLIC. - - DATA ... - CLASS-DATA ... - METHODS ... - CLASS-METHODS ... - -ENDINTERFACE. -``` - -Implementing interfaces: -- A class can implement multiple interfaces. -- Interfaces must be specified in the - declaration part of a class using the statement - [`INTERFACES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces.htm). -- Since all interface components are public, you must include this - statement and the interfaces in the public visibility section of a class. When an interface is implemented in a class, all interface components are added to the other components of the class in the public visibility section. -- Interface components can be addressed using the [interface component - selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninterface_comp_selector_glosry.htm "Glossary Entry"): `... intf~comp ...`. -- You can specify alias names for the interface components using the statement [`ALIASES ... FOR ...`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapaliases.htm). The components can then be addressed using the alias name. -- The class must implement the methods of all implemented interfaces in it unless the methods are flagged as abstract or final. You can adapt some interface components to requirements of your class. - - You can specify the additions [`ABSTRACT METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) followed by method names or [`ALL METHODS ABSTRACT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) for the `INTERFACES` statement in the declaration part of - classes. In this case, the class(es) need not - implement the methods of the interface. The implementation is then relevant for a subclass inheriting from a superclass that includes - such an interface declaration. Note that the whole class must be abstract. - - The additions [`FINAL METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) followed by method names or [`ALL METHODS FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) for the `INTERFACES` statement in the declaration part of classes flag the method(s) as final. -- In the interface, methods can mark their implementation as optional using the additions [`DEFAULT - IGNORE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm) - or [`DEFAULT FAIL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm). - - -Syntax for using interfaces in classes: -``` abap -CLASS class DEFINITION. - PUBLIC SECTION. - "Multiple interface implementations possible - INTERFACES intf. - ALIASES meth_alias FOR intf~some_method. -ENDCLASS. - -CLASS class IMPLEMENTATION. - METHOD intf~some_meth. "Method implementation using the original name - ... - ENDMETHOD. - - "Just for demo purposes: Method implementation using the alias name - "METHOD meth_alias. - " ... - "ENDMETHOD. - - ... -ENDCLASS. - -"Abstract class -CLASS cl_super DEFINITION ABSTRACT. - PUBLIC SECTION. - INTERFACES intf ALL METHODS ABSTRACT. - ALIASES: - meth1 FOR intf~meth1, - meth2 FOR intf~meth2. -ENDCLASS. - -"Subclass inheriting from abstract class and implementing interface methods -CLASS cl_sub DEFINITION INHERITING FROM cl_super. - PUBLIC SECTION. - METHODS: - meth1 REDEFINITION, - meth2 REDEFINITION. -ENDCLASS. - -CLASS cl_sub IMPLEMENTATION. - METHOD meth1. - ... - ENDMETHOD. - METHOD meth2. - ... - ENDMETHOD. -ENDCLASS. -``` - -Interface reference variables and accessing objects: -- As mentioned above, addressing an object happens via an object reference variable with reference to a class. -- An interface variable can contain references to objects of classes that implement the corresponding interface. -- You create an interface reference variable like this: `DATA i_ref TYPE REF TO intf.` - -Addressing interface components: -- Addressing instance components using interface reference variable - - attribute: `i_ref->attr` - - instance method: `i_ref->meth( )` -- Addressing instance components using an object reference variable (Note: The type is a class that implements the interface) is also possible but it's not the recommended way: - - attribute: `cl_ref->intf~attr` - - instance method: `cl_ref->intf~meth` -- Addressing static components: - - static attribute: `class=>intf~attr`, - - static method: `class=>intf~meth( )` - - constant: `intf=>const` - - -``` abap -"Addressing instance interface components using interface reference variable -DATA i_ref TYPE REF TO intf. - -DATA cl_ref TYPE REF TO class. - -"Creating an instance of a class that implements the interface intf -cl_ref = NEW #( ). - -"If the class class implements an interface intf, -"the class reference variable cl_ref can be assigned -"to the interface reference variable i_ref. -"The reference in i_ref then points to the same object -"as the reference in cl_ref. -i_ref = cl_ref. - -"Can also be done directly, i. e. directly creating an object to which the interface reference variable points -i_ref = NEW class( ). - -"Instance interface method via interface reference variable -... i_ref->inst_method( ... ) ... - -"Instance interface attribute via interface reference variable -... i_ref->inst_attr ... - -"Addressing instance components using the class reference variable -"is also possible but it's not the recommended way. -... cl_ref->intf~inst_method( ... ) ... -... cl_ref->intf~inst_attr ... - -"Addressing static interface components -"class=> can be dropped if the method is called in the same class that implements the interface -... class=>intf~stat_method( ... ) ... -... class=>intf~stat_attr ... - -"Just for the record: Static interface components can be called via reference variables, too. -... i_ref->stat_method( ... ) ... -... i_ref->stat_attr ... -... cl_ref->intf~stat_method( ... ) ... - -"Constants -"A constant can be addressed using the options mentioned above. -"Plus, it can be addressed using the following pattern -... intf=>const ... -``` - -

⬆️ back to top

- -## Excursions - -### Friendship - -- The concept of friendship enters the picture if your use case for your classes is to work together very closely. This is true, for example, for [unit -tests](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunit_test_glosry.htm "Glossary Entry") if you want to test private methods. -- Classes can grant access to invisible components for their [friends](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm "Glossary Entry"). -- The friends can be other classes and interfaces. In case of interfaces, friendship is granted to all classes that implement the interface. -- Impact of friendship: - - Access is granted to all components, regardless of the visibility section or the addition `READ-ONLY`. - - Friends of a class can create instances of the class without restrictions. - - Friendship is a one-way street, i. e. a class granting friendship to another class is not granded friendship the other way round. If class `a` grants friendship to class `b`, class `b` must also explicitly grant friendship to class `a` so that `a` can access the invisible components of class `b`. - - Friendship and inheritance: Heirs of friends and interfaces that contain a friend as a component interface also become friends. However, granting friendship is not inherited, i. e. a friend of a superclass is not automatically a friend of its subclasses. - - -You specify the befriended class in the definition part using a `FRIENDS` addition: -``` abap -"For local classes. Friendship can be granted to all classes/interfaces -"of the same program and the class library. -"Multiple classes can be specified as friends. -CLASS lo_class DEFINITION FRIENDS other_class ... . -... - -CLASS lo_class DEFINITION CREATE PRIVATE FRIENDS other_class ... . - -"Addition GLOBAL only allowed for global classes, i. e. if the addition PUBLIC is also used -"Other global classes and interfaces from the class library can be specified after GLOBAL FRIENDS. -CLASS global_class DEFINITION CREATE PUBLIC FRIENDS other_global_class ... . -``` - -

⬆️ back to top

- -### Events - -- [Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_glosry.htm "Glossary Entry") -can trigger the processing of [processing blocks](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocessing_block_glosry.htm "Glossary Entry"). -- Declaring events: Can be declared in a visibility section of the declaration part of a class or in an interface, e. g. as - - instance event using an [`EVENTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapevents.htm) statement. Note that they can only be raised in instance methods of the same class. - - static event using [`CLASS-EVENTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass-events.htm). They can be raised in all methods of the same class or of a class that implements the interface. Static event handlers can be called by the event independently of an instance of the class. - -``` abap -"Declaration part of a class/interface -"Instance events -EVENTS: i_evt1, - -"Events can only have output parameters that are passed by value - i_evt2 EXPORTING VALUE(num) TYPE i ... -... -"Static events -CLASS-EVENTS: st_evt1, - st_evt2 EXPORTING VALUE(num) TYPE i ... - -``` - -- Event handlers: - - An event is raised by a [`RAISE EVENT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_event.htm) statement in another method or in the same method. - - Raising an event means that [event handlers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_handler_glosry.htm "Glossary Entry") are called. - - This event handler must be declared with the following syntax (see more information and more additions [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_event_handler.htm)): - -``` abap -"Event handlers for instance events -METHODS: handler_meth1 FOR EVENT i_evt1 OF some_class, - - "Parameter names must be the same as declared; - "no further additions possible for the parameter (e.g. TYPE); - "the predefined, implicit parameter sender as another formal parameter is possible with instance events, - "it is typed as a reference variable, which itself has the class/interface as a static type, - "If the event handler is called by an instance event, it is passed a reference to the raising object in sender. - handler_meth2 FOR EVENT i_evt2 OF some_class IMPORTING num sender, -... -``` - -- To make sure that an event handler handles a raised event, it must be registered with the statement [`SET HANDLER`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapset_handler.htm). See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapset_handler.htm) (for example, events can also be deregistered). - -```abap -"Registering event for a specific instance -SET HANDLER handler1 FOR ref. - -"Registering event for all instances -SET HANDLER handler2 FOR ALL INSTANCES. - -"Registering static event for the whole class/interface -SET HANDLER handler3. -"Note that multiple handler methods can be specified. -``` - -

⬆️ back to top

- -### Factory Methods and Singletons as Design Patterns - -In object-oriented programming, there a plenty of design patterns. Covering these ones here to get a rough idea: factory methods and singletons. Both are relevant if you want to restrict or control the instantiation of a class by external users of this class. - -A singleton is a design pattern in which it is only up to the class to create objects. In doing so, the class ensures that only one object exists for every internal session that is made available to consumers. - -The following code snippet shows an implementation of the singleton design pattern. The `get_instance` method is used to return the object reference to the object created. Only one instance can be created. - -```abap -"Using the addition CREATE PRIVATE, objects can only be created by the class itself. -CLASS singleton_class DEFINITION CREATE PRIVATE. - PUBLIC SECTION. - CLASS-METHODS get_instance RETURNING VALUE(ret) TYPE REF TO singleton_class. - - PRIVATE SECTION. - CLASS-DATA inst TYPE REF TO singleton_class. -ENDCLASS. - -CLASS singleton_class IMPLEMENTATION. - METHOD get_instance. - IF inst IS NOT BOUND. - inst = NEW #( ). - ENDIF. - ret = inst. - ENDMETHOD. -ENDCLASS. -``` - -Controlling the creation of objects - the instantiation of a class - can be realized using a factory method. For example, certain checks might be required before a class can be instantiated. If a check is not successful, the instantiation is denied. -You might create a (static) factory method as follows: -- A check is carried out in the factory method, for example, by evaluating importing parameters. -- If the check is successful, an object of the class is created. -- The method signature includes an output parameter that returns an object reference to the caller. - -This is rudimentarily demonstrated in the following snippet: - -``` abap -CLASS class DEFINITION CREATE PRIVATE. - PUBLIC SECTION. - CLASS-METHODS - factory_method IMPORTING par ..., - RETURNING VALUE(obj) TYPE REF TO class. - ... -ENDCLASS. - -CLASS class IMPLEMENTATION. - METHOD factory_method. - IF par = ... - obj = NEW class( ). - ELSE. - ... - ENDIF. - - ENDMETHOD. - ... -ENDCLASS. -... - -"Calling a factory method. -DATA obj_factory TYPE REF TO class. - -obj_factory = class=>factory_method( par = ... ). -``` - -

⬆️ back to top

- -## More Information -You can check the subtopics of - -- [ABAP Objects - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_oview.htm) -- [Programming Guidlines - Object-Oriented Programming (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenobj_oriented_gdl.htm) - -in the ABAP Keyword Documentation. - -## Executable Example -[zcl_demo_abap_objects](./src/zcl_demo_abap_objects.clas.abap) - -> **💡 Note**
-> - The executable example covers the following topics, among others: -> - Working with objects and components -> - Redefining methods, inheritance -> - Working with interfaces -> - Upcast and downcast -> - Concepts such as factory methods, singleton and abstract classes -> - Events -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + +# ABAP Object Orientation + +> **💡 Note**
+> This ABAP cheat sheet provides an overview on selected syntax options and concepts related to ABAP object orientation. It is supported by code snippets and an executable example. They are **not** suitable as role models for object-oriented design. Their primary focus is on the syntax and functionality. For more details, refer to the respective topics in the ABAP Keyword Documentation. Find an overview in the topic [ABAP Objects - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_oview.htm). + +- [ABAP Object Orientation](#abap-object-orientation) + - [Classes and Objects](#classes-and-objects) + - [Creating Classes](#creating-classes) + - [Creating a Local Class](#creating-a-local-class) + - [Creating a Global Class](#creating-a-global-class) + - [Visibility of Components](#visibility-of-components) + - [Creating the Visibility Sections](#creating-the-visibility-sections) + - [Defining Components](#defining-components) + - [Working with Objects and Components](#working-with-objects-and-components) + - [Declaring Reference Variables](#declaring-reference-variables) + - [Creating Objects](#creating-objects) + - [Assigning Reference Variables](#assigning-reference-variables) + - [Accessing Attributes](#accessing-attributes) + - [Calling Methods](#calling-methods) + - [Method Chaining](#method-chaining) + - [Self-Reference me](#self-reference-me) + - [Notes on Inheritance](#notes-on-inheritance) + - [Notes on Polymorphism and Casting](#notes-on-polymorphism-and-casting) + - [Notes on Interfaces](#notes-on-interfaces) + - [Excursions](#excursions) + - [Friendship](#friendship) + - [Events](#events) + - [Factory Methods and Singletons as Design Patterns](#factory-methods-and-singletons-as-design-patterns) + - [More Information](#more-information) + - [Executable Example](#executable-example) + +## Classes and Objects + +Object-oriented programming in ABAP means dealing with +[classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_glosry.htm "Glossary Entry") +and +[objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_glosry.htm "Glossary Entry"). + +Objects ... + +- are + [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm "Glossary Entry") + of a + [type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_glosry.htm "Glossary Entry"). + In this context, they are instances of a + [class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_glosry.htm "Glossary Entry"). + The terms *object* and *instance* are used synonymously. +- exist in the [internal + session](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninternal_session_glosry.htm "Glossary Entry") + of an [ABAP + program](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm "Glossary Entry"). + + +Classes ... +- are templates for objects, i. e. they determine how + all instances of a class are set up. All instances are created (i.e they are [instantiated](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstantiation_glosry.htm "Glossary Entry")) based on this template and, thus, have the same setup. + - To give an example: If, for example, a vehicle represents a class, then the + instances of the class `vehicle` have the same setup. + That means they all share the same kind of components like a brand, model and color or the same functionality like the acceleration or braking distance. + However, the values of these components are different from instance to instance. For example, one + instance is a red sedan of brand A having a certain + acceleration; another instance is a black SUV of brand B and so on. You can create an object (or instance respectively) that stands + for an actual vehicle with which you can work with. You might create any number of objects that are based on such a class - if instantiation is allowed. +- contain + [components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_glosry.htm "Glossary Entry"): + - [Attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenattribute_glosry.htm "Glossary Entry") + of the objects (the data object declarations) + - [Methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmethod_glosry.htm "Glossary Entry") + that determine the behavior of an object + - [Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_glosry.htm "Glossary Entry") to trigger the processing of ABAP code + +

⬆️ back to top

+ + +### Creating Classes + +You can either create local or global classes: + + + + + + + + + + +
Local classes
  • can be defined within an ABAP program
  • can only be used in the ABAP program in which the class is defined
Global +classes
  • are defined as + global types, i. e. they are visible as a repository object - in contrast to local classes. As a global type, they can be used - as the name implies - globally in other ABAP programs or global classes
  • are declared in class pools that can contain a CCIMP include and other include programs
+ +> **💡 Note**
+> - If a class is only used in one ABAP program, creating a local class is enough. However, if you choose to create a global class, you must bear in mind that such a class can be used everywhere. Consider the impact on the users of the global class when you change, for example, the visibility section of a component or you delete it. +> - Apart from ADT, global classes can also be created in the ABAP Workbench (`SE80`) or with transaction `SE24` in [classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm). + +Basic structure of classes: +- [Declaration part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_part_glosry.htm "Glossary Entry") that includes declarations of the class components. +- [Implementation part](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimplementation_part_glosry.htm "Glossary Entry") that includes method implementations. +- Both are introduced by `CLASS` and ended by `ENDCLASS`. + +#### Creating a Local Class + +``` abap +"Declaration part +CLASS local_class DEFINITION. + + ... "Here go the declarations for all components and visibility sections. + "You should place the declarations at the beginning of the program. + +ENDCLASS. + +"Implementation part +CLASS local_class IMPLEMENTATION. + + ... "Here go the method implementations. + "Only required if you declare methods in the declaration part. + +ENDCLASS. +``` + +#### Creating a Global Class +The code snippet shows a basic skeleton of a global class. There are [further +additions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_options.htm) +possible for the declaration part. + +``` abap +"Declaration part +CLASS global_class DEFINITION + PUBLIC "Makes the class a global class in the class library. + FINAL "Means that no subclasses can be derived from this class. + CREATE PUBLIC. "This class can be instantiated anywhere it is visible. + + ... "Here go the declarations for all components and visibility sections. + +ENDCLASS. + +"Implementation part +CLASS global_class IMPLEMENTATION. + + ... "Here go the method implementations. + "Only required if you declare methods in the DEFINITION part. + +ENDCLASS. +``` +> **💡 Note**
+> - Addition `... CREATE PROTECTED.`: The class can only be instantiated in methods of its +[subclasses](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry"), +of the class itself, and of its +[friends](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm "Glossary Entry"). +> - Addition `... CREATE PRIVATE`: The class can only +be instantiated in methods of the class itself or of its friends. Hence, +it cannot be instantiated as an inherited component of subclasses. + +

⬆️ back to top

+ +### Visibility of Components + +In the class declaration part, you must specify (at least one of the) three +[visibility +sections](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenvisibility_section_glosry.htm "Glossary Entry") +and include class components to define their visibility. These visibility sections serve the purpose of encapsulation in ABAP Objects. For example, you do not want to make certain components publicly available for all users. The visibility sections are as follows: + + + + + + + + + + + + + + +
PUBLIC SECTION.
Components declared in this section can be accessed from within the class and from all users of the class.
PROTECTED SECTION.
Components declared in this section can be + accessed from within the class and subclasses as well as friends + - concepts related to inheritance.
PRIVATE SECTION.
Components declared in this section can only be accessed from within the class in which they are declared and its friends.
+ +Summary: + +| Visible for | PUBLIC SECTION | PROTECTED SECTION | PRIVATE SECTION | +|---|---|---|---| +| Same class and its friends | X | X | X | +| Any subclasses | X | X | - | +| Any repository objects | X | - | - | + + +#### Creating the Visibility Sections +At least one section must be specified. +``` abap +CLASS local_class DEFINITION. + PUBLIC SECTION. + "Here go the components. + PROTECTED SECTION. + "Here go the components. + PRIVATE SECTION. + "Here go the components. +ENDCLASS. +``` + +

⬆️ back to top

+ +### Defining Components + +All components, i. e. +- attributes (using `TYPES`, `DATA`, `CLASS-DATA`, and `CONSTANTS` for data types and data +objects), +- methods (using `METHODS` and `CLASS-METHODS`), +- events (using `EVENTS` and `CLASS-EVENTS`) as well as +- interfaces, + +are declared in the declaration part of the class. There, they must be +assigned to a visibility section. + +Two +kinds of components are to be distinguished when, for example, looking at declarations using `DATA` and `CLASS-DATA` having a preceding `CLASS-`: + +- [Instance components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_component_glosry.htm "Glossary Entry"): + Components that exist separately for each instance and can only be accessed in instances of a class. +- [Static components](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_component_glosry.htm "Glossary Entry") (the declarations with `CLASS-`): + Components that exist only once per class. They do no not exclusively exist for specific instances. They can be addressed using the name of the class. + +**Attributes** + +- The attributes of a class (or interface) mean the data objects declared within a + class (or interface). +- [Instance + attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_attribute_glosry.htm "Glossary Entry") + (`DATA`): Determine the state of a objects of a class. The data + is only valid in the context of an instance. As shown further down, + instance attributes can only be accessed via an [object reference + variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry"). +- [Static + attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_attribute_glosry.htm "Glossary Entry") + (`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. + + +> **💡 Note**
+> - You can declare constant data objects that should not be +changed using +[`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) +statements. You specify the values for the constants (which are also static attributes) when you declare +them in the declaration part of a class. +> - The addition +[`READ-ONLY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata_options.htm#!ABAP_ADDITION_2@2@) +can be used in the public visibility section. Effect: +> - Can be read from outside of the class +> - Cannot be changed from outside +> - Can only be changed using methods of the class or its subclasses + +Declaring attributes in visibility sections. In the code snippet below, all attributes are declared in the public section of a local class. +``` abap +CLASS local_class DEFINITION. + + PUBLIC SECTION. + TYPES some_type TYPE c LENGTH 3. "Type declaration + + DATA: inst_number TYPE i, "Instance attributes + inst_string TYPE string, + dobj_r_only TYPE c LENGTH 5 READ-ONLY. "Read-only attribute + + CLASS-DATA: stat_number TYPE i, "Static attributes + stat_char TYPE c LENGTH 3. + + CONSTANTS const_num TYPE i VALUE 123. "Non-changeable constant + + PROTECTED SECTION. + "Here go more attributes if needed. + + PRIVATE SECTION. + "Here go more attributes if needed. + +ENDCLASS. + +CLASS local_class IMPLEMENTATION. + + ... "Here go all method implementations. + +ENDCLASS. +``` + +

⬆️ back to top

+ +**Methods** + +- Are internal + [procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm "Glossary Entry") + determining the behavior of the class. +- Can access all of the attributes of a class and, if not defined + otherwise, change their content. +- Have a [parameter + interface](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparameter_interface_glosry.htm "Glossary Entry") + (also known as + [signature](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensignature_glosry.htm "Glossary Entry")) + with which methods can get values to work with when being called and pass values + back to the caller (see the notes on formal and actual parameters below). +- [Static + methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_method_glosry.htm "Glossary Entry") + can only access static attributes of a class and trigger static + events. You declare them using `CLASS-METHODS` statements in + a visibility section. +- [Instance + methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_method_glosry.htm "Glossary Entry") + 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. + +**Parameter Interface** + +In the simplest form, methods can have no parameter at all. Apart from that, methods can be defined with the following parameters: + +| Addition | Details | +|---|---| +|`IMPORTING`|Defines one or more input parameters to be imported by the method. | +|`EXPORTING`|Defines one or more output parameters to be exported by the method. | +|`CHANGING`|Defines one or more input or output parameters, i. e. that can be both imported and exported. | +|`RETURNING`|For [functional methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfunctional_method_glosry.htm "Glossary Entry"), i. e. such methods have only one `RETURNING` parameter that can be defined. As an output parameter like the `EXPORTING` parameter, `RETURNING` parameters pass back values (note that the formal parameters of returning parameters must be passed by value as covered below). In contrast to `EXPORTING` for which multiple parameters can be specified, only one `RETURNING` parameter can be specified in a method. If you only need one output parameter, you can benefit from using a `RETURNING` parameter by shortening the method call and enabling method chaining. Another big plus is that such functional methods can, for example, be used in expressions. In case of standalone method calls, the returned value can be accessed using the addition `RECEIVING`. | +|`RAISING` | Used to declare the [class-based exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_based_exception_glosry.htm "Glossary Entry") that can be propagated from the method to the caller. | + + +> **💡 Note**
+> - You may find the addition `EXCEPTIONS` especially in definitions of older classes. They are for non-class-based exceptions. This addition should not be used in ABAP for Cloud Development. +> - Notes on [formal + parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm "Glossary Entry") + versus [actual + parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenactual_parameter_glosry.htm "Glossary Entry"): +> - You define method parameters by specifying a name with a type which + can be a + [generic](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_data_type_glosry.htm "Glossary Entry") + or + [complete](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplete_data_type_glosry.htm "Glossary Entry") + type. Examples: +> - `fp` is the formal parameter that has a complete type: `... meth IMPORTING fp TYPE string ...` +> - `gen` is the formal parameter that has a generic type: `... meth IMPORTING gen TYPE any ...` +> - Find more information about generic types also in the [Data Types and Data Objects](16_Data_Types_and_Objects.md#generic-types) cheat sheet. +> - This formal parameter includes the specification of how the + value passing should happen. Parameters can be [passed by + reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_reference_glosry.htm "Glossary Entry") + (`... REFERENCE(param) ...`; note that just specifying the + parameter name `... param ...` - as a shorter syntax - + means passing by reference by default) or [by + value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpass_by_value_glosry.htm "Glossary Entry") + (`... VALUE(param) ...`). +> - The actual parameter represents + the data object whose content is passed to or copied from a formal + parameter as an argument when a procedure is called. If + passing by reference is used, a local data object is not created for + the actual parameter. Instead, the procedure is given a + [reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm "Glossary Entry") + to the actual parameter during the call and works with the actual + parameter itself. Note that parameters that are input and passed by + reference cannot be modified in the procedure. However, the use of a + reference is beneficial regarding the performance compared to + creating a local data object. +>- Parameters can be defined as optional using the + [`OPTIONAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_parameters.htm#!ABAP_ONE_ADD@1@) + addition. In doing so, it is not mandatory to pass an actual + parameter. The + [`DEFAULT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_parameters.htm#!ABAP_ONE_ADD@1@) + addition also makes the passing of an actual parameter optional. + However, when using this addition, as the name implies, a default + value is set. + +

⬆️ back to top

+ +**Constructors** + +- [Constructors](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_glosry.htm "Glossary Entry") + are special methods that are usually used for setting a defined + initial value for attributes of the class or its objects. +- A class has exactly one [instance + constructor](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_constructor_glosry.htm "Glossary Entry") + and one [static + constructor](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_constructor_glosry.htm "Glossary Entry"). +- The declaration and use of constructors is optional. +- Static constructor: + - Declared using the predefined name `class_constructor` as part of a + `CLASS-METHODS` statement in the public visibility section. + - Has no parameters. + - Automatically and immediately called once for each class when calling a class for + the first time in an internal session, i. e. when, for example, an instance of a class is created or a component is used. Note: If it is not explicitly declared and implemented, it is merely an empty method. +- Instance constructor: + - Declared using the predefined name `constructor` as part of a + `METHODS` statement. In case of global classes, it can only be declared in the public visibility section. + - Automatically called when a class is + instantiated and an instance is created. + - Can have `IMPORTING` parameters and raise exceptions. + +Example for method definitions: The following snippet shows +multiple method definitions in the public section of a local class. Most of the formal +parameters of the demo methods below are defined by just using the +parameter name. This means passing by reference (returning parameters +require to be passed by value). +``` abap +CLASS local_class DEFINITION. + PUBLIC. + METHODS: inst_meth1, "instance methods + + inst_meth2 IMPORTING a TYPE string, + + inst_meth3 IMPORTING b TYPE i + EXPORTING c TYPE i, + + inst_meth4 IMPORTING d TYPE string + RETURNING VALUE(e) TYPE string, + + inst_meth5 IMPORTING f TYPE i + EXPORTING g TYPE i + CHANGING h TYPE string + RETURNING VALUE(i) TYPE i + RAISING cx_sy_zerodivide, + + constructor IMPORTING j TYPE i. "instance constructor with importing parameter + + CLASS-METHODS: stat_meth1, "static methods + + stat_meth2 IMPORTING k TYPE i + EXPORTING l TYPE i, + + class_constructor, "static constructor + + "Options of formal parameter definitions + stat_meth3 IMPORTING VALUE(m) TYPE i, "pass by value + stat_meth4 IMPORTING REFERENCE(n) TYPE i, "pass by reference + stat_meth5 IMPORTING o TYPE i, "same as n; the specification of REFERENCE(...) is optional + stat_meth6 RETURNING VALUE(p) TYPE i, "pass by value once more (note: it's the only option for returning parameters) + + "OPTIONAL/DEFAULT additions + stat_meth7 IMPORTING q TYPE i DEFAULT 123 + r TYPE i OPTIONAL, + + "The examples above use a complete type for + "the parameter specification. Generic types + "are possible. + stat_meth8 IMPORTING s TYPE any "Any data type + t TYPE any table "Any internal table type + u TYPE clike. "Character-like types (c, n, string, d, t and character-like flat structures) + +ENDCLASS. + +CLASS local_class IMPLEMENTATION. + METHOD inst_meth1. + ... + ENDMETHOD. + + ... "Further method implementations. Note that all declared methods must go here. +ENDCLASS. +``` + +

⬆️ back to top

+ +## Working with Objects and Components + +### Declaring Reference Variables +- To create an object, a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry") +must be declared. +- Such an [object reference +variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_refer_variable_glosry.htm "Glossary Entry") +is also necessary for accessing objects and their components. That means objects are not directly accessed but only via references that point to +those objects. This object reference variable contains the reference to the object - after assigning the reference to the object (see further down). +``` abap +"Declaring object reference variables +DATA: ref1 TYPE REF TO local_class, + ref2 TYPE REF TO global_class, + ref3 LIKE ref1. +``` + +

⬆️ back to top

+ +### Creating Objects + +- Using the instance operator + [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm), + you can create objects of a class (and [anonymous data + objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm "Glossary Entry"), too, that are not dealt with here). As a result, + you get a [reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm "Glossary Entry") + that points to the created object. +- Regarding the type specifications before and parameters within the + parentheses: + - Right before the first parenthesis after `NEW`, the type, i. e. the class, must be specified. The `#` character - instead of the class name - +means that the type (`TYPE REF TO ...`) can be derived from the context (in this case from the type of the reference variable). You can +also omit the explicit declaration of a reference variable by declaring a new reference variable +[inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm), +for example, using `DATA`. In this case, the name of the class must be placed after `NEW` and before the first parenthesis. + - No parameter specified within the parentheses: No values are + passed to the instance constructor of an object. However, non-optional input parameters of the + instance constructor of the instantiated class must be filled. + No parameters are passed for a class without an explicitly declared + instance constructor. See more information: + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennew_constructor_params_class.htm). +- The operator + basically replaces the syntax [`CREATE OBJECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_object.htm) you might stumble on. + +``` abap +"Declaring object reference variable +DATA: ref1 TYPE REF TO some_class. + +"Creating objects +ref1 = NEW #( ). "Type derived from already declared ref1 + +DATA(ref2) = NEW some_class( ). "Reference variable declared inline, explicit type + "(class) specification + +"Old syntax. Do not use. +"CREATE OBJECT ref3. "Type derived from already declared ref3 +"CREATE OBJECT ref4 TYPE some_class. "Corresponds to the result of the expression above +``` + +

⬆️ back to top

+ +### Assigning Reference Variables +To assign or copy +reference variables, use the [assignment +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") +`=`. In the example below, both object reference variables have the same +type. + +``` abap +DATA: ref1 TYPE REF TO some_class, + ref2 TYPE REF TO some_class. + +ref1 = NEW #( ). + +"Assigning existing reference +ref2 = ref1. +``` + +More examples for dealing with object reference variables: + +**Overwriting reference variables**: An [object +reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm "Glossary Entry") +is overwritten when a new object is created with a reference variable +already pointing to an instance. +``` abap +ref1 = NEW #( ). + +"Existing reference is overwritten +ref1 = NEW #( ). +``` + +**Retaining object references**: +- If your use case is to retain the object references, for example, if you create multiple objects using the same object reference variable, you can put the reference variables in internal tables that are declared using `... TYPE TABLE OF REF TO ...`. +- The following code snippet just visualizes that the object references are not overwritten. Three objects are created with the same reference variable. The internal table includes all object references and, thus, their values are retained. +``` abap +DATA: ref TYPE REF TO some_class, + itab TYPE TABLE OF REF TO some_class. + +DO 3 TIMES. + ref = NEW #( ). + itab = VALUE #( BASE itab ( ref ) ). "Adding the reference to itab +ENDDO. +``` + +**Clearing object references**: You can use +[`CLEAR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclear.htm) +statements to explicitly clear a reference variable. +```abap +CLEAR ref. +``` + +> **💡 Note**
+> Objects use up space in the memory and should therefore be +cleared if they are no longer needed. However, the [garbage collector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengarbage_collector_glosry.htm "Glossary Entry") is called periodically and automatically by the [ABAP runtime framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm "Glossary Entry") and clears all objects without any reference. + +

⬆️ back to top

+ +### Accessing Attributes +- Instance attributes: Accessed using +the [object component selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_component_select_glosry.htm "Glossary Entry") +`->` via a reference variable. +- Static attributes: Accessed (if the attributes are visible) using the [class component +selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_component_select_glosry.htm "Glossary Entry") +`=>` via the class name. You can also declare data objects and +types by referring to static attributes. +``` abap +"Accessing instance attribute via an object reference variable + +... ref->some_attribute ... + +"Accessing static attributes via the class name + +... some_class=>static_attribute ... + +"Without the class name only within the class itself +... static_attribute ... + +"Type and data object declarations + +TYPES some_type LIKE some_class=>some_static_attribute. +DATA dobj1 TYPE some_class=>some_type. +DATA dobj2 LIKE some_class=>some_static_attribute. +``` + +

⬆️ back to top

+ +### Calling Methods +- Similar to accessing attributes, instance +methods are called using `->` via a reference variable. +- Static +methods are called using `=>` via the class name. When used +within the class in which it is declared, the static method can also be +called without `class_name=>...`. +- When methods are called, the (non-optional) parameters must be specified within parentheses. +- You might also stumble on method calls with [`CALL METHOD`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_method_static.htm) +statements. These statements should no longer be used. Note that `CALL METHOD` statements are the only option in the context of [dynamic programming](06_Dynamic_Programming.md). Therefore, `CALL METHOD` statements should be reserved for dynamic method calls. + + +Examples for instance method calls and static method calls: +``` abap +"Calling instance methods via reference variable; +"within the parentheses, the parameters must be specified and assigned - if required + +ref->inst_meth( ... ). + +"Calling static methods via/without the class name + +class_name=>stat_meth( ... ). + +"Only within the program in which it is declared. +stat_meth( ... ). + +"Calling (static) method having no parameter + +class_name=>stat_meth( ). + +"Calling (static) methods having a single importing parameter: + +"Note that in the method call, the caller exports values to the +"method having importing parameters defined; hence, the addition +"EXPORTING is relevant for the caller. The following three method calls are the same + +"Explicit use of EXPORTING. +class_name=>meth( EXPORTING a = b ). + +"Only importing parameters in the method signature: explicit EXPORTING not needed + +class_name=>meth( a = b ). + +"If only a single value must be passed: +"the formal parameter name (a) and EXPORTING not needed + +stat_meth( b ). + +"Calling (static) methods having importing/exporting parameters +"Parameters must be specified if they are not marked as optional + +class_name=>meth( EXPORTING a = b c = d "a/c: importing parameters in the method signature + IMPORTING e = f ). "e: exporting parameter in the method signature + +"To store the value of the parameter, you may also declare it inline. + +class_name=>meth( EXPORTING a = b c = d + IMPORTING e = DATA(z) ). + +"Calling (static) methods having a changing parameter; +"should be reserved for changing an existing local variable and value + +DATA h TYPE i VALUE 123. +class_name=>meth( CHANGING g = h ). + +"Calling (static) methods having a returning parameter. +"Basically, they do the same as methods with exporting parameters +"but they are way more versatile, and you can save lines of code. + +"They do not need temporary variables. +"In the example, the return value is stored in a variable declared inline. + +"i and k are importing parameters +DATA(result) = class_name=>meth( i = j k = l ). + +"They can be used with other statements, e. g. logical expressions. +"In the example below, the assumption is that the returning parameter is of type i. +IF class_name=>meth( i = j k = l ) > 100. + ... +ENDIF. + +"They enable method chaining. +"The example shows a method to create random integer values. +"The methods have a returning parameter. +DATA(random_no) = cl_abap_random_int=>create( )->get_next( ). + +"RECEIVING parameter: Available in methods defined with a returning parameter; +"used in standalone method calls only. +"In the snippet, m is the returning parameter; n stores the result. +class_name=>meth( EXPORTING i = j k = l RECEIVING m = DATA(n) ). +``` + +

⬆️ back to top

+ +### Method Chaining + +As shown in the previous example, method chaining is possible for functional method calls (i.e. methods that have exactly one return value declared with `RETURNING`) at appropriate read positions. In this case, the method's return value is used as an ABAP operand. +A chained method call can consist of multiple functional methods that are linked using component selectors `->`. The return values of each method are references to the next method. + +```abap +"The following example demonstrates method chaining +"The following class creates random integers. Find more information in the +"class documentation. +"Both methods have returning parameters specified. +DATA(some_int1) = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) + min = 1 + max = 10 )->get_next( ). + +"Getting to the result as above - not using method chaining and inline declarations. +DATA some_int2 TYPE i. +DATA dref TYPE REF TO cl_abap_random_int. + +dref = cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) + min = 1 + max = 10 ). + +some_int2 = dref->get_next( ). + +"Using the RECEIVING parameter in a standalone method call +DATA some_int3 TYPE i. +dref->get_next( RECEIVING value = some_int3 ). + +"IF statement that uses the return value in a read position +IF cl_abap_random_int=>create( seed = cl_abap_random=>seed( ) + min = 1 + max = 10 )->get_next( ) < 5. + ... "The random number is lower than 5. +ELSE. + ... "The random number is greater than 5. +ENDIF. + +"Examples using classes of the XCO library (see more information in the +"ABAP for Cloud Development and Misc ABAP Classes cheat sheets), in which +"multiple chained method calls can be specified. Each of the methods +"has a returning parameter specified. + +"In the following example, 1 hour is added to the current time. +DATA(add1hour) = xco_cp=>sy->time( xco_cp_time=>time_zone->user )->add( iv_hour = 1 )->as( xco_cp_time=>format->iso_8601_extended )->value. + +"In the following example, a string is converted to xstring using a codepage +DATA(xstr) = xco_cp=>string( `Some string` )->as_xstring( xco_cp_character=>code_page->utf_8 )->value. + +"In the following example, JSON data is created. First, a JSON data builder +"is created. Then, using different methods, JSON data is added. Finally, +"the JSON data is turned to a string. +DATA(json) = xco_cp_json=>data->builder( )->begin_object( + )->add_member( 'CarrierId' )->add_string( 'DL' + )->add_member( 'ConnectionId' )->add_string( '1984' + )->add_member( 'CityFrom' )->add_string( 'San Francisco' + )->add_member( 'CityTo' )->add_string( 'New York' + )->end_object( )->get_data( )->to_string( ). +``` + +

⬆️ 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: +``` 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. + +``` abap +METHOD me_ref. + + DATA str TYPE string VALUE `Local string`. + + DATA(local_string) = str. + + "Assuming there is a variable str declared in the class declaration part. + DATA(other_string) = me->str. + +ENDMETHOD. +``` + +

⬆️ back to top

+ +## Notes on Inheritance + +- Concept: Deriving a new class (i. e. + [subclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubclass_glosry.htm "Glossary Entry")) + from an existing one + ([superclass](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensuperclass_glosry.htm "Glossary Entry")). +- In doing so, you create a hierarchical relationship between superclasses and subclasses + (an [inheritance hierarchy](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_hierarchy_glosry.htm "Glossary Entry")) to form an [inheritance + tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_tree_glosry.htm "Glossary Entry"). This is relevant for a class that can have multiple subclasses and one direct superclass. +- Subclasses ... + - inherit and thus adopt all components from superclasses. + - can be made more specific by declaring new components and + redefining instance methods (i. e. you can alter the implementation of inherited methods). In case a subclass has no further components, it contains exactly the components of the superclass - but the ones of the private visibility section are not visible there. + - can redefine the public and protected instance methods of all preceding superclasses. Note: Regarding the static components of superclasses, accessing them is possible but not redefining them. + - can themselves have multiple direct subclasses but only one direct superclass. +- Components that are changed or added to subclasses are not visible to superclasses, hence, these changes are only relevant for the class itself and its subclasses. +- Classes can rule out derivation: classes cannot inherit from classes that are specified with the addition + [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_abstract_final.htm#!ABAP_ADDITION_2@2@) + (e. g. `CLASS global_class DEFINITION PUBLIC FINAL CREATE PUBLIC. ...`). + +

⬆️ back to top

+ +**Excursion: Additions `ABSTRACT` and `FINAL`** +- Both classes and methods can be defined with the additions `ABSTRACT` and `FINAL`. +- `FINAL` with ...: + - Classes: These classes cannot be inherited. All methods are automatically and implicitly `FINAL`. In this case, the addition `FINAL` cannot be used for methods. + - Methods: These methods cannot be redefined in subclasses. +- `ABSTRACT` with ...: + - Classes: Defines abstract classes. You cannot create an instance of an abstract class. To use instance components of an abstract class, you must create an instance of a subclass of such classes. + - Methods: Defines abstract methods. The addition is only allowed in abstract classes (and not for private methods). These methods cannot be implemented in the implementation part of the class where they are declared. They must be redefined in subclasses. Note that you can also have non-abstract methods in abstract classes. +- See [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_options.htm) more information on class options. + +``` abap +"Declaration of an abstract method of an abstract superclass +"and its implementation in a concrete subclass. +CLASS cls1 DEFINITION ABSTRACT. + PROTECTED SECTION. + METHODS meth ABSTRACT. +ENDCLASS. + +CLASS cls2 DEFINITION INHERITING FROM cls1. + PROTECTED SECTION. + METHODS meth REDEFINITION. +ENDCLASS. + +CLASS cls2 IMPLEMENTATION. + METHOD meth. + ... + ENDMETHOD. +ENDCLASS. +``` + +

⬆️ back to top

+ +**Redefining Methods** + +- Redefining methods is possible for the public and protected instance (not the static) methods of all preceding superclasses in a subclass (but only if the methods are not specified with `FINAL`). +- In the declaration part of the subclass, you must specify the method as follows (and using the same method name): + `METHODS meth REDEFINITION.` +- This must be done in the same + visibility section of the subclass as in the superclass. +- You cannot change the parameters of the method. +- Redefined methods work with private attributes of the subclass and cannot access private attributes of the superclass with the same name. +- If you want to access the identically named method implementation in a superclass from within + the method implementation of the subclass, use the [pseudo + reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpseudo_reference_glosry.htm "Glossary Entry") + [`super->meth`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_method_meth_super.htm). + +> **💡 Note**
+> Inheritance and constructors: +> - Constructors cannot be redefined. +> - If the instance constructor is implemented in a subclass, the instance constructor of the superclass must be called explicitly using `super->constructor`, even if the latter is not explicitly declared. An exception to this: Direct subclasses of the root node `OBJECT`. +> - Regarding the static constructor: When calling a subclass for the first time, the preceding static constructors of all of the entire inheritance tree must have been called first. +> - More information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninheritance_constructors.htm). + +

⬆️ back to top

+ +## Notes on Polymorphism and Casting + +The object orientation concept +[polymorphism](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpolymorphism_glosry.htm "Glossary Entry") +means you can address differently implemented methods belonging to different objects of different classes using one and the +same reference variable, for example, +object reference variables pointing to a superclass can point to objects of a subclass. + +Note the concept of static and dynamic type in this context: + +- Object reference variables (and also interface reference variables) have both a + [static](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_type_glosry.htm "Glossary Entry") + and a [dynamic + type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm "Glossary Entry"). +- When declaring an object reference variable, e. g. `DATA oref TYPE REF TO cl`, you determine the static type, i. e. + `cl` - a class - is used to declare the reference variable that is statically defined in the code. This is the class of an object to which the reference variable points to. +- Similarly, the dynamic type also defines the class of an object which the reference variable points to. However, the dynamic type is determined at runtime, i. e. the class of an object which the reference variable points to can change. +- Relevant for? This differentiation enters the picture in polymorphism when a reference variable typed with reference to a subclass can always be assigned to reference variables typed with reference to one of its superclasses or their interfaces. That's what is called [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm "Glossary Entry") (or widening cast). Or the assignment is done the other way round. That's what is called [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry") (or narrowing cast). + +> **✔️ Hints**
+> - The following basic rule applies: The static type is always more general than or the same as the dynamic type. The other way round: The dynamic type is always more special than or equal to the static type. +>- That means: +> - If the static type is a class, the dynamic type must be the same class or one of its subclasses. +> - If the static type is an interface, the dynamic type must implement the interface. + +- Regarding assignments: If it can be statically checked that an assignment is possible + although the types are different, the assignment is done using the + [assignment + operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") + `=` that triggers an upcast automatically. +- Otherwise, it is a + [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm "Glossary Entry"). + Here, the assignability is not checked until runtime. The downcast - in contrast to upcasts - + must be triggered explicitly using the [casting + operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencasting_operator_glosry.htm "Glossary Entry") + [`CAST`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_cast.htm). You might see code using the older + operator [`?=`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmove_cast.htm). +- See more information in the topic [Assignment Rules for Reference + Variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_references.htm). + +As an example, assume there is an inheritance tree with `lcl_super` as the superclass and `lcl_sub` as a direct subclass. `lcl_sub2` is a direct subclass of `lcl_sub`. + +In the following code snippet, the rule is met since the superclass is either the same as or more generic than the subclass (the subclass has, for example, redefined methods and is, thus, more specific). Hence, the assignment of an object reference variable pointing to the subclass to a variable pointing to a superclass works. An upcast is triggered. After this casting, the type of `oref_super` has changed and the methods of `lcl_sub` can be accessed via `oref_super`. + +``` abap +"Creating object references +DATA(oref_super) = NEW lcl_super( ). + +DATA(oref_sub) = NEW lcl_sub( ). + +"Upcast +oref_super = oref_sub. + +"The casting might be done when creating the object. +DATA super_ref TYPE REF TO lcl_super. + +super_ref = NEW lcl_sub( ). +``` + +- As mentioned above, a downcast must be triggered +manually. Just an assignment like `oref_sub = oref_super.` +does not work. A syntax error occurs saying the right-hand variable's type cannot be converted to the left-hand variable's type. +- If you indeed want to carry out this casting, you must use +`CAST` (or you might see code using the older operator `?=`) to overcome this syntax error (but just the syntax error!). Note: You might also use these casting operators for the upcasts. That means `oref_super = oref_sub.` has the same effect as `oref_super = CAST #( oref_sub ).`. Using the casting operator for upcasts is usually not necessary. +- At runtime, the assignment is checked and if the conversion does not work, you face a (catchable) exception. Even more so, the assignment `oref_sub = CAST #( oref_super ).` does not throw a syntax error but it does not work in this example either because it violates the rule mentioned above (`oref_sub` is more specific than `oref_super`). +- To check whether such an assignment is possible +on specific classes, you can use the predicate expression [`IS INSTANCE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_instance_of.htm) +or the case distinction [`CASE TYPE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase_type.htm). Carrying out an upcast before the downcast ensures that the left-hand variable's type is compatible to the right-hand variable's type. + +``` abap +DATA(oref_super) = NEW lcl_super( ). +DATA(oref_sub) = NEW lcl_sub( ). +DATA(oref_sub2) = NEW lcl_sub2( ). + +"Downcast impossible (oref_sub is more specific than oref_super); +"the exception is caught here + +TRY. + oref_sub = CAST #( oref_super ). + CATCH CX_SY_MOVE_CAST_ERROR INTO DATA(e). + ... +ENDTRY. + +"Working downcast with a prior upcast + +oref_super = oref_sub2. + +"Due to the prior upcast, the following check is actually not necessary. + +IF oref_super IS INSTANCE OF lcl_sub. + oref_sub = CAST #( oref_super ). + ... +ENDIF. + +"Excursion RTTI: Downcasts, CAST and method chaining +"Downcasts particularly play, for example, a role in the context of +"retrieving type information using RTTI. Method chaining is handy +"because it reduces the lines of code in this case. +"The example below shows the retrieval of type information +"regarding the components of a structure. +"Due to the method chaining in the second example, the three +"statements in the first example are reduced to one statement. + +DATA struct4cast TYPE zdemo_abap_carr. + +DATA(rtti_a) = cl_abap_typedescr=>describe_by_data( struct4cast ). +DATA(rtti_b) = CAST cl_abap_structdescr( rtti_a ). +DATA(rtti_c) = rtti_b->components. + +DATA(rtti_d) = CAST cl_abap_structdescr( + cl_abap_typedescr=>describe_by_data( struct4cast ) + )->components. +``` + +

⬆️ back to top

+ +## Notes on Interfaces + +Interfaces ... + +- represent a template for the components in the public visibility + section of classes. +- enhance classes by adding interface components. +- are possible as both + [local](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlocal_interface_glosry.htm "Glossary Entry") + and [global + interfaces](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_interface_glosry.htm "Glossary Entry"). +- support + [polymorphism](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpolymorphism_glosry.htm "Glossary Entry") in classes. Each class that implements an interface can implement its methods differently. [Interface reference variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninterface_ref_variable_glosry.htm "Glossary Entry") can point to objects of all classes that implement the associated interface. +- can be implemented by classes of an inheritance tree. It can be any number of interfaces. However, each interface can be implemented only once in an inheritance tree. +- are different from classes in the following ways: + - They only consist of a part declaring the components without an + implementation part. The implementation is done in classes that use the interface. + - There are no visibility sections. All components of an interface are visible. + - No instances can be created from interfaces. + - Declarations as mentioned for classes, e. g. `DATA`, + `CLASS-DATA`, `METHODS`, + `CLASS-METHODS`, are possible. Constructors are not + possible. + +

⬆️ back to top

+ +Defining interfaces: +- Can be done either globally in the repository or locally in an ABAP program. + +``` abap +INTERFACE intf. +"The addition PUBLIC is for global interfaces: +"INTERFACE intf_g PUBLIC. + + DATA ... + CLASS-DATA ... + METHODS ... + CLASS-METHODS ... + +ENDINTERFACE. +``` + +Implementing interfaces: +- A class can implement multiple interfaces. +- Interfaces must be specified in the + declaration part of a class using the statement + [`INTERFACES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces.htm). +- Since all interface components are public, you must include this + statement and the interfaces in the public visibility section of a class. When an interface is implemented in a class, all interface components are added to the other components of the class in the public visibility section. +- Interface components can be addressed using the [interface component + selector](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninterface_comp_selector_glosry.htm "Glossary Entry"): `... intf~comp ...`. +- You can specify alias names for the interface components using the statement [`ALIASES ... FOR ...`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapaliases.htm). The components can then be addressed using the alias name. +- The class must implement the methods of all implemented interfaces in it unless the methods are flagged as abstract or final. You can adapt some interface components to requirements of your class. + - You can specify the additions [`ABSTRACT METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) followed by method names or [`ALL METHODS ABSTRACT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) for the `INTERFACES` statement in the declaration part of + classes. In this case, the class(es) need not + implement the methods of the interface. The implementation is then relevant for a subclass inheriting from a superclass that includes + such an interface declaration. Note that the whole class must be abstract. + - The additions [`FINAL METHODS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) followed by method names or [`ALL METHODS FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapinterfaces_class.htm) for the `INTERFACES` statement in the declaration part of classes flag the method(s) as final. +- In the interface, methods can mark their implementation as optional using the additions [`DEFAULT + IGNORE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm) + or [`DEFAULT FAIL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_default.htm). + + +Syntax for using interfaces in classes: +``` abap +CLASS class DEFINITION. + PUBLIC SECTION. + "Multiple interface implementations possible + INTERFACES intf. + ALIASES meth_alias FOR intf~some_method. +ENDCLASS. + +CLASS class IMPLEMENTATION. + METHOD intf~some_meth. "Method implementation using the original name + ... + ENDMETHOD. + + "Just for demo purposes: Method implementation using the alias name + "METHOD meth_alias. + " ... + "ENDMETHOD. + + ... +ENDCLASS. + +"Abstract class +CLASS cl_super DEFINITION ABSTRACT. + PUBLIC SECTION. + INTERFACES intf ALL METHODS ABSTRACT. + ALIASES: + meth1 FOR intf~meth1, + meth2 FOR intf~meth2. +ENDCLASS. + +"Subclass inheriting from abstract class and implementing interface methods +CLASS cl_sub DEFINITION INHERITING FROM cl_super. + PUBLIC SECTION. + METHODS: + meth1 REDEFINITION, + meth2 REDEFINITION. +ENDCLASS. + +CLASS cl_sub IMPLEMENTATION. + METHOD meth1. + ... + ENDMETHOD. + METHOD meth2. + ... + ENDMETHOD. +ENDCLASS. +``` + +Interface reference variables and accessing objects: +- As mentioned above, addressing an object happens via an object reference variable with reference to a class. +- An interface variable can contain references to objects of classes that implement the corresponding interface. +- You create an interface reference variable like this: `DATA i_ref TYPE REF TO intf.` + +Addressing interface components: +- Addressing instance components using interface reference variable + - attribute: `i_ref->attr` + - instance method: `i_ref->meth( )` +- Addressing instance components using an object reference variable (Note: The type is a class that implements the interface) is also possible but it's not the recommended way: + - attribute: `cl_ref->intf~attr` + - instance method: `cl_ref->intf~meth` +- Addressing static components: + - static attribute: `class=>intf~attr`, + - static method: `class=>intf~meth( )` + - constant: `intf=>const` + + +``` abap +"Addressing instance interface components using interface reference variable +DATA i_ref TYPE REF TO intf. + +DATA cl_ref TYPE REF TO class. + +"Creating an instance of a class that implements the interface intf +cl_ref = NEW #( ). + +"If the class class implements an interface intf, +"the class reference variable cl_ref can be assigned +"to the interface reference variable i_ref. +"The reference in i_ref then points to the same object +"as the reference in cl_ref. +i_ref = cl_ref. + +"Can also be done directly, i. e. directly creating an object to which the interface reference variable points +i_ref = NEW class( ). + +"Instance interface method via interface reference variable +... i_ref->inst_method( ... ) ... + +"Instance interface attribute via interface reference variable +... i_ref->inst_attr ... + +"Addressing instance components using the class reference variable +"is also possible but it's not the recommended way. +... cl_ref->intf~inst_method( ... ) ... +... cl_ref->intf~inst_attr ... + +"Addressing static interface components +"class=> can be dropped if the method is called in the same class that implements the interface +... class=>intf~stat_method( ... ) ... +... class=>intf~stat_attr ... + +"Just for the record: Static interface components can be called via reference variables, too. +... i_ref->stat_method( ... ) ... +... i_ref->stat_attr ... +... cl_ref->intf~stat_method( ... ) ... + +"Constants +"A constant can be addressed using the options mentioned above. +"Plus, it can be addressed using the following pattern +... intf=>const ... +``` + +

⬆️ back to top

+ +## Excursions + +### Friendship + +- The concept of friendship enters the picture if your use case for your classes is to work together very closely. This is true, for example, for [unit +tests](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunit_test_glosry.htm "Glossary Entry") if you want to test private methods. +- Classes can grant access to invisible components for their [friends](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfriend_glosry.htm "Glossary Entry"). +- The friends can be other classes and interfaces. In case of interfaces, friendship is granted to all classes that implement the interface. +- Impact of friendship: + - Access is granted to all components, regardless of the visibility section or the addition `READ-ONLY`. + - Friends of a class can create instances of the class without restrictions. + - Friendship is a one-way street, i. e. a class granting friendship to another class is not granded friendship the other way round. If class `a` grants friendship to class `b`, class `b` must also explicitly grant friendship to class `a` so that `a` can access the invisible components of class `b`. + - Friendship and inheritance: Heirs of friends and interfaces that contain a friend as a component interface also become friends. However, granting friendship is not inherited, i. e. a friend of a superclass is not automatically a friend of its subclasses. + + +You specify the befriended class in the definition part using a `FRIENDS` addition: +``` abap +"For local classes. Friendship can be granted to all classes/interfaces +"of the same program and the class library. +"Multiple classes can be specified as friends. +CLASS lo_class DEFINITION FRIENDS other_class ... . +... + +CLASS lo_class DEFINITION CREATE PRIVATE FRIENDS other_class ... . + +"Addition GLOBAL only allowed for global classes, i. e. if the addition PUBLIC is also used +"Other global classes and interfaces from the class library can be specified after GLOBAL FRIENDS. +CLASS global_class DEFINITION CREATE PUBLIC FRIENDS other_global_class ... . +``` + +

⬆️ back to top

+ +### Events + +- [Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_glosry.htm "Glossary Entry") +can trigger the processing of [processing blocks](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocessing_block_glosry.htm "Glossary Entry"). +- Declaring events: Can be declared in a visibility section of the declaration part of a class or in an interface, e. g. as + - instance event using an [`EVENTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapevents.htm) statement. Note that they can only be raised in instance methods of the same class. + - static event using [`CLASS-EVENTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass-events.htm). They can be raised in all methods of the same class or of a class that implements the interface. Static event handlers can be called by the event independently of an instance of the class. + +``` abap +"Declaration part of a class/interface +"Instance events +EVENTS: i_evt1, + +"Events can only have output parameters that are passed by value + i_evt2 EXPORTING VALUE(num) TYPE i ... +... +"Static events +CLASS-EVENTS: st_evt1, + st_evt2 EXPORTING VALUE(num) TYPE i ... + +``` + +- Event handlers: + - An event is raised by a [`RAISE EVENT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_event.htm) statement in another method or in the same method. + - Raising an event means that [event handlers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenevent_handler_glosry.htm "Glossary Entry") are called. + - This event handler must be declared with the following syntax (see more information and more additions [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_event_handler.htm)): + +``` abap +"Event handlers for instance events +METHODS: handler_meth1 FOR EVENT i_evt1 OF some_class, + + "Parameter names must be the same as declared; + "no further additions possible for the parameter (e.g. TYPE); + "the predefined, implicit parameter sender as another formal parameter is possible with instance events, + "it is typed as a reference variable, which itself has the class/interface as a static type, + "If the event handler is called by an instance event, it is passed a reference to the raising object in sender. + handler_meth2 FOR EVENT i_evt2 OF some_class IMPORTING num sender, +... +``` + +- To make sure that an event handler handles a raised event, it must be registered with the statement [`SET HANDLER`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapset_handler.htm). See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapset_handler.htm) (for example, events can also be deregistered). + +```abap +"Registering event for a specific instance +SET HANDLER handler1 FOR ref. + +"Registering event for all instances +SET HANDLER handler2 FOR ALL INSTANCES. + +"Registering static event for the whole class/interface +SET HANDLER handler3. +"Note that multiple handler methods can be specified. +``` + +

⬆️ back to top

+ +### Factory Methods and Singletons as Design Patterns + +In object-oriented programming, there a plenty of design patterns. Covering these ones here to get a rough idea: factory methods and singletons. Both are relevant if you want to restrict or control the instantiation of a class by external users of this class. + +A singleton is a design pattern in which it is only up to the class to create objects. In doing so, the class ensures that only one object exists for every internal session that is made available to consumers. + +The following code snippet shows an implementation of the singleton design pattern. The `get_instance` method is used to return the object reference to the object created. Only one instance can be created. + +```abap +"Using the addition CREATE PRIVATE, objects can only be created by the class itself. +CLASS singleton_class DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS get_instance RETURNING VALUE(ret) TYPE REF TO singleton_class. + + PRIVATE SECTION. + CLASS-DATA inst TYPE REF TO singleton_class. +ENDCLASS. + +CLASS singleton_class IMPLEMENTATION. + METHOD get_instance. + IF inst IS NOT BOUND. + inst = NEW #( ). + ENDIF. + ret = inst. + ENDMETHOD. +ENDCLASS. +``` + +Controlling the creation of objects - the instantiation of a class - can be realized using a factory method. For example, certain checks might be required before a class can be instantiated. If a check is not successful, the instantiation is denied. +You might create a (static) factory method as follows: +- A check is carried out in the factory method, for example, by evaluating importing parameters. +- If the check is successful, an object of the class is created. +- The method signature includes an output parameter that returns an object reference to the caller. + +This is rudimentarily demonstrated in the following snippet: + +``` abap +CLASS class DEFINITION CREATE PRIVATE. + PUBLIC SECTION. + CLASS-METHODS + factory_method IMPORTING par ..., + RETURNING VALUE(obj) TYPE REF TO class. + ... +ENDCLASS. + +CLASS class IMPLEMENTATION. + METHOD factory_method. + IF par = ... + obj = NEW class( ). + ELSE. + ... + ENDIF. + + ENDMETHOD. + ... +ENDCLASS. +... + +"Calling a factory method. +DATA obj_factory TYPE REF TO class. + +obj_factory = class=>factory_method( par = ... ). +``` + +

⬆️ back to top

+ +## More Information +You can check the subtopics of + +- [ABAP Objects - Overview](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_oview.htm) +- [Programming Guidlines - Object-Oriented Programming (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenobj_oriented_gdl.htm) + +in the ABAP Keyword Documentation. + +## Executable Example +[zcl_demo_abap_objects](./src/zcl_demo_abap_objects.clas.abap) + +> **💡 Note**
+> - The executable example covers the following topics, among others: +> - Working with objects and components +> - Redefining methods, inheritance +> - Working with interfaces +> - Upcast and downcast +> - Concepts such as factory methods, singleton and abstract classes +> - Events +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) diff --git a/07_String_Processing.md b/07_String_Processing.md index a43b173..36719da 100644 --- a/07_String_Processing.md +++ b/07_String_Processing.md @@ -1,2006 +1,2168 @@ - - -# String Processing - -- [String Processing](#string-processing) - - [Introduction](#introduction) - - [Data Types for Character Strings](#data-types-for-character-strings) - - [Declaring Character-Like Data Objects](#declaring-character-like-data-objects) - - [Assigning Values](#assigning-values) - - [String Templates](#string-templates) - - [Determining the Length of Strings](#determining-the-length-of-strings) - - [Concatenating Strings](#concatenating-strings) - - [Splitting Strings](#splitting-strings) - - [Modifying Strings](#modifying-strings) - - [Processing Substrings](#processing-substrings) - - [Searching and Replacing](#searching-and-replacing) - - [Searching for Specific Characters](#searching-for-specific-characters) - - [Replacing Specific Characters in Strings](#replacing-specific-characters-in-strings) - - [Searching for Substrings in Strings (and Tables)](#searching-for-substrings-in-strings-and-tables) - - [Replacing Substrings in Strings (and Tables)](#replacing-substrings-in-strings-and-tables) - - [Pattern-Based Searching and Replacing in Strings](#pattern-based-searching-and-replacing-in-strings) - - [Simple Pattern-Based Searching Using Comparison Operators](#simple-pattern-based-searching-using-comparison-operators) - - [Complex Searching and Replacing Using Regular Expressions](#complex-searching-and-replacing-using-regular-expressions) - - [Excursion: Common Regular Expressions](#excursion-common-regular-expressions) - - [Searching Using Regular Expressions](#searching-using-regular-expressions) - - [Excursion: System Classes for Regular Expressions](#excursion-system-classes-for-regular-expressions) - - [Replacing Using Regular Expressions](#replacing-using-regular-expressions) - - [More String Functions](#more-string-functions) - - [Checking the Similarity of Strings](#checking-the-similarity-of-strings) - - [Repeating Strings](#repeating-strings) - - [Returning the Smallest/Biggest of a Set of Character-Like Arguments](#returning-the-smallestbiggest-of-a-set-of-character-like-arguments) - - [Escaping Special Characters](#escaping-special-characters) - - [Excursion: String Processing Using the XCO Library](#excursion-string-processing-using-the-xco-library) - - [Executable Example](#executable-example) - - -## Introduction - -ABAP offers plenty of options for processing [character strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencharacter_string_glosry.htm "Glossary Entry"). -The options include ABAP statements (e. g. [`FIND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm)), -[character string expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_expression_glosry.htm "Glossary Entry") -([concatenations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_glosry.htm) and [string templates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_template_glosry.htm "Glossary Entry")) -and built-in [string functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_function_glosry.htm "Glossary Entry") -(e. g. [`strlen`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm)). - -> **💡 Note**
->- Compared to statements, expressions and string functions can help make your ABAP code more - concise and straightforward. For example, you can perform string operations directly in [operand - position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry"), - allowing you to avoid temporary variables. ->- In ABAP statements, modification operations on strings are often performed in read/write positions, meaning that the source and target - fields of an operation are the same. When working with string functions, the source field is passed as an input parameter and the modified value is returned as a [return value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreturn_value_glosry.htm "Glossary Entry"), meaning that the function itself does not modify the source field. Of course, you can assign the function to the source field to achieve its modification. ->- In most cases, string functions provide the same functionality as the - corresponding ABAP statements, or even more. The return value of string functions - that return character strings is always of type `string`. - -

⬆️ back to top

- -## Data Types for Character Strings - -ABAP provides the following built-in data types for data objects that contain character strings. They are distinguished as follows: - -| Type | Details | Length | Value Range | Initial Value | -|---|---|---|---|---| -| `string` | For variable length character strings. [Data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry") of this type are [dynamic data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_data_object_glosry.htm "Glossary Entry"), i. e. the length of a variable can change during the execution of an ABAP program and thus it can contain character strings of different lengths. A data object of type `string` is called *text string* or, in short, just *string*. | No standard length; length is variable | Any [Unicode](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunicode_glosry.htm) characters that can be encoded in ABAP language's code page [UCS-2](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenucs2_glosry.htm). The most common content are alphanumeric characters or special characters. | Empty string with length 0 | -| `c` | For fixed length character strings. Data objects of this type are [static data objects](http://ldcialx.wdf.sap.corp:50018/sap/public/bc/abap/docu?sap-language=EN&object=abenstatic_data_object_glosry&version=X&sap-client=000), i. e. the length of a variable must be defined during its declaration and does not change during the execution of an ABAP program. Thus, it always contains character strings of the same length. A data object of type `c` is called *text field*.|Data objects of this type can contain a string of fixed length (between 1 and 262143 characters); standard length: 1 | Same as for `string` | A blank for each position | - -In addition to these main data types for character strings, there are several other fixed length data types with special meanings: - -- `n` for fixed length numerical character strings - - Data objects of this type are technically almost the same as text fields. However, the only valid characters are the digits 0 to 9. Validity is not checked for assigning values in a regular way but only for [lossless assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlossless_assignment_glosry.htm). Thus, such numeric text fields can contain invalid data, but should only be used for digits that are not intended for arithmetic calculations, such as zip codes or article numbers. The initial value for each position is 0. -- `d` and `t` for date and time fields - - These data types have a predefiend length of 6 and 8. Data objects of these types are used for character representations of dates and times in a predefined format. You can use them directly in date and time calculations. However, these fields can also contain invalid values. - -These data types are not covered further in this cheat sheet. The same is true for the [byte-like data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_like_data_typ_glosry.htm "Glossary Entry") `x` and `xstring` that are closely related to `c` and `string` but contain raw [byte strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_string_glosry.htm). - -> **⚡ Differences between text strings (variable length) and text fields (fixed length)**
->- **Initial value**: The initial value of a text string is an - empty string of length 0. The initial value of text field is represented by blanks at each position. ->- **Internal representation**: Data objects of type `c` and `string` are both [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"). - However, while text fields occupy a block of memory according to their length, text strings are so-called [deep](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_glosry.htm "Glossary Entry") data objects. Internally, they are managed by a [reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm "Glossary Entry") that points to the actual character. This fact has restrictive consequences for the use of strings as components of structures, but can also improve the performance of assignments due to the concept of [sharing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensharing_glosry.htm "Glossary Entry") of deep data objects. ->- **Length**: Theoretically, a text string can use up to 2 GB (one character occupies 2 bytes). - The maximum length of a text field is 262143 characters. ->- **Trailing blanks**: For text strings, trailing blanks are preserved in all operations. For text fields, it depends on the [operand - position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry") whether trailing blanks are respected or not. In most operand positions, trailing blanks are truncated when working with text fields, even when using [text field literals](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentext_field_literal_glosry.htm). For example, if a text field is assigned to a text string, the resulting target string will never contain trailing blanks. See the *Condensing Strings* section in this context. ->- **Flexibility**: Text strings are more flexible than text fields - because you can easily shorten or lengthen them without - worrying that, for example, parts of the character string will be - truncated during processing. On the other hand, when accessing substrings of a string, you have to make sure that the string is long enough, whereas with text fields you always know their length. - -So, when to use what? Text fields are useful when -actually specifying a maximum or mandatory length, e.g. a country code -that must be a maximum of two characters, or for input fields in -forms that should not exceed a certain length. If limiting a string -is not relevant, text strings are a good choice. - -

⬆️ back to top

- -## Declaring Character-Like Data Objects - -- To work with character strings, you need character-like data objects based on the character-like types mentioned above. -- The simplest way of producing text in an ABAP program are [character literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencharacter_literal_glosry.htm). -The following code snippet shows a global class implementing the interface `if_oo_adt_classrun`. - - Using the `write` method, you can display output in the ADT console. In the example, two [untyped literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuntyped_literal_glosry.htm) without a dedicated name ([unnamed data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunnamed_data_object_glosry.htm)) are included. - - In the case below, the data type of the character literals are defined by the delimiters. -- Text string literals are enclosed in backquotes (\`...\`) and have the data type `string`. -- Text field literals are enclosed in single quotes (`'...'`) and have the data type `c`. -- The literals can be (but should not according to the [programming guidelines on literals (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenliterals_guidl.htm)) used like constants of these types in [operand positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm). They should be only used for start values when declaring [named data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm). - -```abap -CLASS zcl_some_test_class DEFINITION PUBLIC FINAL CREATE PUBLIC. - PUBLIC SECTION. - INTERFACES if_oo_adt_classrun. -ENDCLASS. - -CLASS zcl_some_test_class IMPLEMENTATION. - METHOD if_oo_adt_classrun~main. - out->write( `I am a text string literal` ). "text string literal of type string - out->write( 'I am a text field literal' ). "text field literal of type c - ENDMETHOD. -ENDCLASS. -``` - -- [Named](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm) character-like data types and objects can be declared like other types and objects using [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm), [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) and by referring to a character-like data type. -- In addition, character-like data objects can be declared inline with the operators `DATA` and [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm). - -Syntax examples: -``` abap -"Type declarations using built-in types - -TYPES: c_type TYPE c LENGTH 3, "Explicit length specification - str_type TYPE string. - -"Data object declarations using built-in, local and DDIC types - -DATA: flag TYPE c LENGTH 1, "Built-in type - str1 TYPE string, "Built-in type - char1 TYPE c_type, "Local type - str2 LIKE str1, "Deriving type from a local data object - str3 TYPE str_type, "Local type - char2 TYPE s_toairp, "DDIC type (used e. g. for a field in a demo table) - char3 TYPE zdemo_abap_flsch-carrid. "Using the type of a DDIC table component - -"You may also encounter declarations with type c and the length -"specified in parentheses. This is not recommended, to avoid confusion -"with the use of parentheses in dynamic programming. - -DATA char(4) TYPE c. - -"Just a TYPE c specification without length means LENGTH 1. -DATA char_len_one TYPE c. -"No type and length specification: TYPE c LENGTH 1 by default -DATA char_no_type_len. -``` - -

⬆️ back to top

- -## Assigning Values - -- When you declare character-like data objects, you can specify start values directly with the `VALUE` addition, e.g. `DATA chars TYPE c LENGTH 3 VALUE 'abc'.`. -- You can do value assignments to data objects using the the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") `=`. -- As mentioned above, you can declare character-like data objects inline using the operators `DATA` or `FINAL`. -- You can use the operators at many [write positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwrite_position_glosry.htm "Glossary Entry"). -- Unlike the `VALUE` addition of the declaration statements, inline declarations allow you to declare variables for the results of expressions or at other positions where character strings are returned. -- In the case below, a variable specified in parentheses preceded by `DATA` (or `FINAL`) on the left side of the assignment operator automatically derives a data type from the operand on the right. This helps to make your -programs leaner. - -Syntax examples: -``` abap -"Data object declarations including default values with VALUE -"Note the chained statement: DATA followed by a colon, listing the data object declarations, -"separated by a comma. -DATA: flag TYPE c LENGTH 1 VALUE 'X', -      str1 TYPE string VALUE `Hallo!`. - -"Examples for type n -DATA zip_code TYPE n LENGTH 5 VALUE '12345'. -DATA isbn_number TYPE n LENGTH 13 VALUE '1234567890123'. - -"Constant; content cannot be changed at runtime -CONSTANTS pi TYPE p LENGTH 8 DECIMALS 14 VALUE '3.14159265358979'. - -"More data object declarations -DATA: char1 TYPE c LENGTH 5, -      html  TYPE string, -      str2  LIKE html. - -"Value assignments -char1 = 'ab123'. -html  = `

hallo

`. - -"Escaping backquotes in text string literals with another one -str1  = `This is a backquote: ``.`. - -"If possible, avoid unnecessary type conversion; in principle, every -"convertible type can be specified -str2 = 'abc'. "Fixed length string assigned to data object of type string -DATA str3 TYPE string VALUE 'X'. "type c length 1 -DATA str4 TYPE string VALUE -1. "type i - -"Inline declarations -DATA(char2) = 'abcd'. "Type c length 4 -DATA(str5)  = `efgh`. - -"You can use FINAL to create immutable variables. -FINAL(final_string)  = `zyx`. - -"Since char2 is of type c length 4 (the length is also derived), -"characters are truncated in the following example assignment -char2 = 'ijklmnopq'. "ijkl - -"Trailing blanks after assigning fixed length to variable length string -DATA(char3) = 'ab   '. -DATA(str6)  = `cdefgh`. -str6 = char3. "'ab' (trailing blanks are not respected due to conversion rule) -``` - -- When assigning strings, not only data objects can be placed on the right -side. Various expressions and strings can be concatenated using the -[concatenation -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_operator_glosry.htm "Glossary Entry") -`&&`. -- Alternatively, you can concatenate strings using [string -templates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_template_glosry.htm "Glossary Entry"), as described in the *Concatenating Strings* section. -``` abap -str5 = str3 && ` ` && str4 && `!`. "X 1-! -"Note the output for str4 that includes the conversion of type i to -"string above demonstrating a possibly inadvertent specification -"of an integer value for str4 that is of type string. -``` - -Note that there is also the [literal -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator_glosry.htm "Glossary Entry") -`&` that joins [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 `&&`. - -

⬆️ back to top

- -## String Templates -- Using string templates, you can construct strings very elegantly from -literal text and - which is the primary use case - by including -embedded ABAP -[expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexpression_glosry.htm "Glossary Entry") -within a pair of delimiters (`|...|`) if these expressions can be converted to `string`. -- To embed expressions, you enclose them in curly brackets: `{ ... }`. - -> **💡 Note**
-> String templates form a [string -expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_expression_glosry.htm "Glossary Entry") -that is compiled at runtime. Therefore, a string template that contains only -literal text is treated as an expression, which has a performance impact. In such a case, it is preferable to use a text string literal with backquotes. - -Syntax examples: -``` abap -"Value assignment with string templates -"The expression must be convertible to a string. A blank (not within the curly brackets) -"means a blank in the resulting string. -DATA(s1) = |Hallo { cl_abap_context_info=>get_user_technical_name( ) }!|. - -DATA(s2) = `How are you?`. "Literal text only with backquotes -DATA(s3) = |{ s1 } { s2 }|. "Hallo NAME! How are you? - -"Chaining of string templates using && -DATA(s4) = |{ s1 }| && ` ` && |{ s2 }|. "Hallo NAME! How are you? -``` - -- String templates interpret certain character combinations as [control -characters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_templates_separators.htm). -- For example, `\n` is interpreted as a newline. A new line is -started. -- String templates also support various [formatting -options](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcompute_string_format_options.htm). -- Refer to the ABAP Keyword Documentation for all options. - -The following syntax examples demonstrate a selection: -```abap -"Control characters -s4 = |{ s1 }\n{ s2 }\nSee you.|. "\n is interpreted as a line feed - -"Excursion: Class CL_ABAP_CHAR_UTILITIES provides attributes and methods as utilities for string processing. -"See the class documentation -"The following examples demonstrate that attributes that contain control characters can be replaced by -"a representation of control characters in a string template. -ASSERT cl_abap_char_utilities=>newline = |\n|. -ASSERT cl_abap_char_utilities=>horizontal_tab = |\t|. -ASSERT cl_abap_char_utilities=>cr_lf = |\r\n|. - -"Various formatting options -"DATE: Defining the format of a date -"The output is just an example and depends on your settings. -DATA(d) = |The date is { cl_abap_context_info=>get_system_date( ) DATE = USER }.|. "The date is 01/01/2024. -d = |{ cl_abap_context_info=>get_system_date( ) DATE = RAW }|. "20240101 -d = |{ cl_abap_context_info=>get_system_date( ) DATE = ISO }|. "2024-01-01 -d = |{ cl_abap_context_info=>get_system_date( ) DATE = ENVIRONMENT }|. "01/01/2024 - -"TIME: Defining the format of a time -"The output is just an example and depends on your settings. -DATA(tm) = |The time is { cl_abap_context_info=>get_system_time( ) TIME = ISO }.|. "The time is 14:37:24. -tm = |{ cl_abap_context_info=>get_system_time( ) TIME = RAW }|. "143724 -tm = |{ cl_abap_context_info=>get_system_time( ) TIME = USER }|. "14:37:24 -tm = |{ cl_abap_context_info=>get_system_time( ) TIME = ENVIRONMENT }|. "14:37:24 - -"TIMESTAMP: Defining the format of a time stamp -"The output is just an example and depends on your settings. -DATA(ts) = |{ utclong_current( ) TIMESTAMP = SPACE }|. "2024-01-01 14:39:50.4069170 -ts = |{ utclong_current( ) TIMESTAMP = ISO }|. "2024-01-01T14:39:50,4071110 -ts = |{ utclong_current( ) TIMESTAMP = USER }|. "01/01/2024 14:39:50.4072010 -ts = |{ utclong_current( ) TIMESTAMP = ENVIRONMENT }|. "01/01/2024 14:39:50.4073230 -ts = |{ utclong_current( ) }|. "2024-01-01 14:39:50.4074060 - -"TIMEZONE: Defining the format of a time stamp using the rules for time zones -DATA(tz) = |{ utclong_current( ) TIMEZONE = 'UTC' }|. "2024-12-30 14:43:20.6534640 -tz = |{ utclong_current( ) TIMEZONE = 'CET' COUNTRY = 'DE ' }|. "30.12.2024 15:43:20,6536320 -tz = |{ utclong_current( ) TIMEZONE = 'EST' COUNTRY = 'US ' }|. "12/30/2024 09:43:20.6889180 AM - -"CASE: Lowercase and uppercase -s1 = |AbCdEfG|. -s2 = |{ s1 CASE = LOWER }|. "abcdefg -s2 = |{ s1 CASE = UPPER }|. "ABCDEFG - -"WIDTH/ALIGN -s1 = `##`. -s2 = |{ s1 WIDTH = 10 ALIGN = LEFT }<---|. "'## <---' -s2 = |{ s1 WIDTH = 10 ALIGN = CENTER }<---|. "' ## <---' - -"PAD: Used to pad any surplus places in the result with the specified character. -s2 = |{ s1 WIDTH = 10 ALIGN = RIGHT PAD = `.` }<---|. "'........##<---' - -"DECIMALS -s1 = |{ CONV decfloat34( - 1 / 3 ) DECIMALS = 3 }|. "'-0.333' - -"SIGN: Defining the format of the +/- sign when the string represented -"by the embedded expression represents a numeric value -"- left without space, no + -s1 = |{ +1 SIGN = LEFT }|. "1 -"- and + left without space -s1 = |{ 1 SIGN = LEFTPLUS }|. "+1 -"- left without space, blank left for + -s1 = |{ 1 SIGN = LEFTSPACE }|. " 1 -"- right without space, no + -s1 = |{ -1 SIGN = RIGHT }|. "1- -"- and + right without space -s1 = |{ 1 SIGN = RIGHTPLUS }|. "1+ -"- left without space, blank right for + -s1 = |{ +1 SIGN = RIGHTSPACE }|. "1 - -"ZERO: Defining the format of the numeric value zero. -"Only to be specified if the embedded expression has a numeric data type. -s1 = |'{ 0 ZERO = NO }' and '{ 0 ZERO = YES }'|. "'' and '0' - -"XSD: Formatting is applied to an embedded expression (elementary data types) in asXML format that is -"assigned to its data type. Check the information in the ABAP Keyword Documentation about the asXML -"mapping of elementary ABAP types. -DATA xstr TYPE xstring VALUE `41424150`. -DATA dat type d value '20240101'. -DATA tim type t value '123456'. -DATA(utc) = utclong_current( ). "e.g. 2024-01-01 13:51:38.5708800 - -s1 = |{ xstr XSD = YES }|. "QUJBUA== -s1 = |{ dat XSD = YES }|. "2024-01-01 -s1 = |{ tim XSD = YES }|. "12:34:56 -s1 = |{ utc XSD = YES }|. "2024-01-01T13:51:38.57088Z - -"STYLE: Defining the style of decimal floating point numbers; -"see the details in the ABAP Keyword Documentation. -DATA(dcfl34) = CONV decfloat34( '-123.45600' ). -s1 = |{ dcfl34 }|. "-123.456 -"Creates the predefined format -s1 = |{ dcfl34 STYLE = SIMPLE }|. "-123.456 -"+/- added to the right, removes trailing zeros -s1 = |{ dcfl34 STYLE = SIGN_AS_POSTFIX }|. "123.456- -"Retains trailing zeros -s1 = |{ dcfl34 STYLE = SCALE_PRESERVING }|. "-123.45600 -"Scientific notation; at least a two digit exponent with a plus/minus sign -s1 = |{ dcfl34 STYLE = SCIENTIFIC }|. "-1.23456E+02 -"Scientific notation; only one integer digit with the value 0 -s1 = |{ dcfl34 STYLE = SCIENTIFIC_WITH_LEADING_ZERO }|. "-0.123456E+03 -"Scientific notation; exponent has 3 digits for decfloat16 and 4 digits for decfloat34 -s1 = |{ dcfl34 STYLE = SCALE_PRESERVING_SCIENTIFIC }|. "-1.2345600E+0002 -"Technical format -s1 = |{ dcfl34 STYLE = ENGINEERING }|. "-123.456E+00 - -"ALPHA: Adds or removes leading zeros from strings of digits; the data type -"must be string, c, or n -"Adding leading zeros -"Additionally specifying WIDTH -"Note: The specified length is only used if it is greater than -"the length of provided string (without leading zeros) -s1 = |{ '1234' ALPHA = IN WIDTH = 10 }|. "0000001234 -s1 = |{ '00000000000000000000000012' ALPHA = IN WIDTH = 10 }|. "0000000012 -"Fixed-length string provided, WIDTH not specified -s1 = |{ ' 12' ALPHA = IN }|. "00012 -"Removing leading zeros -s1 = |{ '00001234' ALPHA = OUT }|. "1234 -"Do not apply formatting -s1 = |{ '00001234' ALPHA = RAW }|. "00001234 -``` - -> **💡 Note**
-> Escape `\|{}` in string templates using `\`, i. e. `\\` means `\`. - -

⬆️ back to top

- -## Determining the Length of Strings - -- To determine the length of a string, you can use the string function -[`strlen`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm). -- Note that the result depends on the type of the string, i. e. the result for a data object of type `string` includes trailing blanks. A -fixed-length string does not include them. -- To exclude trailing blanks in all cases, regardless of the data type, you can use the built-in -[`numofchar`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm) function. - -Syntax examples: -``` abap -"strlen -DATA(len_c) = strlen( 'abc ' ). "3 -DATA(len_str) = strlen( `abc ` ). "6 - -"numofchar -len_c = numofchar( 'abc ' ). "3 -len_str = numofchar( `abc ` ). "3 -``` - -

⬆️ back to top

- -## Concatenating Strings - -- Two or more strings can be concatenated using the concatenation operator -`&&` and string templates. Alternatively, you can use -[`CONCATENATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconcatenate.htm) -statements. -- It is also possible to concatenate lines from internal tables -into a string to avoid a loop. -- A more modern way is to use -the string function -[`concat_lines_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_functions.htm). - -Syntax examples: -``` abap -"&& and string template -DATA(s1) = `AB` && `AP`. "ABAP -DATA(s2) = `ab` && `ap` && ` ` && s1. "abap ABAP -DATA(s3) = |{ s1 }. { s2 }!|. "ABAP. abap ABAP! - -"CONCATENATE statements -CONCATENATE s1 s2 INTO s3. "ABAPabap ABAP - -"Multiple data objects and target declared inline -CONCATENATE s1 ` ` s2 INTO DATA(s5). "ABAP abap ABAP - -CONCATENATE s1 s2 s5 INTO DATA(s6). "ABAPabap ABAPABAP abap ABAP - -"You can also add a separation sign using the addition SEPARATED BY -CONCATENATE s1 s2 INTO s3 SEPARATED BY ` `. "ABAP abap ABAP - -CONCATENATE s1 s2 INTO s3 SEPARATED BY `#`. "ABAP#abap ABAP - -"Keeping trailing blanks in the result when concatenating fixed length -"strings. The ones of variable length strings are respected by default. -CONCATENATE 'a ' 'b ' 'c ' INTO DATA(ch) RESPECTING BLANKS. "'a b c ' - -"Concatenating lines of internal tables into a string -CONCATENATE LINES OF itab INTO t SEPARATED BY ` `. - -"Using concat_lines_of -s1 = concat_lines_of( table = itab ). "Without separator -s1 = concat_lines_of( table = itab sep = ` ` ). "With separator -``` - -

⬆️ back to top

- -## Splitting Strings - -- You can use -[`SPLIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsplit.htm) -statements to split strings in multiple segments. -- The result of the -split can be stored in separate data objects or internal tables that -have a character-like line type. -- Note that if the number of specified targets is -less than the number of segments returned by the split, the last target receives the remaining unsplit segements. If more targets are specified, the targets that do not receive a segment are -initialized. -- Therefore, specifying individual targets with `SPLIT` -statements is useful if the number of expected segments is known. -Otherwise, splitting into tables is a good choice. -- If you want to get the value of a particular segment, you can use the -string function -[`segment`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensegment_functions.htm). - -Syntax examples: -``` abap -DATA(s1) = `Hallo,world,123`. -DATA: s2 TYPE string, - s3 TYPE string, - s4 TYPE string. - -SPLIT s1 AT `,` INTO s2 s3 s4. "s2 = Hallo / s3 = world / s4 = 123 - -"Less data objects than possible splittings -SPLIT s1 AT `,` INTO s2 s3. "s2 = Hallo / s3 = world,123 - -"Splitting into internal table -DATA itab TYPE TABLE OF string. -SPLIT s1 AT ',' INTO TABLE itab. "Strings are added to itab in individual lines without comma - -"String function segment returning the occurrence of a segment -"index parameter: number of segment -s2 = segment( val = s1 index = 2 sep = `,` ). "world -``` - -

⬆️ back to top

- -## Modifying Strings -**Transforming to Lowercase and Uppercase** - -- The string functions -[`to_lower`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencase_functions.htm) -and -[`to_upper`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencase_functions.htm) -transform characters of a string to either lowercase or uppercase and -store the result in a target variable. -- If you want to apply the transformation to the source directly, you can use -[`TRANSLATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptranslate.htm) -statements. - -Syntax examples: -``` abap -"String functions -DATA(s1) = to_upper( `abap` ). "ABAP -s1 = to_lower( `SOME_FILE.Txt` ). "some_file.txt - -"TRANSLATE statements -s1 = `Hallo`. -TRANSLATE s1 TO UPPER CASE. "HALLO -TRANSLATE s1 TO LOWER CASE. "hallo -``` - -**Shifting Content** - -- You can shift content within a string to a specific position on the left -or right of a string. -[`SHIFT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapshift.htm) -statements have various additions for specific use cases. -- In a more modern way, you can use the string functions -[`shift_left`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshift_functions.htm) -and -[`shift_right`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshift_functions.htm), which store the result in a variable. - - These functions provide additional -functionality. The `sub` parameter can be used to specify a -substring. All substrings in the string that match the value specified -in `sub` on either the left or right side of the string are -removed. - -Syntax examples: -``` abap -"SHIFT statements -"Note that all results below refer to s1 = `hallo`. -DATA(s1) = `hallo`. "Type string - -SHIFT s1. "No addition; string shifted one place to the left: allo -SHIFT s1 BY 2 PLACES. "Without direction, left by default: llo -SHIFT s1 BY 3 PLACES RIGHT. "With direction, variable length strings are extended: ' hallo' - -"Note that all results below refer to ch4 = 'hallo'. -DATA(ch4) = 'hallo'. "Type c length 5 - -SHIFT ch4 BY 3 PLACES RIGHT. "Fixed length string: ' ha' - -"CIRCULAR addition: characters that are moved out of the string are -"added at the other end again -SHIFT ch4 BY 3 PLACES LEFT CIRCULAR. "lohal -SHIFT ch4 UP TO `ll`. "Shift characters up to a specific character set: llo - -"Deleting leading and trailing characters -DATA(s2) = ` hallo `. -DATA(s3) = s2. - -SHIFT s2 LEFT DELETING LEADING ` `. "'hallo ' -SHIFT s3 RIGHT DELETING TRAILING ` `. "' hallo' (length is kept) - -"Removing trailing blanks in strings without leading blanks; -"you can use the following sequence of statements -DATA(s4) = `hallo `. -SHIFT s4 RIGHT DELETING TRAILING ` `. "' hallo' -SHIFT s4 LEFT DELETING LEADING ` `. "'hallo' - -"String functions with parameters -s1 = `hallo`. - -s2 = shift_left( val = s1 places = 3 ). "lo -s2 = shift_left( val = s1 circular = 2 ). "lloha - -"Note that shift_right does not extend a variable length string. -s2 = shift_right( val = s1 places = 3 ). "ha -s2 = shift_right( val = `abc ` sub = ` ` ). "'abc' -s2 = shift_right( val = `abc ` ). "'abc' (same result as above) -``` - -**Condensing Strings** - -- You can use -[`CONDENSE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcondense.htm) -statements or the string function -[`condense`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencondense_functions.htm) -to remove blanks from strings. -- The advantage of using the string function -is that you can specify any character to remove, not just blanks. - -Syntax examples: -``` abap -"CONDENSE statements -DATA(s1) = ` ab cd `. -DATA(s2) = ` ef gh ij `. -DATA(s3) = ` kl mn op `. - -CONDENSE s1. "Trailing and leading blanks are removed: 'ab cd' -CONDENSE s2. "It also replaces sequences of multiple blanks with a single blank: 'ef gh ij' -CONDENSE s3 NO-GAPS. "Removes all blanks: 'klmnop' - -"String function condense -s1 = ` ab cd `. - -"No parameters specified, i. e. their default values are provided. -"Works like CONDENSE statement without the NO-GAPS addition. -s2 = condense( s1 ). "ab cd - -"Parameters del/to not specified. from parameter with initial string -"(could also be a text field literal: from = ' '). This way, leading and -"trailing blanks are removed. -s2 = condense( val = s1 from = `` ). "ab cd - -"Parameter to specified with an initial string. No other parameters. -"Works like CONDENSE statement with the NO-GAPS addition. -s2 = condense( val = s1 to = `` ). "abcd - -"Parameter del specifies the leading/trailing characters to be removed. -s2 = condense( val = `##see###you##` del = `#` ). "see###you - -"If from and to are specified along with del, leading/trailing -"characters specified in del are first removed. Then, in the remaining string, all -"substrings composed of characters specified in from are replaced with -"the first character of the string specified in the to parameter -s2 = condense( val = ` Rock'xxx'Roller` - del = `re ` - from = `x` - to = `n` ). "Rock'n'Roll -``` - -**Reversing Strings** - -The string function -[`reverse`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreverse_functions.htm) -reverses a string: -``` abap -"Result: 'abap' -DATA(s1) = reverse( `paba` ). -``` - -**Inserting Substrings into Strings** - -- The string function -[`insert`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninsert_functions.htm) -inserts a substring at any position within a given string. You can use various parameters to construct the string you want: - - `val`: Original string. - - `sub`: Substring. - - `off`: Optionally sets the offset, i.e. the position where the substring should be added. The default value is 0. When using the function with the default value, the result is like concatenating a string with `&&` (like `res = sub && text`). -- Inserting substrings can also be accomplished using the string function `replace` or `REPLACE` statements, which are are covered below. - -Syntax examples: -``` abap -"Result: 'abcdefghi' -DATA(s1) = insert( val = `abcghi` sub = `def` off = 3 ). - -"Result: 'defabcghi' -s1 = insert( val = `abcghi` sub = `def` ). -``` - -**Overlaying Content** - -You can use [`OVERLAY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapoverlay.htm) statements to replace characters in one variable with characters in another variable that are in the same place there. - -Syntax examples: -``` abap -DATA(incl) = '==============================CP'. -DATA(cl_name) = 'CL_SOME_CLASS '. - -"Addition ONLY is not specified: All blanks are replaced -OVERLAY cl_name WITH incl. -"cl_name: CL_SOME_CLASS=================CP - -DATA(txt1) = 'a.b.c.a.b.c.A'. -DATA(txt2) = 'z.x.y.Z.x.y.z'. - -"Addition ONLY is specified: All characters that are specified after ONLY and that -"occur in the operand are replaced. Note that this is case-sensitive. -OVERLAY txt1 WITH txt2 ONLY 'ab'. -"txt1: z.x.c.Z.x.c.A -``` - -

⬆️ back to top

- -## Processing Substrings - -- The string function -[`substring`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm) allows you to specify the position (parameter `off`) and the length -(`len`) of a substring to be extracted from a given -string (`val`). - - At least one of the two parameters `off` -or `len` must be specified. The default value of `off` -is 0, i.e. when using the default value, the substring is extracted -from the beginning of the string. - - If `len` is not specified, the rest of the remaining characters are respected. If the offset -and length are greater than the actual length of the string, the -exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised. -- You may also encounter the syntax for accessing substrings by specifying the offset -and length using the `+` character after a variable. - - The length is specified in parentheses. Specifying an asterisk (`*`) means -that the rest of the remaining string is respected. - - This syntax option -even allows write access to substrings for fixed-length strings. Read -access is possible for both fixed-length and variable-length strings. - - However, this syntax can be confused with the use of tokens in the -context of dynamic programming. -- There are other string functions available for dealing with substrings, such as -[`substring_after`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm), -[`substring_before`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm), -[`substring_from`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm) -and -[`substring_to`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm). - - These functions offer more options in terms of parameters, such as the use of [PCRE regular -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry"), -which are covered below. - -Syntax examples: -``` abap -DATA(s1) = `Lorem ipsum dolor sit amet`. "Type string - -"Extracting substring starting at a specific position -"'len' not specified means the rest of the remaining characters are -"respected -DATA(s2) = substring( val = s1 off = 6 ). "ipsum dolor sit amet - -"Extracting substring with a specific length -"'off' is not specified and has the default value 0. -s2 = substring( val = s1 len = 5 ). "Lorem - -"Specifying both off and len parameters -s2 = substring( val = s1 off = 6 len = 5 ). "ipsum - -DATA(txt) = 'Lorem ipsum dolor sit amet'. "Type c - -"Offset and length specification using the + sign after a variable -DATA(ch6) = txt+0(5). "Lorem - -"* means respecting the rest of the remaining string -DATA(ch7) = txt+12(*). "dolor sit amet - -CLEAR txt+11(*). "Lorem ipsum - -txt+0(5) = 'Hallo'. "Hallo ipsum dolor sit amet - -"Further string functions -s1 = `aa1bb2aa3bb4`. - -"Extracting a substring ... -"... after a specified substring -s2 = substring_after( val = s1 sub = `aa` ). "1bb2aa3bb4 (only the first occurrence is respected) - -"... after a specified substring specifying the occurence in a string -"and restricting the length -s2 = substring_after( val = s1 sub = `aA` occ = 2 len = 4 case = abap_false ). "3bb4 - -"... before a specified substring -s2 = substring_before( val = s1 sub = `b2` ). "aa1b - -"... from a specified substring on. It includes the substring specified -"in sub. len/off and other parameters are possible. -s2 = substring_from( val = s1 sub = `a3` ). "a3bb4 - -"... up to a specified substring. It includes the substring specified -"in sub. len/off and other parameters are possible. -s2 = substring_to( val = s1 sub = `3b` ). "aa1bb2aa3b -``` - -

⬆️ back to top

- -## Searching and Replacing - -- In ABAP, there are many ways to perform search and replace -operations on strings. These include the use of [comparison -operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") -or the ABAP statements -[`FIND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm) -and -[`REPLACE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace.htm), -or the more modern built-in string functions -[`find`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) -and -[`replace`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreplace_functions.htm), -among others, with their considerable number of additions and parameters. -- Many of these options support rather simple operations -on single characters only or more complex, pattern-based -operations on character sequences using [PCRE regular -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry"). - -

⬆️ back to top

- -### Searching for Specific Characters - -- You can use the [comparison - operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") - [`CA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains any) or its negation - [`NA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains not any) in [comparison - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry") - to determine whether any character of a given character set is contained - in a string. Such an expression is true if at least one character is - found. - - The search is case-sensitive. - - The system variable `sy-fdpos` contains the offset of - the first character found. If nothing is found, - `sy-fdpos` contains the length of the string. - - Note that offset 0 represents the very first position. -- The string functions - [`find_any_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) - and its negation - [`find_any_not_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) - return the offset of the occurrence of any character contained in a - substring. They are special variants of the string function `find`, which is shown below. - - If nothing is found, the value -1 is returned. - - Other optional parameters are possible. For example, the - specification of `occ` determines the search - direction, i.e. a positive value means that the search is performed - from left to right. A negative value means to search from right - to left. -- If you are not interested in the position of characters, but rather how - often they occur in a string, you can use the string function - [`count`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencount_functions.htm), as well as the special variants `count_any_of` and its negation `count_any_not_of`. -- To determine whether a string contains only a certain set of characters, - you can use the comparison operators - [`CO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains only) or its negation - [`CN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains not only) in comparison expressions. - - For `CO`, a comparison is true if the left operand - contains only characters that are also contained in the right - operand. If the comparison returns false, you can use `sy-fdpos` to get the position - of the first character from text that is not contained in the - character. - - For `CN`, a - comparison is true if a string contains characters other than those in the character set. - -Syntax examples: -``` abap -DATA(s1) = `cheers`. -IF s1 CA `aeiou` ... "true, sy-fdpos = 2 -IF s1 NA `xyz`... "true, sy-fdpos = 6 - -IF s1 CO `rs` ... "false, sy-fdpos = 0 -IF s1 CN `cheers` ... "false, sy-fdpos = 6 -``` - -Built-in functions: - -``` abap -"Note that the functions may contain more parameters than those covered in the snippet. -DATA(str) = `Pieces of cakes.`. -DATA res TYPE i. - -"find_end returns the sum of the offset of the occurrence -res = find_end( val = str sub = `of` ). "9 - -"find_any_of returns the offset of the occurrence of any character contained in substring -"The search is always case-sensitive. -res = find_any_of( val = str sub = `x523z4e` ). "2 (character e is found) -res = find_any_of( val = str sub = `zwq85t` ). "-1 - -"find_any_not_of: Negation of the one above -"The search is always case-sensitive. -res = find_any_not_of( val = str sub = `ieces` ). "0 (very first character in the searched string) -res = find_any_not_of( val = str sub = `P` ). "1 - -"count returns the number of all occurrences -res = count( val = str sub = `e` ). "3 -res = count( val = str sub = `x` ). "0 - -"count_any_of -res = count_any_of( val = str sub = `x523z4e` ). "3 -res = count_any_of( val = str sub = `eco` ). "6 - -"count_any_not_of -res = count_any_not_of( val = str sub = `fP` ). "14 -res = count_any_not_of( val = str sub = `Piecs ofak.` ). "0 -``` - - -

⬆️ back to top

- -### Replacing Specific Characters in Strings - -- You can use the string function -[`translate`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentranslate_functions.htm) -to replace certain characters with others. - - The -`from` parameter specifies the characters to be placed in a string, and -the `to` parameter specifies the target characters. - - Note: The -replacement is performed as follows: Each character specified in -`from` is replaced by the character in `to` that is at -the same position, i.e. the second character in `from` is -replaced by the second character specified in `to`. If there is -no equivalent in `to`, the character in `from` is -removed from the result. -- You can use -[`TRANSLATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptranslate.htm) -statements to perform replacements directly on the source field. - -Syntax examples: -``` abap -DATA(s1) = `___abc_def_____ghi_`. -DATA(s2) = translate( val = s1 from = `hi_` to = `##` ). "abcdefg## -s2 = translate( val = s1 from = `_` to = `##` ). "###abc#def#####ghi# - -"TRANSLATE statement. The value after USING is interpreted as a string composed of character pairs. -"Starting with the first pair, a search is performed in text for the -"first character in every pair and each occurrence is replaced with the -"second character of the pair. -TRANSLATE s1 USING `_.a#g+`. "...#bc.def.....+hi. -``` - -

⬆️ back to top

- -### Searching for Substrings in Strings (and Tables) - -- For simple substring searches, you can use the [comparison - operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") - [`CS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains string) or its negation - [`NS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) - (contains no string) in [comparison - expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry"). - The search is not case-sensitive. -- The system variable - `sy-fdpos` contains the offset of the found substring. If - the substring is not found, `sy-fdpos` contains the length - of the searched string. - -``` abap -DATA(s3) = `cheers`. - -IF s3 CS `rs` ... "true, sy-fdpos = 4 (offset) - -IF s3 CS `xy`... "false, sy-fdpos = 6 (length of string) - -IF s3 NS `ee`... "false, sy-fdpos = 2 (offset) - -IF s3 NS `xy`... "true, sy-fdpos = 6 (length of string) -``` - -For more complex and iterative searches, you may want to use `FIND` statements or the string functions below. - -- `FIND` - - Used to search for a character sequence. - - Has a rich set of additions, a selection of which is covered in this cheat sheet. See [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm) for more information. Byte string processing is not included (there are special additions). - - Sets the system fields `sy-subrc`: 0 (search pattern found at least once) or 4 (search pattern not found). - -Syntax Overview (see the syntax diagram in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm)): - -``` abap -FIND - FIRST OCCURRENCE OF "(or) ALL OCCURRENCES OF - "1. Only the first occurrence is searched - "2. All occurrences are searched - "Note: If none of these two additions is specified, only the first occurrence is searched for. - - SUBSTRING some_substring "(or) PCRE some_regex - "1. Searching for exactly one string, specifying SUBSTRING is optional (e.g. for emphasis); - " some_substring is a character-like operand; note: Trailing blanks are not ignored if it is of type string - "2. Searching for a substring matching a regular expression; only the PCRE addition should be used; - " some_regex = character-like operand; note: PCRE syntax is compiled in an extended mode, i.e. unescaped whitespaces - " are ignored; if the regex is too complex, a catchable exception of the class CX_SY_REGEX_TOO_COMPLEX is raised - -IN - SECTION - OFFSET off - LENGTH len - OF - "- Restricting the search to a specific section from an offset specified in off with the length len - "- When using SECTION, at least one of the two options must be specified - " - No OFFSET specification: offset 0 is used implicitly - " - No LENGTH specification: search from specified offset to end of string - " - Note: off and len are of type i; it must be a positive integer value; - " exception: len = -1 (same effect as not using the LENGTH addition) - "- Without the addition SECTION ... OF, the entire data object dobj is searched - -"Character-like data object -dobj - - "Further additional options for advanced evaluation options: - "Specifying whether the search is case-sensitive; not specified means RESEPECTING CASE by default - RESPECTING CASE "(or) IGNORING CASE - - "Determining the number of sequences found, number stored in cnt that is of type i (e.g. a variable declared inline) - "When searching for the first occurrence, the value is always 1 (not found -> 0) - MATCH COUNT cnt - - "Determining position of sequences found - "Note: off holds the position of the last occurrence when searching for all occurrences and if - "there are multiple occurrences (not found -> 0 or the previous value of a finding is retained). - MATCH OFFSET off - - "Determining the length of sequences found - "Note: Similar to above, not finding an occurrence means 0 for len or the previous value of a finding is retained - MATCH LENGTH len - - "Storing offset, length, submatches (only relevant for regular expressions) information in a table or a structure - "tab: of type MATCH_RESULT_TAB; especially for using with ALL OCCURRENCES - "struc: of type MATCH_RESULT; especially for using with FIRST OCCURRENCE - "Note on submatches: table of type SUBMATCH_RESULT_TAB; holds offset and length information of substrings of occurrences - "that are stored in subgroup registers of regular expressions; in FIND IN TABLE statements, the additional component LINE - "is available - RESULTS tab "(or) RESULTS struc - - "Storing content of subgroup register of a regular expression in character-like data objects; - "only to be used if a regular expression pattern is specified. - "Note: Only the last occurrence is evaluated when using ALL OCCURRENCES; the number of the operands specified should match - "the number of subgroups specified - SUBMATCHES sub1 sub2 ... -. -``` - -Examples: - -``` abap -"Note: The code snippets mainly use inline declarations. - -DATA(str) = `She sells seashells by the seashore.`. - -"Determining if a substring is found -"Simple find statement -FIND `se` IN str. - -IF sy-subrc = 0. - "found -ELSE. - "not found -ENDIF. - -"Addition SUBSTRING is optional -FIND SUBSTRING `hi` IN str. - -IF sy-subrc = 0. - "found -ELSE. - "not found -ENDIF. - -"The following examples use the additions MATCH COUNT and MATCH OFFSET to determine -"the number of occurrences and offset - -"Addition FIRST OCCURRENCE OF: Explicit specification to search for the first occurrence -FIND FIRST OCCURRENCE OF `se` IN str - MATCH COUNT DATA(cnt2) "1 (always 1 when searching and finding the first occurrence) - MATCH OFFSET DATA(off2). "4 - -"Omitting FIRST OCCURRENCE OF and ALL OCCURRENCES OF addition means searching for the -"first occurrence by default; same effect as the previous statement -FIND `se` IN str - MATCH COUNT DATA(cnt1) "1 - MATCH OFFSET DATA(off1). "4 - -"Addition ALL OCCURRENCES: Searching for all occurrences -FIND ALL OCCURRENCES OF `se` IN str - MATCH COUNT DATA(cnt3) "3 - MATCH OFFSET DATA(off3). "27 (value for the last occurrence) - -"Addition IN SECTION ... OF: -"Searching in a specified section; both additions OFFSET and LENGTH are specified -FIND ALL OCCURRENCES OF `se` - IN SECTION OFFSET 9 LENGTH 5 OF str - MATCH COUNT DATA(cnt4) "1 - MATCH OFFSET DATA(off4). "10 - -"Only LENGTH specified (OFFSET is 0 by default) -FIND ALL OCCURRENCES OF `se` - IN SECTION LENGTH 7 OF str - MATCH COUNT DATA(cnt5) "1 - MATCH OFFSET DATA(off5). "4 - -"Only OFFSET specified (LENGTH: up to end of string) -FIND ALL OCCURRENCES OF `se` - IN SECTION OFFSET 7 OF str - MATCH COUNT DATA(cnt6). "2 - -"Another string to be searched -DATA(str_abap) = `abap ABAP abap`. - -"Further additional options for advanced evaluation options - -"Specifying the case-sensitivity of the search -"Not specifying the CASE addition means RESPECTING CASE is used by default. -"Here, it is explicitly specified. -FIND FIRST OCCURRENCE OF `A` IN str_abap - MATCH OFFSET DATA(off7) "5 - RESPECTING CASE. - -"Making search case-insensitive -FIND FIRST OCCURRENCE OF `A` IN str_abap - MATCH OFFSET DATA(off8) "0 - IGNORING CASE. - -"MATCH LENGTH addition -"The example uses a regular expression: Non-greedy search for -"a substring starting with lower case a up to an upper case P -FIND FIRST OCCURRENCE OF PCRE `a.*?P` IN str_abap - MATCH LENGTH DATA(len8) "9 - RESPECTING CASE. - -"RESULTS addition -"Example: Because of using ALL OCCURRENCES, the data object declared inline automatically -"has the type match_result_tab -FIND ALL OCCURRENCES OF `ab` IN str_abap - RESULTS DATA(res9) - IGNORING CASE. - -"3 entries in table res9 (tables in SUBMATCHES are initial since no regular expression is used) -"line: always 0 (it's not a table); length: always 2 (search for concrete occurrence of `se`) -"1. line: 0, offset: 0, length: 2, submatches: (initial) -"2. line: 0, offset: 5, length: 2, ... -"3. line: 0, offset: 10, length: 2, ... - -"Example: Because of using FIRST OCCURRENCE, the data object declared inline automatically -"has the type match_result -FIND FIRST OCCURRENCE OF `ab` IN str_abap - RESULTS DATA(res10) - IGNORING CASE. - -"res10: line: 0, offset: 0, length: 2, submatches: (initial) -``` - -You can use [`FIND ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_itab.htm) statements to search for substrings in internal tables (standard tables without secondary table keys; with character-like line type) line by line. - -``` abap -DATA(str_table) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). - -"Finding all occurrences in a table -"Note: res_tab is of type match_result_tab -"You can also restrict the search range in an internal table; see an example in REPLACE ... IN TABLE -FIND ALL OCCURRENCES OF `Z` - IN TABLE str_table - RESULTS DATA(res_tab) - RESPECTING CASE. - -"4 entries in table res_tab (tables in SUBMATCHES are initial since no regular expression is used) -"1. line: 1, offset: 1, length: 1, submatches: (initial) -"2. line: 1, offset: 4, length: 1, ... -"3. line: 2, offset: 2, length: 1, ... -"4. line: 3, offset: 0, length: 1, ... - -"Finding the first occurrence in a table -"Note: res_struc, which is declared inline here, is of type match_result -FIND FIRST OCCURRENCE OF `Z` - IN TABLE str_table - RESULTS DATA(res_struc) - RESPECTING CASE. - -"Entries in structure res_struc -"line: 1, offset: 1, length: 1, submatches: (initial) - -"Alternative to the statement above (storing the information in individual data objects) -FIND FIRST OCCURRENCE OF `Z` - IN TABLE str_table - MATCH LINE DATA(line) "1 - MATCH OFFSET DATA(off) "1 - MATCH LENGTH DATA(len) "1 - RESPECTING CASE. -``` - -**Built-in search functions** -- Built-in search functions, such as `find`, are available for searching strings. -- They return a return value of type i and contain multiple (optional) parameters. -- `FIND` covers the same functionality and more with the many addition options. -- For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) - -Parameters of the `find` function: -- `val`: - - Character-like data object - - Note: If a fixed length string is specified, any trailing blanks are ignored. -- `sub`: - - Contains what is searched for - - A character like expression position; expects arguments with elementary types - - Similar to above, trailing blanks are ignored in fixed length strings -- `case`: - - Search is case-sensitive by default -- `occ`: - - Specifies the occurrence of a match - - Must be of type `i` - - Values: - - 1: default value, searches for the first occurrence from the left - - any positive value: searches for the nth occurrence from the left - - any negative value: searches for the nth occurrence from the right - - 0: raises an exception (`CX_SY_STRG_PAR_VAL`), note: in the context of the `replace` function, 0 means replace all occurrences - - Note: Specifying `occ` affects the default values of `off` and `len` -- `off`: - - Specifies the offset - - Must be of type `i` - - The default value is 0 (search from the beginning of the string) - - Exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised for a negative offset specified and an offset that is longer than the searched string -- `len`: - - Specifies the length - - Must be of type `i` - - The default value is the length of the string (minus a defined offset in `off`) - - The exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised if the offset is negative and a range is not contained in the searched string -- `pcre`: Regular expression - -``` abap -DATA(str) = `Pieces of cakes.`. -DATA res TYPE i. - -"Searching for substring -"Returns offset of substring found -res = find( val = str sub = `ca` ). "10 - -"Substring not found returns -1 -res = find( val = str sub = `xy` ). "-1 - -"Actual parameter of sub must not be initial when using the find function -TRY. - res = find( val = str sub = `` ). - CATCH cx_sy_strg_par_val. - ... -ENDTRY. - -"The search is case-sensitive by default -res = find( val = str sub = `OF` ). "-1 -"Making search case-insensitive -res = find( val = str sub = `OF` case = abap_false ). "7 - -"Specifying occ -res = find( val = str sub = `c` ). "3 -res = find( val = str sub = `c` occ = 2 ). "10 -res = find( val = str sub = `e` occ = -1 ). "13 -res = find( val = str sub = `e` occ = -3 ). "2 - -"Specifying off and len -"Specifying a subarea in which a string is searched -res = find( val = str sub = `e` off = 5 ). "13 -res = find( val = str sub = `e` off = 5 len = 7 ). "-1 -res = find( val = str sub = `e` len = 2 ). "-1 - -TRY. - res = find( val = str sub = `e` off = 5 len = 15 ). - CATCH cx_sy_range_out_of_bounds. - ... -ENDTRY. -``` - -

⬆️ back to top

- -### Replacing Substrings in Strings (and Tables) - -- [`REPLACE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace.htm) and [`REPLACE ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace_itab.htm) statements have a similar syntax as `FIND` and `FIND ... IN TABLE` statements. Refer to the ABAP Keyword Documentation for all possible additions. The following code snippets cover a selection. -- `sy-subrc` is set: 0 (search pattern or section was replaced by the specified content, result was not truncated on the right), 2 (search pattern or section was replaced, result was truncated on the right), 4 (search pattern was not found). -- `REPLACE` statements can be used to directly replace strings (including substrings, which is not possible with the string function). - -``` abap -"Examples for pattern-based replacements in which data objects are searched for character strings -"specified in a pattern and the occurrences are replaced - -DATA(str_original) = `abap ABAP abap`. -DATA(str) = str_original. - -"Simple REPLACE statement -"Omitting the FIRST OCCURRENCE and ALL OCCURRENCES OF additions means -"replacing the first occurrence by default. -REPLACE `ab` IN str WITH `##`. "##ap ABAP abap - -str = str_original. - -"Addition SUBSTRING is optional -REPLACE SUBSTRING `ab` IN str WITH `##`. "##ap ABAP abap - -str = str_original. - -"Addition FIRST OCCURRENCE OF: Explicit specification to replace the -"first occurrence; same effect as the statements above -REPLACE FIRST OCCURRENCE OF `ab` IN str WITH `##`. "##ap ABAP abap - -str = str_original. - -"Addition ALL OCCURRENCES OF: All occurrences are replaced -"Note that the replacement is case-sensitive by default. -REPLACE ALL OCCURRENCES OF `ab` IN str WITH `##`. "##ap ABAP ##ap - -str = str_original. - -"Further additional options for advanced evaluation options - -"IGNORING CASE addition: Making replacements case-insensitive -REPLACE ALL OCCURRENCES OF `ab` - IN str WITH `##` - IGNORING CASE. "##ap ##AP ##ap - -str = str_original. - -"REPLACEMENT COUNT addition -REPLACE ALL OCCURRENCES OF `ab` - IN str WITH `##` - REPLACEMENT COUNT DATA(cnt1) "3 - IGNORING CASE. - -str = str_original. - -"REPLACEMENT OFFSET and LENGTH additions -REPLACE FIRST OCCURRENCE OF `ap` - IN str WITH `##` - REPLACEMENT COUNT DATA(cnt2) "1 (always 1 for replaced first occurrence) - REPLACEMENT OFFSET DATA(off2) "2 - REPLACEMENT LENGTH DATA(len2) "2 - IGNORING CASE. "ab## ABAP abap - -str = str_original. - -"SECTION ... OF addition: Replacing within a specified area -REPLACE ALL OCCURRENCES OF `ap` - IN SECTION OFFSET 4 LENGTH 5 - OF str WITH `##` - REPLACEMENT COUNT DATA(cnt3) "1 - REPLACEMENT OFFSET DATA(off3) "2 - REPLACEMENT LENGTH DATA(len3) "2 - IGNORING CASE. "abap AB## abap - -str = str_original. - -"RESULTS additions with ... -"... ALL OCCURRENCES OF -"Note: repl_tab, which is declared inline here, is of type repl_result_tab -REPLACE ALL OCCURRENCES OF `ap` - IN str WITH `##` - RESULTS DATA(repl_tab) - IGNORING CASE. "ab## AB## ab## - -"repl_tab: -"LINE OFFSET LENGTH -"0 2 2 -"0 7 2 -"0 12 2 - -str = str_original. - -"... FIRST OCCURRENCE OF -"Note: repl_struc, which is declared inline here, is of type repl_result -REPLACE FIRST OCCURRENCE OF `ap` - IN str WITH `##` - RESULTS DATA(repl_struc) - IGNORING CASE. - -"repl_struc: -"LINE OFFSET LENGTH -"0 2 2 -``` - -You can use [`REPLACE SECTION ... OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_section_of.htm) statements for position-based replacements, that is, to replace a section in a string starting at a specified offset for a specified length. - -``` abap -DATA(str_original) = `abap ABAP abap`. -DATA(str) = str_original. - -"OFFSET + LENGTH specified -REPLACE SECTION OFFSET 5 LENGTH 4 OF str WITH `#`. "abap # abap - -str = str_original. - -"Only OFFSET (LENGTH: up to the end of the string) -REPLACE SECTION OFFSET 5 OF str WITH `#`. "abap # - -str = str_original. - -"Only LENGTH (OFFSET: starting from the leftmost position) -REPLACE SECTION LENGTH 6 OF str WITH `#`. "#BAP abap -``` - -Replacements in internal tables with `REPLACE ... IN TABLE`: -``` abap -DATA(str_table_original) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). -DATA(str_table) = str_table_original. - -"Replacing all occurrences in a table -"RESULTS addition: Storing information in an internal table of type repl_result_tab -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - WITH `#` - RESULTS DATA(res_table) - RESPECTING CASE. - -"str_table: a#bz# / cd#ze / #zzf / ghz -"res_table: -"LINE OFFSET LENGTH -"1 1 1 -"1 4 1 -"2 2 1 -"3 0 1 - -str_table = str_table_original. - -"Replacing the first occurrence in a table -"RESULTS addition: Storing information in a structure of type repl_result -REPLACE FIRST OCCURRENCE OF `Z` - IN TABLE str_table - WITH `#` - RESULTS DATA(res_structure) - RESPECTING CASE. - -"str_table: a#bzZ / cdZze / Zzzf / ghz -"res_structure: -"LINE OFFSET LENGTH -"1 1 1 - -str_table = str_table_original. - -"Restricting the search range in an internal table -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - FROM 1 TO 2 - WITH `#` - RESPECTING CASE. - -"str_table: a#bz# / cd#ze / Zzzf / ghz - -str_table = str_table_original. - -"Offsets can be optionally specified (also only the offset of start or end line possible) -REPLACE ALL OCCURRENCES OF `Z` - IN TABLE str_table - FROM 1 OFFSET 3 TO 2 OFFSET 2 - WITH `#` - RESPECTING CASE. - -"str_table: aZbz# / cdZze / Zzzf / ghz -``` - -- The string function -[`replace`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreplace_functions.htm), -allows you to store the result of a substring replacement in a separate -variable. -- What makes it especially powerful is that it -returns a value, so it can be used at almost any [read -positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenread_position_glosry.htm "Glossary Entry"). -- The parameters of the `replace` string functions are similar to those of the `find` function. In addition, there is the `with` parameter for the replacement. Setting `occ` to `0` means that all occurrences are respected for the replacement. - -Syntax examples: -``` abap -DATA(str) = `abap ABAP abap`. -DATA res TYPE string. - -"Note that here only the first occurrence is replaced. -res = replace( val = str sub = `ap` with = `#` ). "ab# ABAP abap - -"Making the search case-insensitive -res = replace( val = str sub = `AB` with = `#` case = abap_false ). "#ap ABAP abap - -"Setting occ -res = replace( val = str sub = `ab` with = `#` occ = 2 case = abap_false ). "abap #AP abap - -"Replacing all occurrences: Setting occ to 0 -res = replace( val = str sub = `ab` with = `#` occ = 0 case = abap_false ). "#ap #AP #ap - -"Negative value for occ: Occurrences are counted from the right -res = replace( val = str sub = `ab` with = `#` occ = -1 ). "abap ABAP #ap - -"Setting off and len for determining a subarea for replacements -"Note: When using off/len, sub and occ cannot be specified. -"Specifying both off and len -res = replace( val = str with = `#` off = 5 len = 3 ). "abap #P abap - -"Specifying only off (len is 0 by default) -res = replace( val = str with = `#` off = 2 ). "ab#ap ABAP abap - -"Note: When specifying only off and not specifying len or len = 0, -"replace works like insert -res = insert( val = str sub = `#` off = 2 ). "ab#ap ABAP abap - -"Specifying only len (off is 0 by default): First segment of length in len is replaced -res = replace( val = str with = `#` len = 3 ). "#p ABAP abap - -"Special case -"- off: equal to the length of the string -"- len: not specified or 0 -"- Result: Value specified for 'with' is appended to the end of the string -res = replace( val = str with = `#` off = strlen( str ) ). "abap ABAP abap# -``` - -## Pattern-Based Searching and Replacing in Strings - -You can perform complex search and replace operations based on -patterns. [PCRE regular -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry") -help you process strings effectively. -> **💡 Note**
-> Do not use [POSIX -regular -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenposix_regex_glosry.htm "Glossary Entry") -anymore, they are obsolete. - -

⬆️ back to top

- -### Simple Pattern-Based Searching Using Comparison Operators - -For simple patterns, you can use the [comparison -operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") -[`CP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) -(conforms to pattern) or its negation -[`NP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) -(does not conform to pattern) in [comparison -expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry") -to determine whether a set of characters is contained in a string that -matches a particular pattern. You can use the following -special characters as patterns: - -| Special Character | Details | -|---|---| -| `*` | Any character sequence (including blanks). | -| `+` | Any character (only one character, including blanks). | -| `#` | Escape character. The following character is marked for an exact comparison. | - -Patterns are not case-sensitive except for characters marked with -`#`. If a pattern is found, the system variable -`sy-fdpos` returns the offset of the first occurrence. -Otherwise, it contains the length of the searched string. -``` abap -DATA(s1) = `abc_def_ghi`. - -"Pattern: f is preceded by any character sequence, must be followed -"by '_' and then followed by any character sequence -IF s1 CP `*f#_*`. ... "true; sy-fdpos = 6 - -"Pattern: 'i' is not followed by another character -IF s1 NP `i+`. ... "true; sy-fdpos = 11 (length of searched string) -``` - -

⬆️ back to top

- -### Complex Searching and Replacing Using Regular Expressions - -#### Excursion: Common Regular Expressions - -There are several ways to perform complex searches in strings using PCRE expressions. They can be quite complex. The following overview shows common PCRE expressions with simple examples. -For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm). - -Characters and character types - -| Expression | Represents | Example Regex | Example String | Matches | Does not Match | -|---|---|---|---|---|---| -| `x` | Specific character | `a` | abcdef | a | Anything else | -| `.` | Anything except a line break | `.` | ab 1# | a, b, the blank, 1, # | ab, 1# | -| `\d` | Any digit (0-9), alternative: `[0-9]` | `\d` | a1-b2 3-4c9 | 1, 2, 3, 4, 9 | a, b, c, the blank and hyphens | -| `\D` | Any non-digit, alternative: `[^0-9]` | `\D` | a1-b2 3-4c9 | a, b, c, the blank and hyphens | 1, 2, 3, 4, 9 | -| `\s` | Any whitespace character such as a blank, tab and new line | `\s` | (hi X ) | The blanks | h, i, X, (, ) | -| `\S` | Any character that is not a whitespace | `\S` | (hi X ) | h, i, X, (, ) | The blanks | -| `\w` | Any word character (letter, digit or the underscore), alternative: `[a-zA-Z0-9_]` | `\w` | (ab 12_c) | a, b, c, 1, 2, _ | (, ), the blank | -| `\W` | Any character that is not a word character, alternative: `[^a-zA-Z0-9_]` | `\W` | (ab 12_c) | (, ), the blank | a, b, c, 1, 2, _ | -| `\` | To include special characters like `[] \ / ^`, use `\` to escape them. Use `\.` to match a period ("."). | `.\.` | ab.cd.ef | a**b.**c**d.**ef | ab**.c**d**.e**f | - -Repetitions and Alternatives - -| Expression | Represents | Example Regex | Example String | Matches | Does not Match | -|---|---|---|---|---|---| -| `x*` | Zero or more repetitions of `x` | `ab*` | abc abbc abbbc a ac | **ab**c **abb**c **abbb**c **a** **a**c | **abc** **abbc** **abbbc** a **ac** | -| `x+` | One or more repetitions of `x` | `ab+` | abc abbc abbbc a ac | **ab**c **abb**c **abbb**c a ac | ... **a** **a**c | -| `x{m,n}` | Between `m` and `n` repetitions of `x` | `ab{2,3}` | abc abbc abbbc a ac | abc **abb**c **abbb**c a ac | **ab**c ... | -| `x{m}` | Exactly `m` repetitions | `ab{3}` | abc abbc abbbc a ac | abc abbc **abbb**c a ac | abc **abb**c ... | -| `x{m,}` | Exactly `m` or more repetitions | `ab{2,}` | abc abbc abbbc a ac | abc **abb**c **abbb**c a ac | **ab**c ... | -| `x?` | Optional `x`, i.e. zero or one time | `ab?` | abc abbc abbbc a ac | **ab**c **ab**bc **ab**bbc **a** **a**c | ... **ac** | -| `x\|y` | Matching alternatives, i. e. `x` or `y` | 1. `b\|2`
2. `b(a\|u)t` | 1. abc 123
2. bit bat but bet | 1. b, 2
2. bat, but | 1. a, c, 1, 3
2. bit, bet | -| `x*?` | `x*` captures greedily, i.e. as much as possible, while `x*?` captures non-greedily, i.e. as few as possible | 1. `bc*?`
2. `a.*?#` | 1. abcd abccccd ab
2. abc#defgh#i | 1. a**b**cd a**b**ccccd a**b**
2. **abc#**defgh#i | 1. a**bc**d a**bcccc**d a**b** (result for `bc*`)
2. **abc#defgh#**i (result for `a.*#`) | -| `x+?` | Same as above: `x+` (greedy), `x+?` (non-greedy) | 1. `bc+?`
2. `<.+?>` | 1. abcd abccccd ab
2. <span>Hallo</span> html. | 1. a**bc**d a**bc**cccd ab
2. **<span>**Hallo**</span>** html. | 1. a**bc**d a**bcccc**d ab (result for `bc+`)
2. **<span>Hallo</span>** html. (result for `<.+>`) | - -Character Sets, Ranges, Subgroups and Lookarounds -| Expression | Represents | Example Regex | Example String | Matches | Does not Match | -|---|---|---|---|---|---| -| `[xy]` | Character set, matches a single character present in the list | `b[iu]` | bit bat but bet | **bi**t bat **bu**t bet | bit **ba**t but **be**t | -| `[x-y]` | Character range, matches a single character in the specified range, note that ranges may be locale-dependent | `a[a-c0-5]` | aa1 ab2 ba3 cac4 da56 a7 |**aa**1 **ab**2 b**a3** c**ac**4 d**a5**6 a7 | aa1 ab2 ba3 cac4 da56 **a7** | -| `[^xy]` | Negation, matches any single character not present in the list | `[^Ap]` | ABap | B, a | A, p | -| `[^x-y]` | Negation, matches any single character not within the range | `[^A-Ca-c1-4]` | ABCDabcd123456 | D, d, 5, 6 | A, B, C, a, b, c, 1, 2, 3, 4 | -| `(...)` | Capturing group to group parts of patterns together | `b(a\|u)t` | bit bat but bet | bat, but | bit, bet | -| `(?=...)` | Positive lookahead, returns characters that are followed by a specified pattern without including this pattern | `a(?=b)` | abc ade | **a**bc ade | abc **a**de | -| `(?!...)` | Negative lookahead, returns characters that are not followed by a specified pattern without including this pattern | `a(?!b)` | abc ade | abc **a**de | **a**bc ade | -| `(?<=...)` | Positive lookbehind, returns characters that are preceded by a specified pattern without including this pattern | `(?<=\s)c` | ab c abcd | ab **c** abcd (it is preceded by a blank) | ab c ab**c**d | -| `(?**c**d (it is not preceded by a blank) | ab **c** abcd | -| `\n` | Backreference, refers to a previous capturing group; n represents the number of the group index that starts with 1 | `(a.)(\w*)\1` | abcdefabghij | **abcdefab**ghij
Note: Capturing group 1 holds `ab` in the example. The second capturing group captures all word characters until `ab` is found. | **ab**cdefabghij | -| `\K` | Resets the starting point of a match, i.e. findings are excluded from the final match | `a.\Kc` | abcd | ab**c**d | **abc**d | - -> **💡 Note**
-> - Subgroups are useful in replacements. By using an expression with `$` and a number, such as `$1`, you can refer to a specific group. For example, you have a string `abcde`. A PCRE expression might be -`(ab|xy)c(d.)`, where two subgroups are specified within two pairs of parentheses. In a replacement pattern, you can refer to the first group with `$1` and the second group with `$2`. Thus, the replacement pattern `$2Z$1` results in `deZab`. -> - `(?:x)` creates a group but it is not captured. Example regular expression: `(?:ab)(ap)`. Example string: 'abap'. It matches 'abap', but `$1` will only contain 'ap'. - -Anchors and Positions - -| Expression | Represents | Example Regex | Example String | Matches | Does not Match | -|---|---|---|---|---|---| -| `^` | Start of line, alternative: `\A` | `^.` or `\A.` | abc def | **a**bc def | abc **d**ef | -| `$` | End of line, alternative: `\Z` | `.$` or `.\Z` | abc def | abc de**f** | **a**bc def | -| `\b` | Start or end of word | 1. `\ba.`
2. `\Dd\b`
3. `\b.d\b` | abcd a12d ed | 1. **ab**cd **a1**2d ed
2. ab**cd** a12d **ed**
3. abcd a12d **ed** | 1. ab**cd** a1**2d** ed
2. abcd a1**2d** ed
3. **abcd** **a12d** ed | -| `\B` | Negation of `\b`, not at the start or end of words | `\Be\B` | see an elefant | s**e**e an el**e**fant | s**ee** an **e**lefant | - -

⬆️ back to top

- -#### Searching Using Regular Expressions - -- Multiple string functions support PCRE expressions by offering the - `pcre` parameter, which you can use to specify such an expression. -`FIND` and `REPLACE` statements support regular -expressions with the `PCRE` addition. -- The string function -[`match`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmatch_functions.htm) -works only with regular expressions. It returns a substring that -matches a regular expression within a string. -- For comparisons, you can -also use the [predicate -function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_function_glosry.htm "Glossary Entry") -[`matches`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmatches_functions.htm), which returns true or false if a string matches a given pattern or not. - -Syntax examples: -``` abap -DATA(s1) = `Cathy's black cat on the mat played with Matt.`. - -"Determining the position of the first occurrence -"Here, the parameter occ is 1 by default. -DATA(int) = find( val = s1 pcre = `at.` ). "1 - -"Determining the number of all occurrences. -"Respects all 'a' characters not followed by 't', all 'at' plus 'att' -int = count( val = s1 pcre = `at*` ). "6 - -"Respects all 'at' plus 'att' -int = count( val = s1 pcre = `at+` ). "4 - -"Extracting a substring matching a given pattern -DATA(s2) = match( val = `The email address is jon.doe@email.com.` - pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ). "jon.doe@email.com - -"Predicate function matches -"Checking the validitiy of an email address -IF matches( val = `jon.doe@email.com` - pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ). "true -... -ENDIF. - -"Examples with the FIND statement -"SUBMATCHES addition: Storing submatches in variables -"Pattern: anything before and after ' on ' -FIND PCRE `(.*)\son\s(.*)` IN s1 IGNORING CASE SUBMATCHES DATA(a) DATA(b). -"a: 'Cathy's black cat' / b: 'the mat played with Matt.'. - -"Determining the number of letters in a string -FIND ALL OCCURRENCES OF PCRE `[A-Za-z]` IN s1 MATCH COUNT DATA(c). "36 - -"Searching in an internal table and retrieving line, offset, length information -DATA(itab) = value string_table( ( `Cathy's black cat on the mat played with the friend of Matt.` ) ). -"Pattern: 't' at the beginning of a word followed by another character -FIND FIRST OCCURRENCE OF PCRE `\bt.` IN TABLE itab - IGNORING CASE MATCH LINE DATA(d) MATCH OFFSET DATA(e) MATCH LENGTH DATA(f). "d: 1, e: 21, f: 2 -``` -

⬆️ back to top

- -##### Excursion: System Classes for Regular Expressions - -- You can create an object-oriented representation of regular expressions using the `CL_ABAP_REGEX` system class. -- For example, the `CREATE_PCRE` method creates instances of regular expressions with PCRE syntax. -- The instances can be used, for example, with the `CL_ABAP_MATCHER` class, which applies the regular expressions. -- A variety of methods and parameters can be specified to accomplish various things and to further specify the handling of the regular expression. -- More information can be found [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_system_classes.htm) and in the class documentation (choose F2 on the class in ADT). - - -``` abap -DATA(str) = `a1 # B2 ? cd . E3`. - -"Creating a regex instance for PCRE regular expressions -"In the example, regex_inst has the type ref to cl_abap_regex. -DATA(regex_inst) = cl_abap_regex=>create_pcre( pattern = `\D\d` "any-non digit followed by a digit - ignore_case = abap_true ). - -"Creating an instance of CL_ABAP_MATCHER using the method CREATE_MATCHER of the class CL_ABAP_REGEX -"You can also specify internal tables with the 'table' parameter and more. -DATA(matcher) = regex_inst->create_matcher( text = str ). - -"Finding all results using the 'find_all' method -"In the example, result has the type match_result_tab containing the findings. -DATA(result) = matcher->find_all( ). - -"Using method chaining -DATA(res) = cl_abap_regex=>create_pcre( pattern = `\s\w` "any blank followed by any word character - ignore_case = abap_true )->create_matcher( text = str )->find_all( ). -``` - -

⬆️ back to top

- -#### Replacing Using Regular Expressions - -- To perform replacement operations using regular expressions, you can use both -the string function `replace` and `REPLACE` statements with the `pcre` parameter or the `PCRE` addition. -- Like the `find` function, among others, and -`FIND` statements, the `replace` function and -`REPLACE` statements offer a number of parameters and additions that you can use to further restrict the area to be replaced. -- For more detailed information, refer to the ABAP -Keyword Documentation. -- The executable example covers many of the PCRE expressions listed above. - -Syntax examples: -``` abap -DATA(s1) = `ab apppc app`. -DATA s2 TYPE string. - -"Replaces 'p' with 2 - 4 repetitions, all occurences -s2 = replace( val = s1 pcre = `p{2,4}` with = `#` occ = 0 ). "ab a#c a# - -"Replaces any single character not present in the list, all occurences -s2 = replace( val = s1 pcre = `[^ac]` with = `#` occ = 0 ). " "a##a###c#a## - -"Replaces first occurence of a blank -s2 = replace( val = s1 pcre = `\s` with = `#` ). "ab#apppc app - -"Greedy search -"The pattern matches anything before 'p'. The matching is carried out as -"often as possible. Hence, in this example the search stretches until the -"end of the string since 'p' is the final character, i. e. this 'p' and -"anything before is replaced. -s2 = replace( val = s1 pcre = `.*p` with = `#` ). "# - -"Non-greedy search -"The pattern matches anything before 'p'. The matching proceeds until -"the first 'p' is found and does not go beyond. It matches as few as -"possible. Hence, the first found 'p' including the content before -"is replaced. -s2 = replace( val = s1 pcre = `.*?p` with = `#` ). "#ppc app - -"Replacements with subgroups -"Replaces 'pp' (case-insensitive here) with '#', the content before and after 'pp' is switched -s2 = replace( val = s1 - pcre = `(.*?)PP(.*)` - with = `$2#$1` - case = abap_false ). "pc app#ab a - -"Changing the source field directly with a REPLACE statement; same as above -REPLACE PCRE `(.*?)PP(.*)` IN s1 WITH `$2#$1` IGNORING CASE. "pc app#ab a -``` - -

⬆️ back to top

- -## More String Functions - -### Checking the Similarity of Strings - -- [`distance`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendistance_functions.htm) returns the Levenshtein distance between two strings, which reflects their similarity. -- Unlike other string functions, the return value has the type `i`. -- Optional addition `max`: Positive integer. The calculation of the Levenshtein distance will stop if the calculated value is greater than this integer. - -```abap -DATA(str_to_check) = `abap`. -DATA(dist1) = distance( val1 = str_to_check val2 = `abap` ). "0 -DATA(dist2) = distance( val1 = str_to_check val2 = `axbap` ). "1 -DATA(dist3) = distance( val1 = str_to_check val2 = `yabyyapy` ). "4 -DATA(dist4) = distance( val1 = str_to_check val2 = `zabapzzzzzzzzzzzz` max = 5 ). "5 - -"If the value of max is 0 or less, an exception is raised. -TRY. - DATA(dist5) = distance( val1 = str_to_check val2 = `#ab#ap#` max = 0 ). - CATCH cx_sy_strg_par_val. - ... -ENDTRY. -``` - -### Repeating Strings -- [`repeat`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrepeat_functions.htm) returns a string that contains the content of a specified string for parameter `val` as many times as specified in the parameter `occ`. -- An empty string is returned when `occ` has the value 0 or `val` is empty. - -```abap -DATA(repeat1) = repeat( val = `abap` occ = 5 ). "abapabapabapabapabap -DATA(repeat2) = |#{ repeat( val = ` ` occ = 10 ) }#|. "# # -DATA(repeat3) = COND #( WHEN repeat( val = `a` occ = 0 ) = `` THEN `Y` ELSE `Z` ). "Y (initial value returned) - -"If occ has a negative value, an exception is raised. -TRY. - DATA(repeat4) = repeat( val = `X` occ = -3 ). - CATCH cx_sy_strg_par_val. - ... -ENDTRY. -``` - -

⬆️ back to top

- -### Returning the Smallest/Biggest of a Set of Character-Like Arguments -- [`cmin/cmax`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencmax_cmin_functions.htm) returns a string that contains the content of the smallest or biggest of a set of character-like arguments -- 'Set' means at least two arguments and a maximum of nine argeuments are passed (`valn` operators) for comparison. -- The comparison is made from left to right, and the first different character found determines the smaller or bigger argument. - -```abap -DATA(min) = cmin( val1 = `zzzzzzz` - val2 = `zzazzzzzzzz` "smallest argument - val3 = `zzzzabc` ). - -DATA(max) = cmax( val1 = `abcdef` "biggest argument - val2 = `aaghij` - val3 = `aaaaklmn` - val4 = `aaaaaaopqrs` - val5 = `aaaaaaaaaatuvwxy` - val6 = `aaaaaaaaaaaaaz` ). -``` - -

⬆️ back to top

- -### Escaping Special Characters -- [`escape`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenescape_functions.htm) returns a string that is provided for the `val` parameter by escaping special characters according to the specification in the `format` parameter. -- Suitable values for the `format` parameter (which expects a data object of type `i`) are available in the `CL_ABAP_FORMAT` class (the constants starting with `E_`). -- Special rules apply to different contexts, such as URLS and JSON. Also note the prevention of Cross Site Scripting (XSS) attacks on web applications. For more information, refer to the [documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenescape_functions.htm). - -```abap -"Context: URLs -DATA(esc1) = escape( val = '...test: 5@8...' - format = cl_abap_format=>e_url_full ). -"...test%3A%205%408... - -"Context: JSON -DATA(esc2) = escape( val = 'some "test" json \ with backslash and double quotes' - format = cl_abap_format=>e_json_string ). -"some \"test\" json \\ with backslash and double quotes - - -"Context: String templates -DATA(esc3) = escape( val = 'Special characters in string templates: |, \, {, }' - format = cl_abap_format=>e_string_tpl ). -"Special characters in string templates: \|, \\, \{, \} - -"Invalid value for the format parameter -TRY. - DATA(esc4) = escape( val = 'This will raise an exception due to an invalid format value.' - format = 123 ). - CATCH cx_sy_strg_par_val. -ENDTRY. -``` - -

⬆️ back to top

- -## Excursion: String Processing Using the XCO Library -The Extension Components Library (XCO) library provides [released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreleased_api_glosry.htm) and offers various development utilities. Find more information [here](https://help.sap.com/docs/btp/sap-business-technology-platform/overview-of-xco-modules). The following code snippet demonstrates several methods of the `XCO_CP` class that deal with string processing. - -```abap -"--------- Extracting a substring from a string --------- -DATA(some_string) = `abcdefghijklmnopqrstuvwxyz`. - -"Creating an encapsulation of a string using XCO -DATA(str) = xco_cp=>string( some_string ). - -"Using the FROM and TO methods, you can determine -"the character position. Note that the value includes the -"character at the position specified. -"The character index pattern for the example string above -"is (the string has 26 characters in total): -"a = 1, b = 2, c = 3 ... z = 26 -"a = -26, b = -25, c = -24 ... z = -1 -"Providing a value that is out of bounds means that -"the first (or the last) character of the string is used -"by default. -"Note: When combining FROM and TO, e.g. with method -"chaining ...->from( ...)->to( ... ), note that another -"instance is created with the first 'from', and another -"character index pattern is created based on the new -"and adjusted string value. - -"bcdefghijklmnopqrstuvwxyz -DATA(sub1) = str->from( 2 )->value. - -"defghijklmnopqrstuvwxyz -DATA(sub2) = str->from( -23 )->value. - -"vwxyz -DATA(sub3) = str->from( -5 )->value. - -"abcde -DATA(sub4) = str->to( 5 )->value. - -"ab -DATA(sub5) = str->to( -25 )->value. - -"Result of 1st 'from' method call: bcdefghijklmnopqrstuvwxyz -"Based on this result, the 'to' method call is -"applied. -"bcdefg -DATA(sub6) = str->from( 2 )->to( 6 )->value. - -"Result of 1st 'to' method call: abcdefghijklmnopq -"Based on this result, the 'from' method call is -"applied. -"defghijklmnopq -DATA(sub7) = str->to( -10 )->from( 4 )->value. - -"Values that are out of bounds. -"In the example, the first and last character of the -"string are used. -"abcdefghijklmnopqrstuvwxyz -DATA(sub8) = str->from( 0 )->to( 100 )->value. - -"--------- Splitting and joining --------- - -"Splitting a string into a string table -DATA(str_table) = xco_cp=>string( `Hello.World.ABAP` )->split( `.` )->value. -"Hello -"World -"ABAP - -"Concatenating a string table into a string; specifying a delimiter -str_table = VALUE #( ( `a` ) ( `b` ) ( `c` ) ). -"a, b, c -DATA(conc_str1) = xco_cp=>strings( str_table )->join( `, ` )->value. - -"Concatenating a string table into a string; specifying a delimiter and -"reversing the table order -"c / b / a -DATA(conc_str2) = xco_cp=>strings( str_table )->reverse( )->join( ` / ` )->value. - -"--------- Prepending and appending strings --------- -DATA(name) = xco_cp=>string( `Max Mustermann` ). - -"Max Mustermann, Some Street 1, 12345 Someplace -DATA(address) = name->append( `, Some Street 1, 12345 Someplace` )->value. - -"Mr. Max Mustermann -DATA(title) = name->prepend( `Mr. ` )->value. - -"--------- Transforming to lowercase and uppercase --------- -"ABAP -DATA(to_upper) = xco_cp=>string( `abap` )->to_upper_case( )->value. - -"hallo world -DATA(to_lower) = xco_cp=>string( `HALLO WORLD` )->to_lower_case( )->value. - -"--------- Checking if a string starts/ends with a specific string --------- -DATA check TYPE string. -DATA(str_check) = xco_cp=>string( `Max Mustermann` ). - -"yes -IF str_check->ends_with( `mann` ). - check = `yes`. -ELSE. - check = `no`. -ENDIF. - -"no -IF str_check->starts_with( `John` ). - check = `yes`. -ELSE. - check = `no`. -ENDIF. - -"--------- Converting strings to xstrings using a codepage --------- -"536F6D6520737472696E67 -DATA(xstr) = xco_cp=>string( `Some string` )->as_xstring( xco_cp_character=>code_page->utf_8 )->value. - -"--------- Camel case compositions and decompositions with split and join operations --------- -"Pascal case is also possible -"someValue -DATA(comp) = xco_cp=>string( `some_value` )->split( `_` )->compose( xco_cp_string=>composition->camel_case )->value. - -"Camel case decomposition -"some_value -DATA(decomp) = xco_cp=>string( `someValue` )->decompose( xco_cp_string=>decomposition->camel_case )->join( `_` )->value. - -"--------- Matching string against regular expression --------- -DATA match TYPE string. - -"yes -IF xco_cp=>string( ` 1` )->matches( `\s\d` ). - match = 'yes'. -ELSE. - match = 'no'. -ENDIF. - -"no -IF xco_cp=>string( ` X` )->matches( `\s\d` ). - match = 'yes'. -ELSE. - match = 'no'. -ENDIF. -``` - -

⬆️ back to top

- -## Executable Example - -[zcl_demo_abap_string_proc](./src/zcl_demo_abap_string_proc.clas.abap) - -> **💡 Note**
-> - The executable example ... -> - covers the following topics: -> - Creating strings and assigning values -> - String templates -> - Operations with strings operations: chaining, concatenating, splitting, modifying -> - Searching and replacing -> - Regular expressions -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + +# String Processing + +- [String Processing](#string-processing) + - [Introduction](#introduction) + - [Data Types for Character Strings](#data-types-for-character-strings) + - [Declaring Character-Like Data Objects](#declaring-character-like-data-objects) + - [Assigning Values](#assigning-values) + - [String Templates](#string-templates) + - [Determining the Length of Strings](#determining-the-length-of-strings) + - [Concatenating Strings](#concatenating-strings) + - [Splitting Strings](#splitting-strings) + - [Modifying Strings](#modifying-strings) + - [Transforming to Lowercase and Uppercase](#transforming-to-lowercase-and-uppercase) + - [Shifting Content](#shifting-content) + - [Condensing Strings](#condensing-strings) + - [Reversing Strings](#reversing-strings) + - [Inserting Substrings into Strings](#inserting-substrings-into-strings) + - [Overlaying Content](#overlaying-content) + - [Processing Substrings](#processing-substrings) + - [Searching and Replacing](#searching-and-replacing) + - [Searching for Specific Characters](#searching-for-specific-characters) + - [Replacing Specific Characters in Strings](#replacing-specific-characters-in-strings) + - [Searching for Substrings in Strings](#searching-for-substrings-in-strings) + - [Searching for Substrings in Tables](#searching-for-substrings-in-tables) + - [String Function find](#string-function-find) + - [Replacing Substrings in Strings](#replacing-substrings-in-strings) + - [Replacing Substrings in Tables](#replacing-substrings-in-tables) + - [String Function replace](#string-function-replace) + - [Pattern-Based Searching and Replacing in Strings](#pattern-based-searching-and-replacing-in-strings) + - [Simple Pattern-Based Searching Using Comparison Operators](#simple-pattern-based-searching-using-comparison-operators) + - [Complex Searching and Replacing Using Regular Expressions](#complex-searching-and-replacing-using-regular-expressions) + - [Excursion: Common Regular Expressions](#excursion-common-regular-expressions) + - [Searching Using Regular Expressions](#searching-using-regular-expressions) + - [System Classes for Regular Expressions](#system-classes-for-regular-expressions) + - [Replacing Using Regular Expressions](#replacing-using-regular-expressions) + - [More String Functions](#more-string-functions) + - [Checking the Similarity of Strings](#checking-the-similarity-of-strings) + - [Repeating Strings](#repeating-strings) + - [Returning the Smallest/Biggest of a Set of Character-Like Arguments](#returning-the-smallestbiggest-of-a-set-of-character-like-arguments) + - [Escaping Special Characters](#escaping-special-characters) + - [Excursions](#excursions) + - [Comparison Operators for Character-Like Data Types in a Nutshell](#comparison-operators-for-character-like-data-types-in-a-nutshell) + - [String Processing Using the XCO Library](#string-processing-using-the-xco-library) + - [Executable Example](#executable-example) + + +## Introduction + +ABAP offers plenty of options for processing [character strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencharacter_string_glosry.htm "Glossary Entry"). +The options include ABAP statements (e. g. [`FIND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm)), +[character string expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_expression_glosry.htm "Glossary Entry") +([concatenations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_glosry.htm) and [string templates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_template_glosry.htm "Glossary Entry")) +and built-in [string functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_function_glosry.htm "Glossary Entry") +(e. g. [`strlen`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm)). + +> **💡 Note**
+>- Compared to statements, expressions and string functions can help make your ABAP code more + concise and straightforward. For example, you can perform string operations directly in [operand + position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry"), + allowing you to avoid temporary variables. +>- In ABAP statements, modification operations on strings are often performed in read/write positions, meaning that the source and target + fields of an operation are the same. When working with string functions, the source field is passed as an input parameter and the modified value is returned as a [return value](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreturn_value_glosry.htm "Glossary Entry"), meaning that the function itself does not modify the source field. Of course, you can assign the function to the source field to achieve its modification. +>- In most cases, string functions provide the same functionality as the + corresponding ABAP statements, or even more. The return value of string functions + that return character strings is always of type `string`. + +

⬆️ back to top

+ +## Data Types for Character Strings + +ABAP provides the following built-in data types for data objects that contain character strings. They are distinguished as follows: + +| Type | Details | Length | Value Range | Initial Value | +|---|---|---|---|---| +| `string` | For variable length character strings. [Data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm "Glossary Entry") of this type are [dynamic data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_data_object_glosry.htm "Glossary Entry"), i. e. the length of a variable can change during the execution of an ABAP program and thus it can contain character strings of different lengths. A data object of type `string` is called *text string* or, in short, just *string*. | No standard length; length is variable | Any [Unicode](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunicode_glosry.htm) characters that can be encoded in ABAP language's code page [UCS-2](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenucs2_glosry.htm). The most common content are alphanumeric characters or special characters. | Empty string with length 0 | +| `c` | For fixed length character strings. Data objects of this type are [static data objects](http://ldcialx.wdf.sap.corp:50018/sap/public/bc/abap/docu?sap-language=EN&object=abenstatic_data_object_glosry&version=X&sap-client=000), i. e. the length of a variable must be defined during its declaration and does not change during the execution of an ABAP program. Thus, it always contains character strings of the same length. A data object of type `c` is called *text field*.|Data objects of this type can contain a string of fixed length (between 1 and 262143 characters); standard length: 1 | Same as for `string` | A blank for each position | + +In addition to these main data types for character strings, there are several other fixed length data types with special meanings: + +- `n` for fixed length numerical character strings + - Data objects of this type are technically almost the same as text fields. However, the only valid characters are the digits 0 to 9. Validity is not checked for assigning values in a regular way but only for [lossless assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlossless_assignment_glosry.htm). Thus, such numeric text fields can contain invalid data, but should only be used for digits that are not intended for arithmetic calculations, such as zip codes or article numbers. The initial value for each position is 0. +- `d` and `t` for date and time fields + - These data types have a predefiend length of 6 and 8. Data objects of these types are used for character representations of dates and times in a predefined format. You can use them directly in date and time calculations. However, these fields can also contain invalid values. + +These data types are not covered further in this cheat sheet. The same is true for the [byte-like data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_like_data_typ_glosry.htm "Glossary Entry") `x` and `xstring` that are closely related to `c` and `string` but contain raw [byte strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_string_glosry.htm). + +> **⚡ Differences between text strings (variable length) and text fields (fixed length)**
+>- **Initial value**: The initial value of a text string is an + empty string of length 0. The initial value of text field is represented by blanks at each position. +>- **Internal representation**: Data objects of type `c` and `string` are both [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"). + However, while text fields occupy a block of memory according to their length, text strings are so-called [deep](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_glosry.htm "Glossary Entry") data objects. Internally, they are managed by a [reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm "Glossary Entry") that points to the actual character. This fact has restrictive consequences for the use of strings as components of structures, but can also improve the performance of assignments due to the concept of [sharing](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensharing_glosry.htm "Glossary Entry") of deep data objects. +>- **Length**: Theoretically, a text string can use up to 2 GB (one character occupies 2 bytes). + The maximum length of a text field is 262143 characters. +>- **Trailing blanks**: For text strings, trailing blanks are preserved in all operations. For text fields, it depends on the [operand + position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm "Glossary Entry") whether trailing blanks are respected or not. In most operand positions, trailing blanks are truncated when working with text fields, even when using [text field literals](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentext_field_literal_glosry.htm). For example, if a text field is assigned to a text string, the resulting target string will never contain trailing blanks. See the *Condensing Strings* section in this context. +>- **Flexibility**: Text strings are more flexible than text fields + because you can easily shorten or lengthen them without + worrying that, for example, parts of the character string will be + truncated during processing. On the other hand, when accessing substrings of a string, you have to make sure that the string is long enough, whereas with text fields you always know their length. + +So, when to use what? Text fields are useful when +actually specifying a maximum or mandatory length, e.g. a country code +that must be a maximum of two characters, or for input fields in +forms that should not exceed a certain length. If limiting a string +is not relevant, text strings are a good choice. + +

⬆️ back to top

+ +## Declaring Character-Like Data Objects + +- To work with character strings, you need character-like data objects based on the character-like types mentioned above. +- The simplest way of producing text in an ABAP program are [character literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencharacter_literal_glosry.htm). +The following code snippet shows a global class implementing the interface `if_oo_adt_classrun`. + - Using the `write` method, you can display output in the ADT console. In the example, two [untyped literals](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuntyped_literal_glosry.htm) without a dedicated name ([unnamed data object](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunnamed_data_object_glosry.htm)) are included. + - In the case below, the data type of the character literals are defined by the delimiters. +- Text string literals are enclosed in backquotes (\`...\`) and have the data type `string`. +- Text field literals are enclosed in single quotes (`'...'`) and have the data type `c`. +- The literals can be (but should not according to the [programming guidelines on literals (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenliterals_guidl.htm)) used like constants of these types in [operand positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm). They should be only used for start values when declaring [named data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm). + +```abap +CLASS zcl_some_test_class DEFINITION PUBLIC FINAL CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. +ENDCLASS. + +CLASS zcl_some_test_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + out->write( `I am a text string literal` ). "text string literal of type string + out->write( 'I am a text field literal' ). "text field literal of type c + ENDMETHOD. +ENDCLASS. +``` + +- [Named](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm) character-like data types and objects can be declared like other types and objects using [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm), [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) and by referring to a character-like data type. +- In addition, character-like data objects can be declared inline with the operators `DATA` and [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm). + +Syntax examples: +``` abap +"Type declarations using built-in types + +TYPES: c_type TYPE c LENGTH 3, "Explicit length specification + str_type TYPE string. + +"Data object declarations using built-in, local and DDIC types + +DATA: flag TYPE c LENGTH 1, "Built-in type + str1 TYPE string, "Built-in type + char1 TYPE c_type, "Local type + str2 LIKE str1, "Deriving type from a local data object + str3 TYPE str_type, "Local type + char2 TYPE s_toairp, "DDIC type (used e. g. for a field in a demo table) + char3 TYPE zdemo_abap_flsch-carrid. "Using the type of a DDIC table component + +"You may also encounter declarations with type c and the length +"specified in parentheses. This is not recommended, to avoid confusion +"with the use of parentheses in dynamic programming. + +DATA char(4) TYPE c. + +"Just a TYPE c specification without length means LENGTH 1. +DATA char_len_one TYPE c. +"No type and length specification: TYPE c LENGTH 1 by default +DATA char_no_type_len. +``` + +

⬆️ back to top

+ +## Assigning Values + +- When you declare character-like data objects, you can specify start values directly with the `VALUE` addition, e.g. `DATA chars TYPE c LENGTH 3 VALUE 'abc'.`. +- You can do value assignments to data objects using the the [assignment operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenassignment_operator_glosry.htm "Glossary Entry") `=`. +- As mentioned above, you can declare character-like data objects inline using the operators `DATA` or `FINAL`. +- You can use the operators at many [write positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwrite_position_glosry.htm "Glossary Entry"). +- Unlike the `VALUE` addition of the declaration statements, inline declarations allow you to declare variables for the results of expressions or at other positions where character strings are returned. +- In the case below, a variable specified in parentheses preceded by `DATA` (or `FINAL`) on the left side of the assignment operator automatically derives a data type from the operand on the right. This helps to make your +programs leaner. + +Syntax examples: +``` abap +"Data object declarations including default values with VALUE +"Note the chained statement: DATA followed by a colon, listing the data object declarations, +"separated by a comma. +DATA: flag TYPE c LENGTH 1 VALUE 'X', +      str1 TYPE string VALUE `Hallo!`. + +"Examples for type n +DATA zip_code TYPE n LENGTH 5 VALUE '12345'. +DATA isbn_number TYPE n LENGTH 13 VALUE '1234567890123'. + +"Constant; content cannot be changed at runtime +CONSTANTS pi TYPE p LENGTH 8 DECIMALS 14 VALUE '3.14159265358979'. + +"More data object declarations +DATA: char1 TYPE c LENGTH 5, +      html  TYPE string, +      str2  LIKE html. + +"Value assignments +char1 = 'ab123'. +html  = `

hallo

`. + +"Escaping backquotes in text string literals with another one +str1  = `This is a backquote: ``.`. + +"If possible, avoid unnecessary type conversion; in principle, every +"convertible type can be specified +str2 = 'abc'. "Fixed length string assigned to data object of type string +DATA str3 TYPE string VALUE 'X'. "type c length 1 +DATA str4 TYPE string VALUE -1. "type i + +"Inline declarations +DATA(char2) = 'abcd'. "Type c length 4 +DATA(str5)  = `efgh`. + +"You can use FINAL to create immutable variables. +FINAL(final_string)  = `zyx`. + +"Since char2 is of type c length 4 (the length is also derived), +"characters are truncated in the following example assignment +char2 = 'ijklmnopq'. "ijkl + +"Trailing blanks after assigning fixed length to variable length string +DATA(char3) = 'ab   '. +DATA(str6)  = `cdefgh`. +str6 = char3. "'ab' (trailing blanks are not respected due to conversion rule) +``` + +- When assigning strings, not only data objects can be placed on the right +side. Various expressions and strings can be concatenated using the +[concatenation +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_operator_glosry.htm "Glossary Entry") +`&&`. +- Alternatively, you can concatenate strings using [string +templates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_template_glosry.htm "Glossary Entry"), as described in the *Concatenating Strings* section. +``` abap +str5 = str3 && ` ` && str4 && `!`. "X 1-! +"Note the output for str4 that includes the conversion of type i to +"string above demonstrating a possibly inadvertent specification +"of an integer value for str4 that is of type string. +``` + +Note that there is also the [literal +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenliteral_operator_glosry.htm "Glossary Entry") +`&` that joins [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 `&&`. + +

⬆️ back to top

+ +## String Templates +- Using string templates, you can construct strings very elegantly from +literal text and - which is the primary use case - by including +embedded ABAP +[expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexpression_glosry.htm "Glossary Entry") +within a pair of delimiters (`|...|`) if these expressions can be converted to `string`. +- To embed expressions, you enclose them in curly brackets: `{ ... }`. + +> **💡 Note**
+> String templates form a [string +expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_expression_glosry.htm "Glossary Entry") +that is compiled at runtime. Therefore, a string template that contains only +literal text is treated as an expression, which has a performance impact. In such a case, it is preferable to use a text string literal with backquotes. + +Syntax examples: +``` abap +"Value assignment with string templates +"The expression must be convertible to a string. A blank (not within the curly brackets) +"means a blank in the resulting string. +DATA(s1) = |Hallo { cl_abap_context_info=>get_user_technical_name( ) }!|. + +DATA(s2) = `How are you?`. "Literal text only with backquotes +DATA(s3) = |{ s1 } { s2 }|. "Hallo NAME! How are you? + +"Chaining of string templates using && +DATA(s4) = |{ s1 }| && ` ` && |{ s2 }|. "Hallo NAME! How are you? +``` + +- String templates interpret certain character combinations as [control +characters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstring_templates_separators.htm). +- For example, `\n` is interpreted as a newline. A new line is +started. +- String templates also support various [formatting +options](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcompute_string_format_options.htm). +- Refer to the ABAP Keyword Documentation for all options. + +The following syntax examples demonstrate a selection: +```abap +"Control characters +s4 = |{ s1 }\n{ s2 }\nSee you.|. "\n is interpreted as a line feed + +"Excursion: Class CL_ABAP_CHAR_UTILITIES provides attributes and methods as utilities for string processing. +"See the class documentation +"The following examples demonstrate that attributes that contain control characters can be replaced by +"a representation of control characters in a string template. +ASSERT cl_abap_char_utilities=>newline = |\n|. +ASSERT cl_abap_char_utilities=>horizontal_tab = |\t|. +ASSERT cl_abap_char_utilities=>cr_lf = |\r\n|. + +"Various formatting options +"DATE: Defining the format of a date +"The output is just an example and depends on your settings. +DATA(d) = |The date is { cl_abap_context_info=>get_system_date( ) DATE = USER }.|. "The date is 01/01/2024. +d = |{ cl_abap_context_info=>get_system_date( ) DATE = RAW }|. "20240101 +d = |{ cl_abap_context_info=>get_system_date( ) DATE = ISO }|. "2024-01-01 +d = |{ cl_abap_context_info=>get_system_date( ) DATE = ENVIRONMENT }|. "01/01/2024 + +"TIME: Defining the format of a time +"The output is just an example and depends on your settings. +DATA(tm) = |The time is { cl_abap_context_info=>get_system_time( ) TIME = ISO }.|. "The time is 14:37:24. +tm = |{ cl_abap_context_info=>get_system_time( ) TIME = RAW }|. "143724 +tm = |{ cl_abap_context_info=>get_system_time( ) TIME = USER }|. "14:37:24 +tm = |{ cl_abap_context_info=>get_system_time( ) TIME = ENVIRONMENT }|. "14:37:24 + +"TIMESTAMP: Defining the format of a time stamp +"The output is just an example and depends on your settings. +DATA(ts) = |{ utclong_current( ) TIMESTAMP = SPACE }|. "2024-01-01 14:39:50.4069170 +ts = |{ utclong_current( ) TIMESTAMP = ISO }|. "2024-01-01T14:39:50,4071110 +ts = |{ utclong_current( ) TIMESTAMP = USER }|. "01/01/2024 14:39:50.4072010 +ts = |{ utclong_current( ) TIMESTAMP = ENVIRONMENT }|. "01/01/2024 14:39:50.4073230 +ts = |{ utclong_current( ) }|. "2024-01-01 14:39:50.4074060 + +"TIMEZONE: Defining the format of a time stamp using the rules for time zones +DATA(tz) = |{ utclong_current( ) TIMEZONE = 'UTC' }|. "2024-12-30 14:43:20.6534640 +tz = |{ utclong_current( ) TIMEZONE = 'CET' COUNTRY = 'DE ' }|. "30.12.2024 15:43:20,6536320 +tz = |{ utclong_current( ) TIMEZONE = 'EST' COUNTRY = 'US ' }|. "12/30/2024 09:43:20.6889180 AM + +"CASE: Lowercase and uppercase +s1 = |AbCdEfG|. +s2 = |{ s1 CASE = LOWER }|. "abcdefg +s2 = |{ s1 CASE = UPPER }|. "ABCDEFG + +"WIDTH/ALIGN +s1 = `##`. +s2 = |{ s1 WIDTH = 10 ALIGN = LEFT }<---|. "'## <---' +s2 = |{ s1 WIDTH = 10 ALIGN = CENTER }<---|. "' ## <---' + +"PAD: Used to pad any surplus places in the result with the specified character. +s2 = |{ s1 WIDTH = 10 ALIGN = RIGHT PAD = `.` }<---|. "'........##<---' + +"DECIMALS +s1 = |{ CONV decfloat34( - 1 / 3 ) DECIMALS = 3 }|. "'-0.333' + +"SIGN: Defining the format of the +/- sign when the string represented +"by the embedded expression represents a numeric value +"- left without space, no + +s1 = |{ +1 SIGN = LEFT }|. "1 +"- and + left without space +s1 = |{ 1 SIGN = LEFTPLUS }|. "+1 +"- left without space, blank left for + +s1 = |{ 1 SIGN = LEFTSPACE }|. " 1 +"- right without space, no + +s1 = |{ -1 SIGN = RIGHT }|. "1- +"- and + right without space +s1 = |{ 1 SIGN = RIGHTPLUS }|. "1+ +"- left without space, blank right for + +s1 = |{ +1 SIGN = RIGHTSPACE }|. "1 + +"ZERO: Defining the format of the numeric value zero. +"Only to be specified if the embedded expression has a numeric data type. +s1 = |'{ 0 ZERO = NO }' and '{ 0 ZERO = YES }'|. "'' and '0' + +"XSD: Formatting is applied to an embedded expression (elementary data types) in asXML format that is +"assigned to its data type. Check the information in the ABAP Keyword Documentation about the asXML +"mapping of elementary ABAP types. +DATA xstr TYPE xstring VALUE `41424150`. +DATA dat type d value '20240101'. +DATA tim type t value '123456'. +DATA(utc) = utclong_current( ). "e.g. 2024-01-01 13:51:38.5708800 + +s1 = |{ xstr XSD = YES }|. "QUJBUA== +s1 = |{ dat XSD = YES }|. "2024-01-01 +s1 = |{ tim XSD = YES }|. "12:34:56 +s1 = |{ utc XSD = YES }|. "2024-01-01T13:51:38.57088Z + +"STYLE: Defining the style of decimal floating point numbers; +"see the details in the ABAP Keyword Documentation. +DATA(dcfl34) = CONV decfloat34( '-123.45600' ). +s1 = |{ dcfl34 }|. "-123.456 +"Creates the predefined format +s1 = |{ dcfl34 STYLE = SIMPLE }|. "-123.456 +"+/- added to the right, removes trailing zeros +s1 = |{ dcfl34 STYLE = SIGN_AS_POSTFIX }|. "123.456- +"Retains trailing zeros +s1 = |{ dcfl34 STYLE = SCALE_PRESERVING }|. "-123.45600 +"Scientific notation; at least a two digit exponent with a plus/minus sign +s1 = |{ dcfl34 STYLE = SCIENTIFIC }|. "-1.23456E+02 +"Scientific notation; only one integer digit with the value 0 +s1 = |{ dcfl34 STYLE = SCIENTIFIC_WITH_LEADING_ZERO }|. "-0.123456E+03 +"Scientific notation; exponent has 3 digits for decfloat16 and 4 digits for decfloat34 +s1 = |{ dcfl34 STYLE = SCALE_PRESERVING_SCIENTIFIC }|. "-1.2345600E+0002 +"Technical format +s1 = |{ dcfl34 STYLE = ENGINEERING }|. "-123.456E+00 + +"ALPHA: Adds or removes leading zeros from strings of digits; the data type +"must be string, c, or n +"Adding leading zeros +"Additionally specifying WIDTH +"Note: The specified length is only used if it is greater than +"the length of provided string (without leading zeros) +s1 = |{ '1234' ALPHA = IN WIDTH = 10 }|. "0000001234 +s1 = |{ '00000000000000000000000012' ALPHA = IN WIDTH = 10 }|. "0000000012 +"Fixed-length string provided, WIDTH not specified +s1 = |{ ' 12' ALPHA = IN }|. "00012 +"Removing leading zeros +s1 = |{ '00001234' ALPHA = OUT }|. "1234 +"Do not apply formatting +s1 = |{ '00001234' ALPHA = RAW }|. "00001234 +``` + +> **💡 Note**
+> Escape `\|{}` in string templates using `\`, i. e. `\\` means `\`. + +

⬆️ back to top

+ +## Determining the Length of Strings + +- To determine the length of a string, you can use the string function +[`strlen`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm). +- Note that the result depends on the type of the string, i. e. the result for a data object of type `string` includes trailing blanks. A +fixed-length string does not include them. +- To exclude trailing blanks in all cases, regardless of the data type, you can use the built-in +[`numofchar`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlength_functions.htm) function. + +Syntax examples: +``` abap +"strlen +DATA(len_c) = strlen( 'abc ' ). "3 +DATA(len_str) = strlen( `abc ` ). "6 + +"numofchar +len_c = numofchar( 'abc ' ). "3 +len_str = numofchar( `abc ` ). "3 +``` + +

⬆️ back to top

+ +## Concatenating Strings + +- Two or more strings can be concatenated using the concatenation operator +`&&` and string templates. Alternatively, you can use +[`CONCATENATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconcatenate.htm) +statements. +- It is also possible to concatenate lines from internal tables +into a string to avoid a loop. +- A more modern way is to use +the string function +[`concat_lines_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconcatenation_functions.htm). + +Syntax examples: +``` abap +"&& and string template +DATA(s1) = `AB` && `AP`. "ABAP +DATA(s2) = `ab` && `ap` && ` ` && s1. "abap ABAP +DATA(s3) = |{ s1 }. { s2 }!|. "ABAP. abap ABAP! + +"CONCATENATE statements +CONCATENATE s1 s2 INTO s3. "ABAPabap ABAP + +"Multiple data objects and target declared inline +CONCATENATE s1 ` ` s2 INTO DATA(s5). "ABAP abap ABAP + +CONCATENATE s1 s2 s5 INTO DATA(s6). "ABAPabap ABAPABAP abap ABAP + +"You can also add a separation sign using the addition SEPARATED BY +CONCATENATE s1 s2 INTO s3 SEPARATED BY ` `. "ABAP abap ABAP + +CONCATENATE s1 s2 INTO s3 SEPARATED BY `#`. "ABAP#abap ABAP + +"Keeping trailing blanks in the result when concatenating fixed length +"strings. The ones of variable length strings are respected by default. +CONCATENATE 'a ' 'b ' 'c ' INTO DATA(ch) RESPECTING BLANKS. "'a b c ' + +"Concatenating lines of internal tables into a string +CONCATENATE LINES OF itab INTO t SEPARATED BY ` `. + +"Using concat_lines_of +s1 = concat_lines_of( table = itab ). "Without separator +s1 = concat_lines_of( table = itab sep = ` ` ). "With separator +``` + +

⬆️ back to top

+ +## Splitting Strings + +- You can use +[`SPLIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsplit.htm) +statements to split strings in multiple segments. +- The result of the +split can be stored in separate data objects or internal tables that +have a character-like line type. +- Note that if the number of specified targets is +less than the number of segments returned by the split, the last target receives the remaining unsplit segements. If more targets are specified, the targets that do not receive a segment are +initialized. +- Therefore, specifying individual targets with `SPLIT` +statements is useful if the number of expected segments is known. +Otherwise, splitting into tables is a good choice. +- If you want to get the value of a particular segment, you can use the +string function +[`segment`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensegment_functions.htm). + +Syntax examples: +``` abap +DATA(s1) = `Hallo,world,123`. +DATA: s2 TYPE string, + s3 TYPE string, + s4 TYPE string. + +SPLIT s1 AT `,` INTO s2 s3 s4. "s2 = Hallo / s3 = world / s4 = 123 + +"Less data objects than possible splittings +SPLIT s1 AT `,` INTO s2 s3. "s2 = Hallo / s3 = world,123 + +"Splitting into internal table +DATA itab TYPE TABLE OF string. +SPLIT s1 AT ',' INTO TABLE itab. "Strings are added to itab in individual lines without comma + +"String function segment returning the occurrence of a segment +"index parameter: number of segment +s2 = segment( val = s1 index = 2 sep = `,` ). "world +``` + +

⬆️ back to top

+ +## Modifying Strings +### Transforming to Lowercase and Uppercase + +- The string functions +[`to_lower`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencase_functions.htm) +and +[`to_upper`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencase_functions.htm) +transform characters of a string to either lowercase or uppercase and +store the result in a target variable. +- If you want to apply the transformation to the source directly, you can use +[`TRANSLATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptranslate.htm) +statements. + +Syntax examples: +``` abap +"String functions +DATA(s1) = to_upper( `abap` ). "ABAP +s1 = to_lower( `SOME_FILE.Txt` ). "some_file.txt + +"TRANSLATE statements +s1 = `Hallo`. +TRANSLATE s1 TO UPPER CASE. "HALLO +TRANSLATE s1 TO LOWER CASE. "hallo +``` + +

⬆️ back to top

+ +### Shifting Content + +- You can shift content within a string to a specific position on the left +or right of a string. +[`SHIFT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapshift.htm) +statements have various additions for specific use cases. +- In a more modern way, you can use the string functions +[`shift_left`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshift_functions.htm) +and +[`shift_right`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshift_functions.htm), which store the result in a variable. + - These functions provide additional +functionality. The `sub` parameter can be used to specify a +substring. All substrings in the string that match the value specified +in `sub` on either the left or right side of the string are +removed. + +Syntax examples: +``` abap +"SHIFT statements +"Note that all results below refer to s1 = `hallo`. +DATA(s1) = `hallo`. "Type string + +SHIFT s1. "No addition; string shifted one place to the left: allo +SHIFT s1 BY 2 PLACES. "Without direction, left by default: llo +SHIFT s1 BY 3 PLACES RIGHT. "With direction, variable length strings are extended: ' hallo' + +"Note that all results below refer to ch4 = 'hallo'. +DATA(ch4) = 'hallo'. "Type c length 5 + +SHIFT ch4 BY 3 PLACES RIGHT. "Fixed length string: ' ha' + +"CIRCULAR addition: characters that are moved out of the string are +"added at the other end again +SHIFT ch4 BY 3 PLACES LEFT CIRCULAR. "lohal +SHIFT ch4 UP TO `ll`. "Shift characters up to a specific character set: llo + +"Deleting leading and trailing characters +DATA(s2) = ` hallo `. +DATA(s3) = s2. + +SHIFT s2 LEFT DELETING LEADING ` `. "'hallo ' +SHIFT s3 RIGHT DELETING TRAILING ` `. "' hallo' (length is kept) + +"Removing trailing blanks in strings without leading blanks; +"you can use the following sequence of statements +DATA(s4) = `hallo `. +SHIFT s4 RIGHT DELETING TRAILING ` `. "' hallo' +SHIFT s4 LEFT DELETING LEADING ` `. "'hallo' + +"String functions with parameters +s1 = `hallo`. + +s2 = shift_left( val = s1 places = 3 ). "lo +s2 = shift_left( val = s1 circular = 2 ). "lloha + +"Note that shift_right does not extend a variable length string. +s2 = shift_right( val = s1 places = 3 ). "ha +s2 = shift_right( val = `abc ` sub = ` ` ). "'abc' +s2 = shift_right( val = `abc ` ). "'abc' (same result as above) +``` + +

⬆️ back to top

+ +### Condensing Strings + +- You can use +[`CONDENSE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcondense.htm) +statements or the string function +[`condense`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencondense_functions.htm) +to remove blanks from strings. +- The advantage of using the string function +is that you can specify any character to remove, not just blanks. + +Syntax examples: +``` abap +"CONDENSE statements +DATA(s1) = ` ab cd `. +DATA(s2) = ` ef gh ij `. +DATA(s3) = ` kl mn op `. + +CONDENSE s1. "Trailing and leading blanks are removed: 'ab cd' +CONDENSE s2. "It also replaces sequences of multiple blanks with a single blank: 'ef gh ij' +CONDENSE s3 NO-GAPS. "Removes all blanks: 'klmnop' + +"String function condense +s1 = ` ab cd `. + +"No parameters specified, i. e. their default values are provided. +"Works like CONDENSE statement without the NO-GAPS addition. +s2 = condense( s1 ). "ab cd + +"Parameters del/to not specified. from parameter with initial string +"(could also be a text field literal: from = ' '). This way, leading and +"trailing blanks are removed. +s2 = condense( val = s1 from = `` ). "ab cd + +"Parameter to specified with an initial string. No other parameters. +"Works like CONDENSE statement with the NO-GAPS addition. +s2 = condense( val = s1 to = `` ). "abcd + +"Parameter del specifies the leading/trailing characters to be removed. +s2 = condense( val = `##see###you##` del = `#` ). "see###you + +"If from and to are specified along with del, leading/trailing +"characters specified in del are first removed. Then, in the remaining string, all +"substrings composed of characters specified in from are replaced with +"the first character of the string specified in the to parameter +s2 = condense( val = ` Rock'xxx'Roller` + del = `re ` + from = `x` + to = `n` ). "Rock'n'Roll +``` + +

⬆️ back to top

+ +### Reversing Strings + +The string function +[`reverse`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreverse_functions.htm) +reverses a string: +``` abap +"Result: 'abap' +DATA(s1) = reverse( `paba` ). +``` + +

⬆️ back to top

+ +### Inserting Substrings into Strings + +- The string function +[`insert`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninsert_functions.htm) +inserts a substring at any position within a given string. You can use various parameters to construct the string you want: + - `val`: Original string. + - `sub`: Substring. + - `off`: Optionally sets the offset, i.e. the position where the substring should be added. The default value is 0. When using the function with the default value, the result is like concatenating a string with `&&` (like `res = sub && text`). +- Inserting substrings can also be accomplished using the string function `replace` or `REPLACE` statements, which are are covered below. + +Syntax examples: +``` abap +"Result: 'abcdefghi' +DATA(s1) = insert( val = `abcghi` sub = `def` off = 3 ). + +"Result: 'defabcghi' +s1 = insert( val = `abcghi` sub = `def` ). +``` + +

⬆️ back to top

+ +### Overlaying Content + +You can use [`OVERLAY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapoverlay.htm) statements to replace characters in one variable with characters in another variable that are in the same place there. + +Syntax examples: +``` abap +DATA(incl) = '==============================CP'. +DATA(cl_name) = 'CL_SOME_CLASS '. + +"Addition ONLY is not specified: All blanks are replaced +OVERLAY cl_name WITH incl. +"cl_name: CL_SOME_CLASS=================CP + +DATA(txt1) = 'a.b.c.a.b.c.A'. +DATA(txt2) = 'z.x.y.Z.x.y.z'. + +"Addition ONLY is specified: All characters that are specified after ONLY and that +"occur in the operand are replaced. Note that this is case-sensitive. +OVERLAY txt1 WITH txt2 ONLY 'ab'. +"txt1: z.x.c.Z.x.c.A +``` + +

⬆️ back to top

+ +## Processing Substrings + +- The string function +[`substring`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm) allows you to specify the position (parameter `off`) and the length +(`len`) of a substring to be extracted from a given +string (`val`). + - At least one of the two parameters `off` +or `len` must be specified. The default value of `off` +is 0, i.e. when using the default value, the substring is extracted +from the beginning of the string. + - If `len` is not specified, the rest of the remaining characters is respected. If the offset +and length are greater than the actual length of the string, the +exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised. +- You may also encounter the syntax for accessing substrings by specifying the offset +and length using the `+` character after a variable. + - The length is specified in parentheses. Specifying an asterisk (`*`) means +that the rest of the remaining string is respected. + - This syntax option +even allows write access to substrings for fixed-length strings. Read +access is possible for both fixed-length and variable-length strings. + - However, this syntax can be confused with the use of tokens in the +context of dynamic programming. +- There are other string functions available for dealing with substrings, such as +[`substring_after`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm), +[`substring_before`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm), +[`substring_from`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm) +and +[`substring_to`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubstring_functions.htm). + - These functions offer more options in terms of parameters, such as the use of [PCRE regular +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry"), +which are covered below. + +Syntax examples: +``` abap +DATA(s1) = `Lorem ipsum dolor sit amet`. "Type string + +"Extracting substring starting at a specific position +"'len' not specified means the rest of the remaining characters is +"respected +DATA(s2) = substring( val = s1 off = 6 ). "ipsum dolor sit amet + +"Extracting substring with a specific length +"'off' is not specified and has the default value 0. +s2 = substring( val = s1 len = 5 ). "Lorem + +"Specifying both off and len parameters +s2 = substring( val = s1 off = 6 len = 5 ). "ipsum + +DATA(txt) = 'Lorem ipsum dolor sit amet'. "Type c + +"Offset and length specification using the + sign after a variable +DATA(ch6) = txt+0(5). "Lorem + +"* means respecting the rest of the remaining string +DATA(ch7) = txt+12(*). "dolor sit amet + +CLEAR txt+11(*). "Lorem ipsum + +txt+0(5) = 'Hallo'. "Hallo ipsum dolor sit amet + +"Further string functions +s1 = `aa1bb2aa3bb4`. + +"Extracting a substring ... +"... after a specified substring +s2 = substring_after( val = s1 sub = `aa` ). "1bb2aa3bb4 (only the first occurrence is respected) + +"... after a specified substring specifying the occurence in a string +"and restricting the length +s2 = substring_after( val = s1 sub = `aA` occ = 2 len = 4 case = abap_false ). "3bb4 + +"... before a specified substring +s2 = substring_before( val = s1 sub = `b2` ). "aa1b + +"... from a specified substring on. It includes the substring specified +"in sub. len/off and other parameters are possible. +s2 = substring_from( val = s1 sub = `a3` ). "a3bb4 + +"... up to a specified substring. It includes the substring specified +"in sub. len/off and other parameters are possible. +s2 = substring_to( val = s1 sub = `3b` ). "aa1bb2aa3b +``` + +

⬆️ back to top

+ +## Searching and Replacing + +- In ABAP, there are many ways to perform search and replace +operations on strings. These include the use of [comparison +operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") +or the ABAP statements +[`FIND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm) +and +[`REPLACE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace.htm), +or the more modern built-in string functions +[`find`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) +and +[`replace`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreplace_functions.htm), +among others, with their considerable number of additions and parameters. +- Many of these options support rather simple operations +on single characters only or more complex, pattern-based +operations on character sequences using [PCRE regular +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry"). + +

⬆️ back to top

+ +### Searching for Specific Characters + +- You can use the [comparison + operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") + [`CA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains any) or its negation + [`NA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains not any) in [comparison + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry") + to determine whether any character of a given character set is contained + in a string. Such an expression is true if at least one character is + found. + - The search is case-sensitive. + - The system variable `sy-fdpos` contains the offset of + the first character found. If nothing is found, + `sy-fdpos` contains the length of the string. + - Note that offset 0 represents the very first position. +- The string functions + [`find_any_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) + and its negation + [`find_any_not_of`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) + return the offset of the occurrence of any character contained in a + substring. They are special variants of the string function `find`, which is shown below. + - If nothing is found, the value -1 is returned. + - Other optional parameters are possible. For example, the + specification of `occ` determines the search + direction, i.e. a positive value means that the search is performed + from left to right. A negative value means to search from right + to left. +- If you are not interested in the position of characters, but rather how + often they occur in a string, you can use the string function + [`count`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencount_functions.htm), as well as the special variants `count_any_of` and its negation `count_any_not_of`. +- To determine whether a string contains only a certain set of characters, + you can use the comparison operators + [`CO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains only) or its negation + [`CN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains not only) in comparison expressions. + - For `CO`, a comparison is true if the left operand + contains only characters that are also contained in the right + operand. If the comparison returns false, you can use `sy-fdpos` to get the position + of the first character from text that is not contained in the + character. + - For `CN`, a + comparison is true if a string contains characters other than those in the character set. + +Syntax examples: +``` abap +DATA(s1) = `cheers`. +IF s1 CA `aeiou` ... "true, sy-fdpos = 2 +IF s1 NA `xyz`... "true, sy-fdpos = 6 + +IF s1 CO `rs` ... "false, sy-fdpos = 0 +IF s1 CN `cheers` ... "false, sy-fdpos = 6 +``` + +Built-in functions: + +``` abap +"Note that the functions may contain more parameters than those covered in the snippet. +DATA(str) = `Pieces of cakes.`. +DATA res TYPE i. + +"find_end returns the sum of the offset of the occurrence +res = find_end( val = str sub = `of` ). "9 + +"find_any_of returns the offset of the occurrence of any character contained in substring +"The search is always case-sensitive. +res = find_any_of( val = str sub = `x523z4e` ). "2 (character e is found) +res = find_any_of( val = str sub = `zwq85t` ). "-1 + +"find_any_not_of: Negation of the one above +"The search is always case-sensitive. +res = find_any_not_of( val = str sub = `ieces` ). "0 (very first character in the searched string) +res = find_any_not_of( val = str sub = `P` ). "1 + +"count returns the number of all occurrences +res = count( val = str sub = `e` ). "3 +res = count( val = str sub = `x` ). "0 + +"count_any_of +res = count_any_of( val = str sub = `x523z4e` ). "3 +res = count_any_of( val = str sub = `eco` ). "6 + +"count_any_not_of +res = count_any_not_of( val = str sub = `fP` ). "14 +res = count_any_not_of( val = str sub = `Piecs ofak.` ). "0 +``` + + +

⬆️ back to top

+ +### Replacing Specific Characters in Strings + +- You can use the string function +[`translate`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentranslate_functions.htm) +to replace certain characters with others. + - The +`from` parameter specifies the characters to be placed in a string, and +the `to` parameter specifies the target characters. + - Note: The +replacement is performed as follows: Each character specified in +`from` is replaced by the character in `to` that is at +the same position, i.e. the second character in `from` is +replaced by the second character specified in `to`. If there is +no equivalent in `to`, the character in `from` is +removed from the result. +- You can use +[`TRANSLATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptranslate.htm) +statements to perform replacements directly on the source field. + +Syntax examples: +``` abap +DATA(s1) = `___abc_def_____ghi_`. +DATA(s2) = translate( val = s1 from = `hi_` to = `##` ). "abcdefg## +s2 = translate( val = s1 from = `_` to = `##` ). "###abc#def#####ghi# + +"TRANSLATE statement. The value after USING is interpreted as a string composed of character pairs. +"Starting with the first pair, a search is performed in text for the +"first character in every pair and each occurrence is replaced with the +"second character of the pair. +TRANSLATE s1 USING `_.a#g+`. "...#bc.def.....+hi. +``` + +

⬆️ back to top

+ +### Searching for Substrings in Strings + +- For simple substring searches, you can use the [comparison + operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") + [`CS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains string) or its negation + [`NS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) + (contains no string) in [comparison + expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry"). + The search is not case-sensitive. +- The system variable + `sy-fdpos` contains the offset of the found substring. If + the substring is not found, `sy-fdpos` contains the length + of the searched string. + +``` abap +DATA(s3) = `cheers`. + +IF s3 CS `rs` ... "true, sy-fdpos = 4 (offset) + +IF s3 CS `xy`... "false, sy-fdpos = 6 (length of string) + +IF s3 NS `ee`... "false, sy-fdpos = 2 (offset) + +IF s3 NS `xy`... "true, sy-fdpos = 6 (length of string) +``` + +For more complex and iterative searches, you may want to use `FIND` statements or the string functions below. + +- `FIND` + - Used to search for a character sequence. + - Has a rich set of additions, a selection of which is covered in this cheat sheet. See [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm) for more information. Byte string processing is not included (there are special additions). + - Sets the system fields `sy-subrc`: 0 (search pattern found at least once) or 4 (search pattern not found). + +Syntax Overview (see the syntax diagram in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind.htm)): + +``` abap +FIND + FIRST OCCURRENCE OF "(or) ALL OCCURRENCES OF + "1. Only the first occurrence is searched + "2. All occurrences are searched + "Note: If none of these two additions is specified, only the first occurrence is searched for. + + SUBSTRING some_substring "(or) PCRE some_regex + "1. Searching for exactly one string, specifying SUBSTRING is optional (e.g. for emphasis); + " some_substring is a character-like operand; note: Trailing blanks are not ignored if it is of type string + "2. Searching for a substring matching a regular expression; only the PCRE addition should be used; + " some_regex = character-like operand; note: PCRE syntax is compiled in an extended mode, i.e. unescaped whitespaces + " are ignored; if the regex is too complex, a catchable exception of the class CX_SY_REGEX_TOO_COMPLEX is raised + +IN + SECTION + OFFSET off + LENGTH len + OF + "- Restricting the search to a specific section from an offset specified in off with the length len + "- When using SECTION, at least one of the two options must be specified + " - No OFFSET specification: offset 0 is used implicitly + " - No LENGTH specification: search from specified offset to end of string + " - Note: off and len are of type i; it must be a positive integer value; + " exception: len = -1 (same effect as not using the LENGTH addition) + "- Without the addition SECTION ... OF, the entire data object dobj is searched + +"Character-like data object +dobj + + "Further additional options for advanced evaluation options: + "Specifying whether the search is case-sensitive; not specified means RESEPECTING CASE by default + RESPECTING CASE "(or) IGNORING CASE + + "Determining the number of sequences found, number stored in cnt that is of type i (e.g. a variable declared inline) + "When searching for the first occurrence, the value is always 1 (not found -> 0) + MATCH COUNT cnt + + "Determining position of sequences found + "Note: off holds the position of the last occurrence when searching for all occurrences and if + "there are multiple occurrences (not found -> 0 or the previous value of a finding is retained). + MATCH OFFSET off + + "Determining the length of sequences found + "Note: Similar to above, not finding an occurrence means 0 for len or the previous value of a finding is retained + MATCH LENGTH len + + "Storing offset, length, submatches (only relevant for regular expressions) information in a table or a structure + "tab: of type MATCH_RESULT_TAB; especially for using with ALL OCCURRENCES + "struc: of type MATCH_RESULT; especially for using with FIRST OCCURRENCE + "Note on submatches: table of type SUBMATCH_RESULT_TAB; holds offset and length information of substrings of occurrences + "that are stored in subgroup registers of regular expressions; in FIND IN TABLE statements, the additional component LINE + "is available + RESULTS tab "(or) RESULTS struc + + "Storing content of subgroup register of a regular expression in character-like data objects; + "only to be used if a regular expression pattern is specified. + "Note: Only the last occurrence is evaluated when using ALL OCCURRENCES; the number of the operands specified should match + "the number of subgroups specified + SUBMATCHES sub1 sub2 ... +. +``` + +Examples: + +``` abap +"Note: The code snippets mainly use inline declarations. + +DATA(str) = `She sells seashells by the seashore.`. + +"Determining if a substring is found +"Simple find statement +FIND `se` IN str. + +IF sy-subrc = 0. + "found +ELSE. + "not found +ENDIF. + +"Addition SUBSTRING is optional +FIND SUBSTRING `hi` IN str. + +IF sy-subrc = 0. + "found +ELSE. + "not found +ENDIF. + +"The following examples use the additions MATCH COUNT and MATCH OFFSET to determine +"the number of occurrences and offset + +"Addition FIRST OCCURRENCE OF: Explicit specification to search for the first occurrence +FIND FIRST OCCURRENCE OF `se` IN str + MATCH COUNT DATA(cnt2) "1 (always 1 when searching and finding the first occurrence) + MATCH OFFSET DATA(off2). "4 + +"Omitting FIRST OCCURRENCE OF and ALL OCCURRENCES OF addition means searching for the +"first occurrence by default; same effect as the previous statement +FIND `se` IN str + MATCH COUNT DATA(cnt1) "1 + MATCH OFFSET DATA(off1). "4 + +"Addition ALL OCCURRENCES: Searching for all occurrences +FIND ALL OCCURRENCES OF `se` IN str + MATCH COUNT DATA(cnt3) "3 + MATCH OFFSET DATA(off3). "27 (value for the last occurrence) + +"Addition IN SECTION ... OF: +"Searching in a specified section; both additions OFFSET and LENGTH are specified +FIND ALL OCCURRENCES OF `se` + IN SECTION OFFSET 9 LENGTH 5 OF str + MATCH COUNT DATA(cnt4) "1 + MATCH OFFSET DATA(off4). "10 + +"Only LENGTH specified (OFFSET is 0 by default) +FIND ALL OCCURRENCES OF `se` + IN SECTION LENGTH 7 OF str + MATCH COUNT DATA(cnt5) "1 + MATCH OFFSET DATA(off5). "4 + +"Only OFFSET specified (LENGTH: up to end of string) +FIND ALL OCCURRENCES OF `se` + IN SECTION OFFSET 7 OF str + MATCH COUNT DATA(cnt6). "2 + +"Another string to be searched +DATA(str_abap) = `abap ABAP abap`. + +"Further additional options for advanced evaluation options + +"Specifying the case-sensitivity of the search +"Not specifying the CASE addition means RESPECTING CASE is used by default. +"Here, it is explicitly specified. +FIND FIRST OCCURRENCE OF `A` IN str_abap + MATCH OFFSET DATA(off7) "5 + RESPECTING CASE. + +"Making search case-insensitive +FIND FIRST OCCURRENCE OF `A` IN str_abap + MATCH OFFSET DATA(off8) "0 + IGNORING CASE. + +"MATCH LENGTH addition +"The example uses a regular expression: Non-greedy search for +"a substring starting with lower case a up to an upper case P +FIND FIRST OCCURRENCE OF PCRE `a.*?P` IN str_abap + MATCH LENGTH DATA(len8) "9 + RESPECTING CASE. + +"RESULTS addition +"Example: Because of using ALL OCCURRENCES, the data object declared inline automatically +"has the type match_result_tab +FIND ALL OCCURRENCES OF `ab` IN str_abap + RESULTS DATA(res9) + IGNORING CASE. + +"3 entries in table res9 (tables in SUBMATCHES are initial since no regular expression is used) +"line: always 0 (it's not a table); length: always 2 (search for concrete occurrence of `se`) +"1. line: 0, offset: 0, length: 2, submatches: (initial) +"2. line: 0, offset: 5, length: 2, ... +"3. line: 0, offset: 10, length: 2, ... + +"Example: Because of using FIRST OCCURRENCE, the data object declared inline automatically +"has the type match_result +FIND FIRST OCCURRENCE OF `ab` IN str_abap + RESULTS DATA(res10) + IGNORING CASE. + +"res10: line: 0, offset: 0, length: 2, submatches: (initial) +``` + +### Searching for Substrings in Tables +You can use [`FIND ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_itab.htm) statements to search for substrings in internal tables (standard tables without secondary table keys; with character-like line type) line by line. + +``` abap +DATA(str_table) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). + +"Finding all occurrences in a table +"Note: res_tab is of type match_result_tab +"You can also restrict the search range in an internal table; see an example in REPLACE ... IN TABLE +FIND ALL OCCURRENCES OF `Z` + IN TABLE str_table + RESULTS DATA(res_tab) + RESPECTING CASE. + +"4 entries in table res_tab (tables in SUBMATCHES are initial since no regular expression is used) +"1. line: 1, offset: 1, length: 1, submatches: (initial) +"2. line: 1, offset: 4, length: 1, ... +"3. line: 2, offset: 2, length: 1, ... +"4. line: 3, offset: 0, length: 1, ... + +"Finding the first occurrence in a table +"Note: res_struc, which is declared inline here, is of type match_result +FIND FIRST OCCURRENCE OF `Z` + IN TABLE str_table + RESULTS DATA(res_struc) + RESPECTING CASE. + +"Entries in structure res_struc +"line: 1, offset: 1, length: 1, submatches: (initial) + +"Alternative to the statement above (storing the information in individual data objects) +FIND FIRST OCCURRENCE OF `Z` + IN TABLE str_table + MATCH LINE DATA(line) "1 + MATCH OFFSET DATA(off) "1 + MATCH LENGTH DATA(len) "1 + RESPECTING CASE. +``` + +### String Function find +- Built-in search functions, such as `find`, are available for searching strings. +- They return a return value of type i and contain multiple (optional) parameters. +- `FIND` covers the same functionality and more with the many addition options. +- For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensearch_functions.htm) + +Parameters of the `find` function: +- `val`: + - Character-like data object + - Note: If a fixed length string is specified, any trailing blanks are ignored. +- `sub`: + - Contains what is searched for + - A character like expression position; expects arguments with elementary types + - Similar to above, trailing blanks are ignored in fixed length strings +- `case`: + - Search is case-sensitive by default +- `occ`: + - Specifies the occurrence of a match + - Must be of type `i` + - Values: + - 1: default value, searches for the first occurrence from the left + - any positive value: searches for the nth occurrence from the left + - any negative value: searches for the nth occurrence from the right + - 0: raises an exception (`CX_SY_STRG_PAR_VAL`), note: in the context of the `replace` function, 0 means replace all occurrences + - Note: Specifying `occ` affects the default values of `off` and `len` +- `off`: + - Specifies the offset + - Must be of type `i` + - The default value is 0 (search from the beginning of the string) + - Exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised for a negative offset specified and an offset that is longer than the searched string +- `len`: + - Specifies the length + - Must be of type `i` + - The default value is the length of the string (minus a defined offset in `off`) + - The exception `CX_SY_RANGE_OUT_OF_BOUNDS` is raised if the offset is negative and a range is not contained in the searched string +- `pcre`: Regular expression + +``` abap +DATA(str) = `Pieces of cakes.`. +DATA res TYPE i. + +"Searching for substring +"Returns offset of substring found +res = find( val = str sub = `ca` ). "10 + +"Substring not found returns -1 +res = find( val = str sub = `xy` ). "-1 + +"Actual parameter of sub must not be initial when using the find function +TRY. + res = find( val = str sub = `` ). + CATCH cx_sy_strg_par_val. + ... +ENDTRY. + +"The search is case-sensitive by default +res = find( val = str sub = `OF` ). "-1 +"Making search case-insensitive +res = find( val = str sub = `OF` case = abap_false ). "7 + +"Specifying occ +res = find( val = str sub = `c` ). "3 +res = find( val = str sub = `c` occ = 2 ). "10 +res = find( val = str sub = `e` occ = -1 ). "13 +res = find( val = str sub = `e` occ = -3 ). "2 + +"Specifying off and len +"Specifying a subarea in which a string is searched +res = find( val = str sub = `e` off = 5 ). "13 +res = find( val = str sub = `e` off = 5 len = 7 ). "-1 +res = find( val = str sub = `e` len = 2 ). "-1 + +TRY. + res = find( val = str sub = `e` off = 5 len = 15 ). + CATCH cx_sy_range_out_of_bounds. + ... +ENDTRY. +``` + +

⬆️ back to top

+ +### Replacing Substrings in Strings + +- [`REPLACE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace.htm) and [`REPLACE ... IN TABLE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreplace_itab.htm) statements have a similar syntax as `FIND` and `FIND ... IN TABLE` statements. Refer to the ABAP Keyword Documentation for all possible additions. The following code snippets cover a selection. +- `sy-subrc` is set: 0 (search pattern or section was replaced by the specified content, result was not truncated on the right), 2 (search pattern or section was replaced, result was truncated on the right), 4 (search pattern was not found). +- `REPLACE` statements can be used to directly replace strings (including substrings, which is not possible with the string function). + +``` abap +"Examples for pattern-based replacements in which data objects are searched for character strings +"specified in a pattern and the occurrences are replaced + +DATA(str_original) = `abap ABAP abap`. +DATA(str) = str_original. + +"Simple REPLACE statement +"Omitting the FIRST OCCURRENCE and ALL OCCURRENCES OF additions means +"replacing the first occurrence by default. +REPLACE `ab` IN str WITH `##`. "##ap ABAP abap + +str = str_original. + +"Addition SUBSTRING is optional +REPLACE SUBSTRING `ab` IN str WITH `##`. "##ap ABAP abap + +str = str_original. + +"Addition FIRST OCCURRENCE OF: Explicit specification to replace the +"first occurrence; same effect as the statements above +REPLACE FIRST OCCURRENCE OF `ab` IN str WITH `##`. "##ap ABAP abap + +str = str_original. + +"Addition ALL OCCURRENCES OF: All occurrences are replaced +"Note that the replacement is case-sensitive by default. +REPLACE ALL OCCURRENCES OF `ab` IN str WITH `##`. "##ap ABAP ##ap + +str = str_original. + +"Further additional options for advanced evaluation options + +"IGNORING CASE addition: Making replacements case-insensitive +REPLACE ALL OCCURRENCES OF `ab` + IN str WITH `##` + IGNORING CASE. "##ap ##AP ##ap + +str = str_original. + +"REPLACEMENT COUNT addition +REPLACE ALL OCCURRENCES OF `ab` + IN str WITH `##` + REPLACEMENT COUNT DATA(cnt1) "3 + IGNORING CASE. + +str = str_original. + +"REPLACEMENT OFFSET and LENGTH additions +REPLACE FIRST OCCURRENCE OF `ap` + IN str WITH `##` + REPLACEMENT COUNT DATA(cnt2) "1 (always 1 for replaced first occurrence) + REPLACEMENT OFFSET DATA(off2) "2 + REPLACEMENT LENGTH DATA(len2) "2 + IGNORING CASE. "ab## ABAP abap + +str = str_original. + +"SECTION ... OF addition: Replacing within a specified area +REPLACE ALL OCCURRENCES OF `ap` + IN SECTION OFFSET 4 LENGTH 5 + OF str WITH `##` + REPLACEMENT COUNT DATA(cnt3) "1 + REPLACEMENT OFFSET DATA(off3) "2 + REPLACEMENT LENGTH DATA(len3) "2 + IGNORING CASE. "abap AB## abap + +str = str_original. + +"RESULTS additions with ... +"... ALL OCCURRENCES OF +"Note: repl_tab, which is declared inline here, is of type repl_result_tab +REPLACE ALL OCCURRENCES OF `ap` + IN str WITH `##` + RESULTS DATA(repl_tab) + IGNORING CASE. "ab## AB## ab## + +"repl_tab: +"LINE OFFSET LENGTH +"0 2 2 +"0 7 2 +"0 12 2 + +str = str_original. + +"... FIRST OCCURRENCE OF +"Note: repl_struc, which is declared inline here, is of type repl_result +REPLACE FIRST OCCURRENCE OF `ap` + IN str WITH `##` + RESULTS DATA(repl_struc) + IGNORING CASE. + +"repl_struc: +"LINE OFFSET LENGTH +"0 2 2 +``` + +You can use [`REPLACE SECTION ... OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapfind_section_of.htm) statements for position-based replacements, that is, to replace a section in a string starting at a specified offset for a specified length. + +``` abap +DATA(str_original) = `abap ABAP abap`. +DATA(str) = str_original. + +"OFFSET + LENGTH specified +REPLACE SECTION OFFSET 5 LENGTH 4 OF str WITH `#`. "abap # abap + +str = str_original. + +"Only OFFSET (LENGTH: up to the end of the string) +REPLACE SECTION OFFSET 5 OF str WITH `#`. "abap # + +str = str_original. + +"Only LENGTH (OFFSET: starting from the leftmost position) +REPLACE SECTION LENGTH 6 OF str WITH `#`. "#BAP abap +``` + +### Replacing Substrings in Tables + +Replacements in internal tables with `REPLACE ... IN TABLE` (see the notes above for searching in internal tables): +``` abap +DATA(str_table_original) = VALUE string_table( ( `aZbzZ` ) ( `cdZze` ) ( `Zzzf` ) ( `ghz` ) ). +DATA(str_table) = str_table_original. + +"Replacing all occurrences in a table +"RESULTS addition: Storing information in an internal table of type repl_result_tab +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + WITH `#` + RESULTS DATA(res_table) + RESPECTING CASE. + +"str_table: a#bz# / cd#ze / #zzf / ghz +"res_table: +"LINE OFFSET LENGTH +"1 1 1 +"1 4 1 +"2 2 1 +"3 0 1 + +str_table = str_table_original. + +"Replacing the first occurrence in a table +"RESULTS addition: Storing information in a structure of type repl_result +REPLACE FIRST OCCURRENCE OF `Z` + IN TABLE str_table + WITH `#` + RESULTS DATA(res_structure) + RESPECTING CASE. + +"str_table: a#bzZ / cdZze / Zzzf / ghz +"res_structure: +"LINE OFFSET LENGTH +"1 1 1 + +str_table = str_table_original. + +"Restricting the search range in an internal table +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + FROM 1 TO 2 + WITH `#` + RESPECTING CASE. + +"str_table: a#bz# / cd#ze / Zzzf / ghz + +str_table = str_table_original. + +"Offsets can be optionally specified (also only the offset of start or end line possible) +REPLACE ALL OCCURRENCES OF `Z` + IN TABLE str_table + FROM 1 OFFSET 3 TO 2 OFFSET 2 + WITH `#` + RESPECTING CASE. + +"str_table: aZbz# / cdZze / Zzzf / ghz +``` + +### String Function replace +- The string function +[`replace`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreplace_functions.htm), +allows you to store the result of a substring replacement in a separate +variable. +- What makes it especially powerful is that it +returns a value, so it can be used at almost any [read +positions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenread_position_glosry.htm "Glossary Entry"). +- The parameters of the `replace` string functions are similar to those of the `find` function. In addition, there is the `with` parameter for the replacement. Setting `occ` to `0` means that all occurrences are respected for the replacement. + +Syntax examples: +``` abap +DATA(str) = `abap ABAP abap`. +DATA res TYPE string. + +"Note that here only the first occurrence is replaced. +res = replace( val = str sub = `ap` with = `#` ). "ab# ABAP abap + +"Making the search case-insensitive +res = replace( val = str sub = `AB` with = `#` case = abap_false ). "#ap ABAP abap + +"Setting occ +res = replace( val = str sub = `ab` with = `#` occ = 2 case = abap_false ). "abap #AP abap + +"Replacing all occurrences: Setting occ to 0 +res = replace( val = str sub = `ab` with = `#` occ = 0 case = abap_false ). "#ap #AP #ap + +"Negative value for occ: Occurrences are counted from the right +res = replace( val = str sub = `ab` with = `#` occ = -1 ). "abap ABAP #ap + +"Setting off and len for determining a subarea for replacements +"Note: When using off/len, sub and occ cannot be specified. +"Specifying both off and len +res = replace( val = str with = `#` off = 5 len = 3 ). "abap #P abap + +"Specifying only off (len is 0 by default) +res = replace( val = str with = `#` off = 2 ). "ab#ap ABAP abap + +"Note: When specifying only off and not specifying len or len = 0, +"replace works like insert +res = insert( val = str sub = `#` off = 2 ). "ab#ap ABAP abap + +"Specifying only len (off is 0 by default): First segment of length in len is replaced +res = replace( val = str with = `#` len = 3 ). "#p ABAP abap + +"Special case +"- off: equal to the length of the string +"- len: not specified or 0 +"- Result: Value specified for 'with' is appended to the end of the string +res = replace( val = str with = `#` off = strlen( str ) ). "abap ABAP abap# +``` + +## Pattern-Based Searching and Replacing in Strings + +You can perform complex search and replace operations based on +patterns. [PCRE regular +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpcre_regex_glosry.htm "Glossary Entry") +help you process strings effectively. +> **💡 Note**
+> Do not use [POSIX +regular +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenposix_regex_glosry.htm "Glossary Entry") +anymore, they are obsolete. + +

⬆️ back to top

+ +### Simple Pattern-Based Searching Using Comparison Operators + +For simple patterns, you can use the [comparison +operators](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomp_operator_glosry.htm "Glossary Entry") +[`CP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) +(conforms to pattern) or its negation +[`NP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_strings.htm) +(does not conform to pattern) in [comparison +expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm "Glossary Entry") +to determine whether a set of characters is contained in a string that +matches a particular pattern. You can use the following +special characters as patterns: + +| Special Character | Details | +|---|---| +| `*` | Any character sequence (including blanks). | +| `+` | Any character (only one character, including blanks). | +| `#` | Escape character. The following character is marked for an exact comparison. | + +Patterns are not case-sensitive except for characters marked with +`#`. If a pattern is found, the system variable +`sy-fdpos` returns the offset of the first occurrence. +Otherwise, it contains the length of the searched string. +``` abap +DATA(s1) = `abc_def_ghi`. + +"Pattern: f is preceded by any character sequence, must be followed +"by '_' and then followed by any character sequence +IF s1 CP `*f#_*`. ... "true; sy-fdpos = 6 + +"Pattern: 'i' is not followed by another character +IF s1 NP `i+`. ... "true; sy-fdpos = 11 (length of searched string) +``` + +

⬆️ back to top

+ +### Complex Searching and Replacing Using Regular Expressions + +#### Excursion: Common Regular Expressions + +There are several ways to perform complex searches in strings using PCRE expressions. They can be quite complex. The following overview shows common PCRE expressions with simple examples. +For more information, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_pcre_syntax_specials.htm). + +Characters and character types + +| Expression | Represents | Example Regex | Example String | Matches | Does not Match | +|---|---|---|---|---|---| +| `x` | Specific character | `a` | abcdef | a | Anything else | +| `.` | Anything except a line break | `.` | ab 1# | a, b, the blank, 1, # | ab, 1# | +| `\d` | Any digit (0-9), alternative: `[0-9]` | `\d` | a1-b2 3-4c9 | 1, 2, 3, 4, 9 | a, b, c, the blank and hyphens | +| `\D` | Any non-digit, alternative: `[^0-9]` | `\D` | a1-b2 3-4c9 | a, b, c, the blank and hyphens | 1, 2, 3, 4, 9 | +| `\s` | Any whitespace character such as a blank, tab and new line | `\s` | (hi X ) | The blanks | h, i, X, (, ) | +| `\S` | Any character that is not a whitespace | `\S` | (hi X ) | h, i, X, (, ) | The blanks | +| `\w` | Any word character (letter, digit or the underscore), alternative: `[a-zA-Z0-9_]` | `\w` | (ab 12_c) | a, b, c, 1, 2, _ | (, ), the blank | +| `\W` | Any character that is not a word character, alternative: `[^a-zA-Z0-9_]` | `\W` | (ab 12_c) | (, ), the blank | a, b, c, 1, 2, _ | +| `\` | To include special characters like `[] \ / ^`, use `\` to escape them. Use `\.` to match a period ("."). | `.\.` | ab.cd.ef | a**b.**c**d.**ef | ab**.c**d**.e**f | + +Repetitions and Alternatives + +| Expression | Represents | Example Regex | Example String | Matches | Does not Match | +|---|---|---|---|---|---| +| `x*` | Zero or more repetitions of `x` | `ab*` | abc abbc abbbc a ac | **ab**c **abb**c **abbb**c **a** **a**c | **abc** **abbc** **abbbc** a **ac** | +| `x+` | One or more repetitions of `x` | `ab+` | abc abbc abbbc a ac | **ab**c **abb**c **abbb**c a ac | ... **a** **a**c | +| `x{m,n}` | Between `m` and `n` repetitions of `x` | `ab{2,3}` | abc abbc abbbc a ac | abc **abb**c **abbb**c a ac | **ab**c ... | +| `x{m}` | Exactly `m` repetitions | `ab{3}` | abc abbc abbbc a ac | abc abbc **abbb**c a ac | abc **abb**c ... | +| `x{m,}` | Exactly `m` or more repetitions | `ab{2,}` | abc abbc abbbc a ac | abc **abb**c **abbb**c a ac | **ab**c ... | +| `x?` | Optional `x`, i.e. zero or one time | `ab?` | abc abbc abbbc a ac | **ab**c **ab**bc **ab**bbc **a** **a**c | ... **ac** | +| `x\|y` | Matching alternatives, i. e. `x` or `y` | 1. `b\|2`
2. `b(a\|u)t` | 1. abc 123
2. bit bat but bet | 1. b, 2
2. bat, but | 1. a, c, 1, 3
2. bit, bet | +| `x*?` | `x*` captures greedily, i.e. as much as possible, while `x*?` captures non-greedily, i.e. as few as possible | 1. `bc*?`
2. `a.*?#` | 1. abcd abccccd ab
2. abc#defgh#i | 1. a**b**cd a**b**ccccd a**b**
2. **abc#**defgh#i | 1. a**bc**d a**bcccc**d a**b** (result for `bc*`)
2. **abc#defgh#**i (result for `a.*#`) | +| `x+?` | Same as above: `x+` (greedy), `x+?` (non-greedy) | 1. `bc+?`
2. `<.+?>` | 1. abcd abccccd ab
2. <span>Hallo</span> html. | 1. a**bc**d a**bc**cccd ab
2. **<span>**Hallo**</span>** html. | 1. a**bc**d a**bcccc**d ab (result for `bc+`)
2. **<span>Hallo</span>** html. (result for `<.+>`) | + +Character Sets, Ranges, Subgroups and Lookarounds +| Expression | Represents | Example Regex | Example String | Matches | Does not Match | +|---|---|---|---|---|---| +| `[xy]` | Character set, matches a single character present in the list | `b[iu]` | bit bat but bet | **bi**t bat **bu**t bet | bit **ba**t but **be**t | +| `[x-y]` | Character range, matches a single character in the specified range, note that ranges may be locale-dependent | `a[a-c0-5]` | aa1 ab2 ba3 cac4 da56 a7 |**aa**1 **ab**2 b**a3** c**ac**4 d**a5**6 a7 | aa1 ab2 ba3 cac4 da56 **a7** | +| `[^xy]` | Negation, matches any single character not present in the list | `[^Ap]` | ABap | B, a | A, p | +| `[^x-y]` | Negation, matches any single character not within the range | `[^A-Ca-c1-4]` | ABCDabcd123456 | D, d, 5, 6 | A, B, C, a, b, c, 1, 2, 3, 4 | +| `(...)` | Capturing group to group parts of patterns together | `b(a\|u)t` | bit bat but bet | bat, but | bit, bet | +| `(?=...)` | Positive lookahead, returns characters that are followed by a specified pattern without including this pattern | `a(?=b)` | abc ade | **a**bc ade | abc **a**de | +| `(?!...)` | Negative lookahead, returns characters that are not followed by a specified pattern without including this pattern | `a(?!b)` | abc ade | abc **a**de | **a**bc ade | +| `(?<=...)` | Positive lookbehind, returns characters that are preceded by a specified pattern without including this pattern | `(?<=\s)c` | ab c abcd | ab **c** abcd (it is preceded by a blank) | ab c ab**c**d | +| `(?**c**d (it is not preceded by a blank) | ab **c** abcd | +| `\n` | Backreference, refers to a previous capturing group; n represents the number of the group index that starts with 1 | `(a.)(\w*)\1` | abcdefabghij | **abcdefab**ghij
Note: Capturing group 1 holds `ab` in the example. The second capturing group captures all word characters until `ab` is found. | **ab**cdefabghij | +| `\K` | Resets the starting point of a match, i.e. findings are excluded from the final match | `a.\Kc` | abcd | ab**c**d | **abc**d | + +> **💡 Note**
+> - Subgroups are useful in replacements. By using an expression with `$` and a number, such as `$1`, you can refer to a specific group. For example, you have a string `abcde`. A PCRE expression might be +`(ab|xy)c(d.)`, where two subgroups are specified within two pairs of parentheses. In a replacement pattern, you can refer to the first group with `$1` and the second group with `$2`. Thus, the replacement pattern `$2Z$1` results in `deZab`. +> - `(?:x)` creates a group but it is not captured. Example regular expression: `(?:ab)(ap)`. Example string: 'abap'. It matches 'abap', but `$1` will only contain 'ap'. + +Anchors and Positions + +| Expression | Represents | Example Regex | Example String | Matches | Does not Match | +|---|---|---|---|---|---| +| `^` | Start of line, alternative: `\A` | `^.` or `\A.` | abc def | **a**bc def | abc **d**ef | +| `$` | End of line, alternative: `\Z` | `.$` or `.\Z` | abc def | abc de**f** | **a**bc def | +| `\b` | Start or end of word | 1. `\ba.`
2. `\Dd\b`
3. `\b.d\b` | abcd a12d ed | 1. **ab**cd **a1**2d ed
2. ab**cd** a12d **ed**
3. abcd a12d **ed** | 1. ab**cd** a1**2d** ed
2. abcd a1**2d** ed
3. **abcd** **a12d** ed | +| `\B` | Negation of `\b`, not at the start or end of words | `\Be\B` | see an elefant | s**e**e an el**e**fant | s**ee** an **e**lefant | + +

⬆️ back to top

+ +#### Searching Using Regular Expressions + +- Multiple string functions support PCRE expressions by offering the + `pcre` parameter, which you can use to specify such an expression. +`FIND` and `REPLACE` statements support regular +expressions with the `PCRE` addition. +- The string function +[`match`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmatch_functions.htm) +works only with regular expressions. It returns a substring that +matches a regular expression within a string. +- For comparisons, you can +also use the [predicate +function](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_function_glosry.htm "Glossary Entry") +[`matches`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmatches_functions.htm), which returns true or false if a string matches a given pattern or not. + +Syntax examples: +``` abap +DATA(s1) = `Cathy's black cat on the mat played with Matt.`. + +"Determining the position of the first occurrence +"Here, the parameter occ is 1 by default. +DATA(int) = find( val = s1 pcre = `at.` ). "1 + +"Determining the number of all occurrences. +"Respects all 'a' characters not followed by 't', all 'at' plus 'att' +int = count( val = s1 pcre = `at*` ). "6 + +"Respects all 'at' plus 'att' +int = count( val = s1 pcre = `at+` ). "4 + +"Extracting a substring matching a given pattern +DATA(s2) = match( val = `The email address is jon.doe@email.com.` + pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ). "jon.doe@email.com + +"Predicate function matches +"Checking the validitiy of an email address +IF matches( val = `jon.doe@email.com` + pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ). "true +... +ENDIF. + +"Examples with the FIND statement +"SUBMATCHES addition: Storing submatches in variables +"Pattern: anything before and after ' on ' +FIND PCRE `(.*)\son\s(.*)` IN s1 IGNORING CASE SUBMATCHES DATA(a) DATA(b). +"a: 'Cathy's black cat' / b: 'the mat played with Matt.'. + +"Determining the number of letters in a string +FIND ALL OCCURRENCES OF PCRE `[A-Za-z]` IN s1 MATCH COUNT DATA(c). "36 + +"Searching in an internal table and retrieving line, offset, length information +DATA(itab) = value string_table( ( `Cathy's black cat on the mat played with the friend of Matt.` ) ). +"Pattern: 't' at the beginning of a word followed by another character +FIND FIRST OCCURRENCE OF PCRE `\bt.` IN TABLE itab + IGNORING CASE MATCH LINE DATA(d) MATCH OFFSET DATA(e) MATCH LENGTH DATA(f). "d: 1, e: 21, f: 2 +``` +

⬆️ back to top

+ +#### System Classes for Regular Expressions + +- You can create an object-oriented representation of regular expressions using the `CL_ABAP_REGEX` system class. +- For example, the `CREATE_PCRE` method creates instances of regular expressions with PCRE syntax. +- The instances can be used, for example, with the `CL_ABAP_MATCHER` class, which applies the regular expressions. +- A variety of methods and parameters can be specified to accomplish various things and to further specify the handling of the regular expression. +- More information can be found [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenregex_system_classes.htm) and in the class documentation (choose F2 on the class in ADT). + + +``` abap +DATA(str) = `a1 # B2 ? cd . E3`. + +"Creating a regex instance for PCRE regular expressions +"In the example, regex_inst has the type ref to cl_abap_regex. +DATA(regex_inst) = cl_abap_regex=>create_pcre( pattern = `\D\d` "any-non digit followed by a digit + ignore_case = abap_true ). + +"Creating an instance of CL_ABAP_MATCHER using the method CREATE_MATCHER of the class CL_ABAP_REGEX +"You can also specify internal tables with the 'table' parameter and more. +DATA(matcher) = regex_inst->create_matcher( text = str ). + +"Finding all results using the 'find_all' method +"In the example, result has the type match_result_tab containing the findings. +DATA(result) = matcher->find_all( ). + +"Using method chaining +DATA(res) = cl_abap_regex=>create_pcre( pattern = `\s\w` "any blank followed by any word character + ignore_case = abap_true )->create_matcher( text = str )->find_all( ). +``` + +

⬆️ back to top

+ +#### Replacing Using Regular Expressions + +- To perform replacement operations using regular expressions, you can use both +the string function `replace` and `REPLACE` statements with the `pcre` parameter or the `PCRE` addition. +- Like the `find` function, among others, and +`FIND` statements, the `replace` function and +`REPLACE` statements offer a number of parameters and additions that you can use to further restrict the area to be replaced. +- For more detailed information, refer to the ABAP +Keyword Documentation. +- The executable example covers many of the PCRE expressions listed above. + +Syntax examples: +``` abap +DATA(s1) = `ab apppc app`. +DATA s2 TYPE string. + +"Replaces 'p' with 2 - 4 repetitions, all occurences +s2 = replace( val = s1 pcre = `p{2,4}` with = `#` occ = 0 ). "ab a#c a# + +"Replaces any single character not present in the list, all occurences +s2 = replace( val = s1 pcre = `[^ac]` with = `#` occ = 0 ). " "a##a###c#a## + +"Replaces first occurence of a blank +s2 = replace( val = s1 pcre = `\s` with = `#` ). "ab#apppc app + +"Greedy search +"The pattern matches anything before 'p'. The matching is carried out as +"often as possible. Hence, in this example the search stretches until the +"end of the string since 'p' is the final character, i. e. this 'p' and +"anything before is replaced. +s2 = replace( val = s1 pcre = `.*p` with = `#` ). "# + +"Non-greedy search +"The pattern matches anything before 'p'. The matching proceeds until +"the first 'p' is found and does not go beyond. It matches as few as +"possible. Hence, the first found 'p' including the content before +"is replaced. +s2 = replace( val = s1 pcre = `.*?p` with = `#` ). "#ppc app + +"Replacements with subgroups +"Replaces 'pp' (case-insensitive here) with '#', the content before and after 'pp' is switched +s2 = replace( val = s1 + pcre = `(.*?)PP(.*)` + with = `$2#$1` + case = abap_false ). "pc app#ab a + +"Changing the source field directly with a REPLACE statement; same as above +REPLACE PCRE `(.*?)PP(.*)` IN s1 WITH `$2#$1` IGNORING CASE. "pc app#ab a +``` + +

⬆️ back to top

+ +## More String Functions + +### Checking the Similarity of Strings + +- [`distance`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendistance_functions.htm) returns the Levenshtein distance between two strings, which reflects their similarity. +- Unlike other string functions, the return value has the type `i`. +- Optional addition `max`: Positive integer. The calculation of the Levenshtein distance will stop if the calculated value is greater than this integer. + +```abap +DATA(str_to_check) = `abap`. +DATA(dist1) = distance( val1 = str_to_check val2 = `abap` ). "0 +DATA(dist2) = distance( val1 = str_to_check val2 = `axbap` ). "1 +DATA(dist3) = distance( val1 = str_to_check val2 = `yabyyapy` ). "4 +DATA(dist4) = distance( val1 = str_to_check val2 = `zabapzzzzzzzzzzzz` max = 5 ). "5 + +"If the value of max is 0 or less, an exception is raised. +TRY. + DATA(dist5) = distance( val1 = str_to_check val2 = `#ab#ap#` max = 0 ). + CATCH cx_sy_strg_par_val. + ... +ENDTRY. +``` + +### Repeating Strings +- [`repeat`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrepeat_functions.htm) returns a string that contains the content of a specified string for parameter `val` as many times as specified in the parameter `occ`. +- An empty string is returned when `occ` has the value 0 or `val` is empty. + +```abap +DATA(repeat1) = repeat( val = `abap` occ = 5 ). "abapabapabapabapabap +DATA(repeat2) = |#{ repeat( val = ` ` occ = 10 ) }#|. "# # +DATA(repeat3) = COND #( WHEN repeat( val = `a` occ = 0 ) = `` THEN `Y` ELSE `Z` ). "Y (initial value returned) + +"If occ has a negative value, an exception is raised. +TRY. + DATA(repeat4) = repeat( val = `X` occ = -3 ). + CATCH cx_sy_strg_par_val. + ... +ENDTRY. +``` + +

⬆️ back to top

+ +### Returning the Smallest/Biggest of a Set of Character-Like Arguments +- [`cmin/cmax`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencmax_cmin_functions.htm) returns a string that contains the content of the smallest or biggest of a set of character-like arguments +- 'Set' means at least two arguments and a maximum of nine argeuments are passed (`valn` operators) for comparison. +- The comparison is made from left to right, and the first different character found determines the smaller or bigger argument. + +```abap +DATA(min) = cmin( val1 = `zzzzzzz` + val2 = `zzazzzzzzzz` "smallest argument + val3 = `zzzzabc` ). + +DATA(max) = cmax( val1 = `abcdef` "biggest argument + val2 = `aaghij` + val3 = `aaaaklmn` + val4 = `aaaaaaopqrs` + val5 = `aaaaaaaaaatuvwxy` + val6 = `aaaaaaaaaaaaaz` ). +``` + +

⬆️ back to top

+ +### Escaping Special Characters +- [`escape`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenescape_functions.htm) returns a string that is provided for the `val` parameter by escaping special characters according to the specification in the `format` parameter. +- Suitable values for the `format` parameter (which expects a data object of type `i`) are available in the `CL_ABAP_FORMAT` class (the constants starting with `E_`). +- Special rules apply to different contexts, such as URLS and JSON. Also note the prevention of Cross Site Scripting (XSS) attacks on web applications. For more information, refer to the [documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenescape_functions.htm). + +```abap +"Context: URLs +DATA(esc1) = escape( val = '...test: 5@8...' + format = cl_abap_format=>e_url_full ). +"...test%3A%205%408... + +"Context: JSON +DATA(esc2) = escape( val = 'some "test" json \ with backslash and double quotes' + format = cl_abap_format=>e_json_string ). +"some \"test\" json \\ with backslash and double quotes + + +"Context: String templates +DATA(esc3) = escape( val = 'Special characters in string templates: |, \, {, }' + format = cl_abap_format=>e_string_tpl ). +"Special characters in string templates: \|, \\, \{, \} + +"Invalid value for the format parameter +TRY. + DATA(esc4) = escape( val = 'This will raise an exception due to an invalid format value.' + format = 123 ). + CATCH cx_sy_strg_par_val. +ENDTRY. +``` + +

⬆️ back to top

+ +## Excursions + +### Comparison Operators for Character-Like Data Types in a Nutshell + +The comparison operators have already been covered in different sections above. This is a summary of the operators. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Comparison OperatorDetailsExample
CAContains any
To determine whether any character of a given character set is contained +in a string.
Note: The search is case-sensitive. sy-fdpos contains the offset of the first character found, while 0 stands for the very first position. If nothing is found, sy-fdpos contains the length of the string.
+ +```abap +DATA(s1) = `cheers`. +IF s1 CA `aeiou`. ... "true; sy-fdpos: 2 +IF s1 CA `xy`. ... "false; sy-fdpos: 6 +``` + +
NAContains not any
To determine whether any character of a given character set is not contained +in a string. See the note above.
+ +```abap +DATA(s2) = `Hallo`. +IF s2 NA `bcdeh`. ... "true; sy-fdpos: 5 +IF s2 NA `bcdeH`. ... "false; sy-fdpos: 0 +``` + +
COContains only
To determine whether a string contains only a certain set of characters. See the note above.
+ +```abap +DATA(s3) = `abcd`. +IF s3 CO `abcd`. ... "true; sy-fdpos: 4 +IF s3 CO `abCd`. ... "false; sy-fdpos: 2 +``` + +
CNContains not only
To determine whether a string does not only contain a certain set of characters, i.e. whether a string contains characters other than those in the character set. See the note above.
+ +```abap +DATA(s4) = `abap`. +IF s4 CN `ab`. ... "true; sy-fdpos: 3 +IF s4 CN `abp`. ... "false; sy-fdpos: 4 +``` + +
CSContains string
For simple substring searches and determining whether a string contains a substring.
Note: The search is not case-sensitive. sy-fdpos contains the offset of the first substring found. If it is not found, sy-fdpos contains the length of the string searched.
+ +```abap +DATA(s5) = `Lorem ipsum dolor sit amet.`. +IF s5 CS `or`. ... "true; sy-fdpos: 1 +IF s5 CS `zz`. ... "false; sy-fdpos: 27 +``` + +
NSContains no string
To determine whether a substring is not contained in a string. See the note for CS.
+ +```abap +DATA(s6) = `some test string`. +IF s6 NS `tests`. ... "true; sy-fdpos: 16 +IF s6 NS `TEST`. ... "false; sy-fdpos: 5 +``` + +
CPConforms to pattern
For simple pattern searches and determining whether a set of characters is contained in a string that matches a particular pattern. You can use the following special characters as patterns:
  • *: Any character sequence (including blanks)
  • +: Any character (only one character, including blanks)
  • #: Escape character. The following character is marked for an exact comparison.
Patterns are not case-sensitive except for characters marked with +#. If a pattern is found, sy-fdpos returns the offset of the first occurrence. Otherwise, it contains the length of the string searched. +
+ +```abap +DATA(s7) = `abc_def_ghi`. + +"Pattern: f is preceded by any character sequence, must be followed +"by '_' and then followed by any character sequence +IF s7 CP `*f#_*`. ... "true; sy-fdpos: 6 + +"Pattern: i is preceded by any character sequence, must be followed +"by any character or a blank +IF s7 CP `*i+`. ... "false; sy-fdpos: 11 +``` + +
NPDoes not conform to pattern
Negation of CP. See the previous notes.
+ +```abap +DATA(s8) = `abcDEFghi`. + +"Pattern: c is preceded by any character sequence, must be followed +"by a small letter d, and then followed by any character sequence +IF s8 NP `*c#d*`. ... "true; sy-fdpos: 9 + +"Pattern: c is preceded by any character sequence, must be followed +"by a capital letter D, and then followed by any character sequence +IF s8 NP `*c#D*`. ... "false; sy-fdpos: 2 +``` + +
+ +

⬆️ back to top

+ +### String Processing Using the XCO Library +The Extension Components Library (XCO) library provides [released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreleased_api_glosry.htm) and offers various development utilities. Find more information [here](https://help.sap.com/docs/btp/sap-business-technology-platform/overview-of-xco-modules). The following code snippet demonstrates several methods of the `XCO_CP` class that deal with string processing. + +```abap +"--------- Extracting a substring from a string --------- +DATA(some_string) = `abcdefghijklmnopqrstuvwxyz`. + +"Creating an encapsulation of a string using XCO +DATA(str) = xco_cp=>string( some_string ). + +"Using the FROM and TO methods, you can determine +"the character position. Note that the value includes the +"character at the position specified. +"The character index pattern for the example string above +"is (the string has 26 characters in total): +"a = 1, b = 2, c = 3 ... z = 26 +"a = -26, b = -25, c = -24 ... z = -1 +"Providing a value that is out of bounds means that +"the first (or the last) character of the string is used +"by default. +"Note: When combining FROM and TO, e.g. with method +"chaining ...->from( ...)->to( ... ), note that another +"instance is created with the first 'from', and another +"character index pattern is created based on the new +"and adjusted string value. + +"bcdefghijklmnopqrstuvwxyz +DATA(sub1) = str->from( 2 )->value. + +"defghijklmnopqrstuvwxyz +DATA(sub2) = str->from( -23 )->value. + +"vwxyz +DATA(sub3) = str->from( -5 )->value. + +"abcde +DATA(sub4) = str->to( 5 )->value. + +"ab +DATA(sub5) = str->to( -25 )->value. + +"Result of 1st 'from' method call: bcdefghijklmnopqrstuvwxyz +"Based on this result, the 'to' method call is +"applied. +"bcdefg +DATA(sub6) = str->from( 2 )->to( 6 )->value. + +"Result of 1st 'to' method call: abcdefghijklmnopq +"Based on this result, the 'from' method call is +"applied. +"defghijklmnopq +DATA(sub7) = str->to( -10 )->from( 4 )->value. + +"Values that are out of bounds. +"In the example, the first and last character of the +"string are used. +"abcdefghijklmnopqrstuvwxyz +DATA(sub8) = str->from( 0 )->to( 100 )->value. + +"--------- Splitting and joining --------- + +"Splitting a string into a string table +DATA(str_table) = xco_cp=>string( `Hello.World.ABAP` )->split( `.` )->value. +"Hello +"World +"ABAP + +"Concatenating a string table into a string; specifying a delimiter +str_table = VALUE #( ( `a` ) ( `b` ) ( `c` ) ). +"a, b, c +DATA(conc_str1) = xco_cp=>strings( str_table )->join( `, ` )->value. + +"Concatenating a string table into a string; specifying a delimiter and +"reversing the table order +"c / b / a +DATA(conc_str2) = xco_cp=>strings( str_table )->reverse( )->join( ` / ` )->value. + +"--------- Prepending and appending strings --------- +DATA(name) = xco_cp=>string( `Max Mustermann` ). + +"Max Mustermann, Some Street 1, 12345 Someplace +DATA(address) = name->append( `, Some Street 1, 12345 Someplace` )->value. + +"Mr. Max Mustermann +DATA(title) = name->prepend( `Mr. ` )->value. + +"--------- Transforming to lowercase and uppercase --------- +"ABAP +DATA(to_upper) = xco_cp=>string( `abap` )->to_upper_case( )->value. + +"hallo world +DATA(to_lower) = xco_cp=>string( `HALLO WORLD` )->to_lower_case( )->value. + +"--------- Checking if a string starts/ends with a specific string --------- +DATA check TYPE string. +DATA(str_check) = xco_cp=>string( `Max Mustermann` ). + +"yes +IF str_check->ends_with( `mann` ). + check = `yes`. +ELSE. + check = `no`. +ENDIF. + +"no +IF str_check->starts_with( `John` ). + check = `yes`. +ELSE. + check = `no`. +ENDIF. + +"--------- Converting strings to xstrings using a codepage --------- +"536F6D6520737472696E67 +DATA(xstr) = xco_cp=>string( `Some string` )->as_xstring( xco_cp_character=>code_page->utf_8 )->value. + +"--------- Camel case compositions and decompositions with split and join operations --------- +"Pascal case is also possible +"someValue +DATA(comp) = xco_cp=>string( `some_value` )->split( `_` )->compose( xco_cp_string=>composition->camel_case )->value. + +"Camel case decomposition +"some_value +DATA(decomp) = xco_cp=>string( `someValue` )->decompose( xco_cp_string=>decomposition->camel_case )->join( `_` )->value. + +"--------- Matching string against regular expression --------- +DATA match TYPE string. + +"yes +IF xco_cp=>string( ` 1` )->matches( `\s\d` ). + match = 'yes'. +ELSE. + match = 'no'. +ENDIF. + +"no +IF xco_cp=>string( ` X` )->matches( `\s\d` ). + match = 'yes'. +ELSE. + match = 'no'. +ENDIF. +``` + +

⬆️ back to top

+ +## Executable Example + +[zcl_demo_abap_string_proc](./src/zcl_demo_abap_string_proc.clas.abap) + +> **💡 Note**
+> - The executable example ... +> - covers the following topics: +> - Creating strings and assigning values +> - String templates +> - Operations with strings operations: chaining, concatenating, splitting, modifying +> - Searching and replacing +> - Regular expressions +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) diff --git a/08_EML_ABAP_for_RAP.md b/08_EML_ABAP_for_RAP.md index 1c67643..a089161 100644 --- a/08_EML_ABAP_for_RAP.md +++ b/08_EML_ABAP_for_RAP.md @@ -1,1719 +1,1719 @@ - - -# ABAP for RAP: Entity Manipulation Language (ABAP EML) - -- [ABAP for RAP: Entity Manipulation Language (ABAP EML)](#abap-for-rap-entity-manipulation-language-abap-eml) - - [RAP Terms](#rap-terms) - - [Excursion: RAP Behavior Definition (BDEF)](#excursion-rap-behavior-definition-bdef) - - [ABAP Behavior Pools (ABP)](#abap-behavior-pools-abp) - - [RAP Handler Classes and Methods](#rap-handler-classes-and-methods) - - [RAP Saver Class and Saver Methods](#rap-saver-class-and-saver-methods) - - [BDEF Derived Types](#bdef-derived-types) - - [Components of BDEF Derived Types](#components-of-bdef-derived-types) - - [EML Syntax](#eml-syntax) - - [EML Syntax for Modifying Operations](#eml-syntax-for-modifying-operations) - - [EML Syntax for Reading Operations](#eml-syntax-for-reading-operations) - - [Dynamic Forms of EML Statements](#dynamic-forms-of-eml-statements) - - [Persisting to the Database](#persisting-to-the-database) - - [Raising RAP Business Events](#raising-rap-business-events) - - [Additions to EML Statements in ABAP Behavior Pools](#additions-to-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) - - [Ensuring Data Consistency in a RAP Transaction](#ensuring-data-consistency-in-a-rap-transaction) - - [More Information](#more-information) - - [Executable Examples](#executable-examples) - -## RAP Terms - -[ABAP Entity Manipulation Language](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenaeml_glosry.htm) (or EML for short) is a subset of ABAP that allows you to access the data of [RAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarap_glosry.htm) business objects in an ABAP program. -The following points cover RAP-related terms such as *RAP business objects* and others for setting the context: - -- RAP business objects (RAP BO) - - A RAP BO is based on a special, tree-like hierarchical structure - of [CDS - entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm "Glossary Entry") - of a data model - - Such a structure of entities consists of [parent - entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparent_entity_glosry.htm "Glossary Entry") - and [child - entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenchild_entity_glosry.htm "Glossary Entry") - that are themselves defined using [CDS - compositions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_composition_glosry.htm "Glossary Entry") - and [to-parent - associations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abento_parent_association_glosry.htm "Glossary Entry"). - - The top parent entity of a [CDS composition - tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_composition_tree_glosry.htm "Glossary Entry") - is the root entity that represents the business object. With a - large composition tree, RAP BOs can be fairly complex. Or they - can be very simple by just consisting of one root entity alone. - - Note: There is a special syntax for the [CDS root entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenroot_entity_glosry.htm) of a RAP BO: [`define root view entity`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_define_root_view_v2.htm) -- [RAP behavior - definition](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_behavior_definition_glosry.htm "Glossary Entry") - (BDEF) - - RAP BOs are described by the definitions specified in a special - [DDIC](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_glosry.htm "Glossary Entry") - artifact: RAP behavior definition (BDEF) - - A BDEF defines the [RAP business object - behavior](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_behavior_glosry.htm "Glossary Entry") - (i. e. the transactional behavior of a RAP BO) - - Transactional behavior means a BDEF defines [behavior - characteristics](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_properties_glosry.htm "Glossary Entry") - and [RAP BO - operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_operation_glosry.htm "Glossary Entry") i. - e. [RAP BO standard - operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_standard_operation_glosry.htm "Glossary Entry") - ([CRUD - operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencrud_glosry.htm "Glossary Entry")), - [non-standard - operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_nstandard_operation_glosry.htm "Glossary Entry") - like specific [RAP - actions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_action_glosry.htm "Glossary Entry") - and - [functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_function_glosry.htm "Glossary Entry"), - and more. - - There are many other things that can be included impacting the - RAP BO behavior like [RAP feature - control](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_feature_control_glosry.htm "Glossary Entry"), - for example, defining which data is mandatory and which is - read-only, or - [determinations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_determination_glosry.htm "Glossary Entry") - and - [validations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_validation_glosry.htm "Glossary Entry"). - - BDEFs use [Behavior Definition - Language](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_glosry.htm "Glossary Entry") - (BDL) for the definitions. Find more information on the topic - and various options to define the transactional behavior in - section [BDL for Behavior - Definitions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl.htm) - in the ABAP Keyword Documentation. -- Transactional buffer and implementation types - - A BDEF defines the behavior of a RAP BO and, thus, how to handle - its data. This data is available in the [RAP transactional - buffer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_buffer_glosry.htm "Glossary Entry"). - - It is a storage for a RAP BO's data that is used and worked on - during an [SAP LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw_glosry.htm). - - This data includes [RAP BO - instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_instance_glosry.htm "Glossary Entry") - (i. e. concrete data sets of an entity). This is where EML - enters the picture: EML is used, among others, to access this data in the transactional buffer. - - Currently, there are two kinds of RAP BOs: - [managed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmanaged_rap_bo_glosry.htm "Glossary Entry") - and [unmanaged RAP - BOs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunmanaged_rap_bo_glosry.htm "Glossary Entry"). - - Managed and unmanaged are implementation types that are also - specified in the BDEF. - - The implementation type determines the [RAP BO - provider](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_provider_glosry.htm "Glossary Entry"), i. - e. how the transactional buffer is provided and how the behavior - of a RAP BO is implemented. -- Managed RAP BOs: - - The managed RAP BO provider fully or partly provides the - transactional buffer and RAP BO behavior (for standard - operations only). In this case, the developers need not cater - for the transactional buffer and implement the standard - operations. This implementation is mostly relevant for - greenfield scenarios when starting from scratch. - - Example: Regarding CRUD operations in managed RAP BOs, - developers need not cater for an implementation at all. The - standard operations work out of the box. For example, in case of - an update operation, RAP BO instance data that is to be updated - is automatically read into the transactional buffer, and then - updated accordingly there. Finally, when triggering the saving, - the updated instance in the transactional buffer is - automatically saved to the database without any custom - development needed. - - The transactional buffer is provided, too. You do not need to - create the buffer yourself. - - Note: Usually, the behavior of a RAP BO requires some - additional implementations also in the context of managed RAP - BOs. For example, non-standard operations or feature controls - must be self-implemented in [ABAP behavior - pools](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbehavior_pool_glosry.htm "Glossary Entry") - (see the details further down). -- Unmanaged RAP BOs: - - Everything must be provided by the [unmanaged RAP BO - provider](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunmanaged_rap_bo_prov_glosry.htm "Glossary Entry"), i. - e. the transactional buffer and all RAP BO operations must be - provided or self-implemented by developers in an ABAP behavior - implementation - - Unmanaged RAP BOs are, for example, relevant for brownfield - scenarios, i. e. in scenarios in which transactional buffers and application logic is already - available and should be embedded in the RAP world. Note that it is possible to have a managed RAP BO with unamanged parts, e.g. unamanged save or additional save. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_rap_bo.htm). -- ABAP behavior implementation in an ABAP behavior pool (ABP) - - An [ABAP behavior - pool](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbehavior_pool_glosry.htm "Glossary Entry") - is a special [class - pool](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_pool_glosry.htm "Glossary Entry") - for an ABAP behavior implementation that implements the - unmanaged RAP BO provider based on definitions in a BDEF. The - class pool's name is specified in the BDEF. - - The [global - class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_class_glosry.htm "Glossary Entry") - of a behavior pool does not implement the behavior itself. It is - (initially) empty apart from the declaration and implementation part skeletons. The behavior implementation is coded in local - [RAP handler - classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm "Glossary Entry") - and a [RAP saver - class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class_glosry.htm "Glossary Entry") - in the [CCIMP - include](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenccimp_glosry.htm "Glossary Entry") - of the behavior pool. These classes are called by the [RAP - runtime - engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_runtime_engine_glosry.htm "Glossary Entry") - when the RAP BO is accessed. This is covered in more detail - further down. - - Usually, saver classes are not needed in managed RAP BOs (except - for special variants of managed RAP BOs which are not covered - here). Local handler classes are, as mentioned above, usually - needed in managed RAP BOs if implementations are required that - go beyond standard operations. - - Note: In more complex scenarios, with RAP BOs that - consist of many entities, you can define behavior pools for - individual entities by adding the syntax to the [`define - behavior - for`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_define_beh.htm) - notation. There is not a saver class for each entity but only - one saver class for the BO as a whole. Any number of behavior - pools can be assigned to a BDEF allowing applications a - structuring into multiple units. - - -Find more terms in the [RAP Glossary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_glossary.htm) of the ABAP Keyword Documentation. -There are more artifacts and concepts related to RAP that go way beyond -the scope of this cheat sheet. For example, a RAP BO can be exposed as a -[business -service](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbusiness_service_glosry.htm "Glossary Entry") -to be accessed from outside [AS -ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenas_abap_sys_environ_glosry.htm "Glossary Entry") -and consumed. A [RAP BO -consumer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_consumer_glosry.htm "Glossary Entry") -is either the [RAP transactional -engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_transac_engine_glosry.htm "Glossary Entry") -that handles requests from outside the AS ABAP or, from inside AS ABAP, -an ABAP program using ABAP EML (which this cheat sheet and the examples -focus on). - -

⬆️ back to top

- -## Excursion: RAP Behavior Definition (BDEF) - -- As mentioned in the RAP terms and as the name implies, a RAP behavior definition describes a RAP business object (RAP BO) by defining its behavior for all of its RAP BO entities. -- BDL source code is used in a BDEF. -- Once you have created ... - - the CDS root entity of a RAP BO, ADT helps you create the skeleton of a BDEF (e.g., right-click on the CDS root entity and choose *New Behavior Definition* from the pop-up). - - the BDEF, ADT helps you create the skeleton of an ABAP behavior pool, as well as RAP handler and saver method declarations and the skeleton of implementations via ADT quick fixes. -- More information (see also the subtopics there): - - [Structure of a RAP behavior definition](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_bdef.htm) - - [Infos about BDL syntax](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_syntax.htm) - - [Infos about behavior definitions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl.htm) - - -The following example shows a commented BDEF. -Note that there is a wide variety of possible specifications and options. The example shows only a selection. For full details, refer to the ABAP Keyword Documentation. -Some of the syntax examples are commented out, just for the sake of showing more syntax options. - -```js -//Possible implementation types: managed, unmanaged, abstract, projection, interface -//(which restrict/enable further specifications) -//You can specifiy one or more implementation classes (behavior pools/ABPs -> bp...) -//for the RAP BO (in some contexts, specifying no ABP is possible). -//Specifying unique is mandatory (each operation can only be implemented once). -managed implementation in class bp_some_demo unique; -//For managed RAP BOs, you can enable user-defined saving options (optional additions -//are available). -//Purpose: Enhancing or replacing the default save sequence (Note: Only in this case, -//the ABP has a local saver class/save_modified saver method) -//managed with additional save with full data implementation in class bp_some_demo unique; -//full data: Full instance data is passed for saving -//managed with unmanaged save implementation in class bp_some_demo unique; - -//Enabling the strict mode (and version) to apply additional syntax checks; handled by -//the RAP framework; it is recommended that you use the most recent version -strict ( 2 ); - -//Enabling RAP draft handling -//with draft; - -//It is mandatory to specify an entity behavior definition for the RAP BO root entity. -//Here, some_demo represents a CDS view entity. -define behavior for some_demo -//Specifying an alias name (e.g. to have a more telling name than the technical name of -//the entity). When specifying an alias name, you should address the entity with the alias -//name instead of the full name (e.g. in the signature of handler methods). -//define behavior for some_demo alias root - -//Specifying the database table a RAP BO is based on (only available/mandatory in managed -//BOs); note further requirements for diverse scenarios in the documentation -persistent table some_dbtab - -//Mandatory specification of a draft table when a RAP BO is draft-enabled -//draft table drafttab - -//Specifying the locking mechanism for entities, e.g. to prevent a simultaneous -//modification. In unmanaged RAP BOs, this must be self-implemented in a dedicated handler -//method -lock master - -//Controlling authorization that is to be implemented in an ABP (also for managed) -//You can specify variants: global (e.g. for restricting certain operations) and/or -//instance (restrictions based on entity instances) or both of them (dedicated handler -//methods must be implemented) -//More variants are available that can be specified in the { ... } block below for -//excluding and delegating authorization checks (e.g. authorization:update) -authorization master ( instance ) -//authorization master ( global ) -//authorization master ( instance, global ) - -//Defining late numbering for primary key fields (see the adjust_numbers handler method) -//More numbering options are available such as early numbering, or, in the { ... } block below, -//the 'numbering : managed' specification for particular fields. -//late numbering - -//Defining a field as entity tag (ETag) field for optimistic concurrency control (i.e. -//enabling transactional access to data by multiple users to avoid inconsistencies when -//unintentionally changing already modified data). More options available, e.g. for -//draft-enabled RAP BOs (total etag). -//etag master some_field - -{ - //RAP BO operations - //Standard operations (Note: Read is implicitly enabled, no specification available) - create; - update; - //More additions are available dealing with authorization, feature control, precheck etc. - //The example shows precheck. In doing so, you can implement a precheck (e.g. to prevent - //unwanted changes) before instances are deleted in a dedicated handler method. A precheck - //implementation is also available for other operations (e.g. actions). - //As is true for various specifications, a comma-separated list of specifications is possible. - delete( precheck ); - - //Note: It is not possible to specify operations multiple times. The following specifications - //just demonstrate syntax options. Anyway, the compiler helps you not to specify wrong notations. - //Applying feature control - //delete( features: global ); - - //Applying authorization control - //delete( authorization : update ); - - //Operations for associations (many specification options are possible) - //The following example means enabling create-by-association operations for associations - //Assumption: _child is specified in the the underlying CDS data model. - association _child { create; } - - //Non-standard operations (check the specification options in the documentation, e.g. feature - //control and others are possible) such as actions (modify RAP BO instance) and functions (return - //information). There are different flavors of actions such as non-factory and factory actions, - //which themselves have different variations. Other flavors of actions are save actions (only to - //be executed during save sequence), determine actions (allow RAP BO consumers to execute - //determinations and validations on request), and draft actions. - - //Non-factory actions (modify existing instances) - //Instance action, relates to instances, modify instances - action act1; - - //Static action, not bound to instances, relates to the entrie entity - static action act2; - - //Internal action, accessible only from within the ABP (internal can also be specified in other - //contexts, e.g. operations) - internal action act3; - - //You can optionally specify input or output parameters or both (not always possible for all - //action types). The following example shows an output parameter, defined with the result - //addition. It stores the result of an action in an internal table. Variants are possible for - //the return type. Here, it is $self (result type is the same type as entity) It can, for - //example, also be an abstract BDEF or a different entity. - action act4 result [1] $self; - - //Input parameter specified following 'parameter' (in this case, a CDS abstract entity) - action act5 parameter some_cds_abstract; - - //Factory action (to create instances, can be instance-bound or static) - //Specifying the cardinality is mandatory - factory action act6 [1]; - - //Draft actions - //Available for draft-enabled RAP BOs, allow data modification on the draft table; are - //implicitly available; it is recommended for the draft actions to be specified explicitly; - //for some of the methods, the 'with additional implementation' addition is available - - //Copies active instances to the draft table - //draft action Edit; - - //Sets a lock for entity instances on the persistent database table - //draft action Resume; - - //Copies draft table content to the persitent database table; recommendation: use the - //optimized addition - //draft action Activate optimized; - - //Clears entries from the draft database table - //draft action Discard; - - //Corresponds to the determine actions for active instances; - //used to validate draft data before transitioning to active data - //draft determine action Prepare - // { - //You can assign validations and determinations defined with 'on save' - // validation val; - // } - - //Functions (similar to actions, there are optional additions, such as static) - //Since they return information, specifying an output parameter is required. - //Instance function - function func1 result [0..*] $self; - - //Static function - static function func2 result [1] some_cds_abstract; - - //Instance function with optional input parameter - function func3 parameter some_cds_abstract result [1] $self; - - //Field characteristics - //Field values cannot be created/updated - field ( readonly ) field1; - - //Read-only during update (especially key fields created during create operations) - field ( readonly : update ) key_field; - - //The mandatory specification denotes that values must be provided for the fields before persisting - //them to the database. - //Comma-separated list possible for the field characteristics in general; - //mutliple characteristics can also be specified in a comma-separated list in the parentheses - field ( mandatory ) field2, field3; - - //Defining access restrictions for fields - field ( features : instance ) field4; - - //Validations - //Checking the consitency of instances; validations are triggered based on conditions - //Conditions (one or more are possible) can be specified for create, update, delete operations - //and modified fields; note: not available for unmanaged, non-draft RAP BOs. - validation val on save { create; field field1; } - - //Determinations - //Modifying instances based on trigger conditions; - //As above, conditions (one or more are possible) can be specified for create, update, delete - //operations and modified fields. The triggering is possible for 'on modify' and 'on save'. - determination det1 on modify { update; delete; field field5, field6; } - determination det2 on save { create; field field7, field8; } - - //RAP business event (derived events with the specification 'managed evt ...' are also possible) - event evt; - - //RAP side effects, to trigger a reload of affected properties on the UI - //Trigger properties: Field changes, action executions - //Multiple side effects can be specified within a { ... } block, separated by a colon - //There are multiple options to specify the target following 'affect'; the example uses fields - //to be reloaded - side effects { field field1 affects field field4; - field field2 affects field field4; - field field3 affects field field4; - action act1 affects field field4; } - -} - - -//It is optional to specify an entity behavior definition for child entities -define behavior for some_child_entity alias child - -//Applying locks dependent on the specified association (locks are delegated to -//the specified association). In this case, it's the parent entity. Assumption: -//_parent is specified in the the underlying CDS data model. -lock dependent by _parent - -//Applying authorization checks dependent on the specified association -//As above, the assumption is that _parent is specified in the underlying CDS -//data model. -authorization dependent by _parent - -{ - update; - delete; - field ( readonly ) key_field; - field ( readonly : update ) key_field_child; - association _parent; -} -``` - -

⬆️ back to top

- -## ABAP Behavior Pools (ABP) - -As mentioned above, you can access RAP BO data from inside AS ABAP using -EML. Among other things, EML allows you to read or modify RAP BOs by -accessing the RAP BO data (the RAP BO instances) in the transactional -buffer and trigger the persistent storage or reset changes. More -precisely, when EML statements are executed, the calling of [RAP handler -methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm "Glossary Entry") -is triggered to access the transactional buffer of a RAP BO. As -mentioned, for unmanaged RAP BOs or unmanaged parts of managed RAP BOs, -the handler methods that are called are part of an ABAP behavior pool. - -The global class of an ABP has the addition [`FOR BEHAVIOR OF bdef`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_for_behavior_of.htm) -to the definition while `bdef` stands for the name of the BDEF. -This class is (initially) empty apart from the declaration and implementation part skeleton. - -```abap -CLASS zbp_demo_abap_rap_draft_m DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_draft_m. -ENDCLASS. - -CLASS zbp_demo_abap_rap_draft_m IMPLEMENTATION. -ENDCLASS. -``` - -The actual implementation is done in local classes in the CCIMP include (*Local Types* tab in ADT) of the behavior pool. There, -two kinds of local classes are to be defined and implemented that are -related to the RAP BO's runtime: one or more [handler -classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm "Glossary Entry") -to implement the RAP BO behavior (in RAP handler methods) during the -[RAP interaction -phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm "Glossary Entry") -(the data reading and modification phase) and a [saver -class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class_glosry.htm "Glossary Entry") -to implement the [RAP save -sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry") -(in [saver -methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_method_glosry.htm "Glossary Entry") -to save data from the transactional buffer to the database). - -

⬆️ back to top

- -### RAP Handler Classes and Methods - -- One or more handler classes implement the RAP interaction phase. For - modularization purposes, one behavior pool can define multiple - handler classes. For example, each entity can have its own handler - class, or individual handler classes can be defined to distinguish - between reading and changing RAP BO entities. -- A handler class inherits from class - `CL_ABAP_BEHAVIOR_HANDLER`. -- These classes are implicitly `ABSTRACT` and `FINAL` - since instantiating and calling only happens through the RAP runtime - engine. -- [ADT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry") - helps you create the classes and methods (and basically the ABP as - such) when creating the BDEF. A quick fix is available that creates - the method definitions and a skeleton of the implementations - automatically. - -Example: Handler class definition -``` abap -CLASS lhc_root DEFINITION INHERITING FROM cl_abap_behavior_handler. -... -ENDCLASS. -``` -- Handler method definitions include the additions `... FOR ... FOR - ...` followed by the kinds of operations. There are various - options depending on the RAP BO operation. -- Depending on the definition in the BDEF, there might be more additions - with dedicated method parameters. For example, an action might - be defined with a result parameter, hence, the method must be - defined with the addition `RESULT` and a parameter. -- The `FOR MODIFY` handler method can handle multiple entities - and operations, i. e. not only create but also update or delete - might be integrated in the method definition. However, it might be - useful to split the handler method into separate methods for better - readability. -- See more details on the handler method definitions in the topic - [`METHODS, FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_for_rap_behv.htm). - -Example: Handler method definitions -``` abap -"Create -METHODS create FOR MODIFY - IMPORTING entities FOR CREATE bdef. - -"Read: Specifying a read result is mandatory. -METHODS read FOR READ - IMPORTING keys FOR READ bdef RESULT result. - -"Action: action name is preceded by the BDEF name and a tilde after FOR ACTION -METHODS some_action FOR MODIFY - IMPORTING keys FOR ACTION bdef~some_action. -``` - -**Parameters of Handler Methods** - -- The handler method definitions contain RAP-specific additions like - `FOR MODIFY`, `FOR CREATE` or `FOR READ` as - well as mandatory or optional additions like `RESULT` that - are followed by parameters. -- Nearly all parameters are typed with [BDEF derived - types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry") - 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 - implicitly. In most cases, entire instances or just key values - of instances are imported. -- All handler methods have changing parameters that are usually not - explicitly specified in the definition but implicitly used. The - explicit specification of the `CHANGING` addition is not needed. In most cases, these are - [RAP response - parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_response_param_glosry.htm "Glossary Entry"). - The following image shows the F2 information in ADT for the create - handler method. - ![RAP_handler_method_parameters](./files/rap_handler_method_parameters.png) -- The response parameters `mapped`, `failed` and - `reported` (the names are predefined) can be considered as - containers for information - information a RAP BO consumer is - provided with by a RAP BO provider, for example, an SAP Fiori app - displays an error message if something went wrong. The availability - of the parameters depends on the handler method used (e. g. - `mapped` is only available for operations creating - instances). - - `mapped`: Used to provide mapping information on RAP BO - instances, for example, which key values were created for given - content IDs ( - [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm)). - - `failed`: Information for identifying the data set for - which an error occurred in a RAP operation - - `reported`: Used, for example, to exchange error messages for each - entity defined in the BDEF and [not related to a specific - entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_other.htm). - - Example: Technically, the `reported` parameter is a - [deep - structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm "Glossary Entry") - containing, for example, the messages of the root entity and - child entities. For example, if a create operation fails for a - RAP BO instance of the root entity, a message, information about - the instance key and other things can be included in this - parameter which is passed to a RAP BO consumer. You could - imagine that such an error message is displayed on an SAP Fiori - UI if something goes wrong to inform the user. - - -

⬆️ back to top

- -### RAP Saver Class and Saver Methods - -- A RAP saver class implements the [RAP save - sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry"). - A saver class is usually only available in unmanaged RAP BOs (except - for special variants of managed RAP BOs that are not outlined here). -- The saver class is implicitly `ABSTRACT` and `FINAL` - since the instantiating and calling only happens through the RAP - runtime engine. -- A saver class can be defined in the CCIMP include of an ABAP - behavior pool. It includes the definitions and implementations of - RAP saver methods. -- The saver methods consist of a set of predefined methods having - predefined names. Some of them are mandatory to implement, some are - optional. The - [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm) - method is only available in [late - numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry") - scenarios. -- A saver class inherits from class - `CL_ABAP_BEHAVIOR_SAVER`. The saver methods are - declared by redefining predefined methods of the superclass. They - implicitly have response parameters. -- In contrast to RAP handler methods, saver methods do not have data - of RAP BO instances as import parameter. Therefore, instance data - must be handled via the transactional buffer when self-implementing - the saver methods. -- Saver methods are called when the RAP save sequence has been triggered by a [`COMMIT - ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm) - statement. Note that in natively supported RAP scenarios, for example, an SAP Fiori app using OData, the `COMMIT ENTITIES` call is performed implicitly and automatically by the [RAP runtime engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_runtime_engine_glosry.htm). -- Find more information on RAP saver methods - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class.htm). - -Example: Definition of a RAP saver class and saver methods -``` abap -CLASS lsc_bdef DEFINITION INHERITING FROM cl_abap_behavior_saver. - PROTECTED SECTION. - - "For final calculations and data modifications involving all - "BOs in the current RAP transaction - METHODS finalize REDEFINITION. - - "Checks the consistency of the transactional buffer before - "the save method saves data to the database - METHODS check_before_save REDEFINITION. - - "Preliminary IDs are mapped to final keys. Only for late numbering. - METHODS adjust_numbers REDEFINITION. - - "Saves the current state of the transactional buffer to the database - METHODS save REDEFINITION. - - "Clear the transactional buffer - METHODS cleanup REDEFINITION. - METHODS cleanup_finalize REDEFINITION. - -ENDCLASS. -``` - -

⬆️ back to top

- -## BDEF Derived Types - -The operands of EML statements and parameters of handler and saver -methods are mainly special messenger tables for passing data and -receiving results or messages, i. e. the communication between a RAP BO -consumer and the RAP BO provider using EML consists (in most cases) of -exchanging data stored in internal tables that have special ABAP types - -[BDEF derived -types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry"). -These types are tailor-made for RAP purposes. - -As the name implies, the types are derived by the [ABAP runtime -framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm "Glossary Entry") -from CDS entities and their behavior definition in the BDEF. With these -special types, a type-safe access to RAP BOs is guaranteed. - -You can create internal tables (using [`TYPE TABLE -FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_table_for.htm)), -structures (using [`TYPE STRUCTURE -FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_structure_for.htm)) -and data types with BDEF derived types. For all operations and behavior -characteristics defined in the BDEF, types can be derived. - -The syntax uses - similar to the method definitions mentioned before - -the addition `FOR` followed by the operation and the name of an -entity (and, if need be, the concrete name, e. g. in case of an action -defined in the BDEF). - -Each BDEF derived type can be categorized as -[input](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_input_der_type_glosry.htm "Glossary Entry") -or [output derived -type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_output_der_type_glosry.htm "Glossary Entry") -according to its use as importing or exporting parameters in methods of -RAP BO providers. In most cases, structures of type `TYPE STRUCTURE -FOR` can be considered as serving as [work -area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry") -and line type of the internal tables. However, there are also structured -derived types that do serve as types for handler method parameters. - -The response parameters `mapped`, `failed` and -`reported` have dedicated derived types: [`TYPE RESPONSE -FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_response_for.htm). -They are deep structures containing the information for the individual -entities of the RAP BO. The components of these structures are internal -tables of appropriate types with `TYPE TABLE FOR`. - -Examples for BDEF derived types: - -``` abap -"Data objects with input derived types (entity = name of a root entity) - -"For an EML create operation -DATA create_tab TYPE TABLE FOR CREATE entity. - -"For an update operation -DATA update_tab TYPE TABLE FOR UPDATE entity. - -"Type for create-by-association operations specifying the name of the entity -"and the association -DATA cba_tab TYPE TABLE FOR CREATE entity\_child. - -"For an action execution; the name of the action is preceded by a tilde -DATA action_imp TYPE TABLE FOR ACTION IMPORT entity~action1. - -"Data objects with output derived types - -"For a read operation -DATA read_tab TYPE TABLE FOR READ RESULT entity. - -"For an action defined with a result -DATA action_res TYPE TABLE FOR ACTION RESULT entity~action2. - -"Examples for structures and types -DATA create_wa TYPE STRUCTURE FOR CREATE entity. - -"For permission retrieval -DATA perm_req TYPE STRUCTURE FOR PERMISSIONS REQUEST entity. - -"For retrieving global features -DATA feat_req TYPE STRUCTURE FOR GLOBAL FEATURES RESULT entity. - -"Type declaration using a BDEF derived type -TYPES der_typ TYPE TABLE FOR DELETE entity. - -"Response parameters -DATA map TYPE RESPONSE FOR MAPPED entity. -DATA fail TYPE RESPONSE FOR FAILED entity. -DATA rep TYPE RESPONSE FOR REPORTED entity. -``` -> **💡 Note**
-> Some of the derived types can only be created and accessed in implementation classes. - -

⬆️ back to top

- -### Components of BDEF Derived Types - -Many of the BDEF derived types contain components of CDS entities like -key and data fields that retain their original data type, for example, a -messenger table typed with `TYPE TABLE FOR CREATE`. Certainly, -if an instance is to be created, key and field values of a RAP BO -instance are of relevance. - -Yet, all BDEF derived types contain special RAP components serving a -dedicated purpose. The names of these RAP components begin with -`%` to avoid naming conflicts with components of the CDS -entities. The following image shows the F2 information of a BDEF derived -type containing the `%` components and fields from the CDS -entity. - -![BDEF_derived_types](./files/bdef_derived_types.png) - -Some of the `%` components are [component -groups](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_group_glosry.htm "Glossary Entry") -summarizing groups of table columns under a single name. In doing so, -they simplify the handling of derived types for developers. For example, -the component group -[`%data`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_data.htm) -contains all primary key and data fields of a RAP BO entity (actually, -by containing the keys, it also contains the component group -[`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm) -in the case above). The F2 information in ADT helps you find out about -the available components in a variable. The image below shows the -details of `%data` when clicking the *derived type* -link in the first ADT F2 information screen. - -![BDEF_derived_type_components](./files/bdef_derived_type_components.png) - -The availability of `%` components depends on definitions in the -BDEF. Their availability also depends on more criteria, for example, the -scenario. For example, the component -[`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) -that represents a preliminary ID for a RAP BO instance is only available -in [late -numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry") -scenarios. The draft indicator -[`%is_draft`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_is_draft.htm) -is only relevant in the context of -[draft](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_with_draft.htm). - -Find more details on the available components in section [Components of -BDEF Derived -Types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_comp.htm). - -Bullet points on selected `%` components: - -- [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm) - - A string to define a content ID. - - Content IDs are used as a unique and preliminary identifier for - RAP BO operations in which instances are created and especially - in cases where the key values of RAP BO instances are not yet - determined - - Assume that you create a RAP BO instance with an EML create - request and the key value has not yet been determined. In the - same request - a save has not yet been triggered - an update is - requested for this RAP BO instance. Using the content ID, it is - guaranteed that the update operation happens for the desired - instance. For this purpose, derived types for operations like - update or delete include the component - [`%cid_ref`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid_ref.htm) - to refer to the content ID `%cid` as the name implies. - - Note: You should always fill `%cid` even if not - needed. The specified content ID is only valid within one ABAP - EML request. You can use the optional addition [`AUTO FILL CID`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm#!ABAP_ONE_ADD@1@) in EML modify operations to create `%cid` automatically. However, if you use this addition, you cannot refer to `%cid` in subsequent operations. -- [`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm)/[`%tky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tky.htm) - - Both are component groups summarizing all primary keys of a RAP - BO instance. - - Where possible, it is recommended that you use `%tky` - instead of `%key`. `%tky` includes - `%key` and also the draft indicator - `%is_draft`. When using `%tky` in non-draft - scenarios, you are prepared for a potential, later switch to a - draft scenario. In doing so, you can avoid lots of adaptations - in your code by manually adding the indicator. -- [`%control`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_control.htm) - - Component group that contains the names of all key - and data fields of a RAP BO instance which indicate flags. - - For example, it is used to get information on which fields are provided or set a - flag for which fields are requested by RAP BO providers or RAP - BO consumers respectively during the current EML request. - - For this purpose, the value of each field in the - `%control` structure is of type - `ABP_BEHV_FLAG`. For the value setting, - you can use the structured constant `mk` of interface - `IF_ABAP_BEHV`. Note that the technical - type is `x length 1`. - - Example: If you want to read data from a RAP BO instance and - particular non-key fields in `%control` are set to - `if_abap_behv=>mk-off`, the values of these fields - are not returned in the result. - -

⬆️ back to top

- -## EML Syntax - -The focus is here on selected EML statements. These statements can be -fairly long and various additions are possible. Find more information on -the EML statements -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeneml.htm). - -### EML Syntax for Modifying Operations - -The modifying operations covered include the standard operations (using -the additions -[`CREATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), -[`CREATE -BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), -[`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), -and -[`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm)) -and non-standard operations (actions) using the addition -[`EXECUTE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm). -All EML statements for the mentioned operations begin with -[`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities.htm). -The following commented code snippets demonstrate the -[short](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_short.htm) -and [long -form](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entities_long.htm) -of EML `MODIFY` statements. - -> **💡 Note**
-> Unlike reading operations, modifying operations are not enabled by default. You must make the respective notations in the BDEF: -> ``` -> ... -> create; -> update; -> delete; -> action some_act; -> ... -> ``` - -Create operation for creating new instances of a RAP BO entity: - -``` abap -"Declaration of data objects using BDEF derived types - -DATA: cr_tab TYPE TABLE FOR CREATE root_ent, "input derived type - mapped_resp TYPE RESPONSE FOR MAPPED root_ent, "response parameters - failed_resp TYPE RESPONSE FOR FAILED root_ent, - reported_resp TYPE RESPONSE FOR REPORTED root_ent. - -"Input derived type for the EML statement is filled using the VALUE operator -"Assumption: key_field is the key field having type i, -"field1 and field2 are data fields with character-like data type. -"Specify %cid even if not used or of interest; it must be unique within a request - -cr_tab = VALUE #( - ( %cid = 'cid1' key_field = 1 - field1 = 'A' field2 = 'B' ) - ( %cid = 'cid2' - "Just to demo %data/%key. You can specify fields with or without - "the derived type components - %data = VALUE #( %key-key_field = 2 - field1 = 'C' - field2 = 'D' ) ) ). - -"EML statement, short form -"root_ent must be the full name of the root entity, it is basically the name of the BDEF - -MODIFY ENTITY root_ent - CREATE "determines the kind of operation - FIELDS ( key_field field1 field2 ) WITH cr_tab "Fields to be respected for the - "input derived type and the input - "derived type itself - MAPPED mapped_resp "mapping information - FAILED failed_resp "information on failures with instances - REPORTED reported_resp. "messages -``` - -> **💡 Note**
-> - Addition [`FIELDS ( ... ) WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm): - This field selection option specifies which fields are to be - respected for the operation. The derived type, i. e. an internal - table containing the concrete RAP BO instance values, follows - `WITH`. If a field is specified in the field list within the - pair of parentheses after `FIELDS`, the `%control` - flag for this field is automatically set to - `if_abap_behv=>mk-on`. Likewise, if a field is not - contained in the list, the flag in `%control` is set to - `if_abap_behv=>mk-off`. Assume `field2` is not - specified in the list. The value for `field2` will not be - respected (even if a value is specified in the internal table). The - initial value will be used for the field. ->- Retrieving the responses and specifying the parameters is optional. - Assuming a data set with the value 2 for `key_field` - already exists on the database for this BO, you should expect an - entry for this particular instance in the `failed_resp` - operand and potentially an error message in - `reported_resp`, too. Nevertheless, especially in ABP - implementations and depending on the context, you should implement - and fill these parameters according to the [RAP BO - contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_contract_glosry.htm "Glossary Entry") - to meet the variety of implementation rules. ->- `%cid` should be provided even if you are not interested in - it and subsequent operations do not require the reference. - -Long form of an EML `MODIFY` statement: -``` abap -MODIFY ENTITIES OF root_ent "full name of root entity - ENTITY root "root or child entity (alias name if available) - CREATE FROM "FROM as further field selection variant - VALUE #( ( %cid = 'cid' "Input derived type created inline - key_field = 3 - field1 = 'E' - field2 = 'F' - %control = VALUE #( "Must be filled when using FROM - key_field = if_abap_behv=>mk-on - field1 = if_abap_behv=>mk-on - field2 = if_abap_behv=>mk-on ) ) ) - MAPPED DATA(m) "Target variables declared inline - FAILED DATA(f) - REPORTED DATA(r). -``` - -> **💡 Note**
->- The entity specified after `ENTITY` can be either the root - entity itself or a child entity. If an alias is defined, the alias - should be used. ->- The addition `FIELDS ( ... ) WITH` from the previous - snippet is basically a shortcut for the addition - [`FROM`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm) - that is used here. When using `FROM`, the values of the - `%control` structure must be specified explicitly. ->- The BDEF derived types can also be created - [inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm) - as shown in the example using a [constructor - expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_glosry.htm "Glossary Entry") - for the input derived type and with `DATA` or - [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) - for the responses. ->- The long form allows you to bundle several operations in one - statement, either different operations on the same entity (for - example, deleting some instances and updating some others) or - operations on different entities of the same RAP BO (for example, - creating a root entity instance and related instances of a child - entity in one EML request). Long and short forms are also available - for other EML statements. ->- The [`SET FIELDS WITH`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodify_entity_entities_fields.htm#!ABAP_VARIANT_4@4@) addition is available as another field specification option. However, it has limitations that you should be aware of. It can cause syntax warnings. Check the documentation. It is recommended that you use `FIELDS ... WITH` and `FROM`. - - -Excursion: Specifying `%control` component values in the short form of `VALUE` constructor expressions - -```abap -"The following EML statement creates RAP BO instances. The BDEF derived -"type is created inline. With the FROM addition, the %control values -"must be specified explicitly. You can provide the corresponding values -"for all table lines using the short form, i.e. outiside of the inner -"parentheses, instead of individually specifying the values for each -"instance within the parentheses. In this case, the corresponding %control -"component value is assigned for all of the following table lines. -MODIFY ENTITIES OF zdemo_abap_rap_ro_m - ENTITY root - CREATE FROM VALUE #( - %control-key_field = if_abap_behv=>mk-on - %control-field1 = if_abap_behv=>mk-on - %control-field2 = if_abap_behv=>mk-on - %control-field3 = if_abap_behv=>mk-on - %control-field4 = if_abap_behv=>mk-off - ( %cid = 'cid1' - key_field = 1 - field1 = 'aaa' - field2 = 'bbb' - field3 = 10 - field4 = 100 ) - ( %cid = 'cid2' - key_field = 2 - field1 = 'ccc' - field2 = 'ddd' - field3 = 20 - field4 = 200 ) ) - MAPPED DATA(m) - FAILED DATA(f) - REPORTED DATA(r). -``` - - -The following EML statement combines multiple operations in one EML -request. It demonstrates the use of `%cid` and -`%cid_ref`. First, two instances are created by specifying -`%cid`. An update operation in the same request only specifies a -certain field within the parentheses of the `FIELDS ( ... ) -WITH` addition which denotes that only this particular field -should be updated. The other field values remain unchanged. The -reference to the instance is made via `%cid_ref`. Consider an -EML request in which no instance to refer to using `%cid_ref` -exists, e. g. for an update operation. You can also make the reference -using the unique key. A delete operation is available in the same -request, too. `DELETE` can only be followed by the addition -`FROM`. In contrast to other derived types, the derived type -that is expected here (`TYPE TABLE FOR DELETE`) only has -`%cid_ref` and the key as components. -``` abap -MODIFY ENTITIES OF root_ent - ENTITY root - CREATE FIELDS ( key_field field1 field2 ) WITH - VALUE #( ( %cid = 'cid4' key_field = 4 - field1 = 'G' field2 = 'H' ) - ( %cid = 'cid5' key_field = 5 - field1 = 'I' field2 = 'J' ) ) - - UPDATE FIELDS ( field2 ) WITH - VALUE #( ( %cid_ref = 'cid4' field2 = 'Z' ) ) - - DELETE FROM - VALUE #( ( %cid_ref = 'cid5' ) "Instance referenced via %cid_ref - ( key_field = 9 ) ) "Instance referenced via the key -... -``` - -EML statement including the execution of an action: -``` abap -MODIFY ENTITIES OF root_ent - ENTITY root - EXECUTE some_action - FROM action_tab - RESULT DATA(action_result) "Assumption: The action is defined with a result parameter. - ... -``` - -The following code snippet shows a deep create. First, an instance is -created for the root entity. Then, in the same request, instances are -created for the child entity based on the root instance. In the example -below, the assumption is that a composition is specified in the root -view entity like `composition [1..*] of root_ent as _child` and `key_field` and -`key_field_child` are the keys of the child view entity. The -[`%target`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_target.htm) -component group enters the picture here which contains the target's -primary key and data fields. -``` abap -MODIFY ENTITIES OF root_ent - ENTITY root_ent - CREATE FIELDS ( key_field field1 field2 ) WITH - VALUE #( ( %cid = 'cid6' key_field = 6 - field1 = 'I' field2 = 'J' ) ) - CREATE BY \_child - FIELDS ( key_field_child field1_child field2_child ) WITH - VALUE #( ( %cid_ref = 'cid6' - %target = VALUE #( ( %cid = 'cid_child_1' - key_field_child = 1 - field1_child = 'aa' - field2_child = 'bb' ) - ( %cid = 'cid_child_2' - key_field_child = 2 - field1_child = 'cc' - field2_child = 'dd' ) ) ) ) -... -``` - -

⬆️ back to top

- -### EML Syntax for Reading Operations - -- Read-only operations always return a result, i.e. the syntax of the - EML statement requires the addition `RESULT` and an operand. -- When RAP BO instances are read, the returned data include the - current status of instances in the transactional buffer which - includes unsaved modifications on instances. If an instance is not - yet available in the transactional buffer, the currently persisted - data set is automatically read into the transactional buffer. -- Note that read operations are always implicitly enabled for each - entity listed in a BDEF, i. e. there is no extra definition in the - BDEF in contrast to, for example, create or update. - -The following code snippet shows the long form of the EML -[`READ`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_op.htm) -statement for reading instances from the root entity. In `READ` -statements, the additions `FIELDS ( ... ) WITH` and -`FROM` can also be used to specify the fields that you intend to -read. Here, the addition [`ALL FIELDS -WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_fields.htm) -is available for reading all field values. - -``` abap -READ ENTITIES OF root_ent - ENTITY root_ent - ALL FIELDS WITH - VALUE #( ( key_field = 1 ) "Derived type TYPE TABLE FOR READ IMPORT only includes the keys - ( key_field = 2 ) ) - RESULT DATA(result) - FAILED DATA(f) - REPORTED DATA(r). -``` - -Read-by-association operations include the optional addition -[`LINK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_op&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_ONE_ADD@1@&tree=X) -with which you can retrieve the keys of the source and target (i. e. the -associated entity). The by-association operations work reciprocally, i. -e. you can, for example, read a child instance via the parent and a -parent instance via the child, too. - -``` abap -"Read-by association operation: parent to child -READ ENTITIES OF root_ent - ENTITY root_ent - BY \_child - ALL FIELDS WITH VALUE #( ( key_field = 1 ) ) - RESULT DATA(rba_res1) - LINK DATA(links1). - ... - -"Read-by association operation: child to parent -READ ENTITIES OF root_ent - ENTITY child_ent - BY \_parent - ALL FIELDS WITH VALUE #( ( key_field = 1 key_field_child = 1 ) ) - RESULT DATA(rba_res2) - LINK DATA(links2). - ... -``` -

⬆️ back to top

- -#### Dynamic Forms of EML Statements - -In addition to the short and long forms described above, various ABAP EML statements also have dynamic forms. -Taking EML read operations as an example, the following code snippet shows a dynamic EML [`READ ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entities_operations.htm) statement. The relevant syntax element is the `OPERATIONS` addition. -The dynamic form allows the collection of read operations for multiple RAP BOs in one EML statement. -For more information, see the ABAP keyword documentation and the comments in the snippet. - -```abap -"The statement is taken from the executable example. The example has a -"root entity and a child entity. For both entities, RAP BO instances -"are to be read (read and read-by-association operation). - -DATA: - "The following data object is the operand of the dynamic EML statement - "It is an internal table and has a special, RAP-specific type. - op_tab TYPE abp_behv_retrievals_tab, - - "More data object declarations (internal tables typed with BDEF - "derived types) that are relevant for the EML statement. - "For both entities (root and child), RAP BO instances are to be - "read. The internal tables are used for components of the internal - "table op_tab further down. - read_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m, - read_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m, - rba_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m\_child, - rba_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m\_child, - rba_dyn_link TYPE TABLE FOR READ LINK zdemo_abap_rap_ro_m\_child. - -"Filling the internal tables, i.e. which instances are to be read -"Root entity -"Example: -"- The key is comprised of the field 'key_field'. It is of type i. -"- The %control structure is filled, flagging those fields that -" are to be read. Flagging the key field is not required. -read_dyn = VALUE #( - ( %key-key_field = 1 - %control = VALUE #( - field1 = if_abap_behv=>mk-on - field2 = if_abap_behv=>mk-on - field3 = if_abap_behv=>mk-on - field4 = if_abap_behv=>mk-on ) ) - ( %key-key_field = 2 - %control = VALUE #( - field1 = if_abap_behv=>mk-on - field2 = if_abap_behv=>mk-on - field3 = if_abap_behv=>mk-on - field4 = if_abap_behv=>mk-on ) ) ). - -"Child entity -"Instances to be read for a read-by-association operation -"The shared key is 'key_field'. -rba_dyn = VALUE #( - ( %key-key_field = 1 - %control = VALUE #( - key_ch = if_abap_behv=>mk-on - field_ch1 = if_abap_behv=>mk-on - field_ch2 = if_abap_behv=>mk-on ) ) - ( %key-key_field = 2 - %control = VALUE #( - key_ch = if_abap_behv=>mk-on - field_ch1 = if_abap_behv=>mk-on - field_ch2 = if_abap_behv=>mk-on ) ) ). - -"Filling the internal table that is the operand of the -"dynamic EML statement -"This table has optional and mandatory components. -op_tab = VALUE #( - ( "op: Specifies the operation to be executed; is mandatory; - " can be set with the predefined constants, e.g. OP-R-READ - " etc., of interface IF_ABAP_BEHV - op = if_abap_behv=>op-r-read - "entity_name: Specifies the name of the RAP BO entity for which - " the operation is executed; is mandatory - entity_name = 'ZDEMO_ABAP_RAP_RO_M' - "instances: Specifies a reference to an internal table holding - " the input keys; must be appropriately typed; is mandatory - instances = REF #( read_dyn ) - "results: Specifies a reference to an internal table with the required - " BDEF derived type for the read results; is mandatory - results = REF #( read_dyn_result ) ) - ( op = if_abap_behv=>op-r-read_ba - entity_name = 'ZDEMO_ABAP_RAP_RO_M' - "sub_name: Only relevant for specifying association names in - " read-by-association operations; in that context, it is mandatory - sub_name = '_CHILD' - "full: Optional flag; specifies if all target instances are to be retrieved - full = abap_true - instances = REF #( rba_dyn ) - results = REF #( rba_dyn_result ) - "links: Reference to internal table holding the key pairs of the source and - " target - links = REF #( rba_dyn_link ) ) ). - -READ ENTITIES OPERATIONS op_tab. -``` -

⬆️ back to top

- -### Persisting to the Database - -- A [`COMMIT - ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm) - statement triggers the RAP save sequence. Without such a statement, - the modified RAP BO instances that are available in the - transactional buffer are not persisted to the database. As mentioned above, in case of a natively supported RAP - scenario (for example, when using OData), the `COMMIT - ENTITIES` request is executed automatically. -- `COMMIT ENTITIES` implicitly includes [`COMMIT - WORK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit.htm). -- Note: `COMMIT ENTITIES` statements cannot be used - in behavior implementations. -- There are multiple variants available for the statement as described - in the ABAP Keyword Documentation - [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm). For example, RAP responses can be retrieved, key conversion in late numbering scenarios, checking a RAP transaction in a simulation mode. -- `COMMIT ENTITIES` statements set the system field - `sy-subrc`. When using `COMMIT ENTITIES`, it is not - guaranteed that `COMMIT WORK` is carried out successfully. - Hence, you should include a check for `sy-subrc` after - `COMMIT ENTITIES` so that you can react to failures - accordingly. - -The following snippet shows a create operation. This operation has only -an impact on the database with the `COMMIT ENTITIES` statement. -Triggering the save sequence means that the execution of the statement -triggers the calling of the saver methods available in the saver class -of a behavior implementation. In managed scenarios (except for some -special variants), the saving is done automatically without implementing -a dedicated saver method. -``` abap -MODIFY ENTITIES OF root_ent - ENTITY root_ent - CREATE FIELDS ( key_field field1 field2 ) WITH - VALUE #( ( %cid = 'cid' key_field = 7 - field1 = 'K' field2 = 'L' ) ). - -COMMIT ENTITIES. - -IF sy-subrc <> 0. - ... -ENDIF. -``` - -

⬆️ back to top

- -### Raising RAP Business Events - -- [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) can be raised in ABAP behavior pools with [`RAISE ENTITY EVENT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_entity_event.htm) statements. -- The focus of the snippets is on the local consumption of RAP business events. Prerequisites: - - `event` specifications are available in the BDEF (e.g. `... event some_evt; ...`). For more details, refer to the [BDL documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_event.htm) - - A [RAP event handler class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_class_glosry.htm) is available that is used to implement [RAP event handler methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_meth_glosry.htm). - - Note that these methods are called asynchronously. - - Similar to RAP handler and saver methods, RAP event handler methods are implemented in the CCIMP include of the RAP event handler class. - - To locally consume RAP business events, a local class that inherits from `CL_ABAP_BEHAVIOR_EVENT_HANDLER` can be implemented in the CCIMP include of a RAP event handler class. -- More information: - - [ABAP for RAP Business Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_events.htm) in the ABAP Keyword Documentation - - [Business Events](https://help.sap.com/docs/abap-cloud/abap-rap/business-events) in the SAP Help Portal - -```abap -"---- Syntax for the declaration part of a global RAP event handler class ---- -CLASS cl_event_handler DEFINITION PUBLIC FOR EVENTS OF some_bdef. - ... -ENDCLASS. - -"---- Syntax for the declaration part of a local event handler class ---- -"---- in the CCIMP include of a RAP event handler class ---- -CLASS lhe_event DEFINITION INHERITING FROM cl_abap_behavior_event_handler. - ... -ENDCLASS. - -"---- RAP event handler method definition ---- -"Notes: -"- Must be defined as instance methods in the private visibility section. -"- The input parameter par is an internal table of type TYPE TABLE FOR EVENT. -"- This type includes the keys of RAP BO instances (and %param, if the event -" is specified with a parameter in the BDEF) -"- The methods do not contain RAP response parameters. -METHODS meth FOR ENTITY EVENT par FOR some_bdef~some_evt. - -"---- RAISE ENTITY EVENT statement in an ABP, e.g. the save_modified method ---- -"---- in managed scenarios with additional save ---- -... -CLASS lsc IMPLEMENTATION. - METHOD save_modified. - "Assumption: An event is specified for create operations in the BDEF as follows - "event created; - IF create-some_bdef IS NOT INITIAL. - RAISE ENTITY EVENT some_bdef~created - FROM VALUE #( FOR IN create-root ( %key = VALUE #( some_key = -some_key ) ) ). - ENDIF. - - "Assumption: An event is specified for delete operations in the BDEF as follows - "event deleted parameter some_abstract_entity; - "The abstract entity has two parameters, for example, with which additional - "information can be passed. - IF delete-some_bdef IS NOT INITIAL. - RAISE ENTITY EVENT some_bdef~deleted - FROM VALUE #( FOR IN delete-some_bdef ( - %key = VALUE #( some_key = -some_key ) - %param = VALUE #( par_a = '01' - par_b = 'Item deleted' ) ) ). - ENDIF. - ENDMETHOD. -ENDCLASS. -``` - -

⬆️ back to top

- -### Additions to 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). - One of them is [`IN LOCAL MODE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapin_local_mode.htm). -- This addition can be used to exclude feature controls and - authorization checks. -- Consider the following use case: There is a field to display the - booking status of a trip on a UI. In the BDEF, this field is - specified as read-only. Hence, it cannot be modified by a user on - the UI. However, there is a button on the UI to book the trip. This - button might trigger an action to book the trip so that the value of - the field changes from open to booked. To enable this, the - underlying handler method for the modify operation with the action - to be executed has the addition `IN LOCAL MODE` that ignores - the feature control. - -Syntax: - -``` abap -MODIFY ENTITIES OF root_ent IN LOCAL MODE - ENTITY root - EXECUTE book - FROM action_tab - ... -``` - -

⬆️ back to top

- -## RAP Excursions - -### Using Keys and Identifying RAP BO Instances in a Nutshell - -
- Expand to view the details - -
- -The following bullet points outline important aspects regarding - keys and identifying [RAP BO -instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_instance_glosry.htm "Glossary Entry") in ABAP EML statements. - -**Why is it important?** - -- The [primary - key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_key_glosry.htm "Glossary Entry") - of a [RAP BO entity instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_entity_inst_glosry.htm "Glossary Entry") - is composed of one or more [key fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenkey_field_glosry.htm "Glossary Entry"). -- These key fields stand for the fields that are specified with - `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. - - 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. - -**How can a RAP BO instance be uniquely identified?** - -- It can be done by using a [RAP instance identifier](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_inst_identifier_glosry.htm "Glossary Entry") - or [RAP content identifier](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_cont_identifier_glosry.htm "Glossary Entry") - or both of them. -- RAP instance identifier: - - It consists of the primary key fields and all relevant [BDEF derived type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry") - components. - - To ease the reference to all of these components, special - [component groups](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_group_glosry.htm "Glossary Entry") - are available to summarize the components and make them - addressable via one single name. - - [`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm): - Contains the primary key fields of a RAP BO instance - - [`%tky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tky.htm): - Specifies the transactional key. Comprises `%key` (and, - thus, the primary key fields of a RAP BO instance) and more - components that are relevant to uniquely identify a RAP BO - instance. Among them, - [`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) - (relevant for late numbering scenarios) and the draft indicator - [`%is_draft`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_is_draft.htm) - (relevant for - [draft](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_with_draft.htm) - scenarios). In non-late numbering or non-draft scenarios, these - extra components are just blank. However, it is recommended that - you use `%tky` in all scenarios since it simplifies a - possible later switch, for example, to a draft scenario. In - doing so, lots of adaptations to the code regarding the keys and - the inclusion of `%is_draft` can be avoided. -- RAP content identifier: - - Reflected in the component - [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm) - which is a string of type - `ABP_BEHV_CID` to define a content ID. - - Used as a unique and preliminary identifier for RAP BO instances - in RAP create operations, especially where no primary key exists - for the particular instance. - - For newly created instances, the ID can then be used for performing further modifications, referencing to those instances using [`%cid_ref`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid_ref.htm) (which has the same value as %cid), for example, in RAP operations using [`CREATE BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm) - and - [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), - as well as - [actions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_action.htm) - with - [`EXECUTE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm)). - - In contrast to the primary key and the preliminary ID - `%pid` for late numbering scenarios, `%cid` (and - `%cid_ref`) are only available on a short-term basis - for the current ABAP EML request within the [RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm "Glossary Entry") in one RAP transaction. - - **Note:** Specify `%cid` even if there are no further operations referring to it. -- Special case: Late numbering - - As mentioned above, in late numbering scenarios newly created - entity instances are given their final key only shortly before - saving in the database, i. e. you deal with preliminary keys in - the RAP interaction phase and the early phase of the [RAP save sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry"). - - In this case, you can use `%key` to hold the preliminary - keys or use a preliminary ID in the dedicated component - [`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) - which is of type `ABP_BEHV_PID` and - only available in late numbering scenarios. - - Similar to above, to uniquely identify RAP BO instances in late - numbering scenarios, you can use either `%key` or - `%pid` or both of them. In any case, the use of - `%tky` is handy because it includes both components. You - must ensure that `%tky` in total uniquely identifies the - instances. - - **Note:** A further component group to refer to the keys is available: [`%pky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pky.htm). `%pky` contains `%pid` and `%key` in late numbering scenarios. In non-late numbering scenarios, it just contains `%key`. `%pky` itself is contained in `%tky`. There are contexts, for example, particular actions, where `%tky` is not available but `%pky` is. This way, there is still the option to summarize `%pid` and `%key` in one component group in the absence of `%tky`. - -**General rule**: A RAP BO instance must - where available - always be uniquely -identifiable by its transactional key (`%tky`) for internal -processing during the RAP interaction phase. `%tky` always -contains all relevant components for the chosen scenario. - -> **💡 Note**
-> Assignment of Key Component Groups -> -> As a general best practice, you should use a RAP BO instance key component group when referring to the entire key, rather than listing the individual key fields. It is recommended that you use `%tky` whenever possible. -> In the following cases, type compatibility cannot be guaranteed in component group assignments: -> - Mixing key component groups when they refer to the same RAP BO entity, e.g. `wa-%tky = wa-%key`. Such an assignment should also be avoided when both component groups have an identical scope in terms of components (e.g. `%tky` and `%key` in non-late-numbering and non-draft scenarios). -> - Mixing the same key component groups when referring to two different RAP BO entities, for example, `wa_root-%tky = wa_child-%tky`. In this case, adding more components later may cause syntax errors for an assignment that worked previously. -> - Defining structured types that have the same components as key component groups, and then assigning data objects of that type to those of the respective, original key component group. -> In the above cases, the `CORRESPONDING` operator can be used to ensure type compatibility in assignments to key component groups: -> ```abap ->... %tky = CORRESPONDING #( wa-%tky ) ... ->... %key = CORRESPONDING #( wa-%key ) ... ->... %pky = CORRESPONDING #( wa-%pky ) ... ->``` -> In cases where different data objects of key component groups of a BDEF derived type are to be assigned to the same key component group of the same entity, a direct assignment works without a syntax warning because the content is identical. A direct assignment is recommended (`...wa1_root-%tky = wa2_root-%tky ...`). The use of the `CORRESPONDING` operator is unnecessary and less performant. This is true, for example, for key component group assignments in the context of RAP response parameters failed and reported. - -
- -### RAP Concepts - -
- Expand to view the details - -
- -**RAP numbering** - -- A concept that deals with setting values for primary key fields. -- There are multiple options to handle the numbering for primary key - fields depending on when (early in the RAP interaction phase or late - in the RAP save sequence) and by whom (RAP BO consumer, behavior - pool, or framework) the primary key values are set. -- When: - - [Early numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_early_numbering_glosry.htm "Glossary Entry"): - The final key values are assigned during a RAP create operation - in the interaction phase. - - [Late numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry"): - The final key values are assigned during the RAP save sequence - (and here only in the RAP saver method - [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm)). -- By whom - - [External numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_ext_numbering_glosry.htm "Glossary Entry"): - Key values are provided by the RAP BO consumer. For example, in - a create operation, the key values are specified by the RAP BO - consumer like other non-key field values. Basically, this is the - concept with which the snippets above are tailored. - - [Internal numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_numbering_glosry.htm "Glossary Entry"): - Key values are provided by the RAP BO provider. For example, in - a create operation, the key values are not specified in an EML - create request by the RAP BO consumer but rather by the RAP BO - provider. In case of a managed RAP BO, the key is automatically - created by the framework which only works if the key is of a - certain type (16-character byte-like - [UUID](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuuid_glosry.htm "Glossary Entry")). - In case of an unmanaged RAP BO, the key values are provided in a - dedicated handler method which must be self-implemented. Note - that late numbering is internal by default since no further RAP - BO consumer interaction is possible in the late phase of the RAP - save sequence. - -**Draft** - -- The draft concept in RAP allows the content of the transactional - buffer to be stored in intermediate storages ([draft tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendraft_table_glosry.htm "Glossary Entry")) - in order to allow transactions to expand over different ABAP - sessions. -- Like the concepts mentioned above, a RAP BO can be draft-enabled in - the BDEF. If enabled, the application allows data modifications and the temporary storage of modifications but does not yet persist them to the database. The users of the application can continue modifying this data later and they might even use a different device from the one where they modified the data previously. -- The draft indicator `%is_draft` is available for RAP BO instance identification. It is used to indicate if a RAP BO - instance is a [draft instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_draft_instance_glosry.htm "Glossary Entry") - or an [active instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_active_instance_glosry.htm "Glossary Entry"). - Conveniently, the component group `%tky` contains - `%is_draft`. `%is_draft` can then be addressed via - `%tky`. - -> **💡 Note**
-> Late numbering and identification in the late phase of the RAP save sequence ->- Context: RAP saver method -> [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm) -> in which the final key values are assigned; the preliminary keys can -> be included in `%key` or `%pid` or both of them. ->- `%pid` and the preliminary key values in `%key` are -> automatically assigned to the following component groups when -> reaching the `adjust_numbers` method: -> - [`%tmp`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tmp.htm): -> A component group that is assigned the preliminary key values -> contained in `%key`. In doing so, `%tmp` takes -> over the role that `%key` has had in the RAP interaction -> phase to hold the preliminary key values. -> - `%pid` remains as is. The component group -> [`%pre`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pre.htm) -> contains `%pid` and `%tmp` and, thus, all -> preliminary identifiers. ->- In the `adjust_numbers` method, the preliminary keys are -> transformed into the final keys, i. e. the preliminary keys are -> mapped to `%key` (which holds the final keys in this -> context) in the `mapped` [response parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_response_param_glosry.htm "Glossary Entry"). ->- Depending on your use case to use either `%pid` or (the -> preliminary key values in) `%key` (which is `%tmp` -> here in this method) during the interaction phase or both of them, -> you must ensure that `%pre` in total (since it contains both -> `%pid` and `%tmp`) is unique and mapped to the final -> keys that are to be contained in `%key`. - -
- -### Ensuring Data Consistency in a RAP Transaction - -
- Expand to view the details - -
- -The [LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenluw_glosry.htm) concept, which deals with the transfer of data from one consistent state to another, applies to applications using RAP. RAP transactions are integrated with the [SAP LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw_glosry.htm), which is a prerequisite for transactional consistency. RAP provides a standardized approach and rules ([RAP BO contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_contract_glosry.htm)) for the [RAP business object (BO)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_glosry.htm) runtime to ensure that the RAP transaction is correctly implemented, data inconsistencies are avoided, and the SAP LUW is successfully completed. - -**Phases of a RAP Transaction** - -A RAP transaction is divided into two phases during the runtime of a RAP BO, while the second phase can be divided into two subphases that serve different purposes. - -![Phases of a RAP Transaction](files/phases_of_rap_luw.png) - -[RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm): -- [RAP handler methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm) are called in a [RAP handler class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm) that inherits from `CL_ABAP_BEHAVIOR_HANDLER`. -- New data, i.e. RAP BO instances, are created in the [RAP transactional buffer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_buffer_glosry.htm), or persisted data is retrieved and inserted into the transactional buffer for further processing. -- The state of the data may become inconsistent in the transactional buffer during this phase. However, the data remains consistent in the database because changes are made only in the transactional buffer. - -[RAP save sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm): -- The RAP save sequence is triggered by a `COMMIT ENTITIES` statement. In natively supported RAP scenarios, such as an SAP Fiori application using OData, the `COMMIT ENTITIES` call is implicitly and automatically performed by the RAP runtime engine. -- RAP saver methods are called in the RAP saver class, which inherits from the base class `CL_ABAP_BEHAVIOR_SAVER`. -- Is divided into the [RAP early save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenearly_rap_save_phase_glosry.htm) (ensures that the RAP BO instances in the transactional buffer - all RAP BOs in the current RAP transaction are involved - are in a consistent state so that they can be saved to the database) and the [RAP late save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) (to finally save data from the transactional buffer to the database). - -(Optional:) Saver methods called in the RAP early save phase: -1. [`finalize`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_finalize.htm): For final calculations and data changes before saving. In managed scenarios, determinations specified with `ON SAVE` are called when reaching this method. - -2. [`check_before_save`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_check_before_save.htm): For data consistency checks in the transactional buffer. In managed scenarios, validations specified with `ON SAVE` are called when this method is reached. - -3. [`cleanup_finalize`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsaver_class_cleanup_finalize.htm): If there are failures in at least one of the previous saver methods, further processing with the RAP late save phase is rejected and the transaction returns to the interaction phase. Before that, this saver method is called, allowing changes made in the finalize method to be rolled back. - -If there are errors in the early save phase, `sy-subrc` returns the value 4 after `COMMIT ENTITIES` statements. If the data in the transactional buffer is consistent after the early save phase, the late save phase is processed, which also means that a point of no return has been reached. Unlike the early save phase, you cannot return to the interaction phase when you reach the late save phase. Either the RAP transaction ends with a successful commit, or the changes are rolled back and a runtime error occurs. - -Saver methods called in the RAP late save phase: -1. [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm): Provides RAP BO instances with their final numbers. This method is available only in late numbering scenarios. -2. [`save`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_save.htm) (or [`save_modified`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaprap_saver_meth_save_modified.htm) in managed scenarios with an unmanaged or additional save): Used to save data from the transactional buffer to the database. If there are no issues, the final database commit is triggered and an implicit `COMMIT WORK` is executed. - -[`cleanup`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_cleanup.htm) method: After a successful save, the [`cleanup`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_cleanup.htm) method clears the transactional buffer. It completes the save sequence. - -**Commit and Rollback in a RAP Transaction** -The default ABAP statements for RAP are `COMMIT ENTITIES` (triggers the RAP save sequence and the final database commit; as mentioned above, in natively supported RAP scenarios, the commit is performed implicitly and automatically by the RAP runtime engine) and `ROLLBACK ENTITIES` (rolls back all changes of the current RAP transaction, i.e. the transactional buffer is cleared by calling the `cleanup` method). Both are RAP-specific and end the RAP transaction. - -*Notes on `COMMIT ...` and `ROLLBACK ...` statements due to the integration of RAP transactions into the SAP LUW:* - -- `COMMIT ENTITIES` implicitly triggers `COMMIT WORK`. -- Using `COMMIT WORK` in RAP (instead of `COMMIT ENTITIES`) also triggers the RAP save sequence. If there are no errors in the RAP save sequence, the final database commit is successful. Only in this best-case scenario does `COMMIT WORK` have the same effect as `COMMIT ENTITIES`. However, if there are errors in the save sequence, a runtime error occurs in any case, while a return to the interaction phase is still possible when using `COMMIT ENTITIES`. -- `COMMIT ENTITIES` provides RAP-specific functionality with various additions that are not possible with `COMMIT WORK`, such as RAP responses can be retrieved, key conversion in late numbering scenarios, checking a RAP transaction in a simulation mode. -- There are short, long, and dynamic forms of `COMMIT ENTITIES` statements. -- `COMMIT ENTITIES` statements implicitly enforce local updates with `COMMIT WORK`, or `COMMIT WORK AND WAIT` if the local update fails. Therefore, the update is either a local update or a synchronous update, but never an asynchronous update. When `COMMIT WORK` is used, the RAP BO consumer can choose between synchronous and asynchronous update for RAP BO entities. -- `ROLLBACK ENTITIES` implicitly triggers `ROLLBACK WORK`. Both have the same effect when used in RAP. Therefore, they are interchangeable. - -> **💡 Note**
-> Special Case: Failures in the Late Save Phase -> - In exceptional cases, for example, when [BAPIs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbapi_glosry.htm) are called to save RAP BO instances in the late save phase, it may happen that the basic rule that failures must not occur in the RAP late save phase and be detected in the RAP early save phase is violated. -> - In such cases, the base class `CL_ABAP_BEHAVIOR_SAVER_FAILED` can be used for the RAP saver class. -> - RAP BO consumers can be informed by filling the RAP response parameters (some of which are not available when using `CL_ABAP_BEHAVIOR_SAVER` as the base class) in the saver method implementation so that they can react accordingly. -> - After a `COMMIT ENTITIES` statement and a failure in the late save phase, `sy-subrc` is set to 8. -> - A subsequent RAP operation may result in a runtime error. If the RAP BO consumer is to continue after an error in the late phase of the RAP save sequence, an explicit `ROLLBACK ENTITIES` is required. - -**Allowed/Forbidden Operations in a Behavior Implementation in a RAP Transaction** - -The following restrictions apply to operations and/or statements in the individual phases of a RAP transaction in ABAP behavior implementations. Note that, depending on setting the strict mode in the BDEF, runtime errors may occur due to the use of forbidden statements, or static code checks may be applied. Note that most operations/statements refer to the use in the unrestricted ABAP language scope. - -|Operations/Statements|Interaction phase|Early save phase|Late save phase|Notes| -|---|---|---|---|---| -|[Database commits](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_commit_glosry.htm) using [secondary connections](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_db_connection_glosry.htm)

(unrestricted ABAP language scope)| X| X| X |Secondary connections are allowed for infrastructure purposes, for example. They can be used to store data that is not part of the main transaction, such as application logs, traces, or number ranges. | -|Database commits using the [standard connection](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_db_connection_glosry.htm)

(unrestricted ABAP language scope)| X| X| -| Database commits can be made in phases other than the late phase, for example, by calling external services or using a `WAIT` statement.| -|[sRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensrfc_glosry.htm) (`CALL FUNCTION ... DESTINATION`), [aRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarfc_glosry.htm) (`CALL FUNCTION ... STARTING NEW TASK`)

(unrestricted ABAP language scope)| X |X |-| Allowed in phases other than the late save phase, e.g. for the purpose of parallelization within the application. It is up to the application to ensure consistency, e.g. to ensure read-only access, to handle a potential two-phase commit, or to provide a proper error handling. | -|Database modifications |- |-| X| Only allowed in the late save phase because the data being processed is always potentially inconsistent. Database changes in other phases would result in multiple database transactions instead of one transaction, which would disrupt the SAP LUW. | -|[Update function module](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_function_module_glosry.htm) (`CALL FUNCTION ... IN UPDATE TASK`)

(unrestricted ABAP language scope)|-| -| X |Can be used to ensure that there is only one database transaction. In addition, registering function modules for update tasks at stages other than the late save phase would interfere with RAP draft scenarios, for example, where data is stored in draft tables. There is no way to unregister function modules once they have been registered. | -|[bgRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbgrfc_glosry.htm) (`CALL FUNCTION ... IN BACKGROUND UNIT`)

(unrestricted ABAP language scope)| -| -| X| | -|[tRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentrfc_2_glosry.htm), [qRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenqrfc_glosry.htm) (`CALL FUNCTION ... IN BACKGROUND TASK`)

(unrestricted ABAP language scope)| -| -| - |Obsolete technologies. | -|`PERFORM ON COMMIT`, `PERFORM ON ROLLBACK`

(unrestricted ABAP language scope)|(X) |(X) |X |Basically possible in all phases, but should be reserved for the late save. Note: The use of these statements indicates improper integration with RAP. It is especially important to check draft scenarios when calling legacy code and using these statements. Instead, ABAP EML or procedure calls that do not include a `COMMIT WORK` should be used. | -|Transaction control `COMMIT WORK`, `ROLLBACK WORK` |X/-| X/-| X/- |When a transactional phase has been explicitly set by methods of the `CL_ABAP_TX` class (find more information [here](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw)), the transaction owner is allowed to execute a commit or rollback statement. In the contexts of RAP (that is, where RAP is the transaction owner, for example, in handler and saver methods), local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm), [bgPF](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbgpf_glosry.htm), and [classified APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassified_api_glosry.htm), commit or rollback statements are not allowed. | -|[Dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) processing (e.g. `SET SCREEN`, `CALL SCREEN`, `LEAVE SCREEN`, `CALL DIALOG`, `SUPPRESS DIALOG`, `MESSAGE` without `INTO`, `WRITE`, `STOP`)

(unrestricted ABAP language scope)|- |- |- |Not allowed in ABAP behavior implementations. Results in a runtime error. | -|Transaction processing (`CALL TRANSACTION`, `LEAVE TRANSACTION`)

(unrestricted ABAP language scope)| -| -| - |Not allowed to prevent (unwanted) integration of other LUWs. | -|Raising an exception (`RAISE EXCEPTION`) |-| -| - |It is not allowed to leave a RAP transaction this way. | -|Report processing (`SUBMIT ...`)

(unrestricted ABAP language scope)|- |- |- |Not allowed in transactional contexts. Results in a syntax or runtime error.
`SUBMIT ... AND RETURN` does not currently return an error, but it leads to potentially unwanted screen processing, and because of the missing return channel, there is no proper error handling. | - - -
- -

⬆️ back to top

- -## More Information - -- Section [ABAP for RAP Business - Objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_rap_bos.htm) - in the ABAP Keyword Documentation including EML -- [RAP Glossary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_glossary.htm) -- [Development guide for the ABAP RESTful Application Programming - Model](https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/289477a81eec4d4e84c0302fb6835035.html) -- [RAP - Contract](https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/3a402c5cf6a74bc1a1de080b2a7c6978.html): - Rules for the RAP BO provider and consumer implementation to ensure - consistency and reliability - -

⬆️ back to top

- -## Executable Examples - -This cheat sheet is supported by different executable examples demonstrating various scenarios: -- Demo RAP scenario with a managed RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_m](./src/zcl_demo_abap_rap_ext_num_m.clas.abap) -- Demo RAP scenario with an unmanaged RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_u](./src/zcl_demo_abap_rap_ext_num_u.clas.abap) -- Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering [zcl_demo_abap_rap_draft_ln_m](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) -- Demonstrating the local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) in the context of a RAP demo scenario (managed RAP BO with managed [internal numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_numbering_glosry.htm) and [additional save](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_add_save_glosry.htm)): [zcl_demo_abap_rap_m_as](./src/zcl_demo_abap_rap_m_as.clas.abap) - -> **💡 Note**
-> - To reduce the complexity, the executable examples only focus on the technical side. ABAP classes play the role of a RAP BO consumer here. -> - The examples do not represent real life scenarios and are not suitable as role models for proper RAP scenarios. They rather focus on the technical side by giving an idea how the communication and data exchange between a RAP BO consumer and RAP BO provider can work. Additionally, the examples show how the methods for non-standard RAP BO operations might be self-implemented in an ABAP behavior pool. -> - Due to the simplification, the examples do not entirely meet all requirements of the [RAP BO contract](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrap_bo_contract_glosry.htm) and do not represent semantic or best practice examples. -> - You can check out the "RAP calculator" example using the preview version of an SAP Fiori Elements UI. See the comments in the class for more information. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + +# ABAP for RAP: Entity Manipulation Language (ABAP EML) + +- [ABAP for RAP: Entity Manipulation Language (ABAP EML)](#abap-for-rap-entity-manipulation-language-abap-eml) + - [RAP Terms](#rap-terms) + - [Excursion: RAP Behavior Definition (BDEF)](#excursion-rap-behavior-definition-bdef) + - [ABAP Behavior Pools (ABP)](#abap-behavior-pools-abp) + - [RAP Handler Classes and Methods](#rap-handler-classes-and-methods) + - [RAP Saver Class and Saver Methods](#rap-saver-class-and-saver-methods) + - [BDEF Derived Types](#bdef-derived-types) + - [Components of BDEF Derived Types](#components-of-bdef-derived-types) + - [EML Syntax](#eml-syntax) + - [EML Syntax for Modifying Operations](#eml-syntax-for-modifying-operations) + - [EML Syntax for Reading Operations](#eml-syntax-for-reading-operations) + - [Dynamic Forms of EML Statements](#dynamic-forms-of-eml-statements) + - [Persisting to the Database](#persisting-to-the-database) + - [Raising RAP Business Events](#raising-rap-business-events) + - [Additions to EML Statements in ABAP Behavior Pools](#additions-to-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) + - [Ensuring Data Consistency in a RAP Transaction](#ensuring-data-consistency-in-a-rap-transaction) + - [More Information](#more-information) + - [Executable Examples](#executable-examples) + +## RAP Terms + +[ABAP Entity Manipulation Language](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenaeml_glosry.htm) (or EML for short) is a subset of ABAP that allows you to access the data of [RAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarap_glosry.htm) business objects in an ABAP program. +The following points cover RAP-related terms such as *RAP business objects* and others for setting the context: + +- RAP business objects (RAP BO) + - A RAP BO is based on a special, tree-like hierarchical structure + of [CDS + entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm "Glossary Entry") + of a data model + - Such a structure of entities consists of [parent + entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenparent_entity_glosry.htm "Glossary Entry") + and [child + entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenchild_entity_glosry.htm "Glossary Entry") + that are themselves defined using [CDS + compositions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_composition_glosry.htm "Glossary Entry") + and [to-parent + associations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abento_parent_association_glosry.htm "Glossary Entry"). + - The top parent entity of a [CDS composition + tree](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_composition_tree_glosry.htm "Glossary Entry") + is the root entity that represents the business object. With a + large composition tree, RAP BOs can be fairly complex. Or they + can be very simple by just consisting of one root entity alone. + - Note: There is a special syntax for the [CDS root entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenroot_entity_glosry.htm) of a RAP BO: [`define root view entity`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_define_root_view_v2.htm) +- [RAP behavior + definition](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_behavior_definition_glosry.htm "Glossary Entry") + (BDEF) + - RAP BOs are described by the definitions specified in a special + [DDIC](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenddic_glosry.htm "Glossary Entry") + artifact: RAP behavior definition (BDEF) + - A BDEF defines the [RAP business object + behavior](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_behavior_glosry.htm "Glossary Entry") + (i. e. the transactional behavior of a RAP BO) + - Transactional behavior means a BDEF defines [behavior + characteristics](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_properties_glosry.htm "Glossary Entry") + and [RAP BO + operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_operation_glosry.htm "Glossary Entry") i. + e. [RAP BO standard + operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_standard_operation_glosry.htm "Glossary Entry") + ([CRUD + operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencrud_glosry.htm "Glossary Entry")), + [non-standard + operations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_nstandard_operation_glosry.htm "Glossary Entry") + like specific [RAP + actions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_action_glosry.htm "Glossary Entry") + and + [functions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_function_glosry.htm "Glossary Entry"), + and more. + - There are many other things that can be included impacting the + RAP BO behavior like [RAP feature + control](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_feature_control_glosry.htm "Glossary Entry"), + for example, defining which data is mandatory and which is + read-only, or + [determinations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_determination_glosry.htm "Glossary Entry") + and + [validations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_validation_glosry.htm "Glossary Entry"). + - BDEFs use [Behavior Definition + Language](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_glosry.htm "Glossary Entry") + (BDL) for the definitions. Find more information on the topic + and various options to define the transactional behavior in + section [BDL for Behavior + Definitions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl.htm) + in the ABAP Keyword Documentation. +- Transactional buffer and implementation types + - A BDEF defines the behavior of a RAP BO and, thus, how to handle + its data. This data is available in the [RAP transactional + buffer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_buffer_glosry.htm "Glossary Entry"). + - It is a storage for a RAP BO's data that is used and worked on + during an [SAP LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw_glosry.htm). + - This data includes [RAP BO + instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_instance_glosry.htm "Glossary Entry") + (i. e. concrete data sets of an entity). This is where EML + enters the picture: EML is used, among others, to access this data in the transactional buffer. + - Currently, there are two kinds of RAP BOs: + [managed](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmanaged_rap_bo_glosry.htm "Glossary Entry") + and [unmanaged RAP + BOs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunmanaged_rap_bo_glosry.htm "Glossary Entry"). + - Managed and unmanaged are implementation types that are also + specified in the BDEF. + - The implementation type determines the [RAP BO + provider](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_provider_glosry.htm "Glossary Entry"), i. + e. how the transactional buffer is provided and how the behavior + of a RAP BO is implemented. +- Managed RAP BOs: + - The managed RAP BO provider fully or partly provides the + transactional buffer and RAP BO behavior (for standard + operations only). In this case, the developers need not cater + for the transactional buffer and implement the standard + operations. This implementation is mostly relevant for + greenfield scenarios when starting from scratch. + - Example: Regarding CRUD operations in managed RAP BOs, + developers need not cater for an implementation at all. The + standard operations work out of the box. For example, in case of + an update operation, RAP BO instance data that is to be updated + is automatically read into the transactional buffer, and then + updated accordingly there. Finally, when triggering the saving, + the updated instance in the transactional buffer is + automatically saved to the database without any custom + development needed. + - The transactional buffer is provided, too. You do not need to + create the buffer yourself. + - Note: Usually, the behavior of a RAP BO requires some + additional implementations also in the context of managed RAP + BOs. For example, non-standard operations or feature controls + must be self-implemented in [ABAP behavior + pools](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbehavior_pool_glosry.htm "Glossary Entry") + (see the details further down). +- Unmanaged RAP BOs: + - Everything must be provided by the [unmanaged RAP BO + provider](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunmanaged_rap_bo_prov_glosry.htm "Glossary Entry"), i. + e. the transactional buffer and all RAP BO operations must be + provided or self-implemented by developers in an ABAP behavior + implementation + - Unmanaged RAP BOs are, for example, relevant for brownfield + scenarios, i. e. in scenarios in which transactional buffers and application logic is already + available and should be embedded in the RAP world. Note that it is possible to have a managed RAP BO with unamanged parts, e.g. unamanged save or additional save. Find more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_rap_bo.htm). +- ABAP behavior implementation in an ABAP behavior pool (ABP) + - An [ABAP behavior + pool](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbehavior_pool_glosry.htm "Glossary Entry") + is a special [class + pool](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_pool_glosry.htm "Glossary Entry") + for an ABAP behavior implementation that implements the + unmanaged RAP BO provider based on definitions in a BDEF. The + class pool's name is specified in the BDEF. + - The [global + class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenglobal_class_glosry.htm "Glossary Entry") + of a behavior pool does not implement the behavior itself. It is + (initially) empty apart from the declaration and implementation part skeletons. The behavior implementation is coded in local + [RAP handler + classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm "Glossary Entry") + and a [RAP saver + class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class_glosry.htm "Glossary Entry") + in the [CCIMP + include](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenccimp_glosry.htm "Glossary Entry") + of the behavior pool. These classes are called by the [RAP + runtime + engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_runtime_engine_glosry.htm "Glossary Entry") + when the RAP BO is accessed. This is covered in more detail + further down. + - Usually, saver classes are not needed in managed RAP BOs (except + for special variants of managed RAP BOs which are not covered + here). Local handler classes are, as mentioned above, usually + needed in managed RAP BOs if implementations are required that + go beyond standard operations. + - Note: In more complex scenarios, with RAP BOs that + consist of many entities, you can define behavior pools for + individual entities by adding the syntax to the [`define + behavior + for`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_define_beh.htm) + notation. There is not a saver class for each entity but only + one saver class for the BO as a whole. Any number of behavior + pools can be assigned to a BDEF allowing applications a + structuring into multiple units. + + +Find more terms in the [RAP Glossary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_glossary.htm) of the ABAP Keyword Documentation. +There are more artifacts and concepts related to RAP that go way beyond +the scope of this cheat sheet. For example, a RAP BO can be exposed as a +[business +service](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbusiness_service_glosry.htm "Glossary Entry") +to be accessed from outside [AS +ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenas_abap_sys_environ_glosry.htm "Glossary Entry") +and consumed. A [RAP BO +consumer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_consumer_glosry.htm "Glossary Entry") +is either the [RAP transactional +engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_transac_engine_glosry.htm "Glossary Entry") +that handles requests from outside the AS ABAP or, from inside AS ABAP, +an ABAP program using ABAP EML (which this cheat sheet and the examples +focus on). + +

⬆️ back to top

+ +## Excursion: RAP Behavior Definition (BDEF) + +- As mentioned in the RAP terms and as the name implies, a RAP behavior definition describes a RAP business object (RAP BO) by defining its behavior for all of its RAP BO entities. +- BDL source code is used in a BDEF. +- Once you have created ... + - the CDS root entity of a RAP BO, ADT helps you create the skeleton of a BDEF (e.g., right-click on the CDS root entity and choose *New Behavior Definition* from the pop-up). + - the BDEF, ADT helps you create the skeleton of an ABAP behavior pool, as well as RAP handler and saver method declarations and the skeleton of implementations via ADT quick fixes. +- More information (see also the subtopics there): + - [Structure of a RAP behavior definition](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_bdef.htm) + - [Infos about BDL syntax](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_syntax.htm) + - [Infos about behavior definitions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl.htm) + + +The following example shows a commented BDEF. +Note that there is a wide variety of possible specifications and options. The example shows only a selection. For full details, refer to the ABAP Keyword Documentation. +Some of the syntax examples are commented out, just for the sake of showing more syntax options. + +```js +//Possible implementation types: managed, unmanaged, abstract, projection, interface +//(which restrict/enable further specifications) +//You can specifiy one or more implementation classes (behavior pools/ABPs -> bp...) +//for the RAP BO (in some contexts, specifying no ABP is possible). +//Specifying unique is mandatory (each operation can only be implemented once). +managed implementation in class bp_some_demo unique; +//For managed RAP BOs, you can enable user-defined saving options (optional additions +//are available). +//Purpose: Enhancing or replacing the default save sequence (Note: Only in this case, +//the ABP has a local saver class/save_modified saver method) +//managed with additional save with full data implementation in class bp_some_demo unique; +//full data: Full instance data is passed for saving +//managed with unmanaged save implementation in class bp_some_demo unique; + +//Enabling the strict mode (and version) to apply additional syntax checks; handled by +//the RAP framework; it is recommended that you use the most recent version +strict ( 2 ); + +//Enabling RAP draft handling +//with draft; + +//It is mandatory to specify an entity behavior definition for the RAP BO root entity. +//Here, some_demo represents a CDS view entity. +define behavior for some_demo +//Specifying an alias name (e.g. to have a more telling name than the technical name of +//the entity). When specifying an alias name, you should address the entity with the alias +//name instead of the full name (e.g. in the signature of handler methods). +//define behavior for some_demo alias root + +//Specifying the database table a RAP BO is based on (only available/mandatory in managed +//BOs); note further requirements for diverse scenarios in the documentation +persistent table some_dbtab + +//Mandatory specification of a draft table when a RAP BO is draft-enabled +//draft table drafttab + +//Specifying the locking mechanism for entities, e.g. to prevent a simultaneous +//modification. In unmanaged RAP BOs, this must be self-implemented in a dedicated handler +//method +lock master + +//Controlling authorization that is to be implemented in an ABP (also for managed) +//You can specify variants: global (e.g. for restricting certain operations) and/or +//instance (restrictions based on entity instances) or both of them (dedicated handler +//methods must be implemented) +//More variants are available that can be specified in the { ... } block below for +//excluding and delegating authorization checks (e.g. authorization:update) +authorization master ( instance ) +//authorization master ( global ) +//authorization master ( instance, global ) + +//Defining late numbering for primary key fields (see the adjust_numbers handler method) +//More numbering options are available such as early numbering, or, in the { ... } block below, +//the 'numbering : managed' specification for particular fields. +//late numbering + +//Defining a field as entity tag (ETag) field for optimistic concurrency control (i.e. +//enabling transactional access to data by multiple users to avoid inconsistencies when +//unintentionally changing already modified data). More options available, e.g. for +//draft-enabled RAP BOs (total etag). +//etag master some_field + +{ + //RAP BO operations + //Standard operations (Note: Read is implicitly enabled, no specification available) + create; + update; + //More additions are available dealing with authorization, feature control, precheck etc. + //The example shows precheck. In doing so, you can implement a precheck (e.g. to prevent + //unwanted changes) before instances are deleted in a dedicated handler method. A precheck + //implementation is also available for other operations (e.g. actions). + //As is true for various specifications, a comma-separated list of specifications is possible. + delete( precheck ); + + //Note: It is not possible to specify operations multiple times. The following specifications + //just demonstrate syntax options. Anyway, the compiler helps you not to specify wrong notations. + //Applying feature control + //delete( features: global ); + + //Applying authorization control + //delete( authorization : update ); + + //Operations for associations (many specification options are possible) + //The following example means enabling create-by-association operations for associations + //Assumption: _child is specified in the the underlying CDS data model. + association _child { create; } + + //Non-standard operations (check the specification options in the documentation, e.g. feature + //control and others are possible) such as actions (modify RAP BO instance) and functions (return + //information). There are different flavors of actions such as non-factory and factory actions, + //which themselves have different variations. Other flavors of actions are save actions (only to + //be executed during save sequence), determine actions (allow RAP BO consumers to execute + //determinations and validations on request), and draft actions. + + //Non-factory actions (modify existing instances) + //Instance action, relates to instances, modify instances + action act1; + + //Static action, not bound to instances, relates to the entrie entity + static action act2; + + //Internal action, accessible only from within the ABP (internal can also be specified in other + //contexts, e.g. operations) + internal action act3; + + //You can optionally specify input or output parameters or both (not always possible for all + //action types). The following example shows an output parameter, defined with the result + //addition. It stores the result of an action in an internal table. Variants are possible for + //the return type. Here, it is $self (result type is the same type as entity) It can, for + //example, also be an abstract BDEF or a different entity. + action act4 result [1] $self; + + //Input parameter specified following 'parameter' (in this case, a CDS abstract entity) + action act5 parameter some_cds_abstract; + + //Factory action (to create instances, can be instance-bound or static) + //Specifying the cardinality is mandatory + factory action act6 [1]; + + //Draft actions + //Available for draft-enabled RAP BOs, allow data modification on the draft table; are + //implicitly available; it is recommended for the draft actions to be specified explicitly; + //for some of the methods, the 'with additional implementation' addition is available + + //Copies active instances to the draft table + //draft action Edit; + + //Sets a lock for entity instances on the persistent database table + //draft action Resume; + + //Copies draft table content to the persitent database table; recommendation: use the + //optimized addition + //draft action Activate optimized; + + //Clears entries from the draft database table + //draft action Discard; + + //Corresponds to the determine actions for active instances; + //used to validate draft data before transitioning to active data + //draft determine action Prepare + // { + //You can assign validations and determinations defined with 'on save' + // validation val; + // } + + //Functions (similar to actions, there are optional additions, such as static) + //Since they return information, specifying an output parameter is required. + //Instance function + function func1 result [0..*] $self; + + //Static function + static function func2 result [1] some_cds_abstract; + + //Instance function with optional input parameter + function func3 parameter some_cds_abstract result [1] $self; + + //Field characteristics + //Field values cannot be created/updated + field ( readonly ) field1; + + //Read-only during update (especially key fields created during create operations) + field ( readonly : update ) key_field; + + //The mandatory specification denotes that values must be provided for the fields before persisting + //them to the database. + //Comma-separated list possible for the field characteristics in general; + //mutliple characteristics can also be specified in a comma-separated list in the parentheses + field ( mandatory ) field2, field3; + + //Defining access restrictions for fields + field ( features : instance ) field4; + + //Validations + //Checking the consitency of instances; validations are triggered based on conditions + //Conditions (one or more are possible) can be specified for create, update, delete operations + //and modified fields; note: not available for unmanaged, non-draft RAP BOs. + validation val on save { create; field field1; } + + //Determinations + //Modifying instances based on trigger conditions; + //As above, conditions (one or more are possible) can be specified for create, update, delete + //operations and modified fields. The triggering is possible for 'on modify' and 'on save'. + determination det1 on modify { update; delete; field field5, field6; } + determination det2 on save { create; field field7, field8; } + + //RAP business event (derived events with the specification 'managed evt ...' are also possible) + event evt; + + //RAP side effects, to trigger a reload of affected properties on the UI + //Trigger properties: Field changes, action executions + //Multiple side effects can be specified within a { ... } block, separated by a colon + //There are multiple options to specify the target following 'affect'; the example uses fields + //to be reloaded + side effects { field field1 affects field field4; + field field2 affects field field4; + field field3 affects field field4; + action act1 affects field field4; } + +} + + +//It is optional to specify an entity behavior definition for child entities +define behavior for some_child_entity alias child + +//Applying locks dependent on the specified association (locks are delegated to +//the specified association). In this case, it's the parent entity. Assumption: +//_parent is specified in the the underlying CDS data model. +lock dependent by _parent + +//Applying authorization checks dependent on the specified association +//As above, the assumption is that _parent is specified in the underlying CDS +//data model. +authorization dependent by _parent + +{ + update; + delete; + field ( readonly ) key_field; + field ( readonly : update ) key_field_child; + association _parent; +} +``` + +

⬆️ back to top

+ +## ABAP Behavior Pools (ABP) + +As mentioned above, you can access RAP BO data from inside AS ABAP using +EML. Among other things, EML allows you to read or modify RAP BOs by +accessing the RAP BO data (the RAP BO instances) in the transactional +buffer and trigger the persistent storage or reset changes. More +precisely, when EML statements are executed, the calling of [RAP handler +methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm "Glossary Entry") +is triggered to access the transactional buffer of a RAP BO. As +mentioned, for unmanaged RAP BOs or unmanaged parts of managed RAP BOs, +the handler methods that are called are part of an ABAP behavior pool. + +The global class of an ABP has the addition [`FOR BEHAVIOR OF bdef`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapclass_for_behavior_of.htm) +to the definition while `bdef` stands for the name of the BDEF. +This class is (initially) empty apart from the declaration and implementation part skeleton. + +```abap +CLASS zbp_demo_abap_rap_draft_m DEFINITION PUBLIC ABSTRACT FINAL FOR BEHAVIOR OF zdemo_abap_rap_draft_m. +ENDCLASS. + +CLASS zbp_demo_abap_rap_draft_m IMPLEMENTATION. +ENDCLASS. +``` + +The actual implementation is done in local classes in the CCIMP include (*Local Types* tab in ADT) of the behavior pool. There, +two kinds of local classes are to be defined and implemented that are +related to the RAP BO's runtime: one or more [handler +classes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm "Glossary Entry") +to implement the RAP BO behavior (in RAP handler methods) during the +[RAP interaction +phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm "Glossary Entry") +(the data reading and modification phase) and a [saver +class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class_glosry.htm "Glossary Entry") +to implement the [RAP save +sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry") +(in [saver +methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_method_glosry.htm "Glossary Entry") +to save data from the transactional buffer to the database). + +

⬆️ back to top

+ +### RAP Handler Classes and Methods + +- One or more handler classes implement the RAP interaction phase. For + modularization purposes, one behavior pool can define multiple + handler classes. For example, each entity can have its own handler + class, or individual handler classes can be defined to distinguish + between reading and changing RAP BO entities. +- A handler class inherits from class + `CL_ABAP_BEHAVIOR_HANDLER`. +- These classes are implicitly `ABSTRACT` and `FINAL` + since instantiating and calling only happens through the RAP runtime + engine. +- [ADT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm "Glossary Entry") + helps you create the classes and methods (and basically the ABP as + such) when creating the BDEF. A quick fix is available that creates + the method definitions and a skeleton of the implementations + automatically. + +Example: Handler class definition +``` abap +CLASS lhc_root DEFINITION INHERITING FROM cl_abap_behavior_handler. +... +ENDCLASS. +``` +- Handler method definitions include the additions `... FOR ... FOR + ...` followed by the kinds of operations. There are various + options depending on the RAP BO operation. +- Depending on the definition in the BDEF, there might be more additions + with dedicated method parameters. For example, an action might + be defined with a result parameter, hence, the method must be + defined with the addition `RESULT` and a parameter. +- The `FOR MODIFY` handler method can handle multiple entities + and operations, i. e. not only create but also update or delete + might be integrated in the method definition. However, it might be + useful to split the handler method into separate methods for better + readability. +- See more details on the handler method definitions in the topic + [`METHODS, FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmethods_for_rap_behv.htm). + +Example: Handler method definitions +``` abap +"Create +METHODS create FOR MODIFY + IMPORTING entities FOR CREATE bdef. + +"Read: Specifying a read result is mandatory. +METHODS read FOR READ + IMPORTING keys FOR READ bdef RESULT result. + +"Action: action name is preceded by the BDEF name and a tilde after FOR ACTION +METHODS some_action FOR MODIFY + IMPORTING keys FOR ACTION bdef~some_action. +``` + +**Parameters of Handler Methods** + +- The handler method definitions contain RAP-specific additions like + `FOR MODIFY`, `FOR CREATE` or `FOR READ` as + well as mandatory or optional additions like `RESULT` that + are followed by parameters. +- Nearly all parameters are typed with [BDEF derived + types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry") + 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 + implicitly. In most cases, entire instances or just key values + of instances are imported. +- All handler methods have changing parameters that are usually not + explicitly specified in the definition but implicitly used. The + explicit specification of the `CHANGING` addition is not needed. In most cases, these are + [RAP response + parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_response_param_glosry.htm "Glossary Entry"). + The following image shows the F2 information in ADT for the create + handler method. + ![RAP_handler_method_parameters](./files/rap_handler_method_parameters.png) +- The response parameters `mapped`, `failed` and + `reported` (the names are predefined) can be considered as + containers for information - information a RAP BO consumer is + provided with by a RAP BO provider, for example, an SAP Fiori app + displays an error message if something went wrong. The availability + of the parameters depends on the handler method used (e. g. + `mapped` is only available for operations creating + instances). + - `mapped`: Used to provide mapping information on RAP BO + instances, for example, which key values were created for given + content IDs ( + [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm)). + - `failed`: Information for identifying the data set for + which an error occurred in a RAP operation + - `reported`: Used, for example, to exchange error messages for each + entity defined in the BDEF and [not related to a specific + entity](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_other.htm). + - Example: Technically, the `reported` parameter is a + [deep + structure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeep_structure_glosry.htm "Glossary Entry") + containing, for example, the messages of the root entity and + child entities. For example, if a create operation fails for a + RAP BO instance of the root entity, a message, information about + the instance key and other things can be included in this + parameter which is passed to a RAP BO consumer. You could + imagine that such an error message is displayed on an SAP Fiori + UI if something goes wrong to inform the user. + + +

⬆️ back to top

+ +### RAP Saver Class and Saver Methods + +- A RAP saver class implements the [RAP save + sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry"). + A saver class is usually only available in unmanaged RAP BOs (except + for special variants of managed RAP BOs that are not outlined here). +- The saver class is implicitly `ABSTRACT` and `FINAL` + since the instantiating and calling only happens through the RAP + runtime engine. +- A saver class can be defined in the CCIMP include of an ABAP + behavior pool. It includes the definitions and implementations of + RAP saver methods. +- The saver methods consist of a set of predefined methods having + predefined names. Some of them are mandatory to implement, some are + optional. The + [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm) + method is only available in [late + numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry") + scenarios. +- A saver class inherits from class + `CL_ABAP_BEHAVIOR_SAVER`. The saver methods are + declared by redefining predefined methods of the superclass. They + implicitly have response parameters. +- In contrast to RAP handler methods, saver methods do not have data + of RAP BO instances as import parameter. Therefore, instance data + must be handled via the transactional buffer when self-implementing + the saver methods. +- Saver methods are called when the RAP save sequence has been triggered by a [`COMMIT + ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm) + statement. Note that in natively supported RAP scenarios, for example, an SAP Fiori app using OData, the `COMMIT ENTITIES` call is performed implicitly and automatically by the [RAP runtime engine](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_runtime_engine_glosry.htm). +- Find more information on RAP saver methods + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_saver_class.htm). + +Example: Definition of a RAP saver class and saver methods +``` abap +CLASS lsc_bdef DEFINITION INHERITING FROM cl_abap_behavior_saver. + PROTECTED SECTION. + + "For final calculations and data modifications involving all + "BOs in the current RAP transaction + METHODS finalize REDEFINITION. + + "Checks the consistency of the transactional buffer before + "the save method saves data to the database + METHODS check_before_save REDEFINITION. + + "Preliminary IDs are mapped to final keys. Only for late numbering. + METHODS adjust_numbers REDEFINITION. + + "Saves the current state of the transactional buffer to the database + METHODS save REDEFINITION. + + "Clear the transactional buffer + METHODS cleanup REDEFINITION. + METHODS cleanup_finalize REDEFINITION. + +ENDCLASS. +``` + +

⬆️ back to top

+ +## BDEF Derived Types + +The operands of EML statements and parameters of handler and saver +methods are mainly special messenger tables for passing data and +receiving results or messages, i. e. the communication between a RAP BO +consumer and the RAP BO provider using EML consists (in most cases) of +exchanging data stored in internal tables that have special ABAP types - +[BDEF derived +types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry"). +These types are tailor-made for RAP purposes. + +As the name implies, the types are derived by the [ABAP runtime +framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm "Glossary Entry") +from CDS entities and their behavior definition in the BDEF. With these +special types, a type-safe access to RAP BOs is guaranteed. + +You can create internal tables (using [`TYPE TABLE +FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_table_for.htm)), +structures (using [`TYPE STRUCTURE +FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_structure_for.htm)) +and data types with BDEF derived types. For all operations and behavior +characteristics defined in the BDEF, types can be derived. + +The syntax uses - similar to the method definitions mentioned before - +the addition `FOR` followed by the operation and the name of an +entity (and, if need be, the concrete name, e. g. in case of an action +defined in the BDEF). + +Each BDEF derived type can be categorized as +[input](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_input_der_type_glosry.htm "Glossary Entry") +or [output derived +type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_output_der_type_glosry.htm "Glossary Entry") +according to its use as importing or exporting parameters in methods of +RAP BO providers. In most cases, structures of type `TYPE STRUCTURE +FOR` can be considered as serving as [work +area](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenwork_area_glosry.htm "Glossary Entry") +and line type of the internal tables. However, there are also structured +derived types that do serve as types for handler method parameters. + +The response parameters `mapped`, `failed` and +`reported` have dedicated derived types: [`TYPE RESPONSE +FOR`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptype_response_for.htm). +They are deep structures containing the information for the individual +entities of the RAP BO. The components of these structures are internal +tables of appropriate types with `TYPE TABLE FOR`. + +Examples for BDEF derived types: + +``` abap +"Data objects with input derived types (entity = name of a root entity) + +"For an EML create operation +DATA create_tab TYPE TABLE FOR CREATE entity. + +"For an update operation +DATA update_tab TYPE TABLE FOR UPDATE entity. + +"Type for create-by-association operations specifying the name of the entity +"and the association +DATA cba_tab TYPE TABLE FOR CREATE entity\_child. + +"For an action execution; the name of the action is preceded by a tilde +DATA action_imp TYPE TABLE FOR ACTION IMPORT entity~action1. + +"Data objects with output derived types + +"For a read operation +DATA read_tab TYPE TABLE FOR READ RESULT entity. + +"For an action defined with a result +DATA action_res TYPE TABLE FOR ACTION RESULT entity~action2. + +"Examples for structures and types +DATA create_wa TYPE STRUCTURE FOR CREATE entity. + +"For permission retrieval +DATA perm_req TYPE STRUCTURE FOR PERMISSIONS REQUEST entity. + +"For retrieving global features +DATA feat_req TYPE STRUCTURE FOR GLOBAL FEATURES RESULT entity. + +"Type declaration using a BDEF derived type +TYPES der_typ TYPE TABLE FOR DELETE entity. + +"Response parameters +DATA map TYPE RESPONSE FOR MAPPED entity. +DATA fail TYPE RESPONSE FOR FAILED entity. +DATA rep TYPE RESPONSE FOR REPORTED entity. +``` +> **💡 Note**
+> Some of the derived types can only be created and accessed in implementation classes. + +

⬆️ back to top

+ +### Components of BDEF Derived Types + +Many of the BDEF derived types contain components of CDS entities like +key and data fields that retain their original data type, for example, a +messenger table typed with `TYPE TABLE FOR CREATE`. Certainly, +if an instance is to be created, key and field values of a RAP BO +instance are of relevance. + +Yet, all BDEF derived types contain special RAP components serving a +dedicated purpose. The names of these RAP components begin with +`%` to avoid naming conflicts with components of the CDS +entities. The following image shows the F2 information of a BDEF derived +type containing the `%` components and fields from the CDS +entity. + +![BDEF_derived_types](./files/bdef_derived_types.png) + +Some of the `%` components are [component +groups](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_group_glosry.htm "Glossary Entry") +summarizing groups of table columns under a single name. In doing so, +they simplify the handling of derived types for developers. For example, +the component group +[`%data`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_data.htm) +contains all primary key and data fields of a RAP BO entity (actually, +by containing the keys, it also contains the component group +[`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm) +in the case above). The F2 information in ADT helps you find out about +the available components in a variable. The image below shows the +details of `%data` when clicking the *derived type* +link in the first ADT F2 information screen. + +![BDEF_derived_type_components](./files/bdef_derived_type_components.png) + +The availability of `%` components depends on definitions in the +BDEF. Their availability also depends on more criteria, for example, the +scenario. For example, the component +[`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) +that represents a preliminary ID for a RAP BO instance is only available +in [late +numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry") +scenarios. The draft indicator +[`%is_draft`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_is_draft.htm) +is only relevant in the context of +[draft](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_with_draft.htm). + +Find more details on the available components in section [Components of +BDEF Derived +Types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_comp.htm). + +Bullet points on selected `%` components: + +- [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm) + - A string to define a content ID. + - Content IDs are used as a unique and preliminary identifier for + RAP BO operations in which instances are created and especially + in cases where the key values of RAP BO instances are not yet + determined + - Assume that you create a RAP BO instance with an EML create + request and the key value has not yet been determined. In the + same request - a save has not yet been triggered - an update is + requested for this RAP BO instance. Using the content ID, it is + guaranteed that the update operation happens for the desired + instance. For this purpose, derived types for operations like + update or delete include the component + [`%cid_ref`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid_ref.htm) + to refer to the content ID `%cid` as the name implies. + - Note: You should always fill `%cid` even if not + needed. The specified content ID is only valid within one ABAP + EML request. You can use the optional addition [`AUTO FILL CID`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm#!ABAP_ONE_ADD@1@) in EML modify operations to create `%cid` automatically. However, if you use this addition, you cannot refer to `%cid` in subsequent operations. +- [`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm)/[`%tky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tky.htm) + - Both are component groups summarizing all primary keys of a RAP + BO instance. + - Where possible, it is recommended that you use `%tky` + instead of `%key`. `%tky` includes + `%key` and also the draft indicator + `%is_draft`. When using `%tky` in non-draft + scenarios, you are prepared for a potential, later switch to a + draft scenario. In doing so, you can avoid lots of adaptations + in your code by manually adding the indicator. +- [`%control`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_control.htm) + - Component group that contains the names of all key + and data fields of a RAP BO instance which indicate flags. + - For example, it is used to get information on which fields are provided or set a + flag for which fields are requested by RAP BO providers or RAP + BO consumers respectively during the current EML request. + - For this purpose, the value of each field in the + `%control` structure is of type + `ABP_BEHV_FLAG`. For the value setting, + you can use the structured constant `mk` of interface + `IF_ABAP_BEHV`. Note that the technical + type is `x length 1`. + - Example: If you want to read data from a RAP BO instance and + particular non-key fields in `%control` are set to + `if_abap_behv=>mk-off`, the values of these fields + are not returned in the result. + +

⬆️ back to top

+ +## EML Syntax + +The focus is here on selected EML statements. These statements can be +fairly long and various additions are possible. Find more information on +the EML statements +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeneml.htm). + +### EML Syntax for Modifying Operations + +The modifying operations covered include the standard operations (using +the additions +[`CREATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), +[`CREATE +BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), +[`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), +and +[`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm)) +and non-standard operations (actions) using the addition +[`EXECUTE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm). +All EML statements for the mentioned operations begin with +[`MODIFY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities.htm). +The following commented code snippets demonstrate the +[short](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_short.htm) +and [long +form](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entities_long.htm) +of EML `MODIFY` statements. + +> **💡 Note**
+> Unlike reading operations, modifying operations are not enabled by default. You must make the respective notations in the BDEF: +> ``` +> ... +> create; +> update; +> delete; +> action some_act; +> ... +> ``` + +Create operation for creating new instances of a RAP BO entity: + +``` abap +"Declaration of data objects using BDEF derived types + +DATA: cr_tab TYPE TABLE FOR CREATE root_ent, "input derived type + mapped_resp TYPE RESPONSE FOR MAPPED root_ent, "response parameters + failed_resp TYPE RESPONSE FOR FAILED root_ent, + reported_resp TYPE RESPONSE FOR REPORTED root_ent. + +"Input derived type for the EML statement is filled using the VALUE operator +"Assumption: key_field is the key field having type i, +"field1 and field2 are data fields with character-like data type. +"Specify %cid even if not used or of interest; it must be unique within a request + +cr_tab = VALUE #( + ( %cid = 'cid1' key_field = 1 + field1 = 'A' field2 = 'B' ) + ( %cid = 'cid2' + "Just to demo %data/%key. You can specify fields with or without + "the derived type components + %data = VALUE #( %key-key_field = 2 + field1 = 'C' + field2 = 'D' ) ) ). + +"EML statement, short form +"root_ent must be the full name of the root entity, it is basically the name of the BDEF + +MODIFY ENTITY root_ent + CREATE "determines the kind of operation + FIELDS ( key_field field1 field2 ) WITH cr_tab "Fields to be respected for the + "input derived type and the input + "derived type itself + MAPPED mapped_resp "mapping information + FAILED failed_resp "information on failures with instances + REPORTED reported_resp. "messages +``` + +> **💡 Note**
+> - Addition [`FIELDS ( ... ) WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm): + This field selection option specifies which fields are to be + respected for the operation. The derived type, i. e. an internal + table containing the concrete RAP BO instance values, follows + `WITH`. If a field is specified in the field list within the + pair of parentheses after `FIELDS`, the `%control` + flag for this field is automatically set to + `if_abap_behv=>mk-on`. Likewise, if a field is not + contained in the list, the flag in `%control` is set to + `if_abap_behv=>mk-off`. Assume `field2` is not + specified in the list. The value for `field2` will not be + respected (even if a value is specified in the internal table). The + initial value will be used for the field. +>- Retrieving the responses and specifying the parameters is optional. + Assuming a data set with the value 2 for `key_field` + already exists on the database for this BO, you should expect an + entry for this particular instance in the `failed_resp` + operand and potentially an error message in + `reported_resp`, too. Nevertheless, especially in ABP + implementations and depending on the context, you should implement + and fill these parameters according to the [RAP BO + contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_contract_glosry.htm "Glossary Entry") + to meet the variety of implementation rules. +>- `%cid` should be provided even if you are not interested in + it and subsequent operations do not require the reference. + +Long form of an EML `MODIFY` statement: +``` abap +MODIFY ENTITIES OF root_ent "full name of root entity + ENTITY root "root or child entity (alias name if available) + CREATE FROM "FROM as further field selection variant + VALUE #( ( %cid = 'cid' "Input derived type created inline + key_field = 3 + field1 = 'E' + field2 = 'F' + %control = VALUE #( "Must be filled when using FROM + key_field = if_abap_behv=>mk-on + field1 = if_abap_behv=>mk-on + field2 = if_abap_behv=>mk-on ) ) ) + MAPPED DATA(m) "Target variables declared inline + FAILED DATA(f) + REPORTED DATA(r). +``` + +> **💡 Note**
+>- The entity specified after `ENTITY` can be either the root + entity itself or a child entity. If an alias is defined, the alias + should be used. +>- The addition `FIELDS ( ... ) WITH` from the previous + snippet is basically a shortcut for the addition + [`FROM`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_fields.htm) + that is used here. When using `FROM`, the values of the + `%control` structure must be specified explicitly. +>- The BDEF derived types can also be created + [inline](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm) + as shown in the example using a [constructor + expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_glosry.htm "Glossary Entry") + for the input derived type and with `DATA` or + [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) + for the responses. +>- The long form allows you to bundle several operations in one + statement, either different operations on the same entity (for + example, deleting some instances and updating some others) or + operations on different entities of the same RAP BO (for example, + creating a root entity instance and related instances of a child + entity in one EML request). Long and short forms are also available + for other EML statements. +>- The [`SET FIELDS WITH`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodify_entity_entities_fields.htm#!ABAP_VARIANT_4@4@) addition is available as another field specification option. However, it has limitations that you should be aware of. It can cause syntax warnings. Check the documentation. It is recommended that you use `FIELDS ... WITH` and `FROM`. + + +Excursion: Specifying `%control` component values in the short form of `VALUE` constructor expressions + +```abap +"The following EML statement creates RAP BO instances. The BDEF derived +"type is created inline. With the FROM addition, the %control values +"must be specified explicitly. You can provide the corresponding values +"for all table lines using the short form, i.e. outiside of the inner +"parentheses, instead of individually specifying the values for each +"instance within the parentheses. In this case, the corresponding %control +"component value is assigned for all of the following table lines. +MODIFY ENTITIES OF zdemo_abap_rap_ro_m + ENTITY root + CREATE FROM VALUE #( + %control-key_field = if_abap_behv=>mk-on + %control-field1 = if_abap_behv=>mk-on + %control-field2 = if_abap_behv=>mk-on + %control-field3 = if_abap_behv=>mk-on + %control-field4 = if_abap_behv=>mk-off + ( %cid = 'cid1' + key_field = 1 + field1 = 'aaa' + field2 = 'bbb' + field3 = 10 + field4 = 100 ) + ( %cid = 'cid2' + key_field = 2 + field1 = 'ccc' + field2 = 'ddd' + field3 = 20 + field4 = 200 ) ) + MAPPED DATA(m) + FAILED DATA(f) + REPORTED DATA(r). +``` + + +The following EML statement combines multiple operations in one EML +request. It demonstrates the use of `%cid` and +`%cid_ref`. First, two instances are created by specifying +`%cid`. An update operation in the same request only specifies a +certain field within the parentheses of the `FIELDS ( ... ) +WITH` addition which denotes that only this particular field +should be updated. The other field values remain unchanged. The +reference to the instance is made via `%cid_ref`. Consider an +EML request in which no instance to refer to using `%cid_ref` +exists, e. g. for an update operation. You can also make the reference +using the unique key. A delete operation is available in the same +request, too. `DELETE` can only be followed by the addition +`FROM`. In contrast to other derived types, the derived type +that is expected here (`TYPE TABLE FOR DELETE`) only has +`%cid_ref` and the key as components. +``` abap +MODIFY ENTITIES OF root_ent + ENTITY root + CREATE FIELDS ( key_field field1 field2 ) WITH + VALUE #( ( %cid = 'cid4' key_field = 4 + field1 = 'G' field2 = 'H' ) + ( %cid = 'cid5' key_field = 5 + field1 = 'I' field2 = 'J' ) ) + + UPDATE FIELDS ( field2 ) WITH + VALUE #( ( %cid_ref = 'cid4' field2 = 'Z' ) ) + + DELETE FROM + VALUE #( ( %cid_ref = 'cid5' ) "Instance referenced via %cid_ref + ( key_field = 9 ) ) "Instance referenced via the key +... +``` + +EML statement including the execution of an action: +``` abap +MODIFY ENTITIES OF root_ent + ENTITY root + EXECUTE some_action + FROM action_tab + RESULT DATA(action_result) "Assumption: The action is defined with a result parameter. + ... +``` + +The following code snippet shows a deep create. First, an instance is +created for the root entity. Then, in the same request, instances are +created for the child entity based on the root instance. In the example +below, the assumption is that a composition is specified in the root +view entity like `composition [1..*] of root_ent as _child` and `key_field` and +`key_field_child` are the keys of the child view entity. The +[`%target`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_target.htm) +component group enters the picture here which contains the target's +primary key and data fields. +``` abap +MODIFY ENTITIES OF root_ent + ENTITY root_ent + CREATE FIELDS ( key_field field1 field2 ) WITH + VALUE #( ( %cid = 'cid6' key_field = 6 + field1 = 'I' field2 = 'J' ) ) + CREATE BY \_child + FIELDS ( key_field_child field1_child field2_child ) WITH + VALUE #( ( %cid_ref = 'cid6' + %target = VALUE #( ( %cid = 'cid_child_1' + key_field_child = 1 + field1_child = 'aa' + field2_child = 'bb' ) + ( %cid = 'cid_child_2' + key_field_child = 2 + field1_child = 'cc' + field2_child = 'dd' ) ) ) ) +... +``` + +

⬆️ back to top

+ +### EML Syntax for Reading Operations + +- Read-only operations always return a result, i.e. the syntax of the + EML statement requires the addition `RESULT` and an operand. +- When RAP BO instances are read, the returned data include the + current status of instances in the transactional buffer which + includes unsaved modifications on instances. If an instance is not + yet available in the transactional buffer, the currently persisted + data set is automatically read into the transactional buffer. +- Note that read operations are always implicitly enabled for each + entity listed in a BDEF, i. e. there is no extra definition in the + BDEF in contrast to, for example, create or update. + +The following code snippet shows the long form of the EML +[`READ`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_op.htm) +statement for reading instances from the root entity. In `READ` +statements, the additions `FIELDS ( ... ) WITH` and +`FROM` can also be used to specify the fields that you intend to +read. Here, the addition [`ALL FIELDS +WITH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_fields.htm) +is available for reading all field values. + +``` abap +READ ENTITIES OF root_ent + ENTITY root_ent + ALL FIELDS WITH + VALUE #( ( key_field = 1 ) "Derived type TYPE TABLE FOR READ IMPORT only includes the keys + ( key_field = 2 ) ) + RESULT DATA(result) + FAILED DATA(f) + REPORTED DATA(r). +``` + +Read-by-association operations include the optional addition +[`LINK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entity_entities_op&sap-language=EN&sap-client=000&version=X&anchor=!ABAP_ONE_ADD@1@&tree=X) +with which you can retrieve the keys of the source and target (i. e. the +associated entity). The by-association operations work reciprocally, i. +e. you can, for example, read a child instance via the parent and a +parent instance via the child, too. + +``` abap +"Read-by association operation: parent to child +READ ENTITIES OF root_ent + ENTITY root_ent + BY \_child + ALL FIELDS WITH VALUE #( ( key_field = 1 ) ) + RESULT DATA(rba_res1) + LINK DATA(links1). + ... + +"Read-by association operation: child to parent +READ ENTITIES OF root_ent + ENTITY child_ent + BY \_parent + ALL FIELDS WITH VALUE #( ( key_field = 1 key_field_child = 1 ) ) + RESULT DATA(rba_res2) + LINK DATA(links2). + ... +``` +

⬆️ back to top

+ +### Dynamic Forms of EML Statements + +In addition to the short and long forms described above, various ABAP EML statements also have dynamic forms. +Taking EML read operations as an example, the following code snippet shows a dynamic EML [`READ ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapread_entities_operations.htm) statement. The relevant syntax element is the `OPERATIONS` addition. +The dynamic form allows the collection of read operations for multiple RAP BOs in one EML statement. +For more information, see the ABAP keyword documentation and the comments in the snippet. + +```abap +"The statement is taken from the executable example. The example has a +"root entity and a child entity. For both entities, RAP BO instances +"are to be read (read and read-by-association operation). + +DATA: + "The following data object is the operand of the dynamic EML statement + "It is an internal table and has a special, RAP-specific type. + op_tab TYPE abp_behv_retrievals_tab, + + "More data object declarations (internal tables typed with BDEF + "derived types) that are relevant for the EML statement. + "For both entities (root and child), RAP BO instances are to be + "read. The internal tables are used for components of the internal + "table op_tab further down. + read_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m, + read_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m, + rba_dyn TYPE TABLE FOR READ IMPORT zdemo_abap_rap_ro_m\_child, + rba_dyn_result TYPE TABLE FOR READ RESULT zdemo_abap_rap_ro_m\_child, + rba_dyn_link TYPE TABLE FOR READ LINK zdemo_abap_rap_ro_m\_child. + +"Filling the internal tables, i.e. which instances are to be read +"Root entity +"Example: +"- The key is comprised of the field 'key_field'. It is of type i. +"- The %control structure is filled, flagging those fields that +" are to be read. Flagging the key field is not required. +read_dyn = VALUE #( + ( %key-key_field = 1 + %control = VALUE #( + field1 = if_abap_behv=>mk-on + field2 = if_abap_behv=>mk-on + field3 = if_abap_behv=>mk-on + field4 = if_abap_behv=>mk-on ) ) + ( %key-key_field = 2 + %control = VALUE #( + field1 = if_abap_behv=>mk-on + field2 = if_abap_behv=>mk-on + field3 = if_abap_behv=>mk-on + field4 = if_abap_behv=>mk-on ) ) ). + +"Child entity +"Instances to be read for a read-by-association operation +"The shared key is 'key_field'. +rba_dyn = VALUE #( + ( %key-key_field = 1 + %control = VALUE #( + key_ch = if_abap_behv=>mk-on + field_ch1 = if_abap_behv=>mk-on + field_ch2 = if_abap_behv=>mk-on ) ) + ( %key-key_field = 2 + %control = VALUE #( + key_ch = if_abap_behv=>mk-on + field_ch1 = if_abap_behv=>mk-on + field_ch2 = if_abap_behv=>mk-on ) ) ). + +"Filling the internal table that is the operand of the +"dynamic EML statement +"This table has optional and mandatory components. +op_tab = VALUE #( + ( "op: Specifies the operation to be executed; is mandatory; + " can be set with the predefined constants, e.g. OP-R-READ + " etc., of interface IF_ABAP_BEHV + op = if_abap_behv=>op-r-read + "entity_name: Specifies the name of the RAP BO entity for which + " the operation is executed; is mandatory + entity_name = 'ZDEMO_ABAP_RAP_RO_M' + "instances: Specifies a reference to an internal table holding + " the input keys; must be appropriately typed; is mandatory + instances = REF #( read_dyn ) + "results: Specifies a reference to an internal table with the required + " BDEF derived type for the read results; is mandatory + results = REF #( read_dyn_result ) ) + ( op = if_abap_behv=>op-r-read_ba + entity_name = 'ZDEMO_ABAP_RAP_RO_M' + "sub_name: Only relevant for specifying association names in + " read-by-association operations; in that context, it is mandatory + sub_name = '_CHILD' + "full: Optional flag; specifies if all target instances are to be retrieved + full = abap_true + instances = REF #( rba_dyn ) + results = REF #( rba_dyn_result ) + "links: Reference to internal table holding the key pairs of the source and + " target + links = REF #( rba_dyn_link ) ) ). + +READ ENTITIES OPERATIONS op_tab. +``` +

⬆️ back to top

+ +### Persisting to the Database + +- A [`COMMIT + ENTITIES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm) + statement triggers the RAP save sequence. Without such a statement, + the modified RAP BO instances that are available in the + transactional buffer are not persisted to the database. As mentioned above, in case of a natively supported RAP + scenario (for example, when using OData), the `COMMIT + ENTITIES` request is executed automatically. +- `COMMIT ENTITIES` implicitly includes [`COMMIT + WORK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit.htm). +- Note: `COMMIT ENTITIES` statements cannot be used + in behavior implementations. +- There are multiple variants available for the statement as described + in the ABAP Keyword Documentation + [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcommit_entities.htm). For example, RAP responses can be retrieved, key conversion in late numbering scenarios, checking a RAP transaction in a simulation mode. +- `COMMIT ENTITIES` statements set the system field + `sy-subrc`. When using `COMMIT ENTITIES`, it is not + guaranteed that `COMMIT WORK` is carried out successfully. + Hence, you should include a check for `sy-subrc` after + `COMMIT ENTITIES` so that you can react to failures + accordingly. + +The following snippet shows a create operation. This operation has only +an impact on the database with the `COMMIT ENTITIES` statement. +Triggering the save sequence means that the execution of the statement +triggers the calling of the saver methods available in the saver class +of a behavior implementation. In managed scenarios (except for some +special variants), the saving is done automatically without implementing +a dedicated saver method. +``` abap +MODIFY ENTITIES OF root_ent + ENTITY root_ent + CREATE FIELDS ( key_field field1 field2 ) WITH + VALUE #( ( %cid = 'cid' key_field = 7 + field1 = 'K' field2 = 'L' ) ). + +COMMIT ENTITIES. + +IF sy-subrc <> 0. + ... +ENDIF. +``` + +

⬆️ back to top

+ +### Raising RAP Business Events + +- [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) can be raised in ABAP behavior pools with [`RAISE ENTITY EVENT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_entity_event.htm) statements. +- The focus of the snippets is on the local consumption of RAP business events. Prerequisites: + - `event` specifications are available in the BDEF (e.g. `... event some_evt; ...`). For more details, refer to the [BDL documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_event.htm) + - A [RAP event handler class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_class_glosry.htm) is available that is used to implement [RAP event handler methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_meth_glosry.htm). + - Note that these methods are called asynchronously. + - Similar to RAP handler and saver methods, RAP event handler methods are implemented in the CCIMP include of the RAP event handler class. + - To locally consume RAP business events, a local class that inherits from `CL_ABAP_BEHAVIOR_EVENT_HANDLER` can be implemented in the CCIMP include of a RAP event handler class. +- More information: + - [ABAP for RAP Business Events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_events.htm) in the ABAP Keyword Documentation + - [Business Events](https://help.sap.com/docs/abap-cloud/abap-rap/business-events) in the SAP Help Portal + +```abap +"---- Syntax for the declaration part of a global RAP event handler class ---- +CLASS cl_event_handler DEFINITION PUBLIC FOR EVENTS OF some_bdef. + ... +ENDCLASS. + +"---- Syntax for the declaration part of a local event handler class ---- +"---- in the CCIMP include of a RAP event handler class ---- +CLASS lhe_event DEFINITION INHERITING FROM cl_abap_behavior_event_handler. + ... +ENDCLASS. + +"---- RAP event handler method definition ---- +"Notes: +"- Must be defined as instance methods in the private visibility section. +"- The input parameter par is an internal table of type TYPE TABLE FOR EVENT. +"- This type includes the keys of RAP BO instances (and %param, if the event +" is specified with a parameter in the BDEF) +"- The methods do not contain RAP response parameters. +METHODS meth FOR ENTITY EVENT par FOR some_bdef~some_evt. + +"---- RAISE ENTITY EVENT statement in an ABP, e.g. the save_modified method ---- +"---- in managed scenarios with additional save ---- +... +CLASS lsc IMPLEMENTATION. + METHOD save_modified. + "Assumption: An event is specified for create operations in the BDEF as follows + "event created; + IF create-some_bdef IS NOT INITIAL. + RAISE ENTITY EVENT some_bdef~created + FROM VALUE #( FOR IN create-root ( %key = VALUE #( some_key = -some_key ) ) ). + ENDIF. + + "Assumption: An event is specified for delete operations in the BDEF as follows + "event deleted parameter some_abstract_entity; + "The abstract entity has two parameters, for example, with which additional + "information can be passed. + IF delete-some_bdef IS NOT INITIAL. + RAISE ENTITY EVENT some_bdef~deleted + FROM VALUE #( FOR IN delete-some_bdef ( + %key = VALUE #( some_key = -some_key ) + %param = VALUE #( par_a = '01' + par_b = 'Item deleted' ) ) ). + ENDIF. + ENDMETHOD. +ENDCLASS. +``` + +

⬆️ back to top

+ +### Additions to 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). + One of them is [`IN LOCAL MODE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapin_local_mode.htm). +- This addition can be used to exclude feature controls and + authorization checks. +- Consider the following use case: There is a field to display the + booking status of a trip on a UI. In the BDEF, this field is + specified as read-only. Hence, it cannot be modified by a user on + the UI. However, there is a button on the UI to book the trip. This + button might trigger an action to book the trip so that the value of + the field changes from open to booked. To enable this, the + underlying handler method for the modify operation with the action + to be executed has the addition `IN LOCAL MODE` that ignores + the feature control. + +Syntax: + +``` abap +MODIFY ENTITIES OF root_ent IN LOCAL MODE + ENTITY root + EXECUTE book + FROM action_tab + ... +``` + +

⬆️ back to top

+ +## RAP Excursions + +### Using Keys and Identifying RAP BO Instances in a Nutshell + +
+ Expand to view the details + +
+ +The following bullet points outline important aspects regarding + keys and identifying [RAP BO +instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_instance_glosry.htm "Glossary Entry") in ABAP EML statements. + +**Why is it important?** + +- The [primary + key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprimary_key_glosry.htm "Glossary Entry") + of a [RAP BO entity instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_entity_inst_glosry.htm "Glossary Entry") + is composed of one or more [key fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenkey_field_glosry.htm "Glossary Entry"). +- These key fields stand for the fields that are specified with + `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. + - 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. + +**How can a RAP BO instance be uniquely identified?** + +- It can be done by using a [RAP instance identifier](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_inst_identifier_glosry.htm "Glossary Entry") + or [RAP content identifier](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_cont_identifier_glosry.htm "Glossary Entry") + or both of them. +- RAP instance identifier: + - It consists of the primary key fields and all relevant [BDEF derived type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm "Glossary Entry") + components. + - To ease the reference to all of these components, special + [component groups](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomponent_group_glosry.htm "Glossary Entry") + are available to summarize the components and make them + addressable via one single name. + - [`%key`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_key.htm): + Contains the primary key fields of a RAP BO instance + - [`%tky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tky.htm): + Specifies the transactional key. Comprises `%key` (and, + thus, the primary key fields of a RAP BO instance) and more + components that are relevant to uniquely identify a RAP BO + instance. Among them, + [`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) + (relevant for late numbering scenarios) and the draft indicator + [`%is_draft`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_is_draft.htm) + (relevant for + [draft](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_with_draft.htm) + scenarios). In non-late numbering or non-draft scenarios, these + extra components are just blank. However, it is recommended that + you use `%tky` in all scenarios since it simplifies a + possible later switch, for example, to a draft scenario. In + doing so, lots of adaptations to the code regarding the keys and + the inclusion of `%is_draft` can be avoided. +- RAP content identifier: + - Reflected in the component + [`%cid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid.htm) + which is a string of type + `ABP_BEHV_CID` to define a content ID. + - Used as a unique and preliminary identifier for RAP BO instances + in RAP create operations, especially where no primary key exists + for the particular instance. + - For newly created instances, the ID can then be used for performing further modifications, referencing to those instances using [`%cid_ref`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_cid_ref.htm) (which has the same value as %cid), for example, in RAP operations using [`CREATE BY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), [`UPDATE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm) + and + [`DELETE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm), + as well as + [actions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbdl_action.htm) + with + [`EXECUTE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapmodify_entity_entities_op.htm)). + - In contrast to the primary key and the preliminary ID + `%pid` for late numbering scenarios, `%cid` (and + `%cid_ref`) are only available on a short-term basis + for the current ABAP EML request within the [RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm "Glossary Entry") in one RAP transaction. + - **Note:** Specify `%cid` even if there are no further operations referring to it. +- Special case: Late numbering + - As mentioned above, in late numbering scenarios newly created + entity instances are given their final key only shortly before + saving in the database, i. e. you deal with preliminary keys in + the RAP interaction phase and the early phase of the [RAP save sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm "Glossary Entry"). + - In this case, you can use `%key` to hold the preliminary + keys or use a preliminary ID in the dedicated component + [`%pid`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pid.htm) + which is of type `ABP_BEHV_PID` and + only available in late numbering scenarios. + - Similar to above, to uniquely identify RAP BO instances in late + numbering scenarios, you can use either `%key` or + `%pid` or both of them. In any case, the use of + `%tky` is handy because it includes both components. You + must ensure that `%tky` in total uniquely identifies the + instances. + - **Note:** A further component group to refer to the keys is available: [`%pky`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pky.htm). `%pky` contains `%pid` and `%key` in late numbering scenarios. In non-late numbering scenarios, it just contains `%key`. `%pky` itself is contained in `%tky`. There are contexts, for example, particular actions, where `%tky` is not available but `%pky` is. This way, there is still the option to summarize `%pid` and `%key` in one component group in the absence of `%tky`. + +**General rule**: A RAP BO instance must - where available - always be uniquely +identifiable by its transactional key (`%tky`) for internal +processing during the RAP interaction phase. `%tky` always +contains all relevant components for the chosen scenario. + +> **💡 Note**
+> Assignment of Key Component Groups +> +> As a general best practice, you should use a RAP BO instance key component group when referring to the entire key, rather than listing the individual key fields. It is recommended that you use `%tky` whenever possible. +> In the following cases, type compatibility cannot be guaranteed in component group assignments: +> - Mixing key component groups when they refer to the same RAP BO entity, e.g. `wa-%tky = wa-%key`. Such an assignment should also be avoided when both component groups have an identical scope in terms of components (e.g. `%tky` and `%key` in non-late-numbering and non-draft scenarios). +> - Mixing the same key component groups when referring to two different RAP BO entities, for example, `wa_root-%tky = wa_child-%tky`. In this case, adding more components later may cause syntax errors for an assignment that worked previously. +> - Defining structured types that have the same components as key component groups, and then assigning data objects of that type to those of the respective, original key component group. +> In the above cases, the `CORRESPONDING` operator can be used to ensure type compatibility in assignments to key component groups: +> ```abap +>... %tky = CORRESPONDING #( wa-%tky ) ... +>... %key = CORRESPONDING #( wa-%key ) ... +>... %pky = CORRESPONDING #( wa-%pky ) ... +>``` +> In cases where different data objects of key component groups of a BDEF derived type are to be assigned to the same key component group of the same entity, a direct assignment works without a syntax warning because the content is identical. A direct assignment is recommended (`...wa1_root-%tky = wa2_root-%tky ...`). The use of the `CORRESPONDING` operator is unnecessary and less performant. This is true, for example, for key component group assignments in the context of RAP response parameters failed and reported. + +
+ +### RAP Concepts + +
+ Expand to view the details + +
+ +**RAP numbering** + +- A concept that deals with setting values for primary key fields. +- There are multiple options to handle the numbering for primary key + fields depending on when (early in the RAP interaction phase or late + in the RAP save sequence) and by whom (RAP BO consumer, behavior + pool, or framework) the primary key values are set. +- When: + - [Early numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_early_numbering_glosry.htm "Glossary Entry"): + The final key values are assigned during a RAP create operation + in the interaction phase. + - [Late numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_late_numbering_glosry.htm "Glossary Entry"): + The final key values are assigned during the RAP save sequence + (and here only in the RAP saver method + [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm)). +- By whom + - [External numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_ext_numbering_glosry.htm "Glossary Entry"): + Key values are provided by the RAP BO consumer. For example, in + a create operation, the key values are specified by the RAP BO + consumer like other non-key field values. Basically, this is the + concept with which the snippets above are tailored. + - [Internal numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_numbering_glosry.htm "Glossary Entry"): + Key values are provided by the RAP BO provider. For example, in + a create operation, the key values are not specified in an EML + create request by the RAP BO consumer but rather by the RAP BO + provider. In case of a managed RAP BO, the key is automatically + created by the framework which only works if the key is of a + certain type (16-character byte-like + [UUID](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuuid_glosry.htm "Glossary Entry")). + In case of an unmanaged RAP BO, the key values are provided in a + dedicated handler method which must be self-implemented. Note + that late numbering is internal by default since no further RAP + BO consumer interaction is possible in the late phase of the RAP + save sequence. + +**Draft** + +- The draft concept in RAP allows the content of the transactional + buffer to be stored in intermediate storages ([draft tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendraft_table_glosry.htm "Glossary Entry")) + in order to allow transactions to expand over different ABAP + sessions. +- Like the concepts mentioned above, a RAP BO can be draft-enabled in + the BDEF. If enabled, the application allows data modifications and the temporary storage of modifications but does not yet persist them to the database. The users of the application can continue modifying this data later and they might even use a different device from the one where they modified the data previously. +- The draft indicator `%is_draft` is available for RAP BO instance identification. It is used to indicate if a RAP BO + instance is a [draft instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_draft_instance_glosry.htm "Glossary Entry") + or an [active instance](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_active_instance_glosry.htm "Glossary Entry"). + Conveniently, the component group `%tky` contains + `%is_draft`. `%is_draft` can then be addressed via + `%tky`. + +> **💡 Note**
+> Late numbering and identification in the late phase of the RAP save sequence +>- Context: RAP saver method +> [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm) +> in which the final key values are assigned; the preliminary keys can +> be included in `%key` or `%pid` or both of them. +>- `%pid` and the preliminary key values in `%key` are +> automatically assigned to the following component groups when +> reaching the `adjust_numbers` method: +> - [`%tmp`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_tmp.htm): +> A component group that is assigned the preliminary key values +> contained in `%key`. In doing so, `%tmp` takes +> over the role that `%key` has had in the RAP interaction +> phase to hold the preliminary key values. +> - `%pid` remains as is. The component group +> [`%pre`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapderived_types_pre.htm) +> contains `%pid` and `%tmp` and, thus, all +> preliminary identifiers. +>- In the `adjust_numbers` method, the preliminary keys are +> transformed into the final keys, i. e. the preliminary keys are +> mapped to `%key` (which holds the final keys in this +> context) in the `mapped` [response parameter](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_response_param_glosry.htm "Glossary Entry"). +>- Depending on your use case to use either `%pid` or (the +> preliminary key values in) `%key` (which is `%tmp` +> here in this method) during the interaction phase or both of them, +> you must ensure that `%pre` in total (since it contains both +> `%pid` and `%tmp`) is unique and mapped to the final +> keys that are to be contained in `%key`. + +
+ +### Ensuring Data Consistency in a RAP Transaction + +
+ Expand to view the details + +
+ +The [LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenluw_glosry.htm) concept, which deals with the transfer of data from one consistent state to another, applies to applications using RAP. RAP transactions are integrated with the [SAP LUW](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw_glosry.htm), which is a prerequisite for transactional consistency. RAP provides a standardized approach and rules ([RAP BO contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_contract_glosry.htm)) for the [RAP business object (BO)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_bo_glosry.htm) runtime to ensure that the RAP transaction is correctly implemented, data inconsistencies are avoided, and the SAP LUW is successfully completed. + +**Phases of a RAP Transaction** + +A RAP transaction is divided into two phases during the runtime of a RAP BO, while the second phase can be divided into two subphases that serve different purposes. + +![Phases of a RAP Transaction](files/phases_of_rap_luw.png) + +[RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm): +- [RAP handler methods](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm) are called in a [RAP handler class](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_class_glosry.htm) that inherits from `CL_ABAP_BEHAVIOR_HANDLER`. +- New data, i.e. RAP BO instances, are created in the [RAP transactional buffer](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_buffer_glosry.htm), or persisted data is retrieved and inserted into the transactional buffer for further processing. +- The state of the data may become inconsistent in the transactional buffer during this phase. However, the data remains consistent in the database because changes are made only in the transactional buffer. + +[RAP save sequence](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_save_seq_glosry.htm): +- The RAP save sequence is triggered by a `COMMIT ENTITIES` statement. In natively supported RAP scenarios, such as an SAP Fiori application using OData, the `COMMIT ENTITIES` call is implicitly and automatically performed by the RAP runtime engine. +- RAP saver methods are called in the RAP saver class, which inherits from the base class `CL_ABAP_BEHAVIOR_SAVER`. +- Is divided into the [RAP early save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenearly_rap_save_phase_glosry.htm) (ensures that the RAP BO instances in the transactional buffer - all RAP BOs in the current RAP transaction are involved - are in a consistent state so that they can be saved to the database) and the [RAP late save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) (to finally save data from the transactional buffer to the database). + +(Optional:) Saver methods called in the RAP early save phase: +1. [`finalize`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_finalize.htm): For final calculations and data changes before saving. In managed scenarios, determinations specified with `ON SAVE` are called when reaching this method. + +2. [`check_before_save`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_check_before_save.htm): For data consistency checks in the transactional buffer. In managed scenarios, validations specified with `ON SAVE` are called when this method is reached. + +3. [`cleanup_finalize`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapsaver_class_cleanup_finalize.htm): If there are failures in at least one of the previous saver methods, further processing with the RAP late save phase is rejected and the transaction returns to the interaction phase. Before that, this saver method is called, allowing changes made in the finalize method to be rolled back. + +If there are errors in the early save phase, `sy-subrc` returns the value 4 after `COMMIT ENTITIES` statements. If the data in the transactional buffer is consistent after the early save phase, the late save phase is processed, which also means that a point of no return has been reached. Unlike the early save phase, you cannot return to the interaction phase when you reach the late save phase. Either the RAP transaction ends with a successful commit, or the changes are rolled back and a runtime error occurs. + +Saver methods called in the RAP late save phase: +1. [`adjust_numbers`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_adjust_numbers.htm): Provides RAP BO instances with their final numbers. This method is available only in late numbering scenarios. +2. [`save`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_save.htm) (or [`save_modified`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaprap_saver_meth_save_modified.htm) in managed scenarios with an unmanaged or additional save): Used to save data from the transactional buffer to the database. If there are no issues, the final database commit is triggered and an implicit `COMMIT WORK` is executed. + +[`cleanup`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_cleanup.htm) method: After a successful save, the [`cleanup`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensaver_method_cleanup.htm) method clears the transactional buffer. It completes the save sequence. + +**Commit and Rollback in a RAP Transaction** +The default ABAP statements for RAP are `COMMIT ENTITIES` (triggers the RAP save sequence and the final database commit; as mentioned above, in natively supported RAP scenarios, the commit is performed implicitly and automatically by the RAP runtime engine) and `ROLLBACK ENTITIES` (rolls back all changes of the current RAP transaction, i.e. the transactional buffer is cleared by calling the `cleanup` method). Both are RAP-specific and end the RAP transaction. + +*Notes on `COMMIT ...` and `ROLLBACK ...` statements due to the integration of RAP transactions into the SAP LUW:* + +- `COMMIT ENTITIES` implicitly triggers `COMMIT WORK`. +- Using `COMMIT WORK` in RAP (instead of `COMMIT ENTITIES`) also triggers the RAP save sequence. If there are no errors in the RAP save sequence, the final database commit is successful. Only in this best-case scenario does `COMMIT WORK` have the same effect as `COMMIT ENTITIES`. However, if there are errors in the save sequence, a runtime error occurs in any case, while a return to the interaction phase is still possible when using `COMMIT ENTITIES`. +- `COMMIT ENTITIES` provides RAP-specific functionality with various additions that are not possible with `COMMIT WORK`, such as RAP responses can be retrieved, key conversion in late numbering scenarios, checking a RAP transaction in a simulation mode. +- There are short, long, and dynamic forms of `COMMIT ENTITIES` statements. +- `COMMIT ENTITIES` statements implicitly enforce local updates with `COMMIT WORK`, or `COMMIT WORK AND WAIT` if the local update fails. Therefore, the update is either a local update or a synchronous update, but never an asynchronous update. When `COMMIT WORK` is used, the RAP BO consumer can choose between synchronous and asynchronous update for RAP BO entities. +- `ROLLBACK ENTITIES` implicitly triggers `ROLLBACK WORK`. Both have the same effect when used in RAP. Therefore, they are interchangeable. + +> **💡 Note**
+> Special Case: Failures in the Late Save Phase +> - In exceptional cases, for example, when [BAPIs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbapi_glosry.htm) are called to save RAP BO instances in the late save phase, it may happen that the basic rule that failures must not occur in the RAP late save phase and be detected in the RAP early save phase is violated. +> - In such cases, the base class `CL_ABAP_BEHAVIOR_SAVER_FAILED` can be used for the RAP saver class. +> - RAP BO consumers can be informed by filling the RAP response parameters (some of which are not available when using `CL_ABAP_BEHAVIOR_SAVER` as the base class) in the saver method implementation so that they can react accordingly. +> - After a `COMMIT ENTITIES` statement and a failure in the late save phase, `sy-subrc` is set to 8. +> - A subsequent RAP operation may result in a runtime error. If the RAP BO consumer is to continue after an error in the late phase of the RAP save sequence, an explicit `ROLLBACK ENTITIES` is required. + +**Allowed/Forbidden Operations in a Behavior Implementation in a RAP Transaction** + +The following restrictions apply to operations and/or statements in the individual phases of a RAP transaction in ABAP behavior implementations. Note that, depending on setting the strict mode in the BDEF, runtime errors may occur due to the use of forbidden statements, or static code checks may be applied. Note that most operations/statements refer to the use in the unrestricted ABAP language scope. + +|Operations/Statements|Interaction phase|Early save phase|Late save phase|Notes| +|---|---|---|---|---| +|[Database commits](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_commit_glosry.htm) using [secondary connections](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_db_connection_glosry.htm)

(unrestricted ABAP language scope)| X| X| X |Secondary connections are allowed for infrastructure purposes, for example. They can be used to store data that is not part of the main transaction, such as application logs, traces, or number ranges. | +|Database commits using the [standard connection](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_db_connection_glosry.htm)

(unrestricted ABAP language scope)| X| X| -| Database commits can be made in phases other than the late phase, for example, by calling external services or using a `WAIT` statement.| +|[sRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensrfc_glosry.htm) (`CALL FUNCTION ... DESTINATION`), [aRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarfc_glosry.htm) (`CALL FUNCTION ... STARTING NEW TASK`)

(unrestricted ABAP language scope)| X |X |-| Allowed in phases other than the late save phase, e.g. for the purpose of parallelization within the application. It is up to the application to ensure consistency, e.g. to ensure read-only access, to handle a potential two-phase commit, or to provide a proper error handling. | +|Database modifications |- |-| X| Only allowed in the late save phase because the data being processed is always potentially inconsistent. Database changes in other phases would result in multiple database transactions instead of one transaction, which would disrupt the SAP LUW. | +|[Update function module](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_function_module_glosry.htm) (`CALL FUNCTION ... IN UPDATE TASK`)

(unrestricted ABAP language scope)|-| -| X |Can be used to ensure that there is only one database transaction. In addition, registering function modules for update tasks at stages other than the late save phase would interfere with RAP draft scenarios, for example, where data is stored in draft tables. There is no way to unregister function modules once they have been registered. | +|[bgRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbgrfc_glosry.htm) (`CALL FUNCTION ... IN BACKGROUND UNIT`)

(unrestricted ABAP language scope)| -| -| X| | +|[tRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentrfc_2_glosry.htm), [qRFC](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenqrfc_glosry.htm) (`CALL FUNCTION ... IN BACKGROUND TASK`)

(unrestricted ABAP language scope)| -| -| - |Obsolete technologies. | +|`PERFORM ON COMMIT`, `PERFORM ON ROLLBACK`

(unrestricted ABAP language scope)|(X) |(X) |X |Basically possible in all phases, but should be reserved for the late save. Note: The use of these statements indicates improper integration with RAP. It is especially important to check draft scenarios when calling legacy code and using these statements. Instead, ABAP EML or procedure calls that do not include a `COMMIT WORK` should be used. | +|Transaction control `COMMIT WORK`, `ROLLBACK WORK` |X/-| X/-| X/- |When a transactional phase has been explicitly set by methods of the `CL_ABAP_TX` class (find more information [here](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw)), the transaction owner is allowed to execute a commit or rollback statement. In the contexts of RAP (that is, where RAP is the transaction owner, for example, in handler and saver methods), local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm), [bgPF](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbgpf_glosry.htm), and [classified APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassified_api_glosry.htm), commit or rollback statements are not allowed. | +|[Dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) processing (e.g. `SET SCREEN`, `CALL SCREEN`, `LEAVE SCREEN`, `CALL DIALOG`, `SUPPRESS DIALOG`, `MESSAGE` without `INTO`, `WRITE`, `STOP`)

(unrestricted ABAP language scope)|- |- |- |Not allowed in ABAP behavior implementations. Results in a runtime error. | +|Transaction processing (`CALL TRANSACTION`, `LEAVE TRANSACTION`)

(unrestricted ABAP language scope)| -| -| - |Not allowed to prevent (unwanted) integration of other LUWs. | +|Raising an exception (`RAISE EXCEPTION`) |-| -| - |It is not allowed to leave a RAP transaction this way. | +|Report processing (`SUBMIT ...`)

(unrestricted ABAP language scope)|- |- |- |Not allowed in transactional contexts. Results in a syntax or runtime error.
`SUBMIT ... AND RETURN` does not currently return an error, but it leads to potentially unwanted screen processing, and because of the missing return channel, there is no proper error handling. | + + +
+ +

⬆️ back to top

+ +## More Information + +- Section [ABAP for RAP Business + Objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_rap_bos.htm) + in the ABAP Keyword Documentation including EML +- [RAP Glossary](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_glossary.htm) +- [Development guide for the ABAP RESTful Application Programming + Model](https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/289477a81eec4d4e84c0302fb6835035.html) +- [RAP + Contract](https://help.sap.com/docs/ABAP_PLATFORM_NEW/fc4c71aa50014fd1b43721701471913d/3a402c5cf6a74bc1a1de080b2a7c6978.html): + Rules for the RAP BO provider and consumer implementation to ensure + consistency and reliability + +

⬆️ back to top

+ +## Executable Examples + +This cheat sheet is supported by different executable examples demonstrating various scenarios: +- Demo RAP scenario with a managed RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_m](./src/zcl_demo_abap_rap_ext_num_m.clas.abap) +- Demo RAP scenario with an unmanaged RAP BO, external numbering: [zcl_demo_abap_rap_ext_num_u](./src/zcl_demo_abap_rap_ext_num_u.clas.abap) +- Demo RAP scenario ("RAP calculator") with a managed, draft-enabled RAP BO, late numbering [zcl_demo_abap_rap_draft_ln_m](./src/zcl_demo_abap_rap_draft_ln_m.clas.abap) +- Demonstrating the local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm) in the context of a RAP demo scenario (managed RAP BO with managed [internal numbering](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_numbering_glosry.htm) and [additional save](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_add_save_glosry.htm)): [zcl_demo_abap_rap_m_as](./src/zcl_demo_abap_rap_m_as.clas.abap) + +> **💡 Note**
+> - To reduce the complexity, the executable examples only focus on the technical side. ABAP classes play the role of a RAP BO consumer here. +> - The examples do not represent real life scenarios and are not suitable as role models for proper RAP scenarios. They rather focus on the technical side by giving an idea how the communication and data exchange between a RAP BO consumer and RAP BO provider can work. Additionally, the examples show how the methods for non-standard RAP BO operations might be self-implemented in an ABAP behavior pool. +> - Due to the simplification, the examples do not entirely meet all requirements of the [RAP BO contract](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrap_bo_contract_glosry.htm) and do not represent semantic or best practice examples. +> - You can check out the "RAP calculator" example using the preview version of an SAP Fiori Elements UI. See the comments in the class for more information. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) diff --git a/13_Program_Flow_Logic.md b/13_Program_Flow_Logic.md index b297a93..a58a79f 100644 --- a/13_Program_Flow_Logic.md +++ b/13_Program_Flow_Logic.md @@ -1,672 +1,725 @@ - - -# Program Flow Logic - -- [Program Flow Logic](#program-flow-logic) - - [Introduction](#introduction) - - [Expressions and Functions for Conditions](#expressions-and-functions-for-conditions) - - [Control Structures](#control-structures) - - [`IF` Statements](#if-statements) - - [Excursion: `COND` Operator](#excursion-cond-operator) - - [`CASE`: Case Distinctions](#case-case-distinctions) - - [Excursion: `SWITCH` Operator](#excursion-switch-operator) - - [Loops](#loops) - - [`DO`: Unconditional Loops](#do-unconditional-loops) - - [Interrupting and Exiting Loops](#interrupting-and-exiting-loops) - - [`WHILE`: Conditional Loops](#while-conditional-loops) - - [Loops Across Tables](#loops-across-tables) - - [Calling Procedures](#calling-procedures) - - [Handling Exceptions](#handling-exceptions) - - [Notes on Exception Classes](#notes-on-exception-classes) - - [Raising Exceptions](#raising-exceptions) - - [Excursion: Runtime Errors and Terminating Programs](#excursion-runtime-errors-and-terminating-programs) - - [Executable Example](#executable-example) - - -This cheat sheet gathers information on program flow logic. Find more details -[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_flow_logic.htm) -in the ABAP Keyword Documentation. - -## Introduction - -In ABAP, the flow of a program is controlled by [control structures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencontrol_structure_glosry.htm), [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm) calls and the raising or handling of [exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexception_glosry.htm). - -Using control structures as an example, you can determine the conditions for further processing of code, for example, if at all or how often a statement block should be executed. Control structures - as, for example, realized by an `IF ... ELSEIF ... ELSE ... ENDIF.` statement - can include multiple [statement blocks](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatement_block_glosry.htm) that are executed depending on conditions. - -In a very simple form, such an [`IF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapif.htm) statement might look as follows: - -```abap -DATA(num) = 1 + 1. - -"A simple condition: Checking if the value of num is 2 -IF num = 2. - ... "Statement block - "Here goes some code that should be executed if the condition is true. -ELSE. - ... "Statement block - "Here goes some code that should be executed if the condition is false. - "For example, if num is 1, 8, 235, 0 etc., then do something else. -ENDIF. -``` - -

⬆️ back to top

- -## Expressions and Functions for Conditions -- So, such control structures are executed depending on conditions as specified above: `... num = 2 ...` - a [logical expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogical_expression_glosry.htm). -- Control structures are generally controlled by logical expressions that define conditions for [operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_glosry.htm). -- The result of such an expression is either true or false. -- Logical expressions are either single [relational expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelational_expression_glosry.htm) or expressions combined from one or more logical expressions with Boolean operators like `NOT`, `AND` and `OR`. - -```abap -"Single relational expression -IF num = 1. - ... -ENDIF. - -"Multiple expressions -IF num = 1 AND flag = 'X'. - ... -ENDIF. - -IF num = 1 OR flag = 'X'. - ... -ENDIF. - -"Multiple expressions can be parenthesized explicitly -IF ( num = 1 AND flag = 'X' ) OR ( num = 2 AND flag = 'X' ). - ... -ENDIF. -``` - -- The components of such relational expressions can be [comparisons](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_glosry.htm) or [predicates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_glosry.htm). Note that for [comparison expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm), -the comparisons are carried out according to [comparison rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules.htm). - -The following code snippet shows a selection of possible expressions and operands of such expressions using a big `IF` statement. Certainly, such a huge statement is far from ideal. Here, the intention is to just cover many syntax options in one go for demonstration purposes. - -```abap -"Some declarations to be used in the IF statement below -DATA(num) = 2. "integer -DATA(empty_string) = ``. "empty string -DATA(flag) = 'x'. -DATA(dref) = NEW string( `ref` ). "data reference variable - -"Object reference variable -DATA oref TYPE REF TO object. -"Creating an object and assigning it to the reference variable -oref = NEW zcl_demo_abap_prog_flow_logic( ). - -"Declaration of and assignment to a field symbol -FIELD-SYMBOLS TYPE string. -ASSIGN `hallo` TO . - -"Creating an internal table of type string inline -DATA(str_table) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). - -"The following IF statement includes multiple expressions combined by AND to demonstrate different options - -"Comparisons -IF 2 = num "equal, alternative EQ -AND 1 <> num "not equal, alternative NE -AND 1 < num "less than, alternative LT -AND 3 > num "greater than, alternative GT -AND 2 >= num "greater equal, alternative GE -AND 2 <= num "less equal, alternative LE - -"Checks whether the content of an operand is within a closed interval -AND num BETWEEN 1 AND 3 -AND NOT num BETWEEN 5 AND 7 "NOT negates a logical expression -AND ( num >= 1 AND num <= 3 ) "Equivalent to 'num BETWEEN 1 AND 3'; - "here, demonstrating the use of parentheses - -"Comparison operators CO, CN ,CA, NA, CS, NS, CP, NP for character-like data types; -"see the cheat sheet on string processing - -"Predicate Expressions -AND empty_string IS INITIAL "Checks whether the operand is initial. The expression - "is true, if the operand contains its type-dependent initial value -AND num IS NOT INITIAL "NOT negates - -AND dref IS BOUND "Checks whether a data reference variable contains a valid reference and - "can be dereferenced; - "Negation (IS NOT BOUND) is possible which is also valid for the following examples -AND oref IS BOUND "Checks whether an object reference variable contains a valid reference - -"IS INSTANCE OF checks whether for a -"a) non-initial object reference variable the dynamic type -"b) for an initial object reference variable the static type -"is more specific or equal to a comparison type. -AND oref IS INSTANCE OF zcl_demo_abap_prog_flow_logic -AND oref IS INSTANCE OF if_oo_adt_classrun - -AND IS ASSIGNED "Checks whether a memory area is assigned to a field symbol - -"See the predicate expression IS SUPPLIED in the executable example. -"It is available in method implementations and checks whether a formal parameter -"of a procedure is filled or requested. - -"Predicate function: Some examples -AND contains( val = pcre = `\D` ) "Checks whether a certain value is contained; - "the example uses the pcre parameter for regular expressions; - "it checks whether there is any non-digit character contained -AND matches( val = pcre = `ha.+` ) "Compares a search range of the argument for the val parameter; - "the example uses the pcre parameter for regular expressions; - "it checks whether the value matches the pattern 'ha' - "and a sequence of any characters - -"Predicate functions for table-like arguments -"Checks whether a line of an internal table specified in the table expression -"exists and returns the corresponding truth value. -AND line_exists( str_table[ 2 ] ) - -"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 method call, -"i. e. the return value of the called function method, is arbitrary. -"A check is made for the type-dependent initial value. -AND check_is_supplied( ) -"It is basically the short form of such a predicate expression: -AND check_is_supplied( ) IS NOT INITIAL - -"Boolean Functions -"Determine the truth value of a logical expression specified as an argument; -"the return value has a data type dependent on the function and expresses -"the truth value of the logical expression with a value of this type. - -"Function boolc: Returns a single-character character string of the type string. -"If the logical expression is true, X is returned. False: A blank is returned. -"Not to be compared with the constants abap_true and abap_false in relational expressions, -"since the latter convert from c to string and ignore any blanks. Note: If the logical -"expression is false, the result of boolc does not meet the condition IS INITIAL since -"a blank and no empty string is returned. If this is desired, the function xsdbool -"can be used instead of boolc. -AND boolc( check_is_supplied( ) ) = abap_true - -"Result has the same ABAP type as abap_bool. -AND xsdbool( check_is_supplied( ) ) = abap_true - -"Examples for possible operands - -"Data objects as shown in the examples above -AND 2 = 2 -AND num = 2 - -"Built-in functions -AND to_upper( flag ) = 'X' -AND NOT to_lower( flag ) = 'X' - -"Numeric functions -AND ipow( base = num exp = 2 ) = 4 - -"Functional methods -"Method with exactly one return value -AND addition( num1 = 1 num2 = 1 ) = 2 - -"Calculation expressions -AND 4 - 3 + 1 = num - -"String expressions -AND `ha` && `llo` = - -"Constructor expression -AND CONV i( '2.03' ) = num -AND VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ) = str_table - -"Table expression -AND str_table[ 2 ] = `b`. - - "All of the logical expressions are true. - -ELSE. - - "At least one of the logical expressions is false. - -ENDIF. -``` - -> **💡 Note**
-> Logical expressions and functions can also be used in other ABAP statements. - -

⬆️ back to top

- -## Control Structures - -### `IF` Statements - -- As already shown above, `IF` statements define statement blocks that can be included in [branches](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbranch_glosry.htm). -- The statement blocks are executed depending on conditions. -- A maximum of one statement block is executed. -- The check is carried out from top to bottom. The statement block after the first logical expression that is true is executed. -- If none of the logical expressions are true, the statement block after the `ELSE` statement is executed. -- `ELSE` and `ELSEIF` statements are optional. However, it is recommended that you specify an `ELSE` so that at least one statement block is executed. -- If the end of the executed statement block is reached or if no statement block has been executed, the processing is continued after `ENDIF.`. - - -```abap -"IF statement with multiple included ELSEIF statements -IF log_exp1. - - ... "statement_block1 - -ELSEIF log_exp2. - - ... "statement_block2 - -ELSEIF log_exp3. - - ... "statement_block3 - -... "further ELSEIF statements - -ELSE. - - ... "statement_blockn - -ENDIF. -``` - - -Control structures can be nested. -```abap -DATA(num) = 1. -DATA(flag) = 'X'. - -IF num = 1. - - IF flag = 'X'. - ... - ELSE. - ... - ENDIF. - -ELSE. - - ... "statement block, e. g. - "ASSERT 1 = 0. - "Not to be executed in this example. - -ENDIF. -``` - -> **💡 Note**
-> - Control structures can be nested. It is recommended that you do not include more than 5 nested control structures since the code will -> get really hard to understand. Better go for outsourcing functionality into methods to reduce nested control control structures. -> - Keep the number of consecutive control structures low. -> - If you are convinced that a specified logical expression must always be true, you might include a statement like `ASSERT 1 = 0.` to go -> sure - as implied in the example's `ELSE` statement above. However, an `ELSE` statement that is never executed might be a hint that -> logical expressions might partly be redundant. - -

⬆️ back to top

- -#### Excursion: `COND` Operator - -- The conditional operator [`COND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconditional_expression_cond.htm) can also be used to implement branches in operand positions that are based on logical expressions. -- Such conditional expressions have a result that is dependent on the logical expressions. -- The result's data type is specified after `COND` right before the first parenthesis. It can also be the `#` character as a symbol for the operand type if the type can be derived from the context. See the ABAP Keyword Documentation and the cheat sheet on constructor expressions for more information. -- All operands specified after `THEN` must be convertible to the result's data type. - -```abap -... COND type( WHEN log_exp1 THEN result1 - WHEN log_exp2 THEN result2 - ... - ELSE resultn ) ... -``` - -

⬆️ back to top

- -### `CASE`: Case Distinctions - -- [`CASE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase.htm) statements are used for case distinctions. -- Such statements can also contain multiple statement blocks of which a maximum of one is executed depending on the value of the operand specified after `CASE`. -- The check is carried out from top to bottom. If the content of an operand specified after `WHEN` matches the content specified after `CASE`, the statement block is executed. Constant values should be specified as operands. -- The `WHEN` statement can include more than one operand using the syntax `WHEN op1 OR op2 OR op3 ...`. -- If no matches are found, the statement block is executed after the statement `WHEN OTHERS.` which is optional. -- If the end of the executed statement block is reached or no statement block is executed, the processing continues after `ENDCASE.`. - - -```abap -CASE operand. - WHEN op1. - ... "statement_block - WHEN op2. - ... "statement_block - WHEN op3 OR op4. - ... "statement_block - WHEN OTHERS. - ... "statement_block -ENDCASE. -``` - -Special control structure introduced by [`CASE TYPE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase_type.htm): Checks the type of object reference variables. - -```abap -"oref must be an object reference variable with the static type of a class or an interface. -CASE TYPE OF oref. - WHEN TYPE some_class. - ... "statement_block - WHEN TYPE some_intf. - ... "statement_block - WHEN OTHERS. - ... "statement_block -ENDCASE. -``` - -

⬆️ back to top

- -#### Excursion: `SWITCH` Operator - -The conditional operator [`SWITCH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconditional_expression_switch.htm) can also be used to make case distinctions in operand positions. As mentioned above for `COND`, a result is constructed. The same criteria apply for `SWITCH` as for `COND` regarding the type. See the ABAP Keyword Documentation and the cheat sheet on constructor expressions for more information. - - -```abap -... SWITCH type( operand - WHEN const1 THEN result1 - WHEN const2 THEN result2 - ... - ELSE resultn ) ... -``` - -

⬆️ back to top

- -### Loops - -#### `DO`: Unconditional Loops - -- A statement block specified between `DO` and `ENDDO` is carried out multiple times. -- The loop is exited when a statement to terminate the loop is reached (`EXIT`, see further down). Otherwise, it is executed endlessly. - - ```abap - DO. - ... "statement_block - "To be terminated with an EXIT statement. - ENDDO. - ``` -- To restrict the loop passes, you can use the `TIMES` addition and specify the maximum number of loop passes. - - ```abap - DO 5 TIMES. - ... "statement_block - ENDDO. - ``` -- The value of the system field `sy-index` within the statement block contains the number of previous loop passes including the current pass. - -

⬆️ back to top

- -#### Interrupting and Exiting Loops - -The following ABAP keywords are available for interrupting and exiting loops: - -| Keyword | Syntax | Details | -|---|---|---| -| [`CONTINUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcontinue.htm) | `CONTINUE.` | The current loop pass is terminated immediately and the program flow is continued with the next loop pass. | -| [`CHECK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcheck_loop.htm) | `CHECK log_exp.` | Conditional termination. If the logical expression `log_exp` is false, the current loop pass is terminated immediately and the program flow is continued with the next loop pass. | -| [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm) | `EXIT.` | The loop is terminated completely. The program flow resumes after the closing statement of the loop. | - -> **💡 Note**
-> - [`RETURN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreturn.htm) statements immediately terminate the current processing block. However, according to the [guidelines (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexit_procedure_guidl.htm), `RETURN` should only be used to exit procedures like methods. -> - `EXIT` and `CHECK` might also be used for exiting procedures. However, their use inside loops is recommended. - -

⬆️ back to top

- -#### `WHILE`: Conditional Loops - -- Conditional loops introduced by `WHILE` and ended by `ENDWHILE` are repeated as long as a logical expression is true. -- These loops can also be exited using the statements mentioned above. -- Like in `DO` loops, the system field `sy-index` contains the number of previous loop passes including the current pass. - -```abap -WHILE log_exp. - ... "statement_block -ENDWHILE. -``` - -

⬆️ back to top

- -#### Loops Across Tables -Further keywords for defining loops are as follows. They are not dealt with here since they are covered in other ABAP cheat sheets. - -- [`LOOP ... ENDLOOP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab.htm) statements are meant for loops across internal tables. See also the cheat sheet on internal tables. - - In contrast to the loops above, the system field `sy-index` is not set. Instead, the system field `sy-tabix` is set and which contains the table index of the current table line in the loop pass. - - You can also realize loops using iteration expressions with `VALUE` and `REDUCE`. For more information, refer to the [Constructor Expressions](05_Constructor_Expressions.md) cheat sheet. -- [`SELECT ... ENDSELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm) statements loop across the result set of a database access. See also the cheat sheet on ABAP SQL. - -

⬆️ back to top

- -## Calling Procedures - -Calling [procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm) would actually fit here in the context of dealing with program flow logic since they can be called explicitly in an [ABAP program](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm). -However, ... -1. in modern ABAP programs, only methods should be implemented (instead of [function modules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfunction_module_glosry.htm) and [subroutines](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubroutine_glosry.htm) in most cases) and -2. methods are described in the context of the ABAP cheat sheet on ABAP object orientation. Hence, see more details there. - -Regarding the exiting of procedures, note the hint mentioned above. The use of `RETURN` is recommended. - -

⬆️ back to top

- -## Handling Exceptions -- [Exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexception_glosry.htm) ... - - are events during the execution of an ABAP program that interrupt the program flow because it is not possible for the program to continue in a meaningful way. For such situations, you can implement an exception handling in which you can react on the situations appropriately. Consider, for example, the implementation of a simple calculation. If there is a division by zero, the program will be terminated with a [runtime error](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenruntime_error_glosry.htm) unless you handle the exception appropriately. - - can be raised either by the program or by the [ABAP runtime framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm). Exceptions raised by the latter are generally caused by error situations that cannot be detected by the static program check. The division by zero is such an example. - - should, in modern ABAP, only be designed as [class-based exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_based_exception_glosry.htm), i. e. exceptions are represented by [objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_glosry.htm) of classes. Global exception classes usually use the naming convention `CX_...`. - - are either [catchable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencatchable_exception_glosry.htm) (they are based on predefined or self-defined exception classes) or [uncatchable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuncatchable_exception_glosry.htm) (they directly produce runtime errors, i. e. error situations cannot be handled appropriately). - -`TRY` control structures are meant for handling catchable exceptions locally: -- To be prepared for potential exceptions that are raised when executing statements, the statements can be included and executed within a *protected area*, a [`TRY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) control structure. -- In doing so, it is possible for the ABAP runtime framework to catch exceptions and react on error situations. - - ```abap - TRY. - "statement block - ENDTRY. - ``` - -- The `TRY` control structure in the snippet above produces a syntax warning. A [`CATCH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcatch_try.htm) block is expected, too. -- One or more class-based exceptions can be handled in one or more subsequent `CATCH` blocks. The `CATCH` statement must include an "appropriate" class-based exception. "Appropriate" means that, certainly, an exception class should be specified that is suitable for the error handling. In the following example, the predefined exception class `CX_SY_ZERODIVIDE` is specified that is, as the name implies, specific for the (potential) exception in case of a division by zero. - - ```abap - TRY. - "TRY block - DATA(div1) = 1 / 0. - - "Predefined exception class cx_sy_zerodivide as suitable exception class to be used here. - "If the exception is not handled, the program is terminated and the runtime error - "COMPUTE_INT_ZERODIVIDE occurs. - CATCH cx_sy_zerodivide. - ... "CATCH block - ENDTRY. - - "Example for catching an exception in the context of a table expression - TRY. - "Copying a line of an internal table - DATA(line) = some_itab[ 12345 ]. - - "Predefined exception class cx_sy_itab_line_not_found as suitable exception class to be used here. - "If the exception is not handled, the program is terminated and the runtime error - "ITAB_LINE_NOT_FOUND occurs. - CATCH cx_sy_itab_line_not_found. - ... "CATCH block - ENDTRY. - - "Note on inheritance relationships in exception classes - TRY. - "TRY block - DATA(div2) = 1 / 0. - - "A CATCH block is in this example not only valid for cx_sy_zerodivide as specified above - "but also for all derived exceptions classes. - "In the following CATCH block, the predefined exception class cx_sy_arithmetic_error - "is specified. cx_sy_zerodivide is derived from cx_sy_arithmetic_error. - "Hence, cx_sy_arithmetic_error can be specified and handle the exception, too. - "Basically, using the exception root class cx_root would be also possible. However, - "choosing an appropriate exception class is recommended. See further down. - - CATCH cx_sy_arithmetic_error. - ... "CATCH block - ENDTRY. - - - "Multiple classes in a list and CATCH blocks can be specified - "Note: If there are multiple CATCH blocks for exceptions that are in an inheritance - "relationship, you must pay attention that the more special exceptions are specified - "before the more general ones. - TRY. - ... "TRY block - CATCH cx_abc cx_bla cx_blabla. - ... "CATCH block - CATCH cx_la cx_lala. - ... "CATCH block - CATCH cx_lalala. - ... "CATCH block - ENDTRY. - ``` - -- If the addition `INTO` is specified in the `CATCH` statement, a reference to the exception object is stored. -- This is relevant to determine the exact exception, for example. In the code snippet above, the exception class `CX_SY_ZERODIVIDE` is mentioned. Consider a calculator. It should not only be able to deal with error situations like zero division but also, for example, overflows in arithmetic operations. The predefined exception class `CX_SY_ARITHMETIC_OVERFLOW` is available. It is also derived from `CX_SY_ARITHMETIC_ERROR`. If you then specify the exception class `CX_SY_ARITHMETIC_ERROR` which is higher up in the inheritance hierarchy and can handle both error situations (`CX_SY_ARITHMETIC_OVERFLOW` and `CX_SY_ZERODIVIDE`), the concrete exception that was raised is unclear. Using the `INTO` clause and the stored exception object, it is possible to carry out certain tasks, for example, retrieving and displaying the exception text. - - ```abap - DATA: exception TYPE REF TO cx_root. "Note the root class - "Note: For a self-defined exception class, the object reference must be typed appropriately. - - TRY. - ... "TRY block - - "Storing a reference to the exception object. - "Note: The type is cx_root since attributes and methods of the root class that are defined there can be accessed. - CATCH INTO exception. - ... "CATCH block - ENDTRY. - - "Inline creation of exception object reference and getting exception texts - TRY. - ... "TRY block - - "The object reference variable can be created inline, for example, using DATA(...). - CATCH cx_sy_arithmetic_error INTO DATA(error_oref). - ... "catch block - "To get exception texts, you can call, for example, the method get_text - DATA(error_text) = error_oref->get_text( ). - - ENDTRY. - ``` - -- Regarding the program flow: - - The statement block following `TRY.` is always processed. If an exception is raised within this `TRY` block, the system searches for an exception handler, i. e. a `CATCH` block that is able to handle the exception. - - If there is no `CATCH` statement that is able to handle the catchable exception or if erroneous code is not within a `TRY` control structure at all, the exception is propagated to the caller. - - Exceptions can be handled either in the context locally (using such a `TRY` control structure) or be propagated to the caller so that the caller is responsible for reacting appropriately (for example, in another `TRY` control structure) to the error situation. In doing so, you can better structure your code by reacting on error situations centrally instead of locally checking, for example, each procedure call individually. - - If, at the end, the exception can nowhere be caught and handled, the program is terminated with a runtime error. - - If the exception can be handled or no exception is raised in the `TRY` block and it reaches its end, the processing continues after `ENDTRY`. - - -> **💡 Note**
-> - Non-class-based exceptions are considered obsolete and should not be defined any more in new developments according to the [guidelines (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclass_exception_guidl.htm) and are not dealt with here. ->- For all exceptions that are raised by the ABAP runtime environment and that are not handled, there is a corresponding runtime error. For example, in the case of exception class `CX_SY_ZERODIVIDE`, it is the runtime error `COMPUTE_INT_ZERODIVIDE`. For self-defined exception classes, an exception that is not handled generally triggers the runtime error `UNCAUGHT_EXCEPTION`. -> - For `TRY` control structures, there are further additions available dealing with more advanced error handling, e. g. [resumable exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapresume.htm). - -

⬆️ back to top

- -#### Notes on Exception Classes -- To distinguish exception classes from *regular* classes, use the naming convention `CX` as prefix and not `CL`. -- All exception classes (also the self-defined ones) are directly or indirectly derived from three abstract subclasses: `CX_STATIC_CHECK`, `CX_DYNAMIC_CHECK` and `CX_NO_CHECK`. These three "exception class categories" have different properties. -- The class `CX_ROOT` is the root class. Directly deriving from `CX_ROOT` is not possible. -- Apart from global classes, exception classes can also be defined as local classes within an ABAP program. -- As mentioned, there are predefined exception classes like `CX_SY_ZERODIVIDE` for divisions by zero. However, you can create your own exception classes so that you can react on issues that are specific to your ABAP program. The exception class must, as stated above, be derived from one of the three abstract classes: - - `CX_STATIC_CHECK`: For forcing users to handle exceptions. - Generally speaking, exceptions that can occur in procedures should be handled locally there in the implementation or be declared explicitly in the [procedure interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenparameter_interface_glosry.htm) so that a caller knows which error situations can be expected. Exception classes of type `CX_STATIC_CHECK` enforce this. A check is carried out statically at compile time. Users of a procedure are then forced to either handle the exception locally in a `TRY` control structure or the users declare the exception themselves in their procedure interface to propagate the exception to their users. If this is not the case, a warning is produced. - - As an example, a method signature might look as follows. The addition `RAISING` in method signatures is used to declare one or more class-based exceptions that can be propagated from the method to the caller. - - When users of this method implement the method, they are made aware of the fact that an error situation can occur and a particular exception can be raised. The assumption is that `CX_SOME_ERROR` is derived from `CX_STATIC_CHECK`. Users of the method should then prepare the code accordingly. - ```abap - "Method definition using the RAISING parameter - CLASS-METHODS: some_meth IMPORTING str TYPE string - RETURNING VALUE(ret_value) TYPE string - RAISING cx_some_error. - - ... - - "Method call: Somewhere in the code of a user that calls the method - "Exception handled locally in a TRY control structure. - TRY. - DATA(val) = some_meth( str = `hallo` ). - - CATCH cx_some_error. - ... - ENDTRY. - - "If it was just like this without the TRY control structure, a warning would be produced. - DATA(val2) = some_meth( str = `hi` ). - ``` - - - `CX_DYNAMIC_CHECK`: For exceptions that can be checked and avoided by preconditions. As a consequence and in contrast to an exception class derived from `CX_STATIC_CHECK`, exception classes of type `CX_DYNAMIC_CHECK` do not enforce the local handling and the declaration in procedure interfaces. However, an appropriate exception handling should be implemented in cases in which you cannot rule out the raising of the exceptions in your program logic. The checking if a local handling or an explicit declaration in procedure interfaces is available is carried out at runtime only ("dynamic check") and only in case the exception is indeed raised. - - If it is determined at runtime that such an exception is neither locally handled nor an interface is declared appropriately - and the exception is raised - a new exception of type `CX_SY_NO_HANDLER` is raised. In this case, the attribute `PREVIOUS` contains a reference to the original exception. - - Example: The predefined class `CX_SY_ZERODIVIDE` is derived from `CX_DYNAMIC_CHECK`. The operands of a calculation can be checked appropriately (e. g. in case of a division, the implementation should guarantee that the second operand is not 0) before carrying out the arithmetic operation. In doing so, the exception can be avoided. - - - `CX_NO_CHECK`: For error situations that can basically occur any time, cannot be locally handled in a meaningful way or cannot be avoided even following a check. An example for such an error situation might be a lack of memory. If the handling of such exceptions was checked statically or dynamically, it would basically mean to specify it in each procedure interface - not ideal for a clear program structuring. - - Note that exceptions derived from `CX_NO_CHECK` are always declared implicitly in all procedure interfaces. - -**Basic rule**: [Use a suitable exception category (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_category_guidl.htm). - -> **💡 Note**
-> - Each exception has a an [exception text](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_text_glosry.htm) that describes the error situation and that you can retrieve as outlined above. It helps you analyze the error. Plus, imagine using exceptions in the context of user interfaces. If a user faces an error situation, such exception texts may be displayed on the UI. -> - Find more information on exception texts [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_texts.htm) in the ABAP Keyword Documentation. - -

⬆️ back to top

- -### Raising Exceptions - -- Either the ABAP runtime framework raises predefined exceptions or you raise exceptions programmatically using dedicated statements. You can raise both predefined and self-defined exceptions. -- As the name implies, [`RAISE EXCEPTION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_exception_class.htm) statements raise class-based exceptions and thus interrupt the execution of the current statement block. -- The `COND` operator includes the optional addition `THROW` to raise class-based exceptions. - -```abap -... -"RAISE EXCEPTION statement -"The TYPE addition specifies the type of the exception, i. e. the exception class. -"The statement is also possible without TYPE. In that case, you can use an existing exception object. -"Note that there are plenty of additions. Check the ABAP Keyword Documentation. -RAISE EXCEPTION TYPE cx_sy_zerodivide. -... - -"THROW addition for the COND operator -... = COND #( WHEN ... THEN ... - WHEN ... THEN ... - ELSE THROW cx_some_error( ) ). -``` - -

⬆️ back to top

- -## Excursion: Runtime Errors and Terminating Programs -- Runtime errors are caused by uncatchable exceptions when a program is executed, when a catchable exception is not caught, or they can be forced by, for example, using [`ASSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapassert.htm) statements. -- Every runtime error terminates the program, which in turn raises a [database rollback](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_rollback_glosry.htm) and is documented by default in a [short dump](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshort_dump_glosry.htm). - -- Regarding `ASSERT` statements: `ASSERT` is followed by a logical expression. If the expression is false, the program is terminated and an uncatchable exception is raised resulting in the runtime error `ASSERTION_FAILED`. Note that each runtime error is identified by a name and assigned to a specific error situation. - -```abap -"The ASSERT keyword is followed by a logical expression. -"If the expression is false, the program is terminated and an uncatchable exception is raised -"resulting in the runtime error ASSERTION_FAILED. - -DATA(flag) = abap_false. - -ASSERT flag = abap_true. -``` - -> **💡 Note**
-> - Each runtime error is identified by a name and assigned to a specific error situation. -> - In ADT, you will see a message popping up and informing you about the runtime error. You can check the details by choosing the "Show" button in the pop-up. Furthermore, you can check the content of the "Feed Reader" tab in ADT. There, just expand your project and find the runtime errors caused by you. - -

⬆️ back to top

- -## Executable Example - -[zcl_demo_abap_prog_flow_logic](./src/zcl_demo_abap_prog_flow_logic.clas.abap) - -> **💡 Note**
-> - The executable example ... -> - covers the following topics, among others: -> - Control structures with `IF`, `CASE`, and `TRY` -> - Excursions: `COND` and `SWITCH` operators -> - Expressions and functions for conditions -> - Predicate expression with `IS SUPPLIED` -> - Loops with `DO`, `WHILE`, and `LOOP` -> - Terminating loop passes -> - Handling exceptions -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). + + +# Program Flow Logic + +- [Program Flow Logic](#program-flow-logic) + - [Introduction](#introduction) + - [Expressions and Functions for Conditions](#expressions-and-functions-for-conditions) + - [Control Structures](#control-structures) + - [`IF` Statements](#if-statements) + - [Excursion: `COND` Operator](#excursion-cond-operator) + - [`CASE`: Case Distinctions](#case-case-distinctions) + - [Excursion: `SWITCH` Operator](#excursion-switch-operator) + - [Loops](#loops) + - [`DO`: Unconditional Loops](#do-unconditional-loops) + - [Interrupting and Exiting Loops](#interrupting-and-exiting-loops) + - [`WHILE`: Conditional Loops](#while-conditional-loops) + - [Loops Across Tables](#loops-across-tables) + - [Calling Procedures](#calling-procedures) + - [Excursion: RETURN](#excursion-return) + - [Handling Exceptions](#handling-exceptions) + - [Notes on Exception Classes](#notes-on-exception-classes) + - [Raising Exceptions](#raising-exceptions) + - [Excursion: Runtime Errors and Terminating Programs](#excursion-runtime-errors-and-terminating-programs) + - [Executable Example](#executable-example) + + +This cheat sheet gathers information on program flow logic. Find more details +[here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_flow_logic.htm) +in the ABAP Keyword Documentation. + +## Introduction + +In ABAP, the flow of a program is controlled by [control structures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencontrol_structure_glosry.htm), [procedure](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm) calls and the raising or handling of [exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexception_glosry.htm). + +Using control structures as an example, you can determine the conditions for further processing of code, for example, if at all or how often a statement block should be executed. Control structures - as, for example, realized by an `IF ... ELSEIF ... ELSE ... ENDIF.` statement - can include multiple [statement blocks](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatement_block_glosry.htm) that are executed depending on conditions. + +In a very simple form, such an [`IF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapif.htm) statement might look as follows: + +```abap +DATA(num) = 1 + 1. + +"A simple condition: Checking if the value of num is 2 +IF num = 2. + ... "Statement block + "Here goes some code that should be executed if the condition is true. +ELSE. + ... "Statement block + "Here goes some code that should be executed if the condition is false. + "For example, if num is 1, 8, 235, 0 etc., then do something else. +ENDIF. +``` + +

⬆️ back to top

+ +## Expressions and Functions for Conditions +- So, such control structures are executed depending on conditions as specified above: `... num = 2 ...` - a [logical expression](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogical_expression_glosry.htm). +- Control structures are generally controlled by logical expressions that define conditions for [operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_glosry.htm). +- The result of such an expression is either true or false. +- Logical expressions are either single [relational expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelational_expression_glosry.htm) or expressions combined from one or more logical expressions with Boolean operators like `NOT`, `AND` and `OR`. + +```abap +"Single relational expression +IF num = 1. + ... +ENDIF. + +"Multiple expressions +IF num = 1 AND flag = 'X'. + ... +ENDIF. + +IF num = 1 OR flag = 'X'. + ... +ENDIF. + +"Multiple expressions can be parenthesized explicitly +IF ( num = 1 AND flag = 'X' ) OR ( num = 2 AND flag = 'X' ). + ... +ENDIF. +``` + +- The components of such relational expressions can be [comparisons](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_glosry.htm) or [predicates](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpredicate_glosry.htm). Note that for [comparison expressions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomparison_expression_glosry.htm), +the comparisons are carried out according to [comparison rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlogexp_rules.htm). + +The following code snippet shows a selection of possible expressions and operands of such expressions using a big `IF` statement. Certainly, such a huge statement is far from ideal. Here, the intention is to just cover many syntax options in one go for demonstration purposes. + +```abap +"Some declarations to be used in the IF statement below +DATA(num) = 2. "integer +DATA(empty_string) = ``. "empty string +DATA(flag) = 'x'. +DATA(dref) = NEW string( `ref` ). "data reference variable + +"Object reference variable +DATA oref TYPE REF TO object. +"Creating an object and assigning it to the reference variable +oref = NEW zcl_demo_abap_prog_flow_logic( ). + +"Declaration of and assignment to a field symbol +FIELD-SYMBOLS TYPE string. +ASSIGN `hallo` TO . + +"Creating an internal table of type string inline +DATA(str_table) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). + +"The following IF statement includes multiple expressions combined by AND to demonstrate different options + +"Comparisons +IF 2 = num "equal, alternative EQ +AND 1 <> num "not equal, alternative NE +AND 1 < num "less than, alternative LT +AND 3 > num "greater than, alternative GT +AND 2 >= num "greater equal, alternative GE +AND 2 <= num "less equal, alternative LE + +"Checks whether the content of an operand is within a closed interval +AND num BETWEEN 1 AND 3 +AND NOT num BETWEEN 5 AND 7 "NOT negates a logical expression +AND ( num >= 1 AND num <= 3 ) "Equivalent to 'num BETWEEN 1 AND 3'; + "here, demonstrating the use of parentheses + +"Comparison operators CO, CN ,CA, NA, CS, NS, CP, NP for character-like data types; +"see the cheat sheet on string processing + +"Predicate Expressions +AND empty_string IS INITIAL "Checks whether the operand is initial. The expression + "is true, if the operand contains its type-dependent initial value +AND num IS NOT INITIAL "NOT negates + +AND dref IS BOUND "Checks whether a data reference variable contains a valid reference and + "can be dereferenced; + "Negation (IS NOT BOUND) is possible which is also valid for the following examples +AND oref IS BOUND "Checks whether an object reference variable contains a valid reference + +"IS INSTANCE OF checks whether for a +"a) non-initial object reference variable the dynamic type +"b) for an initial object reference variable the static type +"is more specific or equal to a comparison type. +AND oref IS INSTANCE OF zcl_demo_abap_prog_flow_logic +AND oref IS INSTANCE OF if_oo_adt_classrun + +AND IS ASSIGNED "Checks whether a memory area is assigned to a field symbol + +"See the predicate expression IS SUPPLIED in the executable example. +"It is available in method implementations and checks whether a formal parameter +"of a procedure is filled or requested. + +"Predicate function: Some examples +AND contains( val = pcre = `\D` ) "Checks whether a certain value is contained; + "the example uses the pcre parameter for regular expressions; + "it checks whether there is any non-digit character contained +AND matches( val = pcre = `ha.+` ) "Compares a search range of the argument for the val parameter; + "the example uses the pcre parameter for regular expressions; + "it checks whether the value matches the pattern 'ha' + "and a sequence of any characters + +"Predicate functions for table-like arguments +"Checks whether a line of an internal table specified in the table expression +"exists and returns the corresponding truth value. +AND line_exists( str_table[ 2 ] ) + +"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 method call, +"i. e. the return value of the called function method, is arbitrary. +"A check is made for the type-dependent initial value. +AND check_is_supplied( ) +"It is basically the short form of such a predicate expression: +AND check_is_supplied( ) IS NOT INITIAL + +"Boolean Functions +"Determine the truth value of a logical expression specified as an argument; +"the return value has a data type dependent on the function and expresses +"the truth value of the logical expression with a value of this type. + +"Function boolc: Returns a single-character character string of the type string. +"If the logical expression is true, X is returned. False: A blank is returned. +"Not to be compared with the constants abap_true and abap_false in relational expressions, +"since the latter convert from c to string and ignore any blanks. Note: If the logical +"expression is false, the result of boolc does not meet the condition IS INITIAL since +"a blank and no empty string is returned. If this is desired, the function xsdbool +"can be used instead of boolc. +AND boolc( check_is_supplied( ) ) = abap_true + +"Result has the same ABAP type as abap_bool. +AND xsdbool( check_is_supplied( ) ) = abap_true + +"Examples for possible operands + +"Data objects as shown in the examples above +AND 2 = 2 +AND num = 2 + +"Built-in functions +AND to_upper( flag ) = 'X' +AND NOT to_lower( flag ) = 'X' + +"Numeric functions +AND ipow( base = num exp = 2 ) = 4 + +"Functional methods +"Method with exactly one return value +AND addition( num1 = 1 num2 = 1 ) = 2 + +"Calculation expressions +AND 4 - 3 + 1 = num + +"String expressions +AND `ha` && `llo` = + +"Constructor expression +AND CONV i( '2.03' ) = num +AND VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ) = str_table + +"Table expression +AND str_table[ 2 ] = `b`. + + "All of the logical expressions are true. + +ELSE. + + "At least one of the logical expressions is false. + +ENDIF. +``` + +> **💡 Note**
+> Logical expressions and functions can also be used in other ABAP statements. + +

⬆️ back to top

+ +## Control Structures + +### `IF` Statements + +- As already shown above, `IF` statements define statement blocks that can be included in [branches](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbranch_glosry.htm). +- The statement blocks are executed depending on conditions. +- A maximum of one statement block is executed. +- The check is carried out from top to bottom. The statement block after the first logical expression that is true is executed. +- If none of the logical expressions are true, the statement block after the `ELSE` statement is executed. +- `ELSE` and `ELSEIF` statements are optional. However, it is recommended that you specify an `ELSE` so that at least one statement block is executed. +- If the end of the executed statement block is reached or if no statement block has been executed, the processing is continued after `ENDIF.`. + + +```abap +"IF statement with multiple included ELSEIF statements +IF log_exp1. + + ... "statement_block1 + +ELSEIF log_exp2. + + ... "statement_block2 + +ELSEIF log_exp3. + + ... "statement_block3 + +... "further ELSEIF statements + +ELSE. + + ... "statement_blockn + +ENDIF. +``` + + +Control structures can be nested. +```abap +DATA(num) = 1. +DATA(flag) = 'X'. + +IF num = 1. + + IF flag = 'X'. + ... + ELSE. + ... + ENDIF. + +ELSE. + + ... "statement block, e. g. + "ASSERT 1 = 0. + "Not to be executed in this example. + +ENDIF. +``` + +> **💡 Note**
+> - Control structures can be nested. It is recommended that you do not include more than 5 nested control structures since the code will +> get really hard to understand. Better go for outsourcing functionality into methods to reduce nested control control structures. +> - Keep the number of consecutive control structures low. +> - If you are convinced that a specified logical expression must always be true, you might include a statement like `ASSERT 1 = 0.` to go +> sure - as implied in the example's `ELSE` statement above. However, an `ELSE` statement that is never executed might be a hint that +> logical expressions might partly be redundant. + +

⬆️ back to top

+ +#### Excursion: `COND` Operator + +- The conditional operator [`COND`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconditional_expression_cond.htm) can also be used to implement branches in operand positions that are based on logical expressions. +- Such conditional expressions have a result that is dependent on the logical expressions. +- The result's data type is specified after `COND` right before the first parenthesis. It can also be the `#` character as a symbol for the operand type if the type can be derived from the context. See the ABAP Keyword Documentation and the cheat sheet on constructor expressions for more information. +- All operands specified after `THEN` must be convertible to the result's data type. + +```abap +... COND type( WHEN log_exp1 THEN result1 + WHEN log_exp2 THEN result2 + ... + ELSE resultn ) ... +``` + +

⬆️ back to top

+ +### `CASE`: Case Distinctions + +- [`CASE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase.htm) statements are used for case distinctions. +- Such statements can also contain multiple statement blocks of which a maximum of one is executed depending on the value of the operand specified after `CASE`. +- The check is carried out from top to bottom. If the content of an operand specified after `WHEN` matches the content specified after `CASE`, the statement block is executed. Constant values should be specified as operands. +- The `WHEN` statement can include more than one operand using the syntax `WHEN op1 OR op2 OR op3 ...`. +- If no matches are found, the statement block is executed after the statement `WHEN OTHERS.` which is optional. +- If the end of the executed statement block is reached or no statement block is executed, the processing continues after `ENDCASE.`. + + +```abap +CASE operand. + WHEN op1. + ... "statement_block + WHEN op2. + ... "statement_block + WHEN op3 OR op4. + ... "statement_block + WHEN OTHERS. + ... "statement_block +ENDCASE. +``` + +Special control structure introduced by [`CASE TYPE OF`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcase_type.htm): Checks the type of object reference variables. + +```abap +"oref must be an object reference variable with the static type of a class or an interface. +CASE TYPE OF oref. + WHEN TYPE some_class. + ... "statement_block + WHEN TYPE some_intf. + ... "statement_block + WHEN OTHERS. + ... "statement_block +ENDCASE. +``` + +

⬆️ back to top

+ +#### Excursion: `SWITCH` Operator + +The conditional operator [`SWITCH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconditional_expression_switch.htm) can also be used to make case distinctions in operand positions. As mentioned above for `COND`, a result is constructed. The same criteria apply for `SWITCH` as for `COND` regarding the type. See the ABAP Keyword Documentation and the cheat sheet on constructor expressions for more information. + + +```abap +... SWITCH type( operand + WHEN const1 THEN result1 + WHEN const2 THEN result2 + ... + ELSE resultn ) ... +``` + +

⬆️ back to top

+ +### Loops + +#### `DO`: Unconditional Loops + +- A statement block specified between `DO` and `ENDDO` is carried out multiple times. +- The loop is exited when a statement to terminate the loop is reached (`EXIT`, see further down). Otherwise, it is executed endlessly. + + ```abap + DO. + ... "statement_block + "To be terminated with an EXIT statement. + ENDDO. + ``` +- To restrict the loop passes, you can use the `TIMES` addition and specify the maximum number of loop passes. + + ```abap + DO 5 TIMES. + ... "statement_block + ENDDO. + ``` +- The value of the system field `sy-index` within the statement block contains the number of previous loop passes including the current pass. + +

⬆️ back to top

+ +#### Interrupting and Exiting Loops + +The following ABAP keywords are available for interrupting and exiting loops: + +| Keyword | Syntax | Details | +|---|---|---| +| [`CONTINUE`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcontinue.htm) | `CONTINUE.` | The current loop pass is terminated immediately and the program flow is continued with the next loop pass. | +| [`CHECK`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcheck_loop.htm) | `CHECK log_exp.` | Conditional termination. If the logical expression `log_exp` is false, the current loop pass is terminated immediately and the program flow is continued with the next loop pass. | +| [`EXIT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapexit_loop.htm) | `EXIT.` | The loop is terminated completely. The program flow resumes after the closing statement of the loop. | + +> **💡 Note**
+> - [`RETURN`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapreturn.htm) statements immediately terminate the current processing block. However, according to the [guidelines (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexit_procedure_guidl.htm), `RETURN` should only be used to exit procedures like methods. +> - `EXIT` and `CHECK` might also be used for exiting procedures. However, their use inside loops is recommended. + +

⬆️ back to top

+ +#### `WHILE`: Conditional Loops + +- Conditional loops introduced by `WHILE` and ended by `ENDWHILE` are repeated as long as a logical expression is true. +- These loops can also be exited using the statements mentioned above. +- Like in `DO` loops, the system field `sy-index` contains the number of previous loop passes including the current pass. + +```abap +WHILE log_exp. + ... "statement_block +ENDWHILE. +``` + +

⬆️ back to top

+ +#### Loops Across Tables +Further keywords for defining loops are as follows. They are not dealt with here since they are covered in other ABAP cheat sheets. + +- [`LOOP ... ENDLOOP`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaploop_at_itab.htm) statements are meant for loops across internal tables. See also the cheat sheet on internal tables. + - In contrast to the loops above, the system field `sy-index` is not set. Instead, the system field `sy-tabix` is set and which contains the table index of the current table line in the loop pass. + - You can also realize loops using iteration expressions with `VALUE` and `REDUCE`. For more information, refer to the [Constructor Expressions](05_Constructor_Expressions.md) cheat sheet. +- [`SELECT ... ENDSELECT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect.htm) statements loop across the result set of a database access. See also the cheat sheet on ABAP SQL. + +

⬆️ back to top

+ +## Calling Procedures + +Calling [procedures](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenprocedure_glosry.htm) would actually fit here in the context of dealing with program flow logic since they can be called explicitly in an [ABAP program](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm). +However, ... +1. in modern ABAP programs, only methods should be implemented (instead of [function modules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfunction_module_glosry.htm) and [subroutines](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensubroutine_glosry.htm) in most cases) and +2. methods are described in the context of the ABAP cheat sheet on ABAP object orientation. Hence, see more details there. + +Regarding the exiting of procedures, note the hint mentioned above. The use of `RETURN` is recommended. + +

⬆️ back to top

+ +### Excursion: RETURN + +As mentioned, `RETURN` terminates the current processing block. Usually, the statement is intended for leaving processing blocks early. +In case of functional method, i.e. methods that have one returning parameter, the `RETURN` statement can also be specified with an expression. In doing so, the +following statement +```abap +res = some_expr. +RETURN. +``` +can also be specified as follows: +```abap +RETURN some_expr. +``` +Here, the expression result is passed to the returning parameter without naming it explicitly. As an expression, you can specify a constructor expression (and using type inference with `#` means using the type of the returning parameter). + +Example: +```abap +CLASS zcl_some_class DEFINITION + PUBLIC + FINAL + CREATE PUBLIC. + PUBLIC SECTION. + INTERFACES: if_oo_adt_classrun. + PROTECTED SECTION. + PRIVATE SECTION. + CLASS-METHODS multiply + IMPORTING num1 TYPE i + num2 TYPE i + RETURNING VALUE(result) TYPE i. +ENDCLASS. +CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + DATA(res1) = multiply( num1 = 2 num2 = 3 ). + DATA(res2) = multiply( num1 = 10 num2 = 10 ). + DATA(res3) = multiply( num1 = 99999999 num2 = 99999999 ). + out->write( res1 ). "6 + out->write( res2 ). "100 + out->write( res3 ). "0 + ENDMETHOD. + METHOD multiply. + TRY. + "result = num1 * num2. + RETURN num1 * num2. + CATCH cx_sy_arithmetic_error. + RETURN VALUE #( ). + ENDTRY. + ENDMETHOD. +ENDCLASS. +``` + +

⬆️ back to top

+ +## Handling Exceptions +- [Exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenexception_glosry.htm) ... + - are events during the execution of an ABAP program that interrupt the program flow because it is not possible for the program to continue in a meaningful way. For such situations, you can implement an exception handling in which you can react on the situations appropriately. Consider, for example, the implementation of a simple calculation. If there is a division by zero, the program will be terminated with a [runtime error](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenruntime_error_glosry.htm) unless you handle the exception appropriately. + - can be raised either by the program or by the [ABAP runtime framework](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_runtime_frmwk_glosry.htm). Exceptions raised by the latter are generally caused by error situations that cannot be detected by the static program check. The division by zero is such an example. + - should, in modern ABAP, only be designed as [class-based exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclass_based_exception_glosry.htm), i. e. exceptions are represented by [objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_glosry.htm) of classes. Global exception classes usually use the naming convention `CX_...`. + - are either [catchable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencatchable_exception_glosry.htm) (they are based on predefined or self-defined exception classes) or [uncatchable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuncatchable_exception_glosry.htm) (they directly produce runtime errors, i. e. error situations cannot be handled appropriately). + +`TRY` control structures are meant for handling catchable exceptions locally: +- To be prepared for potential exceptions that are raised when executing statements, the statements can be included and executed within a *protected area*, a [`TRY`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptry.htm) control structure. +- In doing so, it is possible for the ABAP runtime framework to catch exceptions and react on error situations. + + ```abap + TRY. + "statement block + ENDTRY. + ``` + +- The `TRY` control structure in the snippet above produces a syntax warning. A [`CATCH`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcatch_try.htm) block is expected, too. +- One or more class-based exceptions can be handled in one or more subsequent `CATCH` blocks. The `CATCH` statement must include an "appropriate" class-based exception. "Appropriate" means that, certainly, an exception class should be specified that is suitable for the error handling. In the following example, the predefined exception class `CX_SY_ZERODIVIDE` is specified that is, as the name implies, specific for the (potential) exception in case of a division by zero. + + ```abap + TRY. + "TRY block + DATA(div1) = 1 / 0. + + "Predefined exception class cx_sy_zerodivide as suitable exception class to be used here. + "If the exception is not handled, the program is terminated and the runtime error + "COMPUTE_INT_ZERODIVIDE occurs. + CATCH cx_sy_zerodivide. + ... "CATCH block + ENDTRY. + + "Example for catching an exception in the context of a table expression + TRY. + "Copying a line of an internal table + DATA(line) = some_itab[ 12345 ]. + + "Predefined exception class cx_sy_itab_line_not_found as suitable exception class to be used here. + "If the exception is not handled, the program is terminated and the runtime error + "ITAB_LINE_NOT_FOUND occurs. + CATCH cx_sy_itab_line_not_found. + ... "CATCH block + ENDTRY. + + "Note on inheritance relationships in exception classes + TRY. + "TRY block + DATA(div2) = 1 / 0. + + "A CATCH block is in this example not only valid for cx_sy_zerodivide as specified above + "but also for all derived exceptions classes. + "In the following CATCH block, the predefined exception class cx_sy_arithmetic_error + "is specified. cx_sy_zerodivide is derived from cx_sy_arithmetic_error. + "Hence, cx_sy_arithmetic_error can be specified and handle the exception, too. + "Basically, using the exception root class cx_root would be also possible. However, + "choosing an appropriate exception class is recommended. See further down. + + CATCH cx_sy_arithmetic_error. + ... "CATCH block + ENDTRY. + + + "Multiple classes in a list and CATCH blocks can be specified + "Note: If there are multiple CATCH blocks for exceptions that are in an inheritance + "relationship, you must pay attention that the more special exceptions are specified + "before the more general ones. + TRY. + ... "TRY block + CATCH cx_abc cx_bla cx_blabla. + ... "CATCH block + CATCH cx_la cx_lala. + ... "CATCH block + CATCH cx_lalala. + ... "CATCH block + ENDTRY. + ``` + +- If the addition `INTO` is specified in the `CATCH` statement, a reference to the exception object is stored. +- This is relevant to determine the exact exception, for example. In the code snippet above, the exception class `CX_SY_ZERODIVIDE` is mentioned. Consider a calculator. It should not only be able to deal with error situations like zero division but also, for example, overflows in arithmetic operations. The predefined exception class `CX_SY_ARITHMETIC_OVERFLOW` is available. It is also derived from `CX_SY_ARITHMETIC_ERROR`. If you then specify the exception class `CX_SY_ARITHMETIC_ERROR` which is higher up in the inheritance hierarchy and can handle both error situations (`CX_SY_ARITHMETIC_OVERFLOW` and `CX_SY_ZERODIVIDE`), the concrete exception that was raised is unclear. Using the `INTO` clause and the stored exception object, it is possible to carry out certain tasks, for example, retrieving and displaying the exception text. + + ```abap + DATA: exception TYPE REF TO cx_root. "Note the root class + "Note: For a self-defined exception class, the object reference must be typed appropriately. + + TRY. + ... "TRY block + + "Storing a reference to the exception object. + "Note: The type is cx_root since attributes and methods of the root class that are defined there can be accessed. + CATCH INTO exception. + ... "CATCH block + ENDTRY. + + "Inline creation of exception object reference and getting exception texts + TRY. + ... "TRY block + + "The object reference variable can be created inline, for example, using DATA(...). + CATCH cx_sy_arithmetic_error INTO DATA(error_oref). + ... "catch block + "To get exception texts, you can call, for example, the method get_text + DATA(error_text) = error_oref->get_text( ). + + ENDTRY. + ``` + +- Regarding the program flow: + - The statement block following `TRY.` is always processed. If an exception is raised within this `TRY` block, the system searches for an exception handler, i. e. a `CATCH` block that is able to handle the exception. + - If there is no `CATCH` statement that is able to handle the catchable exception or if erroneous code is not within a `TRY` control structure at all, the exception is propagated to the caller. + - Exceptions can be handled either in the context locally (using such a `TRY` control structure) or be propagated to the caller so that the caller is responsible for reacting appropriately (for example, in another `TRY` control structure) to the error situation. In doing so, you can better structure your code by reacting on error situations centrally instead of locally checking, for example, each procedure call individually. + - If, at the end, the exception can nowhere be caught and handled, the program is terminated with a runtime error. + - If the exception can be handled or no exception is raised in the `TRY` block and it reaches its end, the processing continues after `ENDTRY`. + + +> **💡 Note**
+> - Non-class-based exceptions are considered obsolete and should not be defined any more in new developments according to the [guidelines (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclass_exception_guidl.htm) and are not dealt with here. +>- For all exceptions that are raised by the ABAP runtime environment and that are not handled, there is a corresponding runtime error. For example, in the case of exception class `CX_SY_ZERODIVIDE`, it is the runtime error `COMPUTE_INT_ZERODIVIDE`. For self-defined exception classes, an exception that is not handled generally triggers the runtime error `UNCAUGHT_EXCEPTION`. +> - For `TRY` control structures, there are further additions available dealing with more advanced error handling, e. g. [resumable exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapresume.htm). + +

⬆️ back to top

+ +#### Notes on Exception Classes +- To distinguish exception classes from *regular* classes, use the naming convention `CX` as prefix and not `CL`. +- All exception classes (also the self-defined ones) are directly or indirectly derived from three abstract subclasses: `CX_STATIC_CHECK`, `CX_DYNAMIC_CHECK` and `CX_NO_CHECK`. These three "exception class categories" have different properties. +- The class `CX_ROOT` is the root class. Directly deriving from `CX_ROOT` is not possible. +- Apart from global classes, exception classes can also be defined as local classes within an ABAP program. +- As mentioned, there are predefined exception classes like `CX_SY_ZERODIVIDE` for divisions by zero. However, you can create your own exception classes so that you can react on issues that are specific to your ABAP program. The exception class must, as stated above, be derived from one of the three abstract classes: + - `CX_STATIC_CHECK`: For forcing users to handle exceptions. + Generally speaking, exceptions that can occur in procedures should be handled locally there in the implementation or be declared explicitly in the [procedure interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenparameter_interface_glosry.htm) so that a caller knows which error situations can be expected. Exception classes of type `CX_STATIC_CHECK` enforce this. A check is carried out statically at compile time. Users of a procedure are then forced to either handle the exception locally in a `TRY` control structure or the users declare the exception themselves in their procedure interface to propagate the exception to their users. If this is not the case, a warning is produced. + - As an example, a method signature might look as follows. The addition `RAISING` in method signatures is used to declare one or more class-based exceptions that can be propagated from the method to the caller. + - When users of this method implement the method, they are made aware of the fact that an error situation can occur and a particular exception can be raised. The assumption is that `CX_SOME_ERROR` is derived from `CX_STATIC_CHECK`. Users of the method should then prepare the code accordingly. + ```abap + "Method definition using the RAISING parameter + CLASS-METHODS: some_meth IMPORTING str TYPE string + RETURNING VALUE(ret_value) TYPE string + RAISING cx_some_error. + + ... + + "Method call: Somewhere in the code of a user that calls the method + "Exception handled locally in a TRY control structure. + TRY. + DATA(val) = some_meth( str = `hallo` ). + + CATCH cx_some_error. + ... + ENDTRY. + + "If it was just like this without the TRY control structure, a warning would be produced. + DATA(val2) = some_meth( str = `hi` ). + ``` + + - `CX_DYNAMIC_CHECK`: For exceptions that can be checked and avoided by preconditions. As a consequence and in contrast to an exception class derived from `CX_STATIC_CHECK`, exception classes of type `CX_DYNAMIC_CHECK` do not enforce the local handling and the declaration in procedure interfaces. However, an appropriate exception handling should be implemented in cases in which you cannot rule out the raising of the exceptions in your program logic. The checking if a local handling or an explicit declaration in procedure interfaces is available is carried out at runtime only ("dynamic check") and only in case the exception is indeed raised. + - If it is determined at runtime that such an exception is neither locally handled nor an interface is declared appropriately - and the exception is raised - a new exception of type `CX_SY_NO_HANDLER` is raised. In this case, the attribute `PREVIOUS` contains a reference to the original exception. + - Example: The predefined class `CX_SY_ZERODIVIDE` is derived from `CX_DYNAMIC_CHECK`. The operands of a calculation can be checked appropriately (e. g. in case of a division, the implementation should guarantee that the second operand is not 0) before carrying out the arithmetic operation. In doing so, the exception can be avoided. + + - `CX_NO_CHECK`: For error situations that can basically occur any time, cannot be locally handled in a meaningful way or cannot be avoided even following a check. An example for such an error situation might be a lack of memory. If the handling of such exceptions was checked statically or dynamically, it would basically mean to specify it in each procedure interface - not ideal for a clear program structuring. + - Note that exceptions derived from `CX_NO_CHECK` are always declared implicitly in all procedure interfaces. + +**Basic rule**: [Use a suitable exception category (F1 docu for standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_category_guidl.htm). + +> **💡 Note**
+> - Each exception has a an [exception text](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_text_glosry.htm) that describes the error situation and that you can retrieve as outlined above. It helps you analyze the error. Plus, imagine using exceptions in the context of user interfaces. If a user faces an error situation, such exception texts may be displayed on the UI. +> - Find more information on exception texts [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexception_texts.htm) in the ABAP Keyword Documentation. + +

⬆️ back to top

+ +### Raising Exceptions + +- Either the ABAP runtime framework raises predefined exceptions or you raise exceptions programmatically using dedicated statements. You can raise both predefined and self-defined exceptions. +- As the name implies, [`RAISE EXCEPTION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapraise_exception_class.htm) statements raise class-based exceptions and thus interrupt the execution of the current statement block. +- The `COND` operator includes the optional addition `THROW` to raise class-based exceptions. + +```abap +... +"RAISE EXCEPTION statement +"The TYPE addition specifies the type of the exception, i. e. the exception class. +"The statement is also possible without TYPE. In that case, you can use an existing exception object. +"Note that there are plenty of additions. Check the ABAP Keyword Documentation. +RAISE EXCEPTION TYPE cx_sy_zerodivide. +... + +"THROW addition for the COND operator +... = COND #( WHEN ... THEN ... + WHEN ... THEN ... + ELSE THROW cx_some_error( ) ). +``` + +

⬆️ back to top

+ +## Excursion: Runtime Errors and Terminating Programs +- Runtime errors are caused by uncatchable exceptions when a program is executed, when a catchable exception is not caught, or they can be forced by, for example, using [`ASSERT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapassert.htm) statements. +- Every runtime error terminates the program, which in turn raises a [database rollback](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_rollback_glosry.htm) and is documented by default in a [short dump](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenshort_dump_glosry.htm). + +- Regarding `ASSERT` statements: `ASSERT` is followed by a logical expression. If the expression is false, the program is terminated and an uncatchable exception is raised resulting in the runtime error `ASSERTION_FAILED`. Note that each runtime error is identified by a name and assigned to a specific error situation. + +```abap +"The ASSERT keyword is followed by a logical expression. +"If the expression is false, the program is terminated and an uncatchable exception is raised +"resulting in the runtime error ASSERTION_FAILED. + +DATA(flag) = abap_false. + +ASSERT flag = abap_true. +``` + +> **💡 Note**
+> - Each runtime error is identified by a name and assigned to a specific error situation. +> - In ADT, you will see a message popping up and informing you about the runtime error. You can check the details by choosing the "Show" button in the pop-up. Furthermore, you can check the content of the "Feed Reader" tab in ADT. There, just expand your project and find the runtime errors caused by you. + +

⬆️ back to top

+ +## Executable Example + +[zcl_demo_abap_prog_flow_logic](./src/zcl_demo_abap_prog_flow_logic.clas.abap) + +> **💡 Note**
+> - The executable example ... +> - covers the following topics, among others: +> - Control structures with `IF`, `CASE`, and `TRY` +> - Excursions: `COND` and `SWITCH` operators +> - Expressions and functions for conditions +> - Predicate expression with `IS SUPPLIED` +> - Loops with `DO`, `WHILE`, and `LOOP` +> - Terminating loop passes +> - Handling exceptions +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). > - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file diff --git a/16_Data_Types_and_Objects.md b/16_Data_Types_and_Objects.md index 73a953e..ad56792 100644 --- a/16_Data_Types_and_Objects.md +++ b/16_Data_Types_and_Objects.md @@ -1,1498 +1,1484 @@ - - -# Data Types and Data Objects - -- [Data Types and Data Objects](#data-types-and-data-objects) - - [Introduction](#introduction) - - [Data Types and Objects: Definition](#data-types-and-objects-definition) - - [ABAP Data Types](#abap-data-types) - - [Elementary Data Types](#elementary-data-types) - - [Complex Data Types](#complex-data-types) - - [Reference Types](#reference-types) - - [Declaring Data Types](#declaring-data-types) - - [Generic Types](#generic-types) - - [Data Objects](#data-objects) - - [Declaring Data Objects](#declaring-data-objects) - - [Assigning Values to Data Objects](#assigning-values-to-data-objects) - - [Creating Data Objects Using Inline Declaration](#creating-data-objects-using-inline-declaration) - - [Assigning References to Data Reference Variables](#assigning-references-to-data-reference-variables) - - [Creating Anonymous Data Objects](#creating-anonymous-data-objects) - - [Constants and Immutable Variables](#constants-and-immutable-variables) - - [Type Conversion](#type-conversion) - - [Terms Related to Data Types and Objects in a Nutshell](#terms-related-to-data-types-and-objects-in-a-nutshell) - - [Notes on the Declaration Context](#notes-on-the-declaration-context) - - [Excursions](#excursions) - - [Enumerated Types and Objects](#enumerated-types-and-objects) - - [Getting Type Information and Creating Types at Runtime](#getting-type-information-and-creating-types-at-runtime) - - [Ranges Tables](#ranges-tables) - - [Executable Example](#executable-example) - -## Introduction -[ABAP statements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_statement_glosry.htm) usually work with [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm), that is, with transient data that occupies memory space while the [data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm) defines the technical properties of the data objects. -Since data types and data objects are closely related, this cheat sheet covers both topics. -Note that the topics covered here are also partly covered in other ABAP cheat sheets. The purpose of this cheat sheet is to summarize the basics. - -## Data Types and Objects: Definition - -Data types -- Define technical properties of all data objects that have these data types, such as the maximum length of a [text field](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_field_glosry.htm). -- Are descriptions only, with no data memory attached except for administrative information. -- Can occur in [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) as [bound data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbound_data_type_glosry.htm), that is, the type is a property of a data object, or as a [standalone data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstand-alone_data_type_glosry.htm), that is, the data type is defined independently. -- Can be defined locally in an ABAP program or globally in classes, interfaces and in the [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm). -> **💡 Note**
-> - Note: Data types in the ABAP Dictionary are either created directly as [repository objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrepository_object_glosry.htm) ([DDIC data elements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_element_glosry.htm)) or in a type pool (only in [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm)). [Database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_table_glosry.htm), [CDS entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm) and their components can also be used as data types in ABAP programs. -> - Their existence and visibility depends on the declaration context. - -Data objects: -- Are objects (or [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm)) of a data type (similar to objects/instances of classes in [ABAP Objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_glosry.htm)). -- Occupy memory space and exist in different forms, for example, numeric or textual data can be contained in data objects. -- The type of data that a data object can receive is determined by its data type. -- Like data types, their existence and visibility depend on the declaration context. -- Are usually used in [ABAP statements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_statement_glosry.htm) by specifying them in the [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm). - - -> **💡 Note**
-> There are several differentations that further distinguish and characterize data types and objects. See [here](#terms-related-to-data-types-and-objects-in-a-nutshell). - -

⬆️ back to top

- -## ABAP Data Types - -ABAP is rich in built-in data types and offers a wide range of options for defining data types and data objects in different contexts. -Data types can be divided into three groups: -- [Elementary data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm) -- [Complex data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm) -- [Reference type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm) - -For an overview, see the [ABAP Type Hierarchy](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_hierarchy.htm) in the ABAP Keyword Documentation. - -### Elementary Data Types -- Elementary (or scalar) data types are based directly on a set of [built-in ABAP types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_abap_type_glosry.htm). -- Are not composed of other data types. -- Are types for holding numeric values, text information, binary data and special types for date and time. -- Are further divided into elementary types of fixed and variable length. - - Note: The length and the memory requirements of data objects of fixed length data types are fixed, that is, they cannot change at runtime. The length and memory requirements of data objects of variable length data types can actually change at runtime, depending on their contents. -- The following built-in elementary data types of fixed length are available: - - Numeric types: Integers (`b`, `s`, `i`, `int8`), [decimal floating point numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendecfloat_glosry.htm) (`decfloat16`, `decfloat34`), [binary floating point numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbinfloat_glosry.htm) (`f`), and [packed numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpacked_number_glosry.htm) (`p`) - - Character-like types: text fields (`c`) and [numeric text fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennumeric_text_field_glosry.htm) (`n`) - - Byte-like type: [byte fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_field_glosry.htm) (`x`) - - Character-like date and time types: date fields (`d`) and time fields (`t`) - - Time stamp type for time stamp fields (`utclong`). -- Variable length: - - Character-like type for [text strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_string_glosry.htm) (`string`) - - Byte-like type for [byte strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_string_glosry.htm) (`xstring`) - -> **💡 Note**
-> - The data types `c`, `n`, `x`, and `p` are incomplete, i.e., [generic data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_data_type_glosry.htm), with respect to their length. The type definition syntax has a special addition for this (`LENGTH`). In addition, `p` is also generic with respect to the number of decimal places (`DECIMALS` addition). See more about generic types in the following sections. -> - The other types can be considered as [complete data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplete_data_type_glosry.htm). They don't need any additional syntax elements for the definition. -> - The numeric data types `b` and `s` cannot be specified directly in ABAP programs for short integers. Alternative [built-in DDIC types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_ddic_type_glosry.htm) are available. -> - `decfloat16` and `decfloat34` for decimal floating point numbers can be regarded as more modern versions of `p` and `f`, combining their advantages. -> - Although they are character-like, `t` and `d` can be used for calculations. -> - See the ABAP Keyword Documentation [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuilt_in_types.htm) for more information about the initial values of the data types, the standard length, and so on. - -

⬆️ back to top

- -### Complex Data Types - -- Are composed of other types. -- The following complex data types are available: - - [Structured types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm): Represent a sequence of arbitrary data type (i.e., they can be elementary, reference, or complex data types). The typical syntax element for the local definition of a structure is `... BEGIN OF ... END OF ...`. - - [Table types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm): Consist of a sequence of any number of lines of the same data type. It can be any elementary type, reference type, or complex data type. The type definition includes other properties such as the [table category](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_category_glosry.htm) (defines how tables can be accessed) and [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm) (to identify the table lines). The typical syntax element is `... TABLE OF ...`. - - [Enumerated types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenum_type_glosry.htm): Specify a set of values in addition to the actual type properties. The typical syntax element is `... BEGIN OF ENUM ... END OF ENUM ...`. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_types_usage.htm) and further down. - - [Mesh types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmesh_type_glosry.htm): Special structured type that contains only table types with structured line types as components that can be linked using mesh associations. The typical syntax element is `... BEGIN OF MESH ... END OF MESH ...`. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes_mesh.htm). - - [BDEF derived types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm): RAP-specific structured and table types. The typical syntax elements are `... TYPE STRUCTURE FOR ...` and `... TYPE TABLE FOR ...`. More information can be found [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrpm_derived_types.htm) and in the ABAP cheat sheet on ABAP EML. -- A data object of a complex type can be accessed as a whole or by component. - -> **💡 Note**
-> Structured and table types are used in this cheat sheet as examples for complex types. For more information, see the ABAP Keyword Documentation and the ABAP cheat sheets for structures and internal tables. - -

⬆️ back to top

- -### Reference Types -- Describe data objects that contain [references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm) to other objects (data objects and instances of classes), which are known as [reference variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm). -- There are two kinds of references: [Data references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_glosry.htm) (references to data objects) and [object references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm) (references to objects as instances of classes). -- A reference type must be defined either in the ABAP program or in the ABAP Dictionary. There are no built-in reference types in ABAP. -- The typical syntax element is `... REF TO ...`. - -> **💡 Note**
-> There are [generic ABAP types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_abap_type_glosry.htm). Generic data types are types that do not define all of the properties of a data object. They can only be used for the typing of [formal parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm) and [field symbols](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm). See an example further down. -The only generic types that can be used after `TYPE REF TO` are `data` for the generic typing of data references, and `object`, for the generic typing of object references. - -

⬆️ back to top

- -### Declaring Data Types - -Data types are defined in an ABAP program using the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) statement. Depending on the declaration context, the types can be accessed either locally or globally. As mentioned, data types can also be declared in the ABAP Dictionary. The focus here is on data type declarations in ABAP programs using `TYPES` statements. -You can use built-in and user-defined data types to create data types (and data objects). - -The following code snippet shows various syntax options for declaring data types: - -Elementary types: - -```abap -"Type declaration follows these patterns (LENGTH and DECIMALS only possible for particular types): -"TYPES data_type TYPE some_type [LENGTH len] [DECIMALS dec]. - -"Data type declarations based on built-in ABAP types - -"Numeric types -TYPES te_i TYPE i. -TYPES te_int8 TYPE int8. -TYPES te_decfl16 TYPE decfloat16. -TYPES te_decfl34 TYPE decfloat34. -TYPES te_f TYPE f. -TYPES te_p_l4_d2 TYPE p LENGTH 4 DECIMALS 2. -"Note: LENGTH/DECIMALS must be specified when using the types c, p, n, x. in ABAP Objects contexts. - -"Character-like types -"To combine TYPES statements, you can use chained statements, i.e. TYPES followed by a colon and -"then listing the type declarations separated by a comma. -TYPES: te_c5 TYPE c LENGTH 5, - te_n4 TYPE n LENGTH 4, - te_str TYPE string. - -"Byte-like types -TYPES te_x_l2 TYPE x LENGTH 2. -TYPES te_xstr TYPE xstring. - -"Types for date and time -TYPES te_d TYPE d. -TYPES te_t TYPE t. -TYPES te_utc TYPE utclong. - -"You might also stumble on a length specification in parentheses following the data type name. -"It is recommended that you use addition LENGTH instead of the parentheses. -TYPES te_cfour(4) TYPE c. - -"**** Data type declarations based on existing types or data objects **** - -"Type declaration based on an existing type visible at this location; -"all properties of the specified data type are inherited. -TYPES te_another_i TYPE te_i. - -"Anticipating the data object declaration needed to demonstrate the LIKE addition -DATA do_num TYPE i. - -"LIKE addition: -"Type declaration based on an existing data object visible at this location; -"all properties of the type of the specified data object are inherited. -TYPES te_from_int LIKE do_num. - -"**** Data type declarations based on globally available types or data objects **** - -"DDIC Types -"Note that the built-in types b and s cannot be specified for type declarations. -"However, the value range for these types can be obtained by referencing the built-in DDIC -"types INT1 and INT2. These are data elements. -TYPES te_int1 TYPE int1. -TYPES te_int2 TYPE int2. - -"Referring to types in global classes -"In the example, the type exists in a global interface. -TYPES te_elem_from_itf TYPE zdemo_abap_get_data_itf=>occ_rate. - -"Referring to a data object that exists in a global interface -TYPES te_dobj_from_itf LIKE zdemo_abap_objects_interface=>stat_str. - -"Referring to a data object that exists in the public visibility section of a global class -TYPES te_dobj_from_cl LIKE zcl_demo_abap_objects=>public_string. - -"Referring to a component of a DDIC table (also possible for views; -"the components have elementary types) -TYPES te_comp_ddic_tab TYPE zdemo_abap_carr-carrid. - -"Type pools (ABAP program, administrated by the ABAP Dictionary; may only be created in -"standard ABAP; but is considered obsolete) -"However, the following example is accessible in ABAP for Cloud Development, too. -"The type pool contains the definitions of globally visible data types and constants. -TYPES te_tp TYPE abap_bool. -TYPES te_const_in_tp LIKE abap_true. -``` - -Structure and internal table types as examples for complex types: - -```abap -"Structure type, can contain any type -TYPES: BEGIN OF ts_misc_comps, - comp1 TYPE i, - comp2 TYPE string, - comp3 TYPE te_i, "Existing type - comp4 LIKE do_num, "Referring to existing data object - comp5 TYPE string_table, "Internal table type (available in DDIC) - comp6 TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY, "Internal table type (based on database table) - comp7 TYPE REF TO i, "Reference type - END OF ts_misc_comps. - -"Internal table types -"Note: The examples only use the implicit STANDARD for standard tables. -"Internal table type declaration based on a local structure type -TYPES tt_local_ts TYPE TABLE OF ts_misc_comps WITH EMPTY KEY. - -"Internal table type declaration based on an elementary data type -TYPES tt_int TYPE TABLE OF i. - -"Referring to existing types and data objects - -"Anticipating the creation of structured data objects for the LIKE addition -DATA struc_local_ts TYPE ts_misc_comps. - -"Structure type creation based on an existing structured data object -TYPES ts_w_like LIKE struc_local_ts. - -"Anticipating the creation of an internal table for the LIKE addition -DATA itab_local_ts TYPE TABLE OF ts_misc_comps WITH EMPTY KEY. - -"Internal table type declaration based on an existing internal table -TYPES tt_w_like LIKE itab_local_ts. - -"Internal table type declaration based on the existing internal table type -TYPES tt_another_type TYPE tt_w_like. - -"Structured types based on an internal table's line type -TYPES ts_type_line TYPE LINE OF tt_w_like. -TYPES ts_like_line LIKE LINE OF itab_local_ts. - -"Internal table typed with internal table as line type -TYPES tt_like_table LIKE TABLE OF itab_local_ts. - -"Referring to global types - -"Structure type based on DDIC type -"In this case, a database table is specified whose line type is used as data type -"in this type declaration. You may also use a CDS view (or classic DDIC view in -"standard ABAP) or a dedicated structured type defined in the DDIC. -TYPES ts_ddic_tab TYPE zdemo_abap_carr. - -"Internal table type based on internal type that exists in a gloabl interface -TYPES tt_tab_type_from_itf TYPE zdemo_abap_get_data_itf=>carr_tab. - -"Internal table types with an elementary line type based on globally available types -"Elementary table type -TYPES tt_strtab TYPE string_table. -"Elementary line type; the type is available in a global interface -TYPES tt_elem_type_from_itf TYPE TABLE OF zdemo_abap_get_data_itf=>occ_rate. -``` - -Reference types: -```abap -"Declaring reference types with static types -TYPES tr_i TYPE REF TO i. -TYPES tr_str TYPE REF TO string. -TYPES tr_ddic_tab TYPE REF TO zdemo_abap_carr. -"Using the generic type data as static type -TYPES tr_data TYPE REF TO data. - -"Referring to an existing reference type -TYPES tr_ref_i TYPE tr_i. - -"Anticipating the creation of a data reference variable for showing the LIKE addition -DATA dref_i TYPE REF TO i. - -"Creating a reference type based on a data reference variable -TYPES tr_like_ref_i LIKE dref_i. - -"Creating a data object for the LIKE REF TO addition -DATA str TYPE string. - -"Creating a reference type whose static type is inherited from the data type of the specified data object -TYPES tr_like_ref2str LIKE REF TO str. - -"Reference table types -TYPES tr_tab_ref_i TYPE TABLE OF REF TO i. -DATA itab_str TYPE TABLE OF string. -TYPES tr_like_table_ref LIKE TABLE OF REF TO itab_str. -``` - -

⬆️ back to top

- -### Generic Types - -- Generic types are available with which [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. -- 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. -- More information: - - [Generic ABAP Types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuilt_in_types_generic.htm) - - [ABAP cheat sheet about dynamic programming](06_Dynamic_Programming.md) regarding field symbols and `ASSIGN` statements - -The following code snippet demonstrates generic types with field symbols. - -```abap -FIELD-SYMBOLS: - "Any data type - TYPE data, - TYPE any, - "Any data type can be assigned. Restrictions for formal parameters and 'data': no - "numeric functions, no description functions, and no arithmetic expressions can be - "passed to these parameters. However, you can bypass the restriction by applying the - "CONV operator for the actual parameter. - - "Character-like types - TYPE c, "Text field with a generic length - TYPE clike, "Character-like (c, n, string, d, t and character-like flat structures) - TYPE csequence, "Text-like (c, string) - TYPE n, "Numeric text with generic length - TYPE x, "Byte field with generic length - TYPE xsequence, "Byte-like (x, xstring) - - "Numeric types - TYPE decfloat, "decfloat16, decfloat34 - TYPE numeric, "Numeric ((b, s), i, int8, p, decfloat16, decfloat34, f) -

TYPE p, "Packed number (generic length and number of decimal places) - - "Internal table types - TYPE ANY TABLE, "Internal table with any table type - TYPE HASHED TABLE, - TYPE INDEX TABLE, - TYPE SORTED TABLE, - TYPE STANDARD TABLE, - TYPE table, "Standard table - - "Other types - TYPE simple, "Elementary data type including enumerated types and - "structured types with exclusively character-like flat components - TYPE REF TO object. "object can only be specified after REF TO; can point to any object - -"Data objects to work with -DATA: BEGIN OF s, - c3 TYPE c LENGTH 3, - c10 TYPE c LENGTH 10, - n4 TYPE n LENGTH 4, - str TYPE string, - time TYPE t, - date TYPE d, - dec16 TYPE decfloat16, - dec34 TYPE decfloat34, - int TYPE i, - pl4d2 TYPE p LENGTH 4 DECIMALS 2, - tab_std TYPE STANDARD TABLE OF string WITH EMPTY KEY, - tab_so TYPE SORTED TABLE OF string WITH NON-UNIQUE KEY table_line, - tab_ha TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line, - xl1 TYPE x LENGTH 1, - xstr TYPE xstring, - structure TYPE zdemo_abap_carr, "character-like flat structure - oref TYPE REF TO object, - END OF s. - -"The following static ASSIGN statements demonstrate various assignments -"Note: -"- The statements commented out show impossible assignments. -"- If a static assignment is not successful, sy-subrc is not set and no -" memory area is assigned. Dynamic assignments, however, set the value. - -"----- Any data type ----- -ASSIGN s-c3 TO . -ASSIGN s-time TO . -ASSIGN s-tab_std TO . -ASSIGN s-xstr TO . -ASSIGN s-pl4d2 TO . -ASSIGN s-date TO . -ASSIGN s TO . - -"----- Character-like types ----- -ASSIGN s-c3 TO . -ASSIGN s-c10 TO . -"ASSIGN s-str TO . - -ASSIGN s-c10 TO . -ASSIGN s-str TO . -ASSIGN s-n4 TO . -ASSIGN s-date TO . -ASSIGN s-time TO . -ASSIGN s-structure TO . - -ASSIGN s-c10 TO . -ASSIGN s-str TO . -"ASSIGN s-n4 TO . - -ASSIGN s-n4 TO . -"ASSIGN s-int TO . -"ASSIGN s-time TO . - -ASSIGN s-xl1 TO . -"ASSIGN s-xstr TO . - -ASSIGN s-xl1 TO . -ASSIGN s-xstr TO . - -"----- Numeric types ----- -ASSIGN s-dec16 TO . -ASSIGN s-dec34 TO . -ASSIGN s-int TO . -ASSIGN s-pl4d2 TO . -"ASSIGN s-n4 TO . - -ASSIGN s-dec16 TO . -ASSIGN s-dec34 TO . - -ASSIGN s-pl4d2 TO

. -"ASSIGN s-dec34 TO

. - -"----- Internal table types ----- -ASSIGN s-tab_std TO . -ASSIGN s-tab_so TO . -ASSIGN s-tab_ha TO . - -ASSIGN s-tab_std TO . -ASSIGN s-tab_so TO . -"ASSIGN s-tab_ha TO . - -"ASSIGN s-tab_std TO . -ASSIGN s-tab_so TO . -"ASSIGN s-tab_ha TO . - -ASSIGN s-tab_std TO . -ASSIGN s-tab_std TO

. -"ASSIGN s-tab_so TO . -"ASSIGN s-tab_so TO
. -"ASSIGN s-tab_ha TO . -"ASSIGN s-tab_ha TO
. - -"ASSIGN s-tab_std TO . -"ASSIGN s-tab_so TO . -ASSIGN s-tab_ha TO . - -"----- Other types ----- -ASSIGN s-c10 TO . -ASSIGN s-str TO . -ASSIGN s-dec34 TO . -ASSIGN s-date TO . -ASSIGN s-structure TO . -ASSIGN s-xl1 TO . -"ASSIGN s-tab_ha TO . - -s-oref = NEW zcl_demo_abap_objects( ). -ASSIGN s-oref TO . -"Accessing class attributes using casting -DATA(publ_str) = CAST zcl_demo_abap_objects( )->public_string. -CAST zcl_demo_abap_objects( )->another_string = `ABAP`. -``` - -

⬆️ back to top

- -## Data Objects - -### Declaring Data Objects - -The [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) statement declares a data object of any data type. The declaration of a data object is similar to that of a data type, with only slight differences in terms of the number of possible additions, and follows this syntax pattern: -`DATA dobj TYPE abap_type [LENGTH len] [DECIMALS dec] [VALUE val] [READ-ONLY].` - -Note that `READ-ONLY` can only be used for class attributes. -The data type of a data object is always defined uniquely and cannot be changed at runtime of a program. - -Data objects with elementary types: -```abap -"The elementary, built-in data types can be used as shown for data type declarations. -"Chained statements are also possible with DATA. -"Note that not all types as shown above are used here. -DATA: do_i TYPE i, - do_c_l5 TYPE c LENGTH 5, - do_p_l3_d2 TYPE p LENGTH 3 DECIMALS 2, - do_decfl16 TYPE decfloat16, - do_str TYPE string, - "Specifying the length in parantheses instead of using the - "LENGTH addition is not recommended - do_ctwo(2) TYPE c. - -"Referring to locally declared data types -TYPES te_string TYPE string. -DATA do_another_str TYPE te_string. - -"Referring to other data objects -DATA do_like_dobj LIKE do_i. - -"If the length is not specified explicitly for the ABAP types c, n, p, and x, -"the standard length is defined implicitly. Check the F2 information. -DATA do_c_std TYPE c. -DATA do_p_std TYPE p. - -"If neither TYPE nor LIKE is specified, a data object with the bound -"data type 'c LENGTH 1' is created. -DATA do_c. - -"VALUE addition -"Start values can be set for the data objects when they are declared. -"Without the addition VALUE, data objects are filled with their type-specific initial values. -"The start value can either be specified as a literal or as a predefined constant. -"Note: The VALUE addition is not to be confused with the VALUE operator that can be used to -"construct the content of complex data objects as shown below. -DATA do_c_l2 TYPE c LENGTH 2 VALUE 'hi'. -DATA do_i_val TYPE i VALUE 123. -DATA do_like_val LIKE do_i VALUE 9. - -"Specifying a constant (data object that cannot be changed at runtime) after the VALUE addition -CONSTANTS con TYPE string VALUE `abcdef`. -DATA do_val_con TYPE string VALUE con. - -"VALUE IS INITIAL addition: Explicitly specifying the type-specific initial value -DATA do_i_init TYPE i VALUE IS INITIAL. -DATA do_i_like_init LIKE do_i VALUE IS INITIAL. - -"Data objects can also be created in the declaration part of classes and interfaces. -"There you can use the READ-ONLY addition for data object declarations in the public visibility section. -"In doing so, an attribute declared using CLASS-DATA or DATA can be read from outside of the class but -"can only be changed using methods of the class or its subclasses. -"The following attribute is taken from a executable example. It shows a read access in a control -"structure. If you wanted to assign a new value to the attribute outside of the class in which it is -"declared, a syntax error would be displayed. -"Note that when you are in the class itself, there is no need to specify the class name. -"read_only_attribute = ... would be sufficient. And changing the value would be possible within -"the class, too. -"Declaration in the example: -"CLASS-DATA: read_only_attribute TYPE string VALUE `Hallo` READ-ONLY. -IF zcl_some_class=>read_only_attribute = `abc`. - ... -ELSE. - ... -ENDIF. -``` - -Structures and internal tables as examples for complex types: - -```abap -"Find more examples in the ABAP cheat sheets on structures and internal tables. - -"Creating a structure with DATA and providing start values with the VALUE addition. -"If not specified, then the components have their type-specific initial value. -DATA: BEGIN OF a_structure, - comp1 TYPE i VALUE 1, - comp2 TYPE string VALUE `hi`, - comp3 TYPE string, - END OF a_structure. - -"Creating a structure based on a global type. In this case, it is a DDIC database -"table whose line type is used. You can also use a CDS view or a dedicated structured type -"from the DDIC, for example. -DATA struc_ddic_tab TYPE zdemo_abap_carr. - -"Creating a structure as a constant. Providing values is mandatory. -CONSTANTS: BEGIN OF con_struc, - comp1 TYPE i VALUE 1, - comp2 TYPE string VALUE `hallo`, - comp3 TYPE string VALUE `salut`, - END OF con_struc. - -"Using the constant as start value for a structure declaration. -DATA struc_w_val LIKE con_struc VALUE con_struc. - -"Declaring a structure and explicitly specifying the type-specific -"initial values of the structure components as start values. -DATA struc_init_val LIKE con_struc VALUE IS INITIAL. - -"Creating internal tables ... -"Based on a globally available DDIC database table whose line type is used -DATA itab_ddic_tab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. -"Based on an elementary type -DATA itab_tab_i TYPE TABLE OF i. -"The table type is declared in a global interface -DATA itab_tab_type_from_itf TYPE zdemo_abap_get_data_itf=>carr_tab. -"Based on globally available DDIC internal table type; explicitly specifying as initial -DATA itab_ddic_tab_type TYPE string_table VALUE IS INITIAL. -"Based on locally available structured data object -DATA itab_like_struc LIKE TABLE OF struc_w_val WITH EMPTY KEY. -"Based on locally available internal table -DATA itab_like_another_itab LIKE itab_tab_i. - -"Creating an internal table type locally -TYPES tt_ddic_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. -"... and an internal table based on it. -DATA itab_w_itab_type TYPE tt_ddic_tab. - -"Creating a structure based on the line of an internal table (type) -DATA struc_from_itab_type TYPE LINE OF tt_ddic_tab. -DATA struc_like_line LIKE LINE OF itab_ddic_tab. -``` - - -> **💡 Note**
-> The above data objects are declared by assigning a dedicated name. These data objects can be addressed by that name. This is not true for [anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm), which can only be addressed through reference variables. This is covered [below](#assigning-references-to-data-reference-variables). - - -Data reference variables: - -```abap -"Declaring data reference variables types with static types -DATA dref_int TYPE REF TO i. -DATA dref_str TYPE REF TO string. -DATA dref_ddic_tab TYPE REF TO zdemo_abap_carr. -"Using generic type data as static type -DATA dref_data TYPE REF TO data. - -"Referring to an existing reference type -TYPES tr_int TYPE REF TO i. -DATA dref_tr_int TYPE tr_int. - -"Creating a data reference variable based on a data reference variable -DATA dref_like LIKE dref_int. - -"Creating a data object for the LIKE REF TO addition -DATA do_some_string TYPE string. - -"Reference type is created whose static type is inherited from the data type of the specified data object -DATA dref_like_ref_str LIKE REF TO do_some_string. - -"Reference tables -DATA dref_tab_i TYPE TABLE OF REF TO i. -DATA dref_tab_str LIKE TABLE OF REF TO do_some_string. -``` - -

⬆️ back to top

- -### Assigning Values to Data Objects - -An assignment passes the contents of a source to a target data object. - -> **💡 Note**
-> - There are conversion rules when assigning a source to a target data object that have different types. For more information, see the topic [Assignment and Conversion Rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rules.htm) in the ABAP Keyword Documentation, especially for complex types, since elementary types are usually demonstrated in the cheat sheet. -> - There are many ways to assigning values to data objects in ABAP. Assignments with the assignment operator `=` are mostly used here. -> - In older ABAP code, you may see `MOVE ... TO ...` statements for value assignments. These statements are obsolete. They are not to be confused with `MOVE-CORRESPONDING` statements for complex types. These are not obsolete. - -The following code snippet shows several ways to assign values to data objects. - -```abap -"As mentioned, a start value can be directly assigned when declaring a data object. -DATA some_int TYPE i VALUE 123. - -"Assignment using the assignement operator = -"The source of the assigment on the right side (also known as general expressions posisiton) -"can be specified with many things. - -"Single data object as source of the assignment -"In the following cases, the literal and data object have the exact type as the data -"object on the left side. -some_int = 456. -DATA num TYPE i. -num = some_int. - -DATA str_a1 TYPE string VALUE `hallo`. -DATA str_a2 TYPE string. -str_a2 = str_a1. - -"Functional method as source of the assignment -"In the following example, the method get_next of the class cl_abap_random_int -"returns an integer. Check the F2 information for get_next (return value of type i). -"A random integer that is in the specified value range is assigned to the data object -"on the left side. -num = cl_abap_random_int=>create( - seed = cl_abap_random=>seed( ) min = 1 - max = 10 )->get_next( ). - -"Built-in functions as source of the assignment -"There are plenty of functions available. Check the ABAP Keyword Documentation. - -"Built-in numeric function -"The following built-in function calculates 2 to the power of 4. The -"result is assigned to the data object on the left side. -num = ipow( base = 2 exp = 4 ). - -"Built-in string function -"The following function transforms the specified data object to upper case letters. The -"result is assigned to the data object on the left side. -str_a1 = to_upper( str_a2 ). - -"Constructor expressions as source of the assignment -"There are various options and expressions available (with many additions). Check the -"ABAP Keyword Documentation and the ABAP cheat sheet about constructor expressions. -"Here, taking the VALUE operator as an example. This operator is very handy especially -"for complex types. - -"Creating a structure -DATA some_struc TYPE zdemo_abap_carr. - -"Assignment using the VALUE operator -"Note the # character that stands for the type. Here, the structure type can be derived -"from the context. Hence, the explicit name can but need not be specified. -some_struc = VALUE #( carrid = 'XY' carrname = 'XY Airways' ). - -"Creating an internal table and assigning values -"Note that components that are not specified and assigned a value retain their -"type-specific initial value. -DATA some_itab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. -some_itab = VALUE #( ( carrid = 'XY' carrname = 'XY Airways' ) - ( carrid = 'AB' carrname = 'ABAP Airlines' ) ) . - -"Table expressions as source of the assignment -"A structure is assigned an internal table line -some_struc = some_itab[ 2 ]. - -"Calculation expressions as source of the assignment -"Arithmetic expression -num = 1 + 2. - -"A calculation assignment as follows -num += 1. -"is the short form of -num = num + 1. -"Syntax options: +=, -=, *= and /=, also &&= for the && operator - -"String expressions as source of the assignment -str_a2 = str_a1 && ` blabla`. "Strings are appended using the && operator -str_a2 = |{ str_a1 } some more bla.|. "String templates. Note: Data objects are specified - "in curly brackets. The content is converted to type string - "Note that it must be convertible to type string. - -"An elementary data object is assigned a component of a specific table line -"using a table expression. -"Note: In the following case, the types of source and target are not the same -"(type c versus type string). As shown further down, such an assignment can lead to -"unexpected or undesired results. Type-dependent conversions are made in accordance -"with the conversion rules. -str_a2 = some_itab[ 2 ]-carrname. -``` - -

⬆️ back to top

- -### Creating Data Objects Using Inline Declaration - -An [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm) is made using the declaration operator [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm). It can be specified in any designated [declaration position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_position_glosry.htm). The result of the declaration is used in the current operand position, is statically visible from the current position, and is valid in the current context. - -> **💡 Note**
-> - In an assignment, if the data object is declared inline on the left side, there are many options for what can be placed on the right side as shown in the previous section. The data type of the variable is determined by the operand type. It must be possible to derive this type completely statically. -> - For more information about the possible declaration positions, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_positions.htm). -> - You can use the [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm), as shown below. -> - [Programming guidelines for inline declarations (F1 documentation for Standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendeclaration_inline_guidl.htm) - - -```abap -"Data object declarations and assignements as shown above. -DATA str_b1 TYPE string VALUE `abc`. - -DATA str_b2 TYPE string. -str_b2 = `def`. - -"Using a declaration expression with the declaration operator DATA, a data object can be -"declared inline. -"The data type of the declared variable is determined by the right side. -"In doing so, a data object is assigned a value in one go. -"In the following case, it is a string literal with backquotes on the right side. -"The data type is derived and, hence, the data object is of type string. -DATA(str_b3) = `ghi`. - -"In the following case, it is a text field literal with quotes. Type c is derived. -"The length is derived from the number of characters. -DATA(c_l3) = 'jkl'. "type c length 3 -DATA(c_l4) = 'mnop'. "type c length 4 -"Note the type conversion implications when making an assignment with these two data objects. -c_l3 = c_l4. "c_l3: 'mno' - -"Structures and internal tables -"In declaration expressions, structures and internal tables can be declared inline and filled with, -"for example, the help of the VALUE operator. - -"Structured data type -TYPES: BEGIN OF ts_struc, - comp1 TYPE i, - comp2 TYPE string, - END OF ts_struc. - -"In the following examples, structures are created. The structured data type is derived from the -"type specified before the parentheses. -DATA(struc_b1) = VALUE ts_struc( comp1 = 1 comp2 = `A` ). -"No components specified and values assigned means an initial structure. This syntax is also possible -"for declaring data objects with elementary types and explicitly specifiying initial values, but only -"for initial values. See the CONV operator. -DATA(struc_b2) = VALUE ts_struc( ). -DATA(elem_init) = VALUE i( ). -"Note that components that are not specified and assigned a value remain initial. -DATA(struc_b3) = VALUE zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ). -"An entire structure is assigned. -DATA(struc_b4) = struc_b1. - -"Note: When the structure has already been declared, and you want to assign values, you can use -"the VALUE operator followed by the # character instead of the explicit type name. -"In that case, it is possible to derive the type from the context. -struc_b4 = VALUE #( comp1 = 2 comp2 = `b` ). - -"Internal tables -"The internal table type is specified before the parentheses after the VALUE operator. -"The following example uses a table type that is globally available in the DDIC. -DATA(itab_b1) = VALUE string_table( ( `a` ) - ( `b` ) - ( `c` ) ). - -"Using a local internal table type -TYPES tt_b1 TYPE TABLE OF ts_struc WITH EMPTY KEY. -DATA(itab_b2) = VALUE tt_b1( ( comp1 = 1 comp2 = `a` ) - ( comp1 = 2 comp2 = `b` ) - ( comp1 = 3 comp2 = `c` ) ). - -"In the context of other ABAP statements such as LOOP, READ TABLE or ABAP SQL -"SELECT statements, inline declarations are useful for creating target variables with -"appropriate data types in place. This includes data reference variables and field -"symbols. Field symbols are not covered below. - -"A work area/structure to hold the current internal table line is created inline. -LOOP AT itab_b2 INTO DATA(wa_b1). - wa_b1-comp1 = 12345. - ... -ENDLOOP. - -"Using the REFERENCE addition, a data reference variable can be created inline. -LOOP AT itab_b2 REFERENCE INTO DATA(wa_ref_b1). - wa_ref_b1->comp1 = 67890. - ... -ENDLOOP. - -"A structure to hold the internal table line read is created inline. -READ TABLE itab_b2 INTO DATA(wa_b2) INDEX 2. -"Data reference variable -READ TABLE itab_b2 REFERENCE INTO DATA(wa_ref_b2) INDEX 2. - -"ABAP SQL statements -"A structure as target data object is created inline. -SELECT SINGLE * FROM zdemo_abap_carr INTO @DATA(struc_b5). -"NEW addition of the INTO clause creates a data reference variable -SELECT SINGLE * FROM zdemo_abap_carr INTO NEW @DATA(struc_ref). - -"Internal table as target data object is created inline. -SELECT * FROM zdemo_abap_carr INTO TABLE @DATA(itab_b3). -SELECT * FROM zdemo_abap_carr INTO TABLE NEW @DATA(itab_ref). -``` - -

⬆️ back to top

- -### Assigning References to Data Reference Variables - -- As with other data objects and types, there are [special assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_references.htm) for [data reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm). See the ABAP Keyword Documentation. -- An initial reference variable contains the [null reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_reference_glosry.htm), which does not point to any objects. This means that it has neither a data type nor a class as a [dynamic type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm). -- The concepts of [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm) and [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm) enter the picture here. See the following code snippet. - -```abap -"Declaring data reference variables with static types -"At this stage, initial reference variables contain null references. -DATA dref_1_i TYPE REF TO i. -DATA dref_2_str TYPE REF TO string. -"Generic type as static type -DATA dref_3_data TYPE REF TO data. - -"References in data reference variables can point to existing data objects. -"For assigning the reference, you can use the REF operator. -"There is also an ABAP statement available doing the same: GET REFERENCE. -"It should not be used anymore, especially in ABAP for Cloud development. - -"Creating data objects to refer to and providing a start value -DATA do_number TYPE i VALUE 987. -DATA do_string TYPE string VALUE `abc`. - -"After the assignment, the data reference variable points to the values. -"The data type is derived (dynamic type). -dref_1_i = REF #( do_number ). "Dynamic type is the same as the static type in this case -dref_2_str = REF #( do_string ). "Dynamic type is the same as the static type in this case -"Dynamic types of the followig examples are more specific than static type, -"which is a generic type in this case. -dref_3_data = REF #( do_number ). -dref_3_data = REF #( do_string ). - -"Note: Table expressions can be also specified within the parentheses. - -"Inline declarations are also possible to create data reference variables -"and assigning values in one go. -DATA(dref_4_data) = dref_3_data. -DATA(dref_5_str) = REF #( `hi` ). -DATA(dref_6_i) = REF #( do_number ). - -"Assignments between two data reference variables mean that references are copied. -"The concepts of upcast and downcast enter the picture here. -"Two different assignment operators are used, as well as the casting operator CAST. - -"Upcast is possible for elementary data types -"- The static type of the target variable is more general or identical to the static type of the source variable. -"- Assignment operator used: = -"- Note that the operators for downcasts can also be used explicitly here, but it is usually not needed. -"- In this example, elementary data types are covered. An upcast works ... -" - if the data types have identical type properties (i.e. the built-in types match as well as length and decimal places). -" - the static type of the source variable is completely typed, and the static type of the target variable is generic. - -"The following upcasts work. Both point to data objects of type i or string. -dref_1_i = dref_6_i. -"The source on the right side is completely typed (type i), -"the target on the left side is a generic type (type data). -dref_3_data = dref_1_i. - -"Downcasts -"- The static type of the target variable is more specific than the static type of the source variable. -"- The assignability is not checked until runtime. -"- Must always be performed explicitly using the casting operator ?= or the more modern casting operator CAST. - -"The following example would result in a syntax error due to type incompatibility. -"dref_1_i = dref_3_data. - -"In the following example, the source has a generic static type (data). The target type -"has a more specific type (type i). -"To suppress the syntax error, the CAST operator is needed. -"Note: -"- The assignability is still not checked. This is done at runtime. -" In this example, it works since the dynamic type of the source is also of type i. -"- An advantage of the CAST operator compared to ?= is that the operator enables downcasts in operand positions, -" which helps reduce helper variables. -dref_1_i = CAST #( dref_3_data ). - -"If not caught, the following would result in a runtime error. -"dref_3_data points to a data object of type i, the static type is dref_2_str is string. -"So, the downcast does not work. -TRY. - dref_2_str = CAST #( dref_3_data ). - CATCH cx_sy_move_cast_error INTO DATA(e). -ENDTRY. - -"Old syntax using the ?= operator -dref_1_i ?= dref_3_data. - -"For upcasts, the operators can be used, too, but they are usually not necessary. -"So, an assignment as follows is possible but not needed. Only using = is sufficient. -dref_1_i = CAST #( dref_6_i ). -``` - -

⬆️ back to top

- -### Creating Anonymous Data Objects - -[Anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) are a topic related to data reference variables. -These data objects are [unnamed data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunnamed_data_object_glosry.htm). -Most of the data objects in the snippets above are named data objects (excluding the data reference variables), meaning that they can be addressed by a specific name. Unnamed data objects are literals and anonymous data objects. Anonymous data objects can be addressed using data reference variables. -Unlike data objects created with the `DATA` statement, anonymous data objects are created at runtime. Data objects declared with `DATA` are created when the program is loaded. - -There are several ways to create anonymous data objects: -- [`CREATE DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_data.htm) statements -- Using the instance operator [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm) -- Addition `NEW` of the [`INTO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm) clause in ABAP SQL `SELECT` statements - -```abap -"CREATE DATA statements -"Note that there are many additions available. The examples show a selection. - -"Creating an anonymous data object with an implicit type. -"If neither of the additions TYPE or LIKE are specified, the data reference variable -"must be completely typed. -DATA dref_7_str TYPE REF TO string. -CREATE DATA dref_7_str. - -"Note: If you want to assign a value to the data object, this can't be done directly. -"The data reference variable must be dereferenced first using the dereferencing operator. -dref_7_str->* = `hi`. - -"Creating an anonymous data object with an explicitly specified data type -DATA dref_8_data TYPE REF TO data. -CREATE DATA dref_8_data TYPE p LENGTH 8 DECIMALS 3. -dref_8_data->* = 1 / 3. - -"Creating a named data object -DATA it TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. - -"Creating an anomyous internal table. -"Using the LIKE addition to refer to an existing internal table -CREATE DATA dref_8_data LIKE it. - -"Using the anonymous data object as target in the INTO clause of a SELECT statement -SELECT * - FROM zdemo_abap_carr - INTO TABLE @dref_8_data->*. - -"Creating an anonymous hashed table by specifying the entire table type -CREATE DATA dref_8_data TYPE HASHED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid. - -"Using the anonymous data object as target in the INTO clause of a SELECT statement -SELECT * - FROM zdemo_abap_carr - INTO TABLE @dref_8_data->*. - -"Creating an anonymous structure -CREATE DATA dref_8_data TYPE zdemo_abap_fli. - -"Using the anonymous data object as target in the INTO clause of a SELECT statement -SELECT SINGLE * - FROM zdemo_abap_fli - INTO @dref_8_data->*. - -"NEW operator -"- Works like CREATE DATA dref TYPE type statements and can be used in general expression positions. -"- Allows to assign values to the new anonymous data objects in parentheses - -"Creating data reference variables -DATA: dref_9_data TYPE REF TO data, - dref_10_i TYPE REF TO i. - -"Assining a value to an anonymous data object of the type i -dref_9_data = NEW i( 555 ). - -"The # character can be used instead of the complete type spefication -"when the type can be derived from the context. -dref_10_i = NEW #( 653 ). - -"Inline declarations are handy. -"Creating a suitable anonymous data object in place. Here, the type must be specificed explicitly. -DATA(dref_11_i) = NEW i( 32 ). - -"Creating an anonymous structure -DATA(dref_12_ddic_tab) = NEW zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ). - -"The # character can be omitted when they type can be derived. -DATA dref_13_ddic_tab TYPE REF TO zdemo_abap_carr. -dref_13_ddic_tab = NEW #( carrid = 'AB' carrname = 'AB Airlines' ). - -"ABAP SQL SELECT statement -"Using the NEW addition in the INTO clause, an anonymous data object can be created in place. -SELECT * - FROM zdemo_abap_carr - INTO TABLE NEW @DATA(dref_14_inline). -``` - -

⬆️ back to top

- -### Constants and Immutable Variables - -[Constants](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstant_glosry.htm) are [named data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm) whose value cannot be changed at runtime. You declare them with the [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) statement. Unlike the `DATA` statement, a start value must be specified with the `VALUE` addition. - -[Immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm) can also be declared inline with the [declaration operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_operator_glosry.htm) - [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm). - -```abap -"As mentioned above, constants cannot be changed at runtime. -CONSTANTS con_str TYPE string VALUE `hallo`. - -"Constants as start values for dobj declarations following value -CONSTANTS con_underscores TYPE string VALUE `__________`. -DATA str_w_con_as_start_value TYPE string VALUE con_underscores. - -"Immutable variables -FINAL(do_final_inl) = 1. -DATA(do_data_inl) = 1 + do_final_inl. -"not possible -"do_final_inl = 2. - -SELECT * FROM zdemo_abap_carr INTO TABLE @DATA(itab_data_inl). - -DATA itab_like_inline LIKE itab_data_inl. - -"Using an inline declaration as target of a LOOP statement -"A value is assigned multiple times, but it cannot be changed in any other write positions. -LOOP AT itab_data_inl INTO FINAL(wa_final). - "The following is not possible - "wa_final-carrid = 'd'. - "only read access - APPEND wa_final TO itab_like_inline. -ENDLOOP. - -"SELECT statement with a an immutable target table declared inline -SELECT * FROM zdemo_abap_carr INTO TABLE @FINAL(itab_final_inl). -``` - -

⬆️ back to top

- -## Type Conversion -A value assignment means that the value of a data object is transferred to a target data object. If the data types of the source and target are compatible, the content is copied unchanged. If they are incompatible and a suitable [conversion rule](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rule_glosry.htm) exists, the content is converted. -The following cases must be distinguished with regard to the data type: -- The source and target data types are compatible, i.e. all technical type properties match. The content is transferred from the source to the target without being converted. -- The source and target data types are incompatible, but can be converted. The content of the source is converted according to the conversion rules and then transferred to the target. Two data types are convertible if a conversion rule exists for them. An exception is raised if the content of the source cannot be handled according to the conversion rules. -- If the data objects are neither compatible nor convertible, no assignment can take place. If the syntax check detects this state, a syntax error is raised, otherwise an [uncatchable exception](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuncatchable_exception_glosry.htm) is raised when the program is executed. - -See the conversion rules for the different data types here: [Assignment and Conversion Rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rules.htm) - -> **💡 Note**
-> - The [operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_glosry.htm) of many ABAP statements are assigned internally according to the assignment rules. -> - Typically, assignements are made using the assignment operator `=`. If necessary and applicable, the type is converted implicitly. However, you can also use the conversion operator [`CONV`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_conv.htm) to convert types explicitly. -> - For [lossless assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlossless_assignment_glosry.htm), the lossless operator [`EXACT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_exact.htm) can be used to perform checks before the conversion is performed to ensure that only valid values are assigned and that no values are lost in assignments. -> - In general, no checks are performed on assignments between compatible data objects. If a data object already contains an invalid value, for example, an invalid date or time in a date or time field, it is passed a valid value when the assignment is made to a compatible data object. -> - The `applies_to_data` method of the [RTTI](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm) class `cl_abap_datadescr` can be used to check type compatibility. See the executable example. - - -```abap -"Implicit conversions of the types c and string -DATA do_1_str TYPE string VALUE `abcedf`. -DATA do_2_c3 TYPE c LENGTH 3. -do_2_c3 = do_1_str. -"Result: do_2_c3: 'abc' - -"Implicit conversions of the types i and decfloat34 -DATA do_4_i TYPE i. -DATA do_5_dcfl34 TYPE decfloat34 VALUE '4.56'. -do_4_i = do_5_dcfl34. -"Result: do_4_i: 5 - -"Explicitly converting decfloat34 to i -DATA do_6_dcfl34 TYPE decfloat34 VALUE '2.78'. -DATA(do_7_i) = CONV i( do_6_dcfl34 ). -"Result: do_7_i: 3 - -"Note conversions according to the rules, e.g. from -"type i to string -DATA(i2str) = CONV string( -10 ). -"Result: i2str: `10-` -``` - -

⬆️ back to top

- -## Terms Related to Data Types and Objects in a Nutshell - -```abap -"Standalone and bound data types -"Standalone: Data type that is defined using the statement TYPES in an -" ABAP program, as a data type of the ABAP Dictionary or as -" an CDS entity. -"Bound: Data type that only exists as a property of a data object. - -"Standalone data type -TYPES te_a_c10 TYPE c LENGTH 10. - -"Bound data types -DATA do_a_c20 TYPE c LENGTH 20. -DATA do_b_like LIKE do_a_c20. -TYPES te_b_like LIKE do_a_c20. - -********************************************************************** - -"Complex and elementary data type/object -"Elementary: Data type of fixed or variable length that is neither -" structured, nor a table type or a reference type. -"Complex: Made up of other data types, for example structured data -" type/objects, a table type/internal tables - -"Elementary -DATA do_c_i TYPE i. - -"Complex -DATA: BEGIN OF struc_a, - comp1 TYPE i, - comp2 TYPE string, - comp3 TYPE zdemo_abap_carr, "structure - comp4 TYPE string_table, "internal table - comp5 TYPE REF TO i, "reference type - END OF struc_a. - -********************************************************************** - -"Complete and generic data types -"Complete: Non-generic data type -"Generic: -"- Data type that does not set all properties of a data object. -"- Can only be used for the typing of formal parameters and field symbols, -" except for data reference variables using the generic type 'data'. - -"Complete data type -DATA do_d_i TYPE i. - -"Field symbols typed with generic data types -"Note: A field symbol is a symbolic name for a data object to which actual -"memory can be assigned at runtime. A field symbol can be used as a placeholder -"for a data object at an operand position. For more information, see the ABAP -"Cheat Sheet on dynamic programming. Field symbols are used in this example -"to demonstrate generic types other than just data. -FIELD-SYMBOLS TYPE clike. -FIELD-SYMBOLS TYPE data. - -"Field symbols with generic data types can be assigned appropriate values -DATA do_e_c5 TYPE c LENGTH 5 VALUE 'abcde'. -DATA do_f_str TYPE string VALUE `Hallo, how are you?`. -ASSIGN do_e_c5 TO . -ASSIGN do_f_str TO . - -DATA(itab_a) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). -ASSIGN do_e_c5 TO . -ASSIGN do_f_str TO . -ASSIGN itab_a TO . - -********************************************************************** - -"Variable and constant data objects -"Variable: Named data object whose value can be changed during the runtime -" of an ABAP program. -"Constant: Named data object whose value cannot be changed at runtime. - -"Variable -DATA do_g_i TYPE i VALUE 123. -do_g_i = 456. - -CONSTANTS con_a_i TYPE i VALUE 789. -"Not changeable -"con_a_i = 321. - -********************************************************************** - -"Static and dynamic data objects -"Static: -"- Data object for which all attributes, including memory use, are specified -" statically by the data type. -"- Apart from reference variables, all static data objects are flat. -"Dynamic: -"- Data object for which all properties apart from the memory consumption are -" statically determined by the data type. -"- Dynamic data objects are strings and internal tables. They belong to the -" deep data objects. Structures that contain dynamic components are also -" dynamic data objects. - -"Static data object -DATA do_h_c5 TYPE c LENGTH 3. -"Dynamic data object -DATA do_i_str TYPE string. - -"Assignments -do_h_c5 = 'abc'. -do_h_c5 = 'defghi'. "only 'def' assigned -> length and memory use do not change - -"Memory consumption changes for dynamic data objects -do_i_str = `abc`. -do_i_str = `d`. -do_i_str = `efghijklmnopqrstuvwxyz`. - -********************************************************************** - -"Static type and dynamic type -"Both are data types of a reference variable (reference type) that determine -"the objects a reference variable can point to. -"Static type: For data reference variables, the static type is a data type -" that is always more general than or the same as the dynamic type. -"Dynamic type: For a reference variable, the dynamic type is always more special -" than or equal to the static type. - -"Static type -DATA dref_a_i TYPE REF TO i. "Static type is i -DATA dref_b_data TYPE REF TO data. "Static type can also be generic - -"Creating data objects to refer to -DATA do_j_i TYPE i VALUE 3. -DATA do_k_str TYPE string VALUE `hallo`. - -"Dynamic types -dref_a_i = REF #( do_j_i ). "Only type i possible; the dynamic type is the same - -"The dynamic type is more special than the static type (which is the generic -"type data in this case) -dref_b_data = REF #( do_j_i ). -dref_b_data = REF #( do_k_str ). -dref_b_data = REF #( dref_a_i ). - -********************************************************************** - -"Flat and deep data objects -"Flat: -"- Property of a data type, where the content of its data objects represents -" the actual work data. -"- All elementary data types except string and xstring are flat -"Deep: -"- Dynamic data objects and reference variables are deep, and they contain -" references that refer to the actual content. -"- The handling of references is implicit for dynamic data objects (strings -" and internal tables), and explicit for reference variables. -"- Structures that do not contain any deep components are flat structures. -" Structures that contain at least one deep component are deep structures. - -"Flat elementary data object -DATA do_l_i TYPE i. - -"Flat structure -DATA: BEGIN OF struc_b_flat, - comp1 TYPE i, - comp2 TYPE c LENGTH 3, - END OF struc_b_flat. - -"Deep elementary data object -DATA do_m_str TYPE string. - -"Deep structure -DATA: BEGIN OF struc_c_deep, - comp1 TYPE i, - comp2 TYPE c LENGTH 3, - comp3 TYPE string, "string as deep data object - comp4 TYPE string_table, "internal table as deep data object - END OF struc_c_deep. - -********************************************************************** - -"Named and unnamed data object -"Named: Data object that can be identified via a name. -"Unnamed: Data object that cannot be addressed by a name. Unnamed data -" objects are literals and anonymous data objects. - -"Named data objects -DATA do_n_i TYPE i. -CONSTANTS con_b_str TYPE string VALUE `hi`. - -"Unnamed data objects -"Literal that is output. It cannot be addressed via a dedicated name. -out->write( `I'm a literal...` ). - -"Anonymous data object created using the NEW operator -"Can be addressed using reference variables or field symbols. - -DATA(dref_c_str) = NEW string( `hi` ). - -"Anonymous data object created inline using the NEW addition to the INTO -"clause of a SELECT statement -SELECT * - FROM zdemo_abap_carr - INTO TABLE NEW @DATA(dref_d_tab) - UP TO 3 ROWS. - -********************************************************************** - -"Compatibility, convertibility and conversion regarding source and -"target data objects -"1. Source and target are compatible, all technical type properties -" match -DATA some_dobj TYPE c LENGTH 1 VALUE 'A'. -DATA flag TYPE abap_bool VALUE 'X'. - -"Assignment of compatible types; content transferred without -"conversion -some_dobj = flag. - -"2. Source and target are not compatible but can be converted. -" Content of source is converted according to conversion rules -" and then transferred to the target. Two data types are -" convertible if a conversion rule exists for them. -DATA another_char TYPE c LENGTH 3 VALUE 'abc'. -DATA some_str TYPE string VALUE `defghij`. - -another_char = some_str. - -"3. Data objects are neither compatible nor convertible. No -" assignment possible. If recognized by the syntax check, a -" syntax error is raised, otherwise an uncatchable exception -" is raised when the program is executed. -DATA some_number TYPE i VALUE 123. -DATA itab_str TYPE string_table. - -"Type conversion not possible -"itab_str = some_number. -"some_number = itab_str. -``` - -

⬆️ back to top

- -## Notes on the Declaration Context - -The declaration context of data types (and objects) determines the validity and visibility. - -- Program-local data types with `TYPES` statements - - Local declarations in procedures - - For example, methods. The local data and types can only be addressed within the method itself. - - Class and interface attributes - - Data types and objects can be declared in the declaration part of classes and interfaces. In classes, the visibility sections, as the name implies, determine how the attributes are visible. For example, attributes declared in the `PUBLIC SECTION` are visible globally. - - Note the difference between [static](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_attribute_glosry.htm) and [instance attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_attribute_glosry.htm). Instance attributes of classes are bound to the lifetime of objects. They are created when an object is instantiated. -- Program-independent data types - - Declarations in the ABAP Dictionary, which is a special storage for the declarations of data types that are visible in all repository objects, provided that the [package](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpackage_glosry.htm) check allows this. - - The data types of the ABAP Dictionary are not declared with the `TYPES` statement, but using ADT tools (and/or SAP GUI tools in systems where SAP GUI is available). - - The DDIC has many more [built-in types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_ddic_type_glosry.htm) than ABAP. These types have other names. They cannot be used in ABAP programs. - - The DDIC provides many options for defining types, including elementary data types (defined as data elements), reference types, complex types such as structured types and table types. Note that the name of a database table or a view can be used in type declarations to address the line type of these repository objects (for example, a structure: `DATA a TYPE some_db_table.`). - - Note the following trap: Local declarations hide global declarations of the same name. - -

⬆️ back to top

- -## Excursions -### Enumerated Types and Objects -- ABAP supports the concept of enumerations. -- Enumerations are a mixture of types and constants. -- An [enumerated type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenum_type_glosry.htm) specifies a value set in addition to the actual type properties. -- [Enumerated objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_object_glosry.htm) - data objects with an enumerated type - are mainly used to check allowed values. This usually restricts the actual parameters passed to methods to the enumerated values defined in the class. [Enumerated variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_variable_glosry.htm) are variable enumerated objects. They can only contain the associated enumerated values. - -Syntax: - -```abap -"The definition of an enumerated type in ABAP declares its enumerated constants (these are special enumerated objects). -"a) In the case below, no explicit base type is specified. Then, the standard base type of the constants is i. The -" enumerated values are counted up starting with 0 (a -> 0, b -> 1 ...). - -TYPES: BEGIN OF ENUM t_enum, - a, - b, - c, - d, - END OF ENUM t_enum. - -"b) Explicit base type is specified and start values provided using the VALUE addition -" Note that one value must be initial. - -TYPES: basetype TYPE c LENGTH 2, - BEGIN OF ENUM t_enum_base BASE TYPE basetype, - e VALUE IS INITIAL, - f VALUE 'u', - g VALUE 'v', - h VALUE 'wx', - i VALUE 'yz', - END OF ENUM t_enum_base. - -"c) Optionally an enumerated structure can be declared in the context of the type declaration. -" A component of an enumerated structure: An enumerated constant that exists as a component -" of a constant structure, not as a single data object. - -TYPES: BEGIN OF ENUM t_enum_struc STRUCTURE en_struc BASE TYPE basetype, - j VALUE IS INITIAL, - k VALUE 'hi', - l VALUE 'ab', - m VALUE 'ap', - END OF ENUM t_enum_struc STRUCTURE en_struc. -``` - -Enumerated variables can be declared by referring to the enumerated type. -They can only be assigned the enumerated values defined there that exist as the content of enumerated constants or components of an enumerated structure. - -```abap -DATA dobj_enum TYPE enum_type. - -dobj_enum = a. -``` - -Find more information on enumerated types in the (commented code of the) cheat sheet example and [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_types_usage.htm). - -

⬆️ back to top

- -### Getting Type Information and Creating Types at Runtime -Using [Runtime Type Identification (RTTI)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm "Glossary Entry"), you can get type information on data objects, data types or [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm "Glossary Entry") at runtime ([Runtime Type Identification (RTTI)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm "Glossary Entry")). -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 data 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. - -Find more information in the [cheat sheet about dynamic programming](06_Dynamic_Programming.md#runtime-type-services-rtts). - -### Ranges Tables - -- Internal tables that have the predefined columns `SIGN`, `OPTION`, `LOW`, and `HIGH` -- Declared with the `TYPE RANGE OF` addition in `DATA` and `TYPES` statements -- Used to store range conditions that can be evaluated in expressions using the `IN` operator (each row in the table represents a separate comparison) - -```abap -"Populating an integer table with values from 1 to 20 -TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY. -DATA(inttab) = VALUE int_tab_type( FOR x = 1 WHILE x <= 20 ( x ) ). - -"Declaring a ranges table -DATA rangestab TYPE RANGE OF i. - -"Populating a ranges table using VALUE -rangestab = VALUE #( sign = 'I' - option = 'BT' ( low = 1 high = 3 ) - ( low = 6 high = 8 ) - ( low = 12 high = 15 ) - option = 'GE' ( low = 18 ) ). - -"Using a SELECT statement and the IN addition to retrieve internal table -"content based on the ranges table specifications -SELECT * FROM @inttab AS tab - WHERE table_line IN @rangestab - INTO TABLE @DATA(result). -"result: 1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 18, 19, 20 - -``` - -

⬆️ back to top

- -## Executable Example - -[zcl_demo_abap_dtype_dobj](./src/zcl_demo_abap_dtype_dobj.clas.abap) - -> **💡 Note**
-> - The executable example ... -> - covers, among others, the following topics: -> - Declaring data types -> - Declaring data objects, inline declarations -> - Assignments -> - Creating anonymous data objects -> - Type conversions -> - Getting type information (Runtime Type Information/RTTI) -> - Constants, immutable variables -> - Generic types -> - Enumerated types and objects -> - does not have as many things to be output compared to other ABAP cheat sheet executable examples. The focus is on syntax options and declarations. In the class, you can set breakpoints and use the debugger to check out data objects. You can also use the F2 information for the many types and data objects. Simply select a type or object in the code and press F2 in ADT to check out the information. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) - - - + + +# Data Types and Data Objects + +- [Data Types and Data Objects](#data-types-and-data-objects) + - [Introduction](#introduction) + - [Data Types and Objects: Definition](#data-types-and-objects-definition) + - [ABAP Data Types](#abap-data-types) + - [Elementary Data Types](#elementary-data-types) + - [Complex Data Types](#complex-data-types) + - [Reference Types](#reference-types) + - [Declaring Data Types](#declaring-data-types) + - [Generic Types](#generic-types) + - [Data Objects](#data-objects) + - [Declaring Data Objects](#declaring-data-objects) + - [Assigning Values to Data Objects](#assigning-values-to-data-objects) + - [Creating Data Objects Using Inline Declaration](#creating-data-objects-using-inline-declaration) + - [Assigning References to Data Reference Variables](#assigning-references-to-data-reference-variables) + - [Creating Anonymous Data Objects](#creating-anonymous-data-objects) + - [Constants and Immutable Variables](#constants-and-immutable-variables) + - [Type Conversion](#type-conversion) + - [Terms Related to Data Types and Objects in a Nutshell](#terms-related-to-data-types-and-objects-in-a-nutshell) + - [Notes on the Declaration Context](#notes-on-the-declaration-context) + - [Excursions](#excursions) + - [Enumerated Types and Objects](#enumerated-types-and-objects) + - [Getting Type Information and Creating Types at Runtime](#getting-type-information-and-creating-types-at-runtime) + - [Ranges Tables](#ranges-tables) + - [Executable Example](#executable-example) + +## Introduction +[ABAP statements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_statement_glosry.htm) usually work with [data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_object_glosry.htm), that is, with transient data that occupies memory space while the [data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_type_glosry.htm) defines the technical properties of the data objects. +Since data types and data objects are closely related, this cheat sheet covers both topics. +Note that the topics covered here are also partly covered in other ABAP cheat sheets. The purpose of this cheat sheet is to summarize the basics. + +## Data Types and Objects: Definition + +Data types +- Define technical properties of all data objects that have these data types, such as the maximum length of a [text field](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_field_glosry.htm). +- Are descriptions only, with no data memory attached except for administrative information. +- Can occur in [ABAP programs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_program_glosry.htm) as [bound data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbound_data_type_glosry.htm), that is, the type is a property of a data object, or as a [standalone data type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstand-alone_data_type_glosry.htm), that is, the data type is defined independently. +- Can be defined locally in an ABAP program or globally in classes, interfaces and in the [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_dictionary_glosry.htm). +> **💡 Note**
+> - Note: Data types in the ABAP Dictionary are either created directly as [repository objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrepository_object_glosry.htm) ([DDIC data elements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_element_glosry.htm)) or in a type pool (only in [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm)). [Database tables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendatabase_table_glosry.htm), [CDS entities](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencds_entity_glosry.htm) and their components can also be used as data types in ABAP programs. +> - Their existence and visibility depends on the declaration context. + +Data objects: +- Are objects (or [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm)) of a data type (similar to objects/instances of classes in [ABAP Objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_objects_glosry.htm)). +- Occupy memory space and exist in different forms, for example, numeric or textual data can be contained in data objects. +- The type of data that a data object can receive is determined by its data type. +- Like data types, their existence and visibility depend on the declaration context. +- Are usually used in [ABAP statements](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_statement_glosry.htm) by specifying them in the [operand position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_position_glosry.htm). + + +> **💡 Note**
+> There are several differentations that further distinguish and characterize data types and objects. See [here](#terms-related-to-data-types-and-objects-in-a-nutshell). + +

⬆️ back to top

+ +## ABAP Data Types + +ABAP is rich in built-in data types and offers a wide range of options for defining data types and data objects in different contexts. +Data types can be divided into three groups: +- [Elementary data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenelementary_data_type_glosry.htm) +- [Complex data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplex_data_type_glosry.htm) +- [Reference type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_type_glosry.htm) + +For an overview, see the [ABAP Type Hierarchy](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentype_hierarchy.htm) in the ABAP Keyword Documentation. + +### Elementary Data Types +- Elementary (or scalar) data types are based directly on a set of [built-in ABAP types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_abap_type_glosry.htm). +- Are not composed of other data types. +- Are types for holding numeric values, text information, binary data and special types for date and time. +- Are further divided into elementary types of fixed and variable length. + - Note: The length and the memory requirements of data objects of fixed length data types are fixed, that is, they cannot change at runtime. The length and memory requirements of data objects of variable length data types can actually change at runtime, depending on their contents. +- The following built-in elementary data types of fixed length are available: + - Numeric types: Integers (`b`, `s`, `i`, `int8`), [decimal floating point numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendecfloat_glosry.htm) (`decfloat16`, `decfloat34`), [binary floating point numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbinfloat_glosry.htm) (`f`), and [packed numbers](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpacked_number_glosry.htm) (`p`) + - Character-like types: text fields (`c`) and [numeric text fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennumeric_text_field_glosry.htm) (`n`) + - Byte-like type: [byte fields](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_field_glosry.htm) (`x`) + - Character-like date and time types: date fields (`d`) and time fields (`t`) + - Time stamp type for time stamp fields (`utclong`). +- Variable length: + - Character-like type for [text strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentext_string_glosry.htm) (`string`) + - Byte-like type for [byte strings](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbyte_string_glosry.htm) (`xstring`) + +> **💡 Note**
+> - The data types `c`, `n`, `x`, and `p` are incomplete, i.e., [generic data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_data_type_glosry.htm), with respect to their length. The type definition syntax has a special addition for this (`LENGTH`). In addition, `p` is also generic with respect to the number of decimal places (`DECIMALS` addition). See more about generic types in the following sections. +> - The other types can be considered as [complete data types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencomplete_data_type_glosry.htm). They don't need any additional syntax elements for the definition. +> - The numeric data types `b` and `s` cannot be specified directly in ABAP programs for short integers. Alternative [built-in DDIC types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_ddic_type_glosry.htm) are available. +> - `decfloat16` and `decfloat34` for decimal floating point numbers can be regarded as more modern versions of `p` and `f`, combining their advantages. +> - Although they are character-like, `t` and `d` can be used for calculations. +> - See the ABAP Keyword Documentation [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuilt_in_types.htm) for more information about the initial values of the data types, the standard length, and so on. + +

⬆️ back to top

+ +### Complex Data Types + +- Are composed of other types. +- The following complex data types are available: + - [Structured types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstructured_type_glosry.htm): Represent a sequence of arbitrary data type (i.e., they can be elementary, reference, or complex data types). The typical syntax element for the local definition of a structure is `... BEGIN OF ... END OF ...`. + - [Table types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_type_glosry.htm): Consist of a sequence of any number of lines of the same data type. It can be any elementary type, reference type, or complex data type. The type definition includes other properties such as the [table category](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_category_glosry.htm) (defines how tables can be accessed) and [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm) (to identify the table lines). The typical syntax element is `... TABLE OF ...`. + - [Enumerated types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenum_type_glosry.htm): Specify a set of values in addition to the actual type properties. The typical syntax element is `... BEGIN OF ENUM ... END OF ENUM ...`. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_types_usage.htm) and further down. + - [Mesh types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenmesh_type_glosry.htm): Special structured type that contains only table types with structured line types as components that can be linked using mesh associations. The typical syntax element is `... BEGIN OF MESH ... END OF MESH ...`. See more information [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes_mesh.htm). + - [BDEF derived types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_derived_type_glosry.htm): RAP-specific structured and table types. The typical syntax elements are `... TYPE STRUCTURE FOR ...` and `... TYPE TABLE FOR ...`. More information can be found [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrpm_derived_types.htm) and in the ABAP cheat sheet on ABAP EML. +- A data object of a complex type can be accessed as a whole or by component. + +> **💡 Note**
+> Structured and table types are used in this cheat sheet as examples for complex types. For more information, see the ABAP Keyword Documentation and the ABAP cheat sheets for structures and internal tables. + +

⬆️ back to top

+ +### Reference Types +- Describe data objects that contain [references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_glosry.htm) to other objects (data objects and instances of classes), which are known as [reference variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreference_variable_glosry.htm). +- There are two kinds of references: [Data references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_glosry.htm) (references to data objects) and [object references](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenobject_reference_glosry.htm) (references to objects as instances of classes). +- A reference type must be defined either in the ABAP program or in the ABAP Dictionary. There are no built-in reference types in ABAP. +- The typical syntax element is `... REF TO ...`. + +> **💡 Note**
+> There are [generic ABAP types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abengeneric_abap_type_glosry.htm). Generic data types are types that do not define all of the properties of a data object. They can only be used for the typing of [formal parameters](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenformal_parameter_glosry.htm) and [field symbols](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfield_symbol_glosry.htm). See an example further down. +The only generic types that can be used after `TYPE REF TO` are `data` for the generic typing of data references, and `object`, for the generic typing of object references. + +

⬆️ back to top

+ +### Declaring Data Types + +Data types are defined in an ABAP program using the [`TYPES`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abaptypes.htm) statement. Depending on the declaration context, the types can be accessed either locally or globally. As mentioned, data types can also be declared in the ABAP Dictionary. The focus here is on data type declarations in ABAP programs using `TYPES` statements. +You can use built-in and user-defined data types to create data types (and data objects). + +The following code snippet shows various syntax options for declaring data types: + +Elementary types: + +```abap +"Type declaration follows these patterns (LENGTH and DECIMALS only possible for particular types): +"TYPES data_type TYPE some_type [LENGTH len] [DECIMALS dec]. + +"Data type declarations based on built-in ABAP types + +"Numeric types +TYPES te_i TYPE i. +TYPES te_int8 TYPE int8. +TYPES te_decfl16 TYPE decfloat16. +TYPES te_decfl34 TYPE decfloat34. +TYPES te_f TYPE f. +TYPES te_p_l4_d2 TYPE p LENGTH 4 DECIMALS 2. +"Note: LENGTH/DECIMALS must be specified when using the types c, p, n, x. in ABAP Objects contexts. + +"Character-like types +"To combine TYPES statements, you can use chained statements, i.e. TYPES followed by a colon and +"then listing the type declarations separated by a comma. +TYPES: te_c5 TYPE c LENGTH 5, + te_n4 TYPE n LENGTH 4, + te_str TYPE string. + +"Byte-like types +TYPES te_x_l2 TYPE x LENGTH 2. +TYPES te_xstr TYPE xstring. + +"Types for date and time +TYPES te_d TYPE d. +TYPES te_t TYPE t. +TYPES te_utc TYPE utclong. + +"You might also stumble on a length specification in parentheses following the data type name. +"It is recommended that you use addition LENGTH instead of the parentheses. +TYPES te_cfour(4) TYPE c. + +"**** Data type declarations based on existing types or data objects **** + +"Type declaration based on an existing type visible at this location; +"all properties of the specified data type are inherited. +TYPES te_another_i TYPE te_i. + +"Anticipating the data object declaration needed to demonstrate the LIKE addition +DATA do_num TYPE i. + +"LIKE addition: +"Type declaration based on an existing data object visible at this location; +"all properties of the type of the specified data object are inherited. +TYPES te_from_int LIKE do_num. + +"**** Data type declarations based on globally available types or data objects **** + +"DDIC Types +"Note that the built-in types b and s cannot be specified for type declarations. +"However, the value range for these types can be obtained by referencing the built-in DDIC +"types INT1 and INT2. These are data elements. +TYPES te_int1 TYPE int1. +TYPES te_int2 TYPE int2. + +"Referring to types in global classes +"In the example, the type exists in a global interface. +TYPES te_elem_from_itf TYPE zdemo_abap_get_data_itf=>occ_rate. + +"Referring to a data object that exists in a global interface +TYPES te_dobj_from_itf LIKE zdemo_abap_objects_interface=>stat_str. + +"Referring to a data object that exists in the public visibility section of a global class +TYPES te_dobj_from_cl LIKE zcl_demo_abap_objects=>public_string. + +"Referring to a component of a DDIC table (also possible for views; +"the components have elementary types) +TYPES te_comp_ddic_tab TYPE zdemo_abap_carr-carrid. + +"Type pools (ABAP program, administrated by the ABAP Dictionary; may only be created in +"standard ABAP; but is considered obsolete) +"However, the following example is accessible in ABAP for Cloud Development, too. +"The type pool contains the definitions of globally visible data types and constants. +TYPES te_tp TYPE abap_bool. +TYPES te_const_in_tp LIKE abap_true. +``` + +Structure and internal table types as examples for complex types: + +```abap +"Structure type, can contain any type +TYPES: BEGIN OF ts_misc_comps, + comp1 TYPE i, + comp2 TYPE string, + comp3 TYPE te_i, "Existing type + comp4 LIKE do_num, "Referring to existing data object + comp5 TYPE string_table, "Internal table type (available in DDIC) + comp6 TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY, "Internal table type (based on database table) + comp7 TYPE REF TO i, "Reference type + END OF ts_misc_comps. + +"Internal table types +"Note: The examples only use the implicit STANDARD for standard tables. +"Internal table type declaration based on a local structure type +TYPES tt_local_ts TYPE TABLE OF ts_misc_comps WITH EMPTY KEY. + +"Internal table type declaration based on an elementary data type +TYPES tt_int TYPE TABLE OF i. + +"Referring to existing types and data objects + +"Anticipating the creation of structured data objects for the LIKE addition +DATA struc_local_ts TYPE ts_misc_comps. + +"Structure type creation based on an existing structured data object +TYPES ts_w_like LIKE struc_local_ts. + +"Anticipating the creation of an internal table for the LIKE addition +DATA itab_local_ts TYPE TABLE OF ts_misc_comps WITH EMPTY KEY. + +"Internal table type declaration based on an existing internal table +TYPES tt_w_like LIKE itab_local_ts. + +"Internal table type declaration based on the existing internal table type +TYPES tt_another_type TYPE tt_w_like. + +"Structured types based on an internal table's line type +TYPES ts_type_line TYPE LINE OF tt_w_like. +TYPES ts_like_line LIKE LINE OF itab_local_ts. + +"Internal table typed with internal table as line type +TYPES tt_like_table LIKE TABLE OF itab_local_ts. + +"Referring to global types + +"Structure type based on DDIC type +"In this case, a database table is specified whose line type is used as data type +"in this type declaration. You may also use a CDS view (or classic DDIC view in +"standard ABAP) or a dedicated structured type defined in the DDIC. +TYPES ts_ddic_tab TYPE zdemo_abap_carr. + +"Internal table type based on internal type that exists in a gloabl interface +TYPES tt_tab_type_from_itf TYPE zdemo_abap_get_data_itf=>carr_tab. + +"Internal table types with an elementary line type based on globally available types +"Elementary table type +TYPES tt_strtab TYPE string_table. +"Elementary line type; the type is available in a global interface +TYPES tt_elem_type_from_itf TYPE TABLE OF zdemo_abap_get_data_itf=>occ_rate. +``` + +Reference types: +```abap +"Declaring reference types with static types +TYPES tr_i TYPE REF TO i. +TYPES tr_str TYPE REF TO string. +TYPES tr_ddic_tab TYPE REF TO zdemo_abap_carr. +"Using the generic type data as static type +TYPES tr_data TYPE REF TO data. + +"Referring to an existing reference type +TYPES tr_ref_i TYPE tr_i. + +"Anticipating the creation of a data reference variable for showing the LIKE addition +DATA dref_i TYPE REF TO i. + +"Creating a reference type based on a data reference variable +TYPES tr_like_ref_i LIKE dref_i. + +"Creating a data object for the LIKE REF TO addition +DATA str TYPE string. + +"Creating a reference type whose static type is inherited from the data type of the specified data object +TYPES tr_like_ref2str LIKE REF TO str. + +"Reference table types +TYPES tr_tab_ref_i TYPE TABLE OF REF TO i. +DATA itab_str TYPE TABLE OF string. +TYPES tr_like_table_ref LIKE TABLE OF REF TO itab_str. +``` + +

⬆️ back to top

+ +### Generic Types + +- Generic types are available with which [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. +- 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. +- More information: + - [Generic ABAP Types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuilt_in_types_generic.htm) + - [ABAP cheat sheet about dynamic programming](06_Dynamic_Programming.md) regarding field symbols and `ASSIGN` statements + +The following code snippet demonstrates generic types with field symbols. + +```abap +FIELD-SYMBOLS: + "Any data type + TYPE data, + TYPE any, + "Any data type can be assigned. Restrictions for formal parameters and 'data': no + "numeric functions, no description functions, and no arithmetic expressions can be + "passed to these parameters. However, you can bypass the restriction by applying the + "CONV operator for the actual parameter. + + "Character-like types + TYPE c, "Text field with a generic length + TYPE clike, "Character-like (c, n, string, d, t and character-like flat structures) + TYPE csequence, "Text-like (c, string) + TYPE n, "Numeric text with generic length + TYPE x, "Byte field with generic length + TYPE xsequence, "Byte-like (x, xstring) + + "Numeric types + TYPE decfloat, "decfloat16, decfloat34 + TYPE numeric, "Numeric ((b, s), i, int8, p, decfloat16, decfloat34, f) +

TYPE p, "Packed number (generic length and number of decimal places) + + "Internal table types + TYPE ANY TABLE, "Internal table with any table type + TYPE HASHED TABLE, + TYPE INDEX TABLE, + TYPE SORTED TABLE, + TYPE STANDARD TABLE, +

TYPE table, "Standard table + + "Other types + TYPE simple, "Elementary data type including enumerated types and + "structured types with exclusively character-like flat components + TYPE REF TO object. "object can only be specified after REF TO; can point to any object + +"Data objects to work with +DATA: BEGIN OF s, + c3 TYPE c LENGTH 3, + c10 TYPE c LENGTH 10, + n4 TYPE n LENGTH 4, + str TYPE string, + time TYPE t, + date TYPE d, + dec16 TYPE decfloat16, + dec34 TYPE decfloat34, + int TYPE i, + pl4d2 TYPE p LENGTH 4 DECIMALS 2, + tab_std TYPE STANDARD TABLE OF string WITH EMPTY KEY, + tab_so TYPE SORTED TABLE OF string WITH NON-UNIQUE KEY table_line, + tab_ha TYPE HASHED TABLE OF string WITH UNIQUE KEY table_line, + xl1 TYPE x LENGTH 1, + xstr TYPE xstring, + structure TYPE zdemo_abap_carr, "character-like flat structure + oref TYPE REF TO object, + END OF s. + +"The following static ASSIGN statements demonstrate various assignments +"Note: +"- The statements commented out show impossible assignments. +"- If a static assignment is not successful, sy-subrc is not set and no +" memory area is assigned. Dynamic assignments, however, set the value. + +"----- Any data type ----- +ASSIGN s-c3 TO . +ASSIGN s-time TO . +ASSIGN s-tab_std TO . +ASSIGN s-xstr TO . +ASSIGN s-pl4d2 TO . +ASSIGN s-date TO . +ASSIGN s TO . + +"----- Character-like types ----- +ASSIGN s-c3 TO . +ASSIGN s-c10 TO . +"ASSIGN s-str TO . + +ASSIGN s-c10 TO . +ASSIGN s-str TO . +ASSIGN s-n4 TO . +ASSIGN s-date TO . +ASSIGN s-time TO . +ASSIGN s-structure TO . + +ASSIGN s-c10 TO . +ASSIGN s-str TO . +"ASSIGN s-n4 TO . + +ASSIGN s-n4 TO . +"ASSIGN s-int TO . +"ASSIGN s-time TO . + +ASSIGN s-xl1 TO . +"ASSIGN s-xstr TO . + +ASSIGN s-xl1 TO . +ASSIGN s-xstr TO . + +"----- Numeric types ----- +ASSIGN s-dec16 TO . +ASSIGN s-dec34 TO . +ASSIGN s-int TO . +ASSIGN s-pl4d2 TO . +"ASSIGN s-n4 TO . + +ASSIGN s-dec16 TO . +ASSIGN s-dec34 TO . + +ASSIGN s-pl4d2 TO

. +"ASSIGN s-dec34 TO

. + +"----- Internal table types ----- +ASSIGN s-tab_std TO . +ASSIGN s-tab_so TO . +ASSIGN s-tab_ha TO . + +ASSIGN s-tab_std TO . +ASSIGN s-tab_so TO . +"ASSIGN s-tab_ha TO . + +"ASSIGN s-tab_std TO . +ASSIGN s-tab_so TO . +"ASSIGN s-tab_ha TO . + +ASSIGN s-tab_std TO . +ASSIGN s-tab_std TO

. +"ASSIGN s-tab_so TO . +"ASSIGN s-tab_so TO
. +"ASSIGN s-tab_ha TO . +"ASSIGN s-tab_ha TO
. + +"ASSIGN s-tab_std TO . +"ASSIGN s-tab_so TO . +ASSIGN s-tab_ha TO . + +"----- Other types ----- +ASSIGN s-c10 TO . +ASSIGN s-str TO . +ASSIGN s-dec34 TO . +ASSIGN s-date TO . +ASSIGN s-structure TO . +ASSIGN s-xl1 TO . +"ASSIGN s-tab_ha TO . + +s-oref = NEW zcl_demo_abap_objects( ). +ASSIGN s-oref TO . +"Accessing class attributes using casting +DATA(publ_str) = CAST zcl_demo_abap_objects( )->public_string. +CAST zcl_demo_abap_objects( )->another_string = `ABAP`. +``` + +

⬆️ back to top

+ +## Data Objects + +### Declaring Data Objects + +The [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapdata.htm) statement declares a data object of any data type. The declaration of a data object is similar to that of a data type, with only slight differences in terms of the number of possible additions, and follows this syntax pattern: +`DATA dobj TYPE abap_type [LENGTH len] [DECIMALS dec] [VALUE val] [READ-ONLY].` + +Note that `READ-ONLY` can only be used for class attributes. +The data type of a data object is always defined uniquely and cannot be changed at runtime of a program. + +Data objects with elementary types: +```abap +"The elementary, built-in data types can be used as shown for data type declarations. +"Chained statements are also possible with DATA. +"Note that not all types as shown above are used here. +DATA: do_i TYPE i, + do_c_l5 TYPE c LENGTH 5, + do_p_l3_d2 TYPE p LENGTH 3 DECIMALS 2, + do_decfl16 TYPE decfloat16, + do_str TYPE string, + "Specifying the length in parantheses instead of using the + "LENGTH addition is not recommended + do_ctwo(2) TYPE c. + +"Referring to locally declared data types +TYPES te_string TYPE string. +DATA do_another_str TYPE te_string. + +"Referring to other data objects +DATA do_like_dobj LIKE do_i. + +"If the length is not specified explicitly for the ABAP types c, n, p, and x, +"the standard length is defined implicitly. Check the F2 information. +DATA do_c_std TYPE c. +DATA do_p_std TYPE p. + +"If neither TYPE nor LIKE is specified, a data object with the bound +"data type 'c LENGTH 1' is created. +DATA do_c. + +"VALUE addition +"Start values can be set for the data objects when they are declared. +"Without the addition VALUE, data objects are filled with their type-specific initial values. +"The start value can either be specified as a literal or as a predefined constant. +"Note: The VALUE addition is not to be confused with the VALUE operator that can be used to +"construct the content of complex data objects as shown below. +DATA do_c_l2 TYPE c LENGTH 2 VALUE 'hi'. +DATA do_i_val TYPE i VALUE 123. +DATA do_like_val LIKE do_i VALUE 9. + +"Specifying a constant (data object that cannot be changed at runtime) after the VALUE addition +CONSTANTS con TYPE string VALUE `abcdef`. +DATA do_val_con TYPE string VALUE con. + +"VALUE IS INITIAL addition: Explicitly specifying the type-specific initial value +DATA do_i_init TYPE i VALUE IS INITIAL. +DATA do_i_like_init LIKE do_i VALUE IS INITIAL. + +"Data objects can also be created in the declaration part of classes and interfaces. +"There you can use the READ-ONLY addition for data object declarations in the public visibility section. +"In doing so, an attribute declared using CLASS-DATA or DATA can be read from outside of the class but +"can only be changed using methods of the class or its subclasses. +"The following attribute is taken from a executable example. It shows a read access in a control +"structure. If you wanted to assign a new value to the attribute outside of the class in which it is +"declared, a syntax error would be displayed. +"Note that when you are in the class itself, there is no need to specify the class name. +"read_only_attribute = ... would be sufficient. And changing the value would be possible within +"the class, too. +"Declaration in the example: +"CLASS-DATA: read_only_attribute TYPE string VALUE `Hallo` READ-ONLY. +IF zcl_some_class=>read_only_attribute = `abc`. + ... +ELSE. + ... +ENDIF. +``` + +Structures and internal tables as examples for complex types: + +```abap +"Find more examples in the ABAP cheat sheets on structures and internal tables. + +"Creating a structure with DATA and providing start values with the VALUE addition. +"If not specified, then the components have their type-specific initial value. +DATA: BEGIN OF a_structure, + comp1 TYPE i VALUE 1, + comp2 TYPE string VALUE `hi`, + comp3 TYPE string, + END OF a_structure. + +"Creating a structure based on a global type. In this case, it is a DDIC database +"table whose line type is used. You can also use a CDS view or a dedicated structured type +"from the DDIC, for example. +DATA struc_ddic_tab TYPE zdemo_abap_carr. + +"Creating a structure as a constant. Providing values is mandatory. +CONSTANTS: BEGIN OF con_struc, + comp1 TYPE i VALUE 1, + comp2 TYPE string VALUE `hallo`, + comp3 TYPE string VALUE `salut`, + END OF con_struc. + +"Using the constant as start value for a structure declaration. +DATA struc_w_val LIKE con_struc VALUE con_struc. + +"Declaring a structure and explicitly specifying the type-specific +"initial values of the structure components as start values. +DATA struc_init_val LIKE con_struc VALUE IS INITIAL. + +"Creating internal tables ... +"Based on a globally available DDIC database table whose line type is used +DATA itab_ddic_tab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. +"Based on an elementary type +DATA itab_tab_i TYPE TABLE OF i. +"The table type is declared in a global interface +DATA itab_tab_type_from_itf TYPE zdemo_abap_get_data_itf=>carr_tab. +"Based on globally available DDIC internal table type; explicitly specifying as initial +DATA itab_ddic_tab_type TYPE string_table VALUE IS INITIAL. +"Based on locally available structured data object +DATA itab_like_struc LIKE TABLE OF struc_w_val WITH EMPTY KEY. +"Based on locally available internal table +DATA itab_like_another_itab LIKE itab_tab_i. + +"Creating an internal table type locally +TYPES tt_ddic_tab TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY. +"... and an internal table based on it. +DATA itab_w_itab_type TYPE tt_ddic_tab. + +"Creating a structure based on the line of an internal table (type) +DATA struc_from_itab_type TYPE LINE OF tt_ddic_tab. +DATA struc_like_line LIKE LINE OF itab_ddic_tab. +``` + + +> **💡 Note**
+> The above data objects are declared by assigning a dedicated name. These data objects can be addressed by that name. This is not true for [anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm), which can only be addressed through reference variables. This is covered [below](#assigning-references-to-data-reference-variables). + + +Data reference variables: + +```abap +"Declaring data reference variables types with static types +DATA dref_int TYPE REF TO i. +DATA dref_str TYPE REF TO string. +DATA dref_ddic_tab TYPE REF TO zdemo_abap_carr. +"Using generic type data as static type +DATA dref_data TYPE REF TO data. + +"Referring to an existing reference type +TYPES tr_int TYPE REF TO i. +DATA dref_tr_int TYPE tr_int. + +"Creating a data reference variable based on a data reference variable +DATA dref_like LIKE dref_int. + +"Creating a data object for the LIKE REF TO addition +DATA do_some_string TYPE string. + +"Reference type is created whose static type is inherited from the data type of the specified data object +DATA dref_like_ref_str LIKE REF TO do_some_string. + +"Reference tables +DATA dref_tab_i TYPE TABLE OF REF TO i. +DATA dref_tab_str LIKE TABLE OF REF TO do_some_string. +``` + +

⬆️ back to top

+ +### Assigning Values to Data Objects + +An assignment passes the contents of a source to a target data object. + +> **💡 Note**
+> - There are conversion rules when assigning a source to a target data object that have different types. For more information, see the topic [Assignment and Conversion Rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rules.htm) in the ABAP Keyword Documentation, especially for complex types, since elementary types are usually demonstrated in the cheat sheet. +> - There are many ways to assigning values to data objects in ABAP. Assignments with the assignment operator `=` are mostly used here. +> - In older ABAP code, you may see `MOVE ... TO ...` statements for value assignments. These statements are obsolete. They are not to be confused with `MOVE-CORRESPONDING` statements for complex types. These are not obsolete. + +The following code snippet shows several ways to assign values to data objects. + +```abap +"As mentioned, a start value can be directly assigned when declaring a data object. +DATA some_int TYPE i VALUE 123. + +"Assignment using the assignement operator = +"The source of the assigment on the right side (also known as general expressions posisiton) +"can be specified with many things. + +"Single data object as source of the assignment +"In the following cases, the literal and data object have the exact type as the data +"object on the left side. +some_int = 456. +DATA num TYPE i. +num = some_int. + +DATA str_a1 TYPE string VALUE `hallo`. +DATA str_a2 TYPE string. +str_a2 = str_a1. + +"Functional method as source of the assignment +"In the following example, the method get_next of the class cl_abap_random_int +"returns an integer. Check the F2 information for get_next (return value of type i). +"A random integer that is in the specified value range is assigned to the data object +"on the left side. +num = cl_abap_random_int=>create( + seed = cl_abap_random=>seed( ) min = 1 + max = 10 )->get_next( ). + +"Built-in functions as source of the assignment +"There are plenty of functions available. Check the ABAP Keyword Documentation. + +"Built-in numeric function +"The following built-in function calculates 2 to the power of 4. The +"result is assigned to the data object on the left side. +num = ipow( base = 2 exp = 4 ). + +"Built-in string function +"The following function transforms the specified data object to upper case letters. The +"result is assigned to the data object on the left side. +str_a1 = to_upper( str_a2 ). + +"Constructor expressions as source of the assignment +"There are various options and expressions available (with many additions). Check the +"ABAP Keyword Documentation and the ABAP cheat sheet about constructor expressions. +"Here, taking the VALUE operator as an example. This operator is very handy especially +"for complex types. + +"Creating a structure +DATA some_struc TYPE zdemo_abap_carr. + +"Assignment using the VALUE operator +"Note the # character that stands for the type. Here, the structure type can be derived +"from the context. Hence, the explicit name can but need not be specified. +some_struc = VALUE #( carrid = 'XY' carrname = 'XY Airways' ). + +"Creating an internal table and assigning values +"Note that components that are not specified and assigned a value retain their +"type-specific initial value. +DATA some_itab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. +some_itab = VALUE #( ( carrid = 'XY' carrname = 'XY Airways' ) + ( carrid = 'AB' carrname = 'ABAP Airlines' ) ) . + +"Table expressions as source of the assignment +"A structure is assigned an internal table line +some_struc = some_itab[ 2 ]. + +"Calculation expressions as source of the assignment +"Arithmetic expression +num = 1 + 2. + +"A calculation assignment as follows +num += 1. +"is the short form of +num = num + 1. +"Syntax options: +=, -=, *= and /=, also &&= for the && operator + +"String expressions as source of the assignment +str_a2 = str_a1 && ` blabla`. "Strings are appended using the && operator +str_a2 = |{ str_a1 } some more bla.|. "String templates. Note: Data objects are specified + "in curly brackets. The content is converted to type string + "Note that it must be convertible to type string. + +"An elementary data object is assigned a component of a specific table line +"using a table expression. +"Note: In the following case, the types of source and target are not the same +"(type c versus type string). As shown further down, such an assignment can lead to +"unexpected or undesired results. Type-dependent conversions are made in accordance +"with the conversion rules. +str_a2 = some_itab[ 2 ]-carrname. +``` + +

⬆️ back to top

+ +### Creating Data Objects Using Inline Declaration + +An [inline declaration](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninline_declaration_glosry.htm) is made using the declaration operator [`DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_inline.htm). It can be specified in any designated [declaration position](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_position_glosry.htm). The result of the declaration is used in the current operand position, is statically visible from the current position, and is valid in the current context. + +> **💡 Note**
+> - In an assignment, if the data object is declared inline on the left side, there are many options for what can be placed on the right side as shown in the previous section. The data type of the variable is determined by the operand type. It must be possible to derive this type completely statically. +> - For more information about the possible declaration positions, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_positions.htm). +> - You can use the [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm) declaration operator to create [immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm), as shown below. +> - [Programming guidelines for inline declarations (F1 documentation for Standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendeclaration_inline_guidl.htm) + + +```abap +"Data object declarations and assignements as shown above. +DATA str_b1 TYPE string VALUE `abc`. + +DATA str_b2 TYPE string. +str_b2 = `def`. + +"Using a declaration expression with the declaration operator DATA, a data object can be +"declared inline. +"The data type of the declared variable is determined by the right side. +"In doing so, a data object is assigned a value in one go. +"In the following case, it is a string literal with backquotes on the right side. +"The data type is derived and, hence, the data object is of type string. +DATA(str_b3) = `ghi`. + +"In the following case, it is a text field literal with quotes. Type c is derived. +"The length is derived from the number of characters. +DATA(c_l3) = 'jkl'. "type c length 3 +DATA(c_l4) = 'mnop'. "type c length 4 +"Note the type conversion implications when making an assignment with these two data objects. +c_l3 = c_l4. "c_l3: 'mno' + +"Structures and internal tables +"In declaration expressions, structures and internal tables can be declared inline and filled with, +"for example, the help of the VALUE operator. + +"Structured data type +TYPES: BEGIN OF ts_struc, + comp1 TYPE i, + comp2 TYPE string, + END OF ts_struc. + +"In the following examples, structures are created. The structured data type is derived from the +"type specified before the parentheses. +DATA(struc_b1) = VALUE ts_struc( comp1 = 1 comp2 = `A` ). +"No components specified and values assigned means an initial structure. This syntax is also possible +"for declaring data objects with elementary types and explicitly specifiying initial values, but only +"for initial values. See the CONV operator. +DATA(struc_b2) = VALUE ts_struc( ). +DATA(elem_init) = VALUE i( ). +"Note that components that are not specified and assigned a value remain initial. +DATA(struc_b3) = VALUE zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ). +"An entire structure is assigned. +DATA(struc_b4) = struc_b1. + +"Note: When the structure has already been declared, and you want to assign values, you can use +"the VALUE operator followed by the # character instead of the explicit type name. +"In that case, it is possible to derive the type from the context. +struc_b4 = VALUE #( comp1 = 2 comp2 = `b` ). + +"Internal tables +"The internal table type is specified before the parentheses after the VALUE operator. +"The following example uses a table type that is globally available in the DDIC. +DATA(itab_b1) = VALUE string_table( ( `a` ) + ( `b` ) + ( `c` ) ). + +"Using a local internal table type +TYPES tt_b1 TYPE TABLE OF ts_struc WITH EMPTY KEY. +DATA(itab_b2) = VALUE tt_b1( ( comp1 = 1 comp2 = `a` ) + ( comp1 = 2 comp2 = `b` ) + ( comp1 = 3 comp2 = `c` ) ). + +"In the context of other ABAP statements such as LOOP, READ TABLE or ABAP SQL +"SELECT statements, inline declarations are useful for creating target variables with +"appropriate data types in place. This includes data reference variables and field +"symbols. Field symbols are not covered below. + +"A work area/structure to hold the current internal table line is created inline. +LOOP AT itab_b2 INTO DATA(wa_b1). + wa_b1-comp1 = 12345. + ... +ENDLOOP. + +"Using the REFERENCE addition, a data reference variable can be created inline. +LOOP AT itab_b2 REFERENCE INTO DATA(wa_ref_b1). + wa_ref_b1->comp1 = 67890. + ... +ENDLOOP. + +"A structure to hold the internal table line read is created inline. +READ TABLE itab_b2 INTO DATA(wa_b2) INDEX 2. +"Data reference variable +READ TABLE itab_b2 REFERENCE INTO DATA(wa_ref_b2) INDEX 2. + +"ABAP SQL statements +"A structure as target data object is created inline. +SELECT SINGLE * FROM zdemo_abap_carr INTO @DATA(struc_b5). +"NEW addition of the INTO clause creates a data reference variable +SELECT SINGLE * FROM zdemo_abap_carr INTO NEW @DATA(struc_ref). + +"Internal table as target data object is created inline. +SELECT * FROM zdemo_abap_carr INTO TABLE @DATA(itab_b3). +SELECT * FROM zdemo_abap_carr INTO TABLE NEW @DATA(itab_ref). +``` + +

⬆️ back to top

+ +### Assigning References to Data Reference Variables + +- As with other data objects and types, there are [special assignment rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_references.htm) for [data reference variable](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendata_reference_variable_glosry.htm). See the ABAP Keyword Documentation. +- An initial reference variable contains the [null reference](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennull_reference_glosry.htm), which does not point to any objects. This means that it has neither a data type nor a class as a [dynamic type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendynamic_type_glosry.htm). +- The concepts of [upcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenup_cast_glosry.htm) and [downcast](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendown_cast_glosry.htm) enter the picture here. See the following code snippet. + +```abap +"Declaring data reference variables with static types +"At this stage, initial reference variables contain null references. +DATA dref_1_i TYPE REF TO i. +DATA dref_2_str TYPE REF TO string. +"Generic type as static type +DATA dref_3_data TYPE REF TO data. + +"References in data reference variables can point to existing data objects. +"For assigning the reference, you can use the REF operator. +"There is also an ABAP statement available doing the same: GET REFERENCE. +"It should not be used anymore, especially in ABAP for Cloud development. + +"Creating data objects to refer to and providing a start value +DATA do_number TYPE i VALUE 987. +DATA do_string TYPE string VALUE `abc`. + +"After the assignment, the data reference variable points to the values. +"The data type is derived (dynamic type). +dref_1_i = REF #( do_number ). "Dynamic type is the same as the static type in this case +dref_2_str = REF #( do_string ). "Dynamic type is the same as the static type in this case +"Dynamic types of the followig examples are more specific than static type, +"which is a generic type in this case. +dref_3_data = REF #( do_number ). +dref_3_data = REF #( do_string ). + +"Note: Table expressions can be also specified within the parentheses. + +"Inline declarations are also possible to create data reference variables +"and assigning values in one go. +DATA(dref_4_data) = dref_3_data. +DATA(dref_5_str) = REF #( `hi` ). +DATA(dref_6_i) = REF #( do_number ). + +"Assignments between two data reference variables mean that references are copied. +"The concepts of upcast and downcast enter the picture here. +"Two different assignment operators are used, as well as the casting operator CAST. + +"--------------------- Upcasts -------------------- +"Upcasts are possible for elementary data types +"- The static type of the target variable is more general or identical to the static type of the source variable. +"- Assignment operator used: = +"- Note that the operators for downcasts can also be used explicitly here, but it is usually not needed. +"- In this example, elementary data types are covered. An upcast works ... +" - if the data types have identical type properties (i.e. the built-in types match as well as length and decimal places). +" - the static type of the source variable is completely typed, and the static type of the target variable is generic. + +"The following upcasts work. Both point to data objects of type i or string. +dref_1_i = dref_6_i. +"The source on the right side is completely typed (type i), +"the target on the left side is a generic type (type data). +dref_3_data = dref_1_i. + +"--------------------- Downcasts -------------------- +"- The static type of the target variable is more specific than the static type of the source variable. +"- The assignability is not checked until runtime. +"- Must always be performed explicitly using the casting operator ?= or the more modern casting operator CAST. + +"The following example would result in a syntax error due to type incompatibility. +"dref_1_i = dref_3_data. + +"In the following example, the source has a generic static type (data). The target type +"has a more specific type (type i). +"To suppress the syntax error, the CAST operator is needed. +"Note: +"- The assignability is still not checked. This is done at runtime. +" In this example, it works since the dynamic type of the source is also of type i. +"- An advantage of the CAST operator compared to ?= is that the operator enables downcasts in operand positions, +" which helps reduce helper variables. +dref_1_i = CAST #( dref_3_data ). + +"If not caught, the following would result in a runtime error. +"dref_3_data points to a data object of type i, the static type is dref_2_str is string. +"So, the downcast does not work. +TRY. + dref_2_str = CAST #( dref_3_data ). + CATCH cx_sy_move_cast_error INTO DATA(e). +ENDTRY. + +"Old syntax using the ?= operator +dref_1_i ?= dref_3_data. + +"For upcasts, the operators can be used, too, but they are usually not necessary. +"So, an assignment as follows is possible but not needed. Only using = is sufficient. +dref_1_i = CAST #( dref_6_i ). +``` + +

⬆️ back to top

+ +### Creating Anonymous Data Objects + +[Anonymous data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenanonymous_data_object_glosry.htm) are a topic related to data reference variables. +These data objects are [unnamed data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenunnamed_data_object_glosry.htm). +Most of the data objects in the snippets above are named data objects (excluding the data reference variables), meaning that they can be addressed by a specific name. Unnamed data objects are literals and anonymous data objects. Anonymous data objects can be addressed using data reference variables. +Unlike data objects created with the `DATA` statement, anonymous data objects are created at runtime. Data objects declared with `DATA` are created when the program is loaded. + +There are several ways to create anonymous data objects: +- [`CREATE DATA`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcreate_data.htm) statements +- Using the instance operator [`NEW`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_new.htm) +- Addition `NEW` of the [`INTO`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapselect_into_target.htm) clause in ABAP SQL `SELECT` statements + +```abap +"--------------------- CREATE DATA statements -------------------- +"Note that there are many additions available. The examples show a selection. + +"Creating an anonymous data object with an implicit type. +"If neither of the additions TYPE or LIKE are specified, the data reference variable +"must be completely typed. +DATA dref_7_str TYPE REF TO string. +CREATE DATA dref_7_str. + +"Note: If you want to assign a value to the data object, this can't be done directly. +"The data reference variable must be dereferenced first using the dereferencing operator. +dref_7_str->* = `hi`. + +"Creating an anonymous data object with an explicitly specified data type +DATA dref_8_data TYPE REF TO data. +CREATE DATA dref_8_data TYPE p LENGTH 8 DECIMALS 3. +dref_8_data->* = 1 / 3. + +"Creating a named data object +DATA it TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY. + +"Creating an anomyous internal table. +"Using the LIKE addition to refer to an existing internal table +CREATE DATA dref_8_data LIKE it. + +"Using the anonymous data object as target in the INTO clause of a SELECT statement +SELECT * + FROM zdemo_abap_carr + INTO TABLE @dref_8_data->*. + +"Creating an anonymous hashed table by specifying the entire table type +CREATE DATA dref_8_data TYPE HASHED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid. + +"Using the anonymous data object as target in the INTO clause of a SELECT statement +SELECT * + FROM zdemo_abap_carr + INTO TABLE @dref_8_data->*. + +"Creating an anonymous structure +CREATE DATA dref_8_data TYPE zdemo_abap_fli. + +"Using the anonymous data object as target in the INTO clause of a SELECT statement +SELECT SINGLE * + FROM zdemo_abap_fli + INTO @dref_8_data->*. + +"--------------------- NEW operator -------------------- +"- Works like CREATE DATA dref TYPE type statements and can be used in general expression positions. +"- Allows to assign values to the new anonymous data objects in parentheses + +"Creating data reference variables +DATA: dref_9_data TYPE REF TO data, + dref_10_i TYPE REF TO i. + +"Assining a value to an anonymous data object of the type i +dref_9_data = NEW i( 555 ). + +"The # character can be used instead of the complete type spefication +"when the type can be derived from the context. +dref_10_i = NEW #( 653 ). + +"Inline declarations are handy. +"Creating a suitable anonymous data object in place. Here, the type must be specificed explicitly. +DATA(dref_11_i) = NEW i( 32 ). + +"Creating an anonymous structure +DATA(dref_12_ddic_tab) = NEW zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ). + +"The # character can be omitted when they type can be derived. +DATA dref_13_ddic_tab TYPE REF TO zdemo_abap_carr. +dref_13_ddic_tab = NEW #( carrid = 'AB' carrname = 'AB Airlines' ). + +"ABAP SQL SELECT statement +"Using the NEW addition in the INTO clause, an anonymous data object can be created in place. +SELECT * + FROM zdemo_abap_carr + INTO TABLE NEW @DATA(dref_14_inline). +``` + +

⬆️ back to top

+ +### Constants and Immutable Variables + +[Constants](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstant_glosry.htm) are [named data objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abennamed_data_object_glosry.htm) whose value cannot be changed at runtime. You declare them with the [`CONSTANTS`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapconstants.htm) statement. Unlike the `DATA` statement, a start value must be specified with the `VALUE` addition. + +[Immutable variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenimmutable_variable_glosry.htm) can also be declared inline with the [declaration operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abendeclaration_operator_glosry.htm) + [`FINAL`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenfinal_inline.htm). + +```abap +"--------------------- Constants -------------------- +"As mentioned above, constants cannot be changed at runtime. +CONSTANTS con_str TYPE string VALUE `hallo`. + +"Constants as start values for dobj declarations following value +CONSTANTS con_underscores TYPE string VALUE `__________`. +DATA str_w_con_as_start_value TYPE string VALUE con_underscores. + +"--------------------- Immutable variables -------------------- +FINAL(do_final_inl) = 1. +DATA(do_data_inl) = 1 + do_final_inl. +"not possible +"do_final_inl = 2. + +SELECT * FROM zdemo_abap_carr INTO TABLE @DATA(itab_data_inl). + +DATA itab_like_inline LIKE itab_data_inl. + +"Using an inline declaration as target of a LOOP statement +"A value is assigned multiple times, but it cannot be changed in any other write positions. +LOOP AT itab_data_inl INTO FINAL(wa_final). + "The following is not possible + "wa_final-carrid = 'd'. + "only read access + APPEND wa_final TO itab_like_inline. +ENDLOOP. + +"SELECT statement with a an immutable target table declared inline +SELECT * FROM zdemo_abap_carr INTO TABLE @FINAL(itab_final_inl). +``` + +

⬆️ back to top

+ +## Type Conversion +A value assignment means that the value of a data object is transferred to a target data object. If the data types of the source and target are compatible, the content is copied unchanged. If they are incompatible and a suitable [conversion rule](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rule_glosry.htm) exists, the content is converted. +The following cases must be distinguished with regard to the data type: +- The source and target data types are compatible, i.e. all technical type properties match. The content is transferred from the source to the target without being converted. +- The source and target data types are incompatible, but can be converted. The content of the source is converted according to the conversion rules and then transferred to the target. Two data types are convertible if a conversion rule exists for them. An exception is raised if the content of the source cannot be handled according to the conversion rules. +- If the data objects are neither compatible nor convertible, no assignment can take place. If the syntax check detects this state, a syntax error is raised, otherwise an [uncatchable exception](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenuncatchable_exception_glosry.htm) is raised when the program is executed. + +See the conversion rules for the different data types here: [Assignment and Conversion Rules](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconversion_rules.htm) + +> **💡 Note**
+> - The [operands](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_glosry.htm) of many ABAP statements are assigned internally according to the assignment rules. +> - Typically, assignements are made using the assignment operator `=`. If necessary and applicable, the type is converted implicitly. However, you can also use the conversion operator [`CONV`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_conv.htm) to convert types explicitly. +> - For [lossless assignments](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlossless_assignment_glosry.htm), the lossless operator [`EXACT`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_exact.htm) can be used to perform checks before the conversion is performed to ensure that only valid values are assigned and that no values are lost in assignments. +> - In general, no checks are performed on assignments between compatible data objects. If a data object already contains an invalid value, for example, an invalid date or time in a date or time field, it is passed a valid value when the assignment is made to a compatible data object. +> - The `applies_to_data` method of the [RTTI](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm) class `cl_abap_datadescr` can be used to check type compatibility. See the executable example. + + +```abap +"Implicit conversions of the types c and string +DATA do_1_str TYPE string VALUE `abcedf`. +DATA do_2_c3 TYPE c LENGTH 3. +do_2_c3 = do_1_str. +"Result: do_2_c3: 'abc' + +"Implicit conversions of the types i and decfloat34 +DATA do_4_i TYPE i. +DATA do_5_dcfl34 TYPE decfloat34 VALUE '4.56'. +do_4_i = do_5_dcfl34. +"Result: do_4_i: 5 + +"Explicitly converting decfloat34 to i +DATA do_6_dcfl34 TYPE decfloat34 VALUE '2.78'. +DATA(do_7_i) = CONV i( do_6_dcfl34 ). +"Result: do_7_i: 3 + +"Note conversions according to the rules, e.g. from +"type i to string +DATA(i2str) = CONV string( -10 ). +"Result: i2str: `10-` +``` + +

⬆️ back to top

+ +## Terms Related to Data Types and Objects in a Nutshell + +```abap +"----------------- Standalone and bound data types ----------------- +"Standalone: Data type that is defined using the statement TYPES in an +" ABAP program, as a data type of the ABAP Dictionary or as +" an CDS entity. +"Bound: Data type that only exists as a property of a data object. + +"Standalone data type +TYPES te_a_c10 TYPE c LENGTH 10. + +"Bound data types +DATA do_a_c20 TYPE c LENGTH 20. +DATA do_b_like LIKE do_a_c20. +TYPES te_b_like LIKE do_a_c20. + +"-------------- Complex and elementary data type/object -------------- +"Elementary: Data type of fixed or variable length that is neither +" structured, nor a table type or a reference type. +"Complex: Made up of other data types, for example structured data +" type/objects, a table type/internal tables + +"Elementary +DATA do_c_i TYPE i. + +"Complex +DATA: BEGIN OF struc_a, + comp1 TYPE i, + comp2 TYPE string, + comp3 TYPE zdemo_abap_carr, "structure + comp4 TYPE string_table, "internal table + comp5 TYPE REF TO i, "reference type + END OF struc_a. + +"------------------ Complete and generic data types ------------------ +"Complete: Non-generic data type +"Generic: +"- Data type that does not set all properties of a data object. +"- Can only be used for the typing of formal parameters and field symbols, +" except for data reference variables using the generic type 'data'. + +"Complete data type +DATA do_d_i TYPE i. + +"Field symbols typed with generic data types +"Note: A field symbol is a symbolic name for a data object to which actual +"memory can be assigned at runtime. A field symbol can be used as a placeholder +"for a data object at an operand position. For more information, see the ABAP +"Cheat Sheet on dynamic programming. Field symbols are used in this example +"to demonstrate generic types other than just data. +FIELD-SYMBOLS TYPE clike. +FIELD-SYMBOLS TYPE data. + +"Field symbols with generic data types can be assigned appropriate values +DATA do_e_c5 TYPE c LENGTH 5 VALUE 'abcde'. +DATA do_f_str TYPE string VALUE `Hallo, how are you?`. +ASSIGN do_e_c5 TO . +ASSIGN do_f_str TO . + +DATA(itab_a) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). +ASSIGN do_e_c5 TO . +ASSIGN do_f_str TO . +ASSIGN itab_a TO . + +"------------------ Variable and constant data objects ------------------ +"Variable: Named data object whose value can be changed during the runtime +" of an ABAP program. +"Constant: Named data object whose value cannot be changed at runtime. + +"Variable +DATA do_g_i TYPE i VALUE 123. +do_g_i = 456. + +CONSTANTS con_a_i TYPE i VALUE 789. +"Not changeable +"con_a_i = 321. + +"--------------------- Static and dynamic data objects -------------------- +"Static: +"- Data object for which all attributes, including memory use, are specified +" statically by the data type. +"- Apart from reference variables, all static data objects are flat. +"Dynamic: +"- Data object for which all properties apart from the memory consumption are +" statically determined by the data type. +"- Dynamic data objects are strings and internal tables. They belong to the +" deep data objects. Structures that contain dynamic components are also +" dynamic data objects. + +"Static data object +DATA do_h_c5 TYPE c LENGTH 3. +"Dynamic data object +DATA do_i_str TYPE string. + +"Assignments +do_h_c5 = 'abc'. +do_h_c5 = 'defghi'. "only 'def' assigned -> length and memory use do not change + +"Memory consumption changes for dynamic data objects +do_i_str = `abc`. +do_i_str = `d`. +do_i_str = `efghijklmnopqrstuvwxyz`. + +"------------------------ Static type and dynamic type ----------------------- +"Both are data types of a reference variable (reference type) that determine +"the objects a reference variable can point to. +"Static type: For data reference variables, the static type is a data type +" that is always more general than or the same as the dynamic type. +"Dynamic type: For a reference variable, the dynamic type is always more special +" than or equal to the static type. + +"Static type +DATA dref_a_i TYPE REF TO i. "Static type is i +DATA dref_b_data TYPE REF TO data. "Static type can also be generic + +"Creating data objects to refer to +DATA do_j_i TYPE i VALUE 3. +DATA do_k_str TYPE string VALUE `hallo`. + +"Dynamic types +dref_a_i = REF #( do_j_i ). "Only type i possible; the dynamic type is the same + +"The dynamic type is more special than the static type (which is the generic +"type data in this case) +dref_b_data = REF #( do_j_i ). +dref_b_data = REF #( do_k_str ). +dref_b_data = REF #( dref_a_i ). + +"------------------------ Flat and deep data objects ----------------------- +"Flat: +"- Property of a data type, where the content of its data objects represents +" the actual work data. +"- All elementary data types except string and xstring are flat +"Deep: +"- Dynamic data objects and reference variables are deep, and they contain +" references that refer to the actual content. +"- The handling of references is implicit for dynamic data objects (strings +" and internal tables), and explicit for reference variables. +"- Structures that do not contain any deep components are flat structures. +" Structures that contain at least one deep component are deep structures. + +"Flat elementary data object +DATA do_l_i TYPE i. + +"Flat structure +DATA: BEGIN OF struc_b_flat, + comp1 TYPE i, + comp2 TYPE c LENGTH 3, + END OF struc_b_flat. + +"Deep elementary data object +DATA do_m_str TYPE string. + +"Deep structure +DATA: BEGIN OF struc_c_deep, + comp1 TYPE i, + comp2 TYPE c LENGTH 3, + comp3 TYPE string, "string as deep data object + comp4 TYPE string_table, "internal table as deep data object + END OF struc_c_deep. + +"---------------------- Named and unnamed data object --------------------- +"Named: Data object that can be identified via a name. +"Unnamed: Data object that cannot be addressed by a name. Unnamed data +" objects are literals and anonymous data objects. + +"Named data objects +DATA do_n_i TYPE i. +CONSTANTS con_b_str TYPE string VALUE `hi`. + +"Unnamed data objects +"Literal that is output. It cannot be addressed via a dedicated name. +out->write( `I'm a literal...` ). + +"Anonymous data object created using the NEW operator +"Can be addressed using reference variables or field symbols. + +DATA(dref_c_str) = NEW string( `hi` ). + +"Anonymous data object created inline using the NEW addition to the INTO +"clause of a SELECT statement +SELECT * + FROM zdemo_abap_carr + INTO TABLE NEW @DATA(dref_d_tab) + UP TO 3 ROWS. + +"--- Compatibility, convertibility and conversion regarding source and --- +"--- target data objects ------------------------------------------------- +"1. Source and target are compatible, all technical type properties +" match +DATA some_dobj TYPE c LENGTH 1 VALUE 'A'. +DATA flag TYPE abap_bool VALUE 'X'. + +"Assignment of compatible types; content transferred without +"conversion +some_dobj = flag. + +"2. Source and target are not compatible but can be converted. +" Content of source is converted according to conversion rules +" and then transferred to the target. Two data types are +" convertible if a conversion rule exists for them. +DATA another_char TYPE c LENGTH 3 VALUE 'abc'. +DATA some_str TYPE string VALUE `defghij`. + +another_char = some_str. + +"3. Data objects are neither compatible nor convertible. No +" assignment possible. If recognized by the syntax check, a +" syntax error is raised, otherwise an uncatchable exception +" is raised when the program is executed. +DATA some_number TYPE i VALUE 123. +DATA itab_str TYPE string_table. + +"Type conversion not possible +"itab_str = some_number. +"some_number = itab_str. +``` + +

⬆️ back to top

+ +## Notes on the Declaration Context + +The declaration context of data types (and objects) determines the validity and visibility. + +- Program-local data types with `TYPES` statements + - Local declarations in procedures + - For example, methods. The local data and types can only be addressed within the method itself. + - Class and interface attributes + - Data types and objects can be declared in the declaration part of classes and interfaces. In classes, the visibility sections, as the name implies, determine how the attributes are visible. For example, attributes declared in the `PUBLIC SECTION` are visible globally. + - Note the difference between [static](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstatic_attribute_glosry.htm) and [instance attributes](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_attribute_glosry.htm). Instance attributes of classes are bound to the lifetime of objects. They are created when an object is instantiated. +- Program-independent data types + - Declarations in the ABAP Dictionary, which is a special storage for the declarations of data types that are visible in all repository objects, provided that the [package](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenpackage_glosry.htm) check allows this. + - The data types of the ABAP Dictionary are not declared with the `TYPES` statement, but using ADT tools (and/or SAP GUI tools in systems where SAP GUI is available). + - The DDIC has many more [built-in types](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbuiltin_ddic_type_glosry.htm) than ABAP. These types have other names. They cannot be used in ABAP programs. + - The DDIC provides many options for defining types, including elementary data types (defined as data elements), reference types, complex types such as structured types and table types. Note that the name of a database table or a view can be used in type declarations to address the line type of these repository objects (for example, a structure: `DATA a TYPE some_db_table.`). + - Note the following trap: Local declarations hide global declarations of the same name. + +

⬆️ back to top

+ +## Excursions +### Enumerated Types and Objects +- ABAP supports the concept of enumerations. +- Enumerations are a mixture of types and constants. +- An [enumerated type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenum_type_glosry.htm) specifies a value set in addition to the actual type properties. +- [Enumerated objects](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_object_glosry.htm) - data objects with an enumerated type - are mainly used to check allowed values. This usually restricts the actual parameters passed to methods to the enumerated values defined in the class. [Enumerated variables](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_variable_glosry.htm) are variable enumerated objects. They can only contain the associated enumerated values. + +Syntax: + +```abap +"The definition of an enumerated type in ABAP declares its enumerated constants (these are special enumerated objects). +"a) In the case below, no explicit base type is specified. Then, the standard base type of the constants is i. The +" enumerated values are counted up starting with 0 (a -> 0, b -> 1 ...). + +TYPES: BEGIN OF ENUM t_enum, + a, + b, + c, + d, + END OF ENUM t_enum. + +"b) Explicit base type is specified and start values provided using the VALUE addition +" Note that one value must be initial. + +TYPES: basetype TYPE c LENGTH 2, + BEGIN OF ENUM t_enum_base BASE TYPE basetype, + e VALUE IS INITIAL, + f VALUE 'u', + g VALUE 'v', + h VALUE 'wx', + i VALUE 'yz', + END OF ENUM t_enum_base. + +"c) Optionally an enumerated structure can be declared in the context of the type declaration. +" A component of an enumerated structure: An enumerated constant that exists as a component +" of a constant structure, not as a single data object. + +TYPES: BEGIN OF ENUM t_enum_struc STRUCTURE en_struc BASE TYPE basetype, + j VALUE IS INITIAL, + k VALUE 'hi', + l VALUE 'ab', + m VALUE 'ap', + END OF ENUM t_enum_struc STRUCTURE en_struc. +``` + +Enumerated variables can be declared by referring to the enumerated type. +They can only be assigned the enumerated values defined there that exist as the content of enumerated constants or components of an enumerated structure. + +```abap +DATA dobj_enum TYPE enum_type. + +dobj_enum = a. +``` + +Find more information on enumerated types in the (commented code of the) cheat sheet example and [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenenumerated_types_usage.htm). + +

⬆️ back to top

+ +### Getting Type Information and Creating Types at Runtime +Using [Runtime Type Identification (RTTI)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm "Glossary Entry"), you can get type information on data objects, data types or [instances](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abeninstance_glosry.htm "Glossary Entry") at runtime ([Runtime Type Identification (RTTI)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrun_time_type_identific_glosry.htm "Glossary Entry")). +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 data 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. + +Find more information in the [cheat sheet about dynamic programming](06_Dynamic_Programming.md#runtime-type-services-rtts). + +### Ranges Tables + +- Internal tables that have the predefined columns `SIGN`, `OPTION`, `LOW`, and `HIGH` +- Declared with the `TYPE RANGE OF` addition in `DATA` and `TYPES` statements +- Used to store range conditions that can be evaluated in expressions using the `IN` operator (each row in the table represents a separate comparison) + +```abap +"Populating an integer table with values from 1 to 20 +TYPES int_tab_type TYPE TABLE OF i WITH EMPTY KEY. +DATA(inttab) = VALUE int_tab_type( FOR x = 1 WHILE x <= 20 ( x ) ). + +"Declaring a ranges table +DATA rangestab TYPE RANGE OF i. + +"Populating a ranges table using VALUE +rangestab = VALUE #( sign = 'I' + option = 'BT' ( low = 1 high = 3 ) + ( low = 6 high = 8 ) + ( low = 12 high = 15 ) + option = 'GE' ( low = 18 ) ). + +"Using a SELECT statement and the IN addition to retrieve internal table +"content based on the ranges table specifications +SELECT * FROM @inttab AS tab + WHERE table_line IN @rangestab + INTO TABLE @DATA(result). +"result: 1, 2, 3, 6, 7, 8, 12, 13, 14, 15, 18, 19, 20 + +``` + +

⬆️ back to top

+ +## Executable Example + +[zcl_demo_abap_dtype_dobj](./src/zcl_demo_abap_dtype_dobj.clas.abap) + +> **💡 Note**
+> - The executable example ... +> - covers, among others, the following topics: +> - Declaring data types +> - Declaring data objects, inline declarations +> - Assignments +> - Creating anonymous data objects +> - Type conversions +> - Getting type information (Runtime Type Information/RTTI) +> - Constants, immutable variables +> - Generic types +> - Enumerated types and objects +> - does not have as many things to be output compared to other ABAP cheat sheet executable examples. The focus is on syntax options and declarations. In the class, you can set breakpoints and use the debugger to check out data objects. You can also use the F2 information for the many types and data objects. Simply select a type or object in the code and press F2 in ADT to check out the information. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + + diff --git a/17_SAP_LUW.md b/17_SAP_LUW.md index 7e29e18..b0228e3 100644 --- a/17_SAP_LUW.md +++ b/17_SAP_LUW.md @@ -1,457 +1,445 @@ - - -# SAP LUW -- [SAP LUW](#sap-luw) - - [Introduction](#introduction) - - [Terms](#terms) - - [SAP LUW Overview](#sap-luw-overview) - - [Bundling Techniques](#bundling-techniques) - - [Related ABAP Statements](#related-abap-statements) - - [Concepts Related to the SAP LUW](#concepts-related-to-the-sap-luw) - - [The SAP LUW in ABAP Cloud and RAP](#the-sap-luw-in-abap-cloud-and-rap) - - [Controlled SAP LUW](#controlled-sap-luw) - - [More Information](#more-information) - - [Executable Example](#executable-example) - -## Introduction - -⚠️ The concept is relevant to both ABAP Cloud and classic ABAP, but some of the statements covered in the cheat sheet and the executable example are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). - -This cheat sheet provides a high-level overview of the [SAP LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_luw_glosry.htm) concept that deals with data consistency with a focus on SAP LUW-related statements, supported by an executable example to check the syntax in action. - -When you run an application, you typically change data in a [transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_glosry.htm), which may be temporarily stored in transactional buffers. -This data may be temporarily inconsistent in the buffers, but it is important that the data be in a consistent state at the end of the transaction so that it can be saved to the database. - -Consider the following example of transactional consistency: -- A transaction consists of a money transfer from account A to account B, assuming the accounts are in the same bank and the data is stored in the same database. -- Such a transaction represents a logical unit. The transaction is successful when the money is debited from account A and credited to account B. -- This transaction may include other related tasks. Data may be loaded into a buffer, processed there, and become inconsistent during this time. It may also take a while for the whole process to be completed. -- However, at the end of the transaction, all data must be in a consistent state so that the database can be updated accordingly. Or, if errors occur during the transaction, it must be ensured that all changes can be reversed. It must not happen that money is credited to account B without also updating the totals of account A. In such a case, the previous consistent state must be restored. - -> **💡 Note**
-> - This cheat sheet focuses on [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). Hence, the links in this cheat sheet open topics in the ABAP Keyword Documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm). -> - The SAP LUW concept is certainly relevant to ABAP Cloud, too. The [ABAP RESTful Application Programming Model (RAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarap_glosry.htm) is the transactional programming model for [ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_cloud_glosry.htm). It comes with a well-defined transactional model and follows the rules of the SAP LUW. Find out more in this [blog](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/). - -## Terms - -The following terms are related to the concept of the SAP LUW and try to give you some context about it: - -- [Transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_glosry.htm) - - In a business context, a transaction describes a sequence of related and/or interdependent actions, such as retrieving or modifying data. - - The result of the transaction is a consistent state of data in the database. - -- [Logical unit of work (LUW)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenluw_glosry.htm) - - Describes the time interval at which one consistent state of the database is transitioned to another consistent state. - - Follows an all-or-nothing approach: It ends either with a single and final commit, which saves the changed data in the database, or with a rollback, which undoes all changes and restores the consistent state before the changes (for example, in the case of an error during the LUW). Either all data changes are committed, or none at all. - - For an [Application Server ABAP (AS ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenas_abap_glosry.htm), two types of LUWs come into play to achieve data consistency: Database LUW and SAP LUW (which is covered below). - -- [Database LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_luw_glosry.htm) - - Also called database transaction. - - Is an SAP-independent mechanism for transactional consistency in the database. - - Describes an indivisible sequence of database operations concluded by a [database commit](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_commit_glosry.htm), that persists data to the database. - - The [database system](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_system_glosry.htm) either executes the database LUW completely or not at all. If an error is detected within a database LUW, a [database rollback](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_rollback_glosry.htm) undoes all database changes made since the start of the database LUW. - -- [Database commit](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_commit_glosry.htm) - - Marks the end of a database LUW in which changed data records are written to the database. - - An important question for developers is how and when database commits and rollbacks are triggered (especially implicitly). - - In AS ABAP, database commits can be triggered implicitly as well as by means of explicit requests. - - Find more information [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendb_commit.htm). - -- Implicit database commits. Among others, implicit database commits are triggered by: - - Completing a [dialog step](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_step_glosry.htm) in the context of dynpros - - A dialog step describes the state of a [user session](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_session_glosry.htm) between a [user action](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_action_glosry.htm) on the user interface of a dynpro and the sending of a new [screen layout](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_glosry.htm), i.e. it covers logic implemented in the [PAI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpai_glosry.htm) of the current dynpro and [PBO](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpbo_glosry.htm) of the following dynpro - - When the next screen is displayed, the program waits for a user action and does not occupy a [work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) during this time. - - The next free work process is assigned to the program in the next dialog step. - - A work process change requires and implicitly triggers a database commit. - - Calling a [function module](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_module_glosry.htm) in a [synchronous (sRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensynchronous_rfc_glosry.htm) or [asynchronous remote function call (aRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenasynchronous_rfc_glosry.htm) - - This is when the current work process passes control to another work process or system. Exception: [Updates](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_glosry.htm). - - HTTP/HTTPS/SMTP communication executed using the [Internet Communication Framework (ICF)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenicf_glosry.htm) - - [`WAIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapwait_up_to.htm) statements that interrupt the current work process - - Sending messages ([error messages](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenerror_message_glosry.htm), [information message](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninformation_message_glosry.htm), and [warning](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwarning_glosry.htm)) - -- Explicit database commits. For example, database commits can be triggered explicitly in ABAP programs in the following ways: - - Using the relevant database-specific [Native SQL](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abennative_sql_glosry.htm) statement - - Using the ABAP SQL statement [`COMMIT CONNECTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_rollback_connection.htm) - - Calling the function module `DB_COMMIT`, which encapsulates the corresponding Native SQL statement. - - Using the ABAP SQL statement [`COMMIT WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit.htm). Note that the statement is particularly relevant to the SAP LUW as shown below. It also ends the SAP LUW. - -- [Database rollback](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_rollback_glosry.htm) - - Like a database commit, ... - - a database rollback marks the end of a database LUW. Here, all modifying database operations are undone until the beginning of the LUW. - - are triggered implicitly, as well as by explicit requests. - - They are implicitly triggered, for example, by a [runtime error](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenruntime_error_glosry.htm) or a [termination message](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentermination_message_glosry.htm) (message of type `A`). - - For example, explicit rollbacks are triggered by: - - Using the relevant database-specific Native SQL statement - - Using the ABAP SQL statement [`ROLLBACK CONNECTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_rollback_connection.htm) - - Calling the function module `DB_ROLLBACK`, which encapsulates the corresponding Native SQL statement. - - Using the ABAP SQL statement [`ROLLBACK WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback.htm). Note that the statement is particularly relevant to the SAP LUW as shown below. It also ends the SAP LUW. - -- [Work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) - - As a component of an AS ABAP AS instance, work processes execute ABAP applications. Each ABAP program that is currently active requires a work process. - - AS ABAP uses its own work processes to log on to the database system. Different types of work processes are available for applications, including dialog, enqueue, background, spool, and update work processes. - - As mentioned earlier, in dialog processing, a work process is assigned to an ABAP program for the duration of a dialog step. An application program can be divided into several program sections and, in the case of dynpros, into several dialog steps that are processed sequentially by different work processes. - - For example, in the context of a dynpro, when a dialog step that is waiting for user interaction completes, the work process is released (for another workload) and a new work process is assigned. The current workload is persisted and resources are released. This approach requires an (implicit) database commit that ends the database LUW. - - A work process can execute only a single database LUW. It cannot interfere with the database LUWs of other work processes. - - -

⬆️ back to top

- - -## SAP LUW Overview - -For an [SAP LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_luw_glosry.htm), the following aspects come into play: - -- Usually, an SAP LUW is started by opening a new [internal session](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninternal_session_glosry.htm). The execution of programming units can be distributed among several work processes. -- Database commits persist data in the database (especially implicit database commits when work processes are switched). -- The all-or-nothing rule applies: All database changes that occur during a transaction constitute a logical unit of work. They must be committed together, or rolled back together in the event of an error. -- This means that all database changes must be deferred and made in a final database commit (that is, in a single database LUW) at the end of a transaction - not in between. -- To ensure data consistency, all database changes are bundled, for example, in temporary tables or transactional buffers, and then, at the end of the transaction, all changes are written to the database together in a single work process, that is, in a single database LUW with a single database commit. This can be done directly using ABAP SQL statements at this stage, or using bundling techniques - special ABAP programming techniques. - -Using the above bank transfer as an example: -- At the end of the transaction, the new totals of both accounts are updated (money is debited from account A and credited to B). -- You cannot debit account A in one work process and then credit account B in a separate work process. When the work process changes, new totals would be available in one account, but not in the other. -- Consider the consequences if an error occurs and the new totals for account B cannot be updated, and so on. You would no longer be able to easily roll back the changes. Consider prematurely updating the database and notifying the users or processing the data while the logical unit has not been successfully completed. - -

⬆️ back to top

- -### Bundling Techniques -The following bundling techniques are available for classic ABAP. This means that programming units are registered in different work processes, but are executed by a single work process. All database changes are put into one database LUW, and all changes are committed in one final database commit. - -**Using [update function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_function_module_glosry.htm)** -- Are specially marked, i.e. the *update module* property is marked -- Can be given specific attributes to determine the priority with which they are processed in the update work process -- Usually contain database modification operations/statements -- [`CALL FUNCTION ... IN UPDATE TASK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_function_update.htm) statements are used to register the update function modules for later execution; the actual execution is triggered by a `COMMIT WORK` statement - -- Example of a simple function module that has an importing parameter (a structure that is used to modify a database table). It simply shows a database modifying statement contained in a function module. The code alone does not distinguish it as an update function module. For example, check the example function modules from the imported repository that are used in the executable example. In ADT, right-click a function module and choose *Open with → SAP GUI*. In SAP GUI, choose the *Attributes* tab. The *Update Module* checkbox is selected. - ```abap - FUNCTION zsome_update_fu_mod - IMPORTING - VALUE(values) TYPE some_dbtab. - - MODIFY some_dbtab FROM @values. - - ENDFUNCTION. - ``` - -- Depending on your use case, you can run the update work process in several ways: - - [Synchronous update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensynchronous_update_glosry.htm): The calling program waits until the update work process has finished. The `COMMIT WORK` statement with the `AND WAIT` addition triggers a synchronous update in a separate update work process. - - [Asynchronous update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenasynchronous_update_glosry.htm): The calling program does not wait for the update work process to finish. The `COMMIT WORK` statement triggers an asynchronous update in a separate update work process. - - [Local update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlocal_update_glosry.htm): The update is performed immediately in the current work process in a separate internal session and not in a separate update work process. This is true regardless of whether `COMMIT WORK` is used with `AND WAIT` or not. By default, the local update is deactivated at the start of each SAP LUW. If required, you can activate local update for an SAP LUW using the [`SET UPDATE TASK LOCAL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_update_task_local.htm) statement before registering the update function modules. - - - ```abap - "Synchronous update - - DATA(st_a) = VALUE some_type( ... ). - - ... - - "Registering the update function module specified in uppercase letters - CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK - EXPORTING values = st_a. - - ... - - "Triggering the synchronous update - COMMIT WORK AND WAIT. - - *********************************************************************** - "Asynchronous update - - DATA(st_b) = VALUE some_type( ... ). - - ... - - CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK - EXPORTING values = st_b. - - ... - - "Triggering the asynchronous update - COMMIT WORK. - - *********************************************************************** - "Local update - - "Before update function modules are registered. - SET UPDATE TASK LOCAL. - - DATA(st_c) = VALUE some_type( ... ). - - ... - - CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK - EXPORTING values = st_c. - - ... - - "The update will be synchronous no matter if you use the COMMIT WORK - "statement with or without the addition AND WAIT. - COMMIT WORK. - "COMMIT WORK AND WAIT. - ``` - -> **💡 Note**
-> If a runtime error occurs during the update, the update work process executes a database rollback, and notifies the user whose program created the entries. - -**Using [remote-enabled function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenremote_enabled_fm_glosry.htm)** -- Also in this case, the bundling is done through function modules. -- They are also specially marked as remote-enabled function modules. -- For example, you can register them for later asynchronous execution in the background and through the [RFC interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrfc_interface_glosry.htm) ([background Remote Function Call (bgRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbg_remote_function_glosry.htm)). With this technology, you can make calls in the same or different ABAP systems. -- More information: - - [SAP Help Portal documentation about RFC](https://help.sap.com/docs/ABAP_PLATFORM_NEW/753088fc00704d0a80e7fbd6803c8adb/4888068AD9134076E10000000A42189D) - - [`CALL FUNCTION ... IN BACKGROUND UNIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_function_background_unit.htm) - - Note the [background processing framework (bgPF)](https://help.sap.com/docs/abap-cloud/abap-concepts/background-processing-framework) as a successor technology - -**Using [subroutines](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensubroutine_glosry.htm)** -- Subroutines (that are no longer recommended for use ⚠️) can be registered for later execution. - -- They are registered with the [`PERFORM ... ON COMMIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapperform_on_commit.htm) statement. These subroutines are executed when a `COMMIT WORK` statement is called. -- An addition is available to control the order of execution. -- Similarly, a subroutine can be registered "on rollback" with [`PERFORM ... ON ROLLBACK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapperform_on_commit.htm). These subroutines are executed when a `ROLLBACK WORK` statement is called. -- When executed: - - In the current work process, before update function modules. - - When they are registered in an update function module with `ON COMMIT`, they are executed at the end of the update. This happens in the update work process for non-local updates, and in the current work process for local updates. - -

⬆️ back to top

- -### Related ABAP Statements - -An SAP LUW is usually started by opening a new internal session. -The statements to end an SAP LUW have already been mentioned above: [`COMMIT WORK [AND WAIT]`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit.htm) and [`ROLLBACK WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback.htm). - -`COMMIT WORK [AND WAIT]` -- Closes the current SAP LUW and opens a new one. -- Commits all change requests in the current SAP LUW. -- Among other things, this statement triggers ... - - the processing of all registered update function modules. - - the update work process and the local updates in the current work process. - - a database commit for all currently open [database connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_connection_glosry.htm), which also terminates the current database LUW. -- Note that `COMMIT WORK` triggers an asynchronous, `COMMIT WORK AND WAIT` a synchronous update. - -`ROLLBACK WORK` -- Similar to `COMMIT WORK` statements, this statement closes the current SAP LUW and opens a new one. -- Among other things, this statement ... - - causes all changes within a SAP LUW to be undone, that is, all previous registrations for the current SAP LUW are removed. - - triggers a database rollback on all currently open database connections, which also terminates the current database LUW. - -> **💡 Note**
-> Notes on database connections: -> - The [database interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_interface_glosry.htm) uses the [standard connection](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_db_connection_glosry.htm) of the current work process to access the [standard database](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_db_glosry.htm) by default. -> - Optionally, database accesses can also be made by using [secondary connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_db_connection_glosry.htm) to [secondary databases](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_db_glosry.htm) or by using [service connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenservice_connection_glosry.htm) to the standard database. The secondary connections are usually used by technical components. For example, they are used for caches, traces, logs, and so on. -> - The implicit database rollback is performed on all database connections that are currently open. -> - Within the SAP LUW, database changes and commits are allowed on service connections or through secondary database connections. - - -

⬆️ back to top

- -## Concepts Related to the SAP LUW -The following concepts are related to the SAP LUW to ensure transactional consistency. They are not discussed in detail here. For more information, see the links. - -**Authorization concept** -- In an SAP system, you need to protect data from unauthorized access by making sure that only those [authorized](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenauthorization_glosry.htm) to access it can see and modify it. -- Authorization to access data can be set. Before a user can perform certain operations in your application, you need to implement authorization checks. -- Since ABAP SQL statements do not trigger any [authorization checks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenauthorization_check_glosry.htm) in the database system, this is even more important. Database tables may be accessed without restriction using these statements. Conversely, not all users in a system are authorized to access all data available to ABAP SQL statements. -- Thus, it is up to the programmer to ensure that each user who can call the program is authorized to access the data it handles. -- More information: - - [Authorizations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbc_authority_check.htm) - - [`AUTHORITY-CHECK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapauthority-check.htm) - - -**Lock concept** -- The database system automatically sets [database locks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_lock_glosry.htm) when ABAP SQL statements are called to modify database table entries. -- These locks are implemented by automatically setting a lock flag, which can only be set for existing database table entries. -- After a database commit, these flags are removed. -- As a result, database locks are not available for more than one database LUW, which must be considered in the context of an SAP LUW, since multiple database LUWs may be involved. Therefore, the lock flags that are set in a transaction are not sufficient. For the duration of an entire SAP LUW, a lock on database entries must remain set. -- This is where the SAP lock concept comes into play, which is independent of the automatic database locks. It is based on [lock objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlock_object_glosry.htm). -- Lock objects ... - - are [repository objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrepository_object_glosry.htm) that are defined in the [ABAP Dictionary](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dictionary_glosry.htm). - - specify the database tables in which records are to be locked with a lock request. - - contain the key fields on which a lock is to be set. -- When a lock object is created, two [lock function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlock_function_module_glosry.htm) (`ENQUEUE_...` and `DEQUEUE_...`) are automatically generated. They are executed in a special enqueue work process. When a record is locked during a transaction (by the enqueue function module), a central lock table is filled with the table name and key field information. Unlike database locks, a locked entry in a lock object does not necessarily have to exist in a database table. Also, the locking must be done proactively, i. e. there is no automatic locking. You must make sure that the application implementation checks the lock entries. -- At the end of an SAP LUW, all locks should be released, either automatically during the database update or explicitly when you call the corresponding dequeue function module. -- More information: - - [SAP Locks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_lock.htm) - - Note the information on the `CL_ABAP_LOCK_OBJECT_FACTORY` class that is related to this context [here](https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/lock-objects). - -> **💡 Note**
-> For more information about related topics in RAP, see the sections [Authorization Control](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/375a8124b22948688ac1c55297868d06.html) and [Concurrency Control](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/d315c13677d94a6891beb3418e3e02ed.html) in the *Development guide for the ABAP RESTful Application Programming Model*. - -

⬆️ back to top

- -## The SAP LUW in ABAP Cloud and RAP - -A limited set of ABAP language features is available in ABAP Cloud ([restricted ABAP language version](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrestricted_version_glosry.htm)). -The limitations include the fact that the above bundling techniques are not available. Note that the local update is enabled by default in ABAP Cloud. Find more information in this [blog](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/). - -In fact, RAP is the transactional programming model for ABAP Cloud. -And RAP comes with a well-defined transactional model and follows the rules of the SAP LUW. At the end of an SAP LUW in RAP, database modification operations should be performed in a final step in the [RAP late save phase](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) by persisting the consistent data in the [RAP transactional buffer](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransactional_buffer_glosry.htm) to the database. - -There are RAP-specific [ABAP EML](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_eml_glosry.htm) statements for commit and rollback: -- [`COMMIT ENTITIES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_entities.htm) implicitly triggers `COMMIT WORK`. Furthermore, `COMMIT ENTITIES` provides RAP-specific functionality with various additions. These EML statements implicitly enforce local updates with `COMMIT WORK`, or `COMMIT WORK AND WAIT` if the local update fails. Therefore, the update is either a local update or a synchronous update, but never an asynchronous update. -- [`ROLLBACK ENTITIES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback_entities.htm): Resets all changes of the current transaction and clears the transactional buffer. The statement triggers `ROLLBACK WORK`. -- Find more information in the [ABAP cheat sheet about EML](08_EML_ABAP_for_RAP.md). - -

⬆️ back to top

- -## Controlled SAP LUW - -- The *controlled SAP LUW* is an enhancement to the SAP LUW concept. -- It introduces a check mechanism to detect violations of [transactional contracts](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_contract_glosry.htm) to guarantee transactional consistency. -- Such contracts specify which ABAP statements and operations are allowed and which are not allowed in a [transactional phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentr_phase_glosry.htm). -- In this way, applications can be made more robust and the SAP LUW can be made more tangible. -- Violations that are detected result in a runtime error (or are logged). -- There are mainly two transactional phases: *modify* and *save*. -- In RAP, these two phases are set implicitly, and they are subdivided as follows (see more information in the EML cheat sheet and the RAP guide): - - *modify* - - [RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm) - - [RAP early save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenearly_rap_save_phase_glosry.htm) - - *save* - - [RAP late save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) -- Using the static methods `modify` and `save` of the `CL_ABAP_TX` class, you can activate the transactional phases explicitly. -- The controlled SAP LUW is automatically and implicitly supported by newer ABAP concepts such as RAP (i.e. the transactional phases are implicitly active when RAP handler methods are called), [background Processing Framework (bgPF)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbgpf_glosry.htm), and local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm). -- Furthermore, transactional contracts define where (i. e. in which transactional phase) a [classified API](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassified_api_glosry.htm), such as a method of a class, can be used. The classifications start with `IF_ABAP_TX_...`, for example, `IF_ABAP_TX_SAVE`, and are, in the case of methods, typcially included as types in the local types of the class ([CCDEF include](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenccdef_glosry.htm), *Class-Relevant Local Types* tab in ADT). The classifications detail out and restrict the scope of use, so as not to use a classified API in phases where not allowed. Follow the links below for more information. - - Example of a classified API: Open the class `CL_BCS_MAIL_MESSAGE` (which is used for sending emails). In ADT, go to the *Class-Relevant Local Types* tab, and find classifications for methods, for example, the `send_async` method. Calling this method in the *modify* transactional phase results in a violation. You can also get information about the transactional contract using the F2 information in ADT. In the case of the method mentioned, choose F2 on `send_async` (`... cl_bcs_mail_message=>create_instance( ... )->send_async( ). ...`) to view the transactional contract information. -- Regarding the concrete restrictions and for more information, follow the links. -- Examples for violations, such as database modifications. They are only allowed in the *save* transactional phase because the data being processed in the *modify* phase may be inconsistent: - - Database modification (e.g. `MODIFY dbtab FROM @row.`) performed when the *modify* transactional phase is active. - - Database modifcation in a [RAP handler method](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm) implementation. Here, the *modify* transactional phase is active by default. - - Database modifcation in a [RAP event handler method](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_meth_glosry.htm) implementation when the *save* transactional phase has not been activated explicitly. Note: When RAP event handler methods are called, they are started in the *modify* transactional phase. Modifying a database right away there, without the activation of the *save* phase, means a violation. - - Calling a classified API in a phase where not allowed, such as `... cl_bcs_mail_message=>create_instance( ... )->send_async( ). ...` (classified with `IF_ABAP_TX_SAVE`) in the *modify* transactional phase. -- More information: - - [Controlled SAP LUW](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw) in the SAP Help Portal - - ABAP Keyword Documentation (Standard ABAP): - - [Restrictions in Transactional Phases](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapinvalid_stmts_in_tx.htm) - - [API Classifications](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapapi_classification.htm) - - [Restrictions in RAP Handler and Saver Methods](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapinvalid_stmts_in_rap_methods.htm) - - -Example using `CL_ABAP_TX`: - -```abap -... - -"Activating the modify transactional phase -cl_abap_tx=>modify( ). - -"The following database modification statement is not allowed in the -"modify transactional phase. In certain contexts, e.g. in ABAP Cloud, -"the runtime error BEHAVIOR_ILLEGAL_STMT_IN_CALL occurs. -MODIFY zdemo_abap_carr FROM TABLE @( VALUE #( - ( carrid = 'XY' - carrname = 'XY Airlines' - currcode = 'EUR' - url = 'some_url' ) ) ). - -... - -"Activating the save transactional phase -cl_abap_tx=>save( ). - -"In this phase, database modifications are allowed. -MODIFY zdemo_abap_carr FROM TABLE @( VALUE #( - ( carrid = 'XY' - carrname = 'XY Airlines' - currcode = 'EUR' - url = 'some_url' ) ) ). -... -``` - -

⬆️ back to top

- -## More Information -- [The RAP Transactional Model and the SAP LUW](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/ccda1094b0f845e28b88f9f50a68dfc4.html) (Development guide for the ABAP RESTful Application Programming Model) -- [The SAP LUW in ABAP Cloud](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/) (blog) -- [SAP LUW in the ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw.htm) -- [Controlled SAP LUW](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw) as an enhancement of the SAP LUW concept - -

⬆️ back to top

- -## Executable Example - -After the import of the repository, proceed as follows: -- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. -- Enter `zdemo_abap_sap_luw` and open the program. -- Run the program by choosing `F8`. - -> **💡 Note**
-> - The executable example ... -> - demonstrates the SAP LUW using classic dynpros to provide a self-contained and simple example that highlights the considerations regarding implicit database commits, without putting the spotlight on dynpros. Note that classic dynpros are outdated for application programs. New developments should use web-based UIs, such as SAPUI5 or Web Dynpro. -> - covers the following topics in simple contexts: -> - Demonstrating synchronous update, asynchronous update, and local update triggered by `COMMIT WORK`, `COMMIT WORK AND WAIT`, and `SET UPDATE TASK LOCAL` using update function modules. -> - Demonstrating the statements `PERFORM ... ON COMMIT` and `PERFORM ... ON ROLLBACK` using subroutines. -> - does not claim to include meaningful dynpros with meaningful dynpro sequences and is not intended to be a role model for proper dynpro design. -> - is not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. -> - is only intended to demonstrate a selection of keywords and visualize SAP LUW-related syntax in action on a high level. -> - is explained in more detail in the expandable section below. Click to view the details. -> - Dynpros cannot be created in ABAP Cloud. As mentioned earlier, RAP is the transactional programming model for ABAP Cloud. It comes with a well-defined transactional model and follows the rules of the SAP LUW. See the links in the [More Information](#more-information) section. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) - - -
-
- Expand to see explanations of the executable example - -
-The example demonstrates the SAP LUW using dynpros and bundling techniques with update function modules and subroutines. In the dynpros, you can select various options that determine how the program runs. It covers the following aspects: - -- Demonstrating synchronous update, asynchronous update, and local update triggered by `COMMIT WORK`, `COMMIT WORK AND WAIT`, and `SET UPDATE TASK LOCAL` using update function modules. -- Demonstrating the statements `PERFORM ... ON COMMIT` and `PERFORM ... ON ROLLBACK` using subroutines. - - - -The selection options follow this pattern: - -**First dynpro**: -- The SAP LUW is started. -- The entries in a database table are displayed. There are four entries in total. -- After you have selected an option to continue with either the update task, or the update task and perform a local update, or subroutines, an update function module or subroutine is registered to delete all entries from the database table. - -**Second dynpro**: -- You can create a new database table entry by making entries in input fields displayed on the dynpro. -- When the program continues, it registers an update function module or subroutine that inserts the new entry into the database table. - -**Third dynpro**: -- The SAP LUW is ended. You have several options for ending the SAP LUW. -- In addition to the `COMMIT WORK` and `COMMIT WORK AND WAIT` statements, you can use `ROLLBACK WORK` to roll back the changes. -- Another option is to deliberately make the current SAP LUW fail. If a type A message is triggered, the SAP LUW is also terminated. - -During program execution, logs are collected and eventually written to a database table (also using an update function module or subroutine). These logs document the progress of the transaction with various pieces of information. These include work process information, SAP LUW key retrieval, and transaction state retrieval (using methods of the `CL_SYSTEM_TRANSACTION_STATE` class). - -If the program is not terminated immediately and the SAP LUW has ended, another program is called that displays a dynpro. - -**Fourth dynpro** (part of a new program that is started): -- The database table entries and logs are displayed. -- If the transaction was successful, a single entry (the one created during the execution of the previous program) should be displayed for the modified database table, as well as the entries of the log table. -- Note that a helper class is available for this example. Methods perform various tasks, such as retrieving work process information. - -**Notes on the various options for checking out the SAP LUW:** - - **Asynchronous update** with `COMMIT WORK`: Immediately after the `COMMIT WORK` statement, a `SELECT` statement is executed, retrieving all the entries of the database table. In this case, the number of the retrieved entries should be the number of the original database table entries, i.e. 4 entries, and not 1, demonstrating the asynchronous update. The current number of records is displayed in a message. Result: The database table is deleted and a single new entry is added. -The log shows the value 1 for the transaction state after the update task is executed and the update function modules are called. - - **Synchronous update** with `COMMIT WORK AND WAIT`: Immediately after the `COMMIT WORK AND WAIT` statement, a `SELECT` statement is executed to retrieve all the entries in the database table. In this case, there should be one entry instead of four to demonstrate the synchronous update. The current number of records is displayed in a message. - - **Local update** using a `SET UPDATE TASK LOCAL` statement: Once the local update is enabled, it does not matter whether you choose `COMMIT WORK` or `COMMIT WORK AND WAIT` in the next step. It will be a synchronous update, so the number of current database table entries displayed in the message will be 1 in both cases. The log will show the value 1 for the transaction state after the `SET UPDATE TASK LOCAL` statement has been executed. - - **Rolling back changes**: Although update function modules or subroutines are registered, none of them affect the database. All changes are rolled back. Result: The database table is not deleted, no new entry is created. The original content of the database table should be displayed. - - **Causing a failure in the current SAP LUW**: An update function module intentionally includes a statement that causes a runtime error if not caught (zero division). All changes are rolled back implicitly. If the local update is active, you should be informed of the problem directly. The program is terminated. In this case, you can check the database table entries that remain unchanged. You can also use transaction ST22 to display the runtime error that occurred. In the case of a non-local update, you should receive a mail in the Business Workplace informing you of the problem in the SAP LUW. The original content of the database table should be displayed on the next screen. In this case, you can also check transaction ST22 for the runtime error. - - **Terminating the program with an error message** of type A: This option only indicates that if such a message is generated, the program is terminated and all changes are implicitly rolled back. In this case, you may want to check the database table entries that remain unchanged. -- **Using subroutines**: - - Note that subroutines are considered obsolete and should no longer be used. This is to demonstrate the effect as a bundling technique in an SAP LUW. Selecting this option triggers the registration of subroutines for commit (to delete the database table entry, insert a newly created entry, insert entries in the log table) and rollback (the subroutine in the example does not do anything specific; it is just to demonstrate that the subroutine is called in the event of a rollback). - - When you select the commit options, the subroutines registered with `ON COMMIT` are executed in the current work process. - - Choosing `COMMIT WORK` or `COMMIT WORK AND WAIT` has the same effect: When these statements are called and a `SELECT` statement follows, the number of database table entries is 1 in both cases. - - If the rollback option is selected, the subroutine registered with `ON ROLLBACK` is executed in the current work process. - - The transaction state in the log is 1 for `ON COMMIT` or `ON ROLLBACK` when the corresponding subroutines are called. - - Note that registered subroutines cannot have a parameter interface, so no parameters can be passed in this type of bundling. Therefore, data can only be passed through external interfaces, such as ABAP memory. In this example, the database table entry created is passed to and from ABAP memory using `EXPORT` and `IMPORT` statements. The subroutines do not implement the writes themselves, but instead call methods of a class. -- The following aspects are valid for all selected options regarding the logs: - - Before the commit is triggered (in the last PAI), the transaction state shows the value 0 for all retrieved transaction states. - - The work process information may change due to the fact that database commits are triggered when completing a dialog step. So you might expect different numbers there, but not necessarily. The new free work process can also be the same as the one before it was freed. However, there will be no different work process information for the update. The numbers will be the same because the update is performed in a single work process. - - Before calling the program that displays database entries and the log, the SAP LUW key is the same throughout the transaction. It does not change until a new SAP LUW is opened. See and compare the last entry for the SAP LUW key in the log that is retrieved for the program submitted. -
- - - - - - - - + + +# SAP LUW +- [SAP LUW](#sap-luw) + - [Introduction](#introduction) + - [Terms](#terms) + - [SAP LUW Overview](#sap-luw-overview) + - [Bundling Techniques](#bundling-techniques) + - [Related ABAP Statements](#related-abap-statements) + - [Concepts Related to the SAP LUW](#concepts-related-to-the-sap-luw) + - [The SAP LUW in ABAP Cloud and RAP](#the-sap-luw-in-abap-cloud-and-rap) + - [Controlled SAP LUW](#controlled-sap-luw) + - [More Information](#more-information) + - [Executable Example](#executable-example) + +## Introduction + +⚠️ The concept is relevant to both ABAP Cloud and classic ABAP, but some of the statements covered in the cheat sheet and the executable example are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). + +This cheat sheet provides a high-level overview of the [SAP LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_luw_glosry.htm) concept that deals with data consistency with a focus on SAP LUW-related statements, supported by an executable example to check the syntax in action. + +When you run an application, you typically change data in a [transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_glosry.htm), which may be temporarily stored in transactional buffers. +This data may be temporarily inconsistent in the buffers, but it is important that the data be in a consistent state at the end of the transaction so that it can be saved to the database. + +Consider the following example of transactional consistency: +- A transaction consists of a money transfer from account A to account B, assuming the accounts are in the same bank and the data is stored in the same database. +- Such a transaction represents a logical unit. The transaction is successful when the money is debited from account A and credited to account B. +- This transaction may include other related tasks. Data may be loaded into a buffer, processed there, and become inconsistent during this time. It may also take a while for the whole process to be completed. +- However, at the end of the transaction, all data must be in a consistent state so that the database can be updated accordingly. Or, if errors occur during the transaction, it must be ensured that all changes can be reversed. It must not happen that money is credited to account B without also updating the totals of account A. In such a case, the previous consistent state must be restored. + +> **💡 Note**
+> - This cheat sheet focuses on [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). Hence, the links in this cheat sheet open topics in the ABAP Keyword Documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm). +> - The SAP LUW concept is certainly relevant to ABAP Cloud, too. The [ABAP RESTful Application Programming Model (RAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenarap_glosry.htm) is the transactional programming model for [ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_cloud_glosry.htm). It comes with a well-defined transactional model and follows the rules of the SAP LUW. Find out more in this [blog](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/). + +## Terms + +The following terms are related to the concept of the SAP LUW and try to give you some context about it: + +- [Transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_glosry.htm) + - In a business context, a transaction describes a sequence of related and/or interdependent actions, such as retrieving or modifying data. + - The result of the transaction is a consistent state of data in the database. + +- [Logical unit of work (LUW)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenluw_glosry.htm) + - Describes the time interval at which one consistent state of the database is transitioned to another consistent state. + - Follows an all-or-nothing approach: It ends either with a single and final commit, which saves the changed data in the database, or with a rollback, which undoes all changes and restores the consistent state before the changes (for example, in the case of an error during the LUW). Either all data changes are committed, or none at all. + - For an [Application Server ABAP (AS ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenas_abap_glosry.htm), two types of LUWs come into play to achieve data consistency: Database LUW and SAP LUW (which is covered below). + +- [Database LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_luw_glosry.htm) + - Also called database transaction. + - Is an SAP-independent mechanism for transactional consistency in the database. + - Describes an indivisible sequence of database operations concluded by a [database commit](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_commit_glosry.htm), that persists data to the database. + - The [database system](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_system_glosry.htm) either executes the database LUW completely or not at all. If an error is detected within a database LUW, a [database rollback](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_rollback_glosry.htm) undoes all database changes made since the start of the database LUW. + +- [Database commit](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_commit_glosry.htm) + - Marks the end of a database LUW in which changed data records are written to the database. + - An important question for developers is how and when database commits and rollbacks are triggered (especially implicitly). + - In AS ABAP, database commits can be triggered implicitly as well as by means of explicit requests. + - Find more information [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendb_commit.htm). + +- Implicit database commits. Among others, implicit database commits are triggered by: + - Completing a [dialog step](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_step_glosry.htm) in the context of dynpros + - A dialog step describes the state of a [user session](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_session_glosry.htm) between a [user action](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_action_glosry.htm) on the user interface of a dynpro and the sending of a new [screen layout](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_glosry.htm), i.e. it covers logic implemented in the [PAI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpai_glosry.htm) of the current dynpro and [PBO](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpbo_glosry.htm) of the following dynpro + - When the next screen is displayed, the program waits for a user action and does not occupy a [work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) during this time. + - The next free work process is assigned to the program in the next dialog step. + - A work process change requires and implicitly triggers a database commit. + - Calling a [function module](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_module_glosry.htm) in a [synchronous (sRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensynchronous_rfc_glosry.htm) or [asynchronous remote function call (aRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenasynchronous_rfc_glosry.htm) + - This is when the current work process passes control to another work process or system. Exception: [Updates](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_glosry.htm). + - HTTP/HTTPS/SMTP communication executed using the [Internet Communication Framework (ICF)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenicf_glosry.htm) + - [`WAIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapwait_up_to.htm) statements that interrupt the current work process + - Sending messages ([error messages](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenerror_message_glosry.htm), [information message](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninformation_message_glosry.htm), and [warning](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwarning_glosry.htm)) + +- Explicit database commits. For example, database commits can be triggered explicitly in ABAP programs in the following ways: + - Using the relevant database-specific [Native SQL](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abennative_sql_glosry.htm) statement + - Using the ABAP SQL statement [`COMMIT CONNECTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_rollback_connection.htm) + - Calling the function module `DB_COMMIT`, which encapsulates the corresponding Native SQL statement. + - Using the ABAP SQL statement [`COMMIT WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit.htm). Note that the statement is particularly relevant to the SAP LUW as shown below. It also ends the SAP LUW. + +- [Database rollback](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_rollback_glosry.htm) + - Like a database commit, ... + - a database rollback marks the end of a database LUW. Here, all modifying database operations are undone until the beginning of the LUW. + - are triggered implicitly, as well as by explicit requests. + - They are implicitly triggered, for example, by a [runtime error](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenruntime_error_glosry.htm) or a [termination message](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentermination_message_glosry.htm) (message of type `A`). + - For example, explicit rollbacks are triggered by: + - Using the relevant database-specific Native SQL statement + - Using the ABAP SQL statement [`ROLLBACK CONNECTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_rollback_connection.htm) + - Calling the function module `DB_ROLLBACK`, which encapsulates the corresponding Native SQL statement. + - Using the ABAP SQL statement [`ROLLBACK WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback.htm). Note that the statement is particularly relevant to the SAP LUW as shown below. It also ends the SAP LUW. + +- [Work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) + - As a component of an AS ABAP AS instance, work processes execute ABAP applications. Each ABAP program that is currently active requires a work process. + - AS ABAP uses its own work processes to log on to the database system. Different types of work processes are available for applications, including dialog, enqueue, background, spool, and update work processes. + - As mentioned earlier, in dialog processing, a work process is assigned to an ABAP program for the duration of a dialog step. An application program can be divided into several program sections and, in the case of dynpros, into several dialog steps that are processed sequentially by different work processes. + - For example, in the context of a dynpro, when a dialog step that is waiting for user interaction completes, the work process is released (for another workload) and a new work process is assigned. The current workload is persisted and resources are released. This approach requires an (implicit) database commit that ends the database LUW. + - A work process can execute only a single database LUW. It cannot interfere with the database LUWs of other work processes. + + +

⬆️ back to top

+ + +## SAP LUW Overview + +For an [SAP LUW](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_luw_glosry.htm), the following aspects come into play: + +- Usually, an SAP LUW is started by opening a new [internal session](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninternal_session_glosry.htm). The execution of programming units can be distributed among several work processes. +- Database commits persist data in the database (especially implicit database commits when work processes are switched). +- The all-or-nothing rule applies: All database changes that occur during a transaction constitute a logical unit of work. They must be committed together, or rolled back together in the event of an error. +- This means that all database changes must be deferred and made in a final database commit (that is, in a single database LUW) at the end of a transaction - not in between. +- To ensure data consistency, all database changes are bundled, for example, in temporary tables or transactional buffers, and then, at the end of the transaction, all changes are written to the database together in a single work process, that is, in a single database LUW with a single database commit. This can be done directly using ABAP SQL statements at this stage, or using bundling techniques - special ABAP programming techniques. + +Using the above bank transfer as an example: +- At the end of the transaction, the new totals of both accounts are updated (money is debited from account A and credited to B). +- You cannot debit account A in one work process and then credit account B in a separate work process. When the work process changes, new totals would be available in one account, but not in the other. +- Consider the consequences if an error occurs and the new totals for account B cannot be updated, and so on. You would no longer be able to easily roll back the changes. Consider prematurely updating the database and notifying the users or processing the data while the logical unit has not been successfully completed. + +

⬆️ back to top

+ +### Bundling Techniques +The following bundling techniques are available for classic ABAP. This means that programming units are registered in different work processes, but are executed by a single work process. All database changes are put into one database LUW, and all changes are committed in one final database commit. + +**Using [update function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenupdate_function_module_glosry.htm)** +- Are specially marked, i.e. the *update module* property is marked +- Can be given specific attributes to determine the priority with which they are processed in the update work process +- Usually contain database modification operations/statements +- [`CALL FUNCTION ... IN UPDATE TASK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_function_update.htm) statements are used to register the update function modules for later execution; the actual execution is triggered by a `COMMIT WORK` statement + +- Example of a simple function module that has an importing parameter (a structure that is used to modify a database table). It simply shows a database modifying statement contained in a function module. The code alone does not distinguish it as an update function module. For example, check the example function modules from the imported repository that are used in the executable example. In ADT, right-click a function module and choose *Open with → SAP GUI*. In SAP GUI, choose the *Attributes* tab. The *Update Module* checkbox is selected. + ```abap + FUNCTION zsome_update_fu_mod + IMPORTING + VALUE(values) TYPE some_dbtab. + + MODIFY some_dbtab FROM @values. + + ENDFUNCTION. + ``` + +- Depending on your use case, you can run the update work process in several ways: + - [Synchronous update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensynchronous_update_glosry.htm): The calling program waits until the update work process has finished. The `COMMIT WORK` statement with the `AND WAIT` addition triggers a synchronous update in a separate update work process. + - [Asynchronous update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenasynchronous_update_glosry.htm): The calling program does not wait for the update work process to finish. The `COMMIT WORK` statement triggers an asynchronous update in a separate update work process. + - [Local update](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlocal_update_glosry.htm): The update is performed immediately in the current work process in a separate internal session and not in a separate update work process. This is true regardless of whether `COMMIT WORK` is used with `AND WAIT` or not. By default, the local update is deactivated at the start of each SAP LUW. If required, you can activate local update for an SAP LUW using the [`SET UPDATE TASK LOCAL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_update_task_local.htm) statement before registering the update function modules. + + + ```abap + "--------------------- Synchronous update --------------------- + DATA(st_a) = VALUE some_type( ... ). + + ... + + "Registering the update function module specified in uppercase letters + CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK + EXPORTING values = st_a. + + ... + + "Triggering the synchronous update + COMMIT WORK AND WAIT. + + "--------------------- Asynchronous update --------------------- + DATA(st_b) = VALUE some_type( ... ). + + ... + + CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK + EXPORTING values = st_b. + + ... + + "Triggering the asynchronous update + COMMIT WORK. + + "--------------------- Local update --------------------- + + "Before update function modules are registered. + SET UPDATE TASK LOCAL. + + DATA(st_c) = VALUE some_type( ... ). + + ... + + CALL FUNCTION 'ZSOME_UPDATE_FU_MOD' IN UPDATE TASK + EXPORTING values = st_c. + + ... + + "The update will be synchronous no matter if you use the COMMIT WORK + "statement with or without the addition AND WAIT. + COMMIT WORK. + "COMMIT WORK AND WAIT. + ``` + +> **💡 Note**
+> If a runtime error occurs during the update, the update work process executes a database rollback, and notifies the user whose program created the entries. + +**Using [remote-enabled function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenremote_enabled_fm_glosry.htm)** +- Also in this case, the bundling is done through function modules. +- They are also specially marked as remote-enabled function modules. +- For example, you can register them for later asynchronous execution in the background and through the [RFC interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrfc_interface_glosry.htm) ([background Remote Function Call (bgRFC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbg_remote_function_glosry.htm)). With this technology, you can make calls in the same or different ABAP systems. +- More information: + - [SAP Help Portal documentation about RFC](https://help.sap.com/docs/ABAP_PLATFORM_NEW/753088fc00704d0a80e7fbd6803c8adb/4888068AD9134076E10000000A42189D) + - [`CALL FUNCTION ... IN BACKGROUND UNIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_function_background_unit.htm) + - Note the [background processing framework (bgPF)](https://help.sap.com/docs/abap-cloud/abap-concepts/background-processing-framework) as a successor technology + +**Using [subroutines](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensubroutine_glosry.htm)** +- Subroutines (that are no longer recommended for use ⚠️) can be registered for later execution. + +- They are registered with the [`PERFORM ... ON COMMIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapperform_on_commit.htm) statement. These subroutines are executed when a `COMMIT WORK` statement is called. +- An addition is available to control the order of execution. +- Similarly, a subroutine can be registered "on rollback" with [`PERFORM ... ON ROLLBACK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapperform_on_commit.htm). These subroutines are executed when a `ROLLBACK WORK` statement is called. +- When executed: + - In the current work process, before update function modules. + - When they are registered in an update function module with `ON COMMIT`, they are executed at the end of the update. This happens in the update work process for non-local updates, and in the current work process for local updates. + +

⬆️ back to top

+ +### Related ABAP Statements + +An SAP LUW is usually started by opening a new internal session. +The statements to end an SAP LUW have already been mentioned above: [`COMMIT WORK [AND WAIT]`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit.htm) and [`ROLLBACK WORK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback.htm). + +`COMMIT WORK [AND WAIT]` +- Closes the current SAP LUW and opens a new one. +- Commits all change requests in the current SAP LUW. +- Among other things, this statement triggers ... + - the processing of all registered update function modules. + - the update work process and the local updates in the current work process. + - a database commit for all currently open [database connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_connection_glosry.htm), which also terminates the current database LUW. +- Note that `COMMIT WORK` triggers an asynchronous, `COMMIT WORK AND WAIT` a synchronous update. + +`ROLLBACK WORK` +- Similar to `COMMIT WORK` statements, this statement closes the current SAP LUW and opens a new one. +- Among other things, this statement ... + - causes all changes within a SAP LUW to be undone, that is, all previous registrations for the current SAP LUW are removed. + - triggers a database rollback on all currently open database connections, which also terminates the current database LUW. + +> **💡 Note**
+> Notes on database connections: +> - The [database interface](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_interface_glosry.htm) uses the [standard connection](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_db_connection_glosry.htm) of the current work process to access the [standard database](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_db_glosry.htm) by default. +> - Optionally, database accesses can also be made by using [secondary connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_db_connection_glosry.htm) to [secondary databases](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensecondary_db_glosry.htm) or by using [service connections](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenservice_connection_glosry.htm) to the standard database. The secondary connections are usually used by technical components. For example, they are used for caches, traces, logs, and so on. +> - The implicit database rollback is performed on all database connections that are currently open. +> - Within the SAP LUW, database changes and commits are allowed on service connections or through secondary database connections. + + +

⬆️ back to top

+ +## Concepts Related to the SAP LUW +The following concepts are related to the SAP LUW to ensure transactional consistency. They are not discussed in detail here. For more information, see the links. + +**Authorization concept** +- In an SAP system, you need to protect data from unauthorized access by making sure that only those [authorized](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenauthorization_glosry.htm) to access it can see and modify it. +- Authorization to access data can be set. Before a user can perform certain operations in your application, you need to implement authorization checks. +- Since ABAP SQL statements do not trigger any [authorization checks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenauthorization_check_glosry.htm) in the database system, this is even more important. Database tables may be accessed without restriction using these statements. Conversely, not all users in a system are authorized to access all data available to ABAP SQL statements. +- Thus, it is up to the programmer to ensure that each user who can call the program is authorized to access the data it handles. +- More information: + - [Authorizations](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbc_authority_check.htm) + - [`AUTHORITY-CHECK`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapauthority-check.htm) + + +**Lock concept** +- The database system automatically sets [database locks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendatabase_lock_glosry.htm) when ABAP SQL statements are called to modify database table entries. +- These locks are implemented by automatically setting a lock flag, which can only be set for existing database table entries. +- After a database commit, these flags are removed. +- As a result, database locks are not available for more than one database LUW, which must be considered in the context of an SAP LUW, since multiple database LUWs may be involved. Therefore, the lock flags that are set in a transaction are not sufficient. For the duration of an entire SAP LUW, a lock on database entries must remain set. +- This is where the SAP lock concept comes into play, which is independent of the automatic database locks. It is based on [lock objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlock_object_glosry.htm). +- Lock objects ... + - are [repository objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrepository_object_glosry.htm) that are defined in the [ABAP Dictionary](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dictionary_glosry.htm). + - specify the database tables in which records are to be locked with a lock request. + - contain the key fields on which a lock is to be set. +- When a lock object is created, two [lock function modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlock_function_module_glosry.htm) (`ENQUEUE_...` and `DEQUEUE_...`) are automatically generated. They are executed in a special enqueue work process. When a record is locked during a transaction (by the enqueue function module), a central lock table is filled with the table name and key field information. Unlike database locks, a locked entry in a lock object does not necessarily have to exist in a database table. Also, the locking must be done proactively, i. e. there is no automatic locking. You must make sure that the application implementation checks the lock entries. +- At the end of an SAP LUW, all locks should be released, either automatically during the database update or explicitly when you call the corresponding dequeue function module. +- More information: + - [SAP Locks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_lock.htm) + - Note the information on the `CL_ABAP_LOCK_OBJECT_FACTORY` class that is related to this context [here](https://help.sap.com/docs/sap-btp-abap-environment/abap-environment/lock-objects). + +> **💡 Note**
+> For more information about related topics in RAP, see the sections [Authorization Control](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/375a8124b22948688ac1c55297868d06.html) and [Concurrency Control](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/d315c13677d94a6891beb3418e3e02ed.html) in the *Development guide for the ABAP RESTful Application Programming Model*. + +

⬆️ back to top

+ +## The SAP LUW in ABAP Cloud and RAP + +A limited set of ABAP language features is available in ABAP Cloud ([restricted ABAP language version](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenrestricted_version_glosry.htm)). +The limitations include the fact that the above bundling techniques are not available. Note that the local update is enabled by default in ABAP Cloud. Find more information in this [blog](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/). + +In fact, RAP is the transactional programming model for ABAP Cloud. +And RAP comes with a well-defined transactional model and follows the rules of the SAP LUW. At the end of an SAP LUW in RAP, database modification operations should be performed in a final step in the [RAP late save phase](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) by persisting the consistent data in the [RAP transactional buffer](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransactional_buffer_glosry.htm) to the database. + +There are RAP-specific [ABAP EML](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_eml_glosry.htm) statements for commit and rollback: +- [`COMMIT ENTITIES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcommit_entities.htm) implicitly triggers `COMMIT WORK`. Furthermore, `COMMIT ENTITIES` provides RAP-specific functionality with various additions. These EML statements implicitly enforce local updates with `COMMIT WORK`, or `COMMIT WORK AND WAIT` if the local update fails. Therefore, the update is either a local update or a synchronous update, but never an asynchronous update. +- [`ROLLBACK ENTITIES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprollback_entities.htm): Resets all changes of the current transaction and clears the transactional buffer. The statement triggers `ROLLBACK WORK`. +- Find more information in the [ABAP cheat sheet about EML](08_EML_ABAP_for_RAP.md). + +

⬆️ back to top

+ +## Controlled SAP LUW + +- The *controlled SAP LUW* is an enhancement to the SAP LUW concept. +- It introduces a check mechanism to detect violations of [transactional contracts](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentransactional_contract_glosry.htm) to guarantee transactional consistency. +- Such contracts specify which ABAP statements and operations are allowed and which are not allowed in a [transactional phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentr_phase_glosry.htm). +- In this way, applications can be made more robust and the SAP LUW can be made more tangible. +- Violations that are detected result in a runtime error (or are logged). +- There are mainly two transactional phases: *modify* and *save*. +- In RAP, these two phases are set implicitly, and they are subdivided as follows (see more information in the EML cheat sheet and the RAP guide): + - *modify* + - [RAP interaction phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_int_phase_glosry.htm) + - [RAP early save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenearly_rap_save_phase_glosry.htm) + - *save* + - [RAP late save phase](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenlate_rap_save_phase_glosry.htm) +- Using the static methods `modify` and `save` of the `CL_ABAP_TX` class, you can activate the transactional phases explicitly. +- The controlled SAP LUW is automatically and implicitly supported by newer ABAP concepts such as RAP (i.e. the transactional phases are implicitly active when RAP handler methods are called), [background Processing Framework (bgPF)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenbgpf_glosry.htm), and local consumption of [RAP business events](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_entity_event_glosry.htm). +- Furthermore, transactional contracts define where (i. e. in which transactional phase) a [classified API](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassified_api_glosry.htm), such as a method of a class, can be used. The classifications start with `IF_ABAP_TX_...`, for example, `IF_ABAP_TX_SAVE`, and are, in the case of methods, typcially included as types in the local types of the class ([CCDEF include](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenccdef_glosry.htm), *Class-Relevant Local Types* tab in ADT). The classifications detail out and restrict the scope of use, so as not to use a classified API in phases where not allowed. Follow the links below for more information. + - Example of a classified API: Open the class `CL_BCS_MAIL_MESSAGE` (which is used for sending emails). In ADT, go to the *Class-Relevant Local Types* tab, and find classifications for methods, for example, the `send_async` method. Calling this method in the *modify* transactional phase results in a violation. You can also get information about the transactional contract using the F2 information in ADT. In the case of the method mentioned, choose F2 on `send_async` (`... cl_bcs_mail_message=>create_instance( ... )->send_async( ). ...`) to view the transactional contract information. +- Regarding the concrete restrictions and for more information, follow the links. +- Examples for violations, such as database modifications. They are only allowed in the *save* transactional phase because the data being processed in the *modify* phase may be inconsistent: + - Database modification (e.g. `MODIFY dbtab FROM @row.`) performed when the *modify* transactional phase is active. + - Database modifcation in a [RAP handler method](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabp_handler_method_glosry.htm) implementation. Here, the *modify* transactional phase is active by default. + - Database modifcation in a [RAP event handler method](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrap_event_handler_meth_glosry.htm) implementation when the *save* transactional phase has not been activated explicitly. Note: When RAP event handler methods are called, they are started in the *modify* transactional phase. Modifying a database right away there, without the activation of the *save* phase, means a violation. + - Calling a classified API in a phase where not allowed, such as `... cl_bcs_mail_message=>create_instance( ... )->send_async( ). ...` (classified with `IF_ABAP_TX_SAVE`) in the *modify* transactional phase. +- More information: + - [Controlled SAP LUW](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw) in the SAP Help Portal + - ABAP Keyword Documentation (Standard ABAP): + - [Restrictions in Transactional Phases](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapinvalid_stmts_in_tx.htm) + - [API Classifications](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapapi_classification.htm) + - [Restrictions in RAP Handler and Saver Methods](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapinvalid_stmts_in_rap_methods.htm) + + +Example using `CL_ABAP_TX`: + +```abap +... + +"------------- Activating the modify transactional phase ------------- +cl_abap_tx=>modify( ). + +"The following database modification statement is not allowed in the +"modify transactional phase. In certain contexts, e.g. in ABAP Cloud, +"the runtime error BEHAVIOR_ILLEGAL_STMT_IN_CALL occurs. +MODIFY zdemo_abap_carr FROM TABLE @( VALUE #( + ( carrid = 'XY' + carrname = 'XY Airlines' + currcode = 'EUR' + url = 'some_url' ) ) ). + +... + +"------------- Activating the save transactional phase ------------- +cl_abap_tx=>save( ). + +"In this phase, database modifications are allowed. +MODIFY zdemo_abap_carr FROM TABLE @( VALUE #( + ( carrid = 'XY' + carrname = 'XY Airlines' + currcode = 'EUR' + url = 'some_url' ) ) ). +... +``` + +

⬆️ back to top

+ +## More Information +- [The RAP Transactional Model and the SAP LUW](https://help.sap.com/docs/SAP_S4HANA_CLOUD/e5522a8a7b174979913c99268bc03f1a/ccda1094b0f845e28b88f9f50a68dfc4.html) (Development guide for the ABAP RESTful Application Programming Model) +- [The SAP LUW in ABAP Cloud](https://blogs.sap.com/2022/12/05/the-sap-luw-in-abap-cloud/) (blog) +- [SAP LUW in the ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_luw.htm) +- [Controlled SAP LUW](https://help.sap.com/docs/abap-cloud/abap-concepts/controlled-sap-luw) as an enhancement of the SAP LUW concept + +

⬆️ back to top

+ +## Executable Example + +After the import of the repository, proceed as follows: +- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. +- Enter `zdemo_abap_sap_luw` and open the program. +- Run the program by choosing `F8`. + +> **💡 Note**
+> - The executable example ... +> - demonstrates the SAP LUW using classic dynpros to provide a self-contained and simple example that highlights the considerations regarding implicit database commits, without putting the spotlight on dynpros. Note that classic dynpros are outdated for application programs. New developments should use web-based UIs, such as SAPUI5 or Web Dynpro. +> - covers the following topics in simple contexts: +> - Demonstrating synchronous update, asynchronous update, and local update triggered by `COMMIT WORK`, `COMMIT WORK AND WAIT`, and `SET UPDATE TASK LOCAL` using update function modules. +> - Demonstrating the statements `PERFORM ... ON COMMIT` and `PERFORM ... ON ROLLBACK` using subroutines. +> - does not claim to include meaningful dynpros with meaningful dynpro sequences and is not intended to be a role model for proper dynpro design. +> - is not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. +> - is only intended to demonstrate a selection of keywords and visualize SAP LUW-related syntax in action on a high level. +> - is explained in more detail in the expandable section below. Click to view the details. +> - Dynpros cannot be created in ABAP Cloud. As mentioned earlier, RAP is the transactional programming model for ABAP Cloud. It comes with a well-defined transactional model and follows the rules of the SAP LUW. See the links in the [More Information](#more-information) section. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + + +
+
+ Expand to see explanations of the executable example + +
+The example demonstrates the SAP LUW using dynpros and bundling techniques with update function modules and subroutines. In the dynpros, you can select various options that determine how the program runs. It covers the following aspects: + +- Demonstrating synchronous update, asynchronous update, and local update triggered by `COMMIT WORK`, `COMMIT WORK AND WAIT`, and `SET UPDATE TASK LOCAL` using update function modules. +- Demonstrating the statements `PERFORM ... ON COMMIT` and `PERFORM ... ON ROLLBACK` using subroutines. + + + +The selection options follow this pattern: + +**First dynpro**: +- The SAP LUW is started. +- The entries in a database table are displayed. There are four entries in total. +- After you have selected an option to continue with either the update task, or the update task and perform a local update, or subroutines, an update function module or subroutine is registered to delete all entries from the database table. + +**Second dynpro**: +- You can create a new database table entry by making entries in input fields displayed on the dynpro. +- When the program continues, it registers an update function module or subroutine that inserts the new entry into the database table. + +**Third dynpro**: +- The SAP LUW is ended. You have several options for ending the SAP LUW. +- In addition to the `COMMIT WORK` and `COMMIT WORK AND WAIT` statements, you can use `ROLLBACK WORK` to roll back the changes. +- Another option is to deliberately make the current SAP LUW fail. If a type A message is triggered, the SAP LUW is also terminated. + +During program execution, logs are collected and eventually written to a database table (also using an update function module or subroutine). These logs document the progress of the transaction with various pieces of information. These include work process information, SAP LUW key retrieval, and transaction state retrieval (using methods of the `CL_SYSTEM_TRANSACTION_STATE` class). + +If the program is not terminated immediately and the SAP LUW has ended, another program is called that displays a dynpro. + +**Fourth dynpro** (part of a new program that is started): +- The database table entries and logs are displayed. +- If the transaction was successful, a single entry (the one created during the execution of the previous program) should be displayed for the modified database table, as well as the entries of the log table. +- Note that a helper class is available for this example. Methods perform various tasks, such as retrieving work process information. + +**Notes on the various options for checking out the SAP LUW:** + - **Asynchronous update** with `COMMIT WORK`: Immediately after the `COMMIT WORK` statement, a `SELECT` statement is executed, retrieving all the entries of the database table. In this case, the number of the retrieved entries should be the number of the original database table entries, i.e. 4 entries, and not 1, demonstrating the asynchronous update. The current number of records is displayed in a message. Result: The database table is deleted and a single new entry is added. +The log shows the value 1 for the transaction state after the update task is executed and the update function modules are called. + - **Synchronous update** with `COMMIT WORK AND WAIT`: Immediately after the `COMMIT WORK AND WAIT` statement, a `SELECT` statement is executed to retrieve all the entries in the database table. In this case, there should be one entry instead of four to demonstrate the synchronous update. The current number of records is displayed in a message. + - **Local update** using a `SET UPDATE TASK LOCAL` statement: Once the local update is enabled, it does not matter whether you choose `COMMIT WORK` or `COMMIT WORK AND WAIT` in the next step. It will be a synchronous update, so the number of current database table entries displayed in the message will be 1 in both cases. The log will show the value 1 for the transaction state after the `SET UPDATE TASK LOCAL` statement has been executed. + - **Rolling back changes**: Although update function modules or subroutines are registered, none of them affect the database. All changes are rolled back. Result: The database table is not deleted, no new entry is created. The original content of the database table should be displayed. + - **Causing a failure in the current SAP LUW**: An update function module intentionally includes a statement that causes a runtime error if not caught (zero division). All changes are rolled back implicitly. If the local update is active, you should be informed of the problem directly. The program is terminated. In this case, you can check the database table entries that remain unchanged. You can also use transaction ST22 to display the runtime error that occurred. In the case of a non-local update, you should receive a mail in the Business Workplace informing you of the problem in the SAP LUW. The original content of the database table should be displayed on the next screen. In this case, you can also check transaction ST22 for the runtime error. + - **Terminating the program with an error message** of type A: This option only indicates that if such a message is generated, the program is terminated and all changes are implicitly rolled back. In this case, you may want to check the database table entries that remain unchanged. +- **Using subroutines**: + - Note that subroutines are considered obsolete and should no longer be used. This is to demonstrate the effect as a bundling technique in an SAP LUW. Selecting this option triggers the registration of subroutines for commit (to delete the database table entry, insert a newly created entry, insert entries in the log table) and rollback (the subroutine in the example does not do anything specific; it is just to demonstrate that the subroutine is called in the event of a rollback). + - When you select the commit options, the subroutines registered with `ON COMMIT` are executed in the current work process. + - Choosing `COMMIT WORK` or `COMMIT WORK AND WAIT` has the same effect: When these statements are called and a `SELECT` statement follows, the number of database table entries is 1 in both cases. + - If the rollback option is selected, the subroutine registered with `ON ROLLBACK` is executed in the current work process. + - The transaction state in the log is 1 for `ON COMMIT` or `ON ROLLBACK` when the corresponding subroutines are called. + - Note that registered subroutines cannot have a parameter interface, so no parameters can be passed in this type of bundling. Therefore, data can only be passed through external interfaces, such as ABAP memory. In this example, the database table entry created is passed to and from ABAP memory using `EXPORT` and `IMPORT` statements. The subroutines do not implement the writes themselves, but instead call methods of a class. +- The following aspects are valid for all selected options regarding the logs: + - Before the commit is triggered (in the last PAI), the transaction state shows the value 0 for all retrieved transaction states. + - The work process information may change due to the fact that database commits are triggered when completing a dialog step. So you might expect different numbers there, but not necessarily. The new free work process can also be the same as the one before it was freed. However, there will be no different work process information for the update. The numbers will be the same because the update is performed in a single work process. + - Before calling the program that displays database entries and the log, the SAP LUW key is the same throughout the transaction. It does not change until a new SAP LUW is opened. See and compare the last entry for the SAP LUW key in the log that is retrieved for the program submitted. +
diff --git a/18_Dynpro.md b/18_Dynpro.md index 9198ab1..c0e1949 100644 --- a/18_Dynpro.md +++ b/18_Dynpro.md @@ -1,776 +1,778 @@ - - -# Dynpro - -- [Dynpro](#dynpro) - - [Introduction](#introduction) - - [About Dynpros](#about-dynpros) - - [Dynpro Flow Logic](#dynpro-flow-logic) - - [Dialog Modules](#dialog-modules) - - [Transporting Data between Dynpros and the ABAP Program](#transporting-data-between-dynpros-and-the-abap-program) - - [Dynpro Fields](#dynpro-fields) - - [OK Field and Function Codes](#ok-field-and-function-codes) - - [Program-Controlled Data Transport](#program-controlled-data-transport) - - [Calling Dialog Modules Conditionally](#calling-dialog-modules-conditionally) - - [Input Checks](#input-checks) - - [Field and Input Help](#field-and-input-help) - - [Dnypro Sequence, Calling and Leaving Dynpros](#dnypro-sequence-calling-and-leaving-dynpros) - - [Dynpro Sequence](#dynpro-sequence) - - [ABAP Statements for Calling and Leaving Dynpros](#abap-statements-for-calling-and-leaving-dynpros) - - [Modifying Static Attributes of Screen Elements](#modifying-static-attributes-of-screen-elements) - - [Statements for the GUI Status and Title](#statements-for-the-gui-status-and-title) - - [Controls](#controls) - - [Table Controls](#table-controls) - - [Tabstrips Controls](#tabstrips-controls) - - [GUI Controls](#gui-controls) - - [More Information](#more-information) - - [Executable Example](#executable-example) - -## Introduction - -⚠️ The content of this cheat sheet and the executable example are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). - -[User interfaces (UI)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_interface_glosry.htm) are not limited to displaying some information, they must also allow the user to interact with the program. -In modern UI technologies, this can be achieved through [events](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_glosry.htm), i.e. [user actions](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_action_glosry.htm) on a UI trigger events, and UI methods register these events and react accordingly. In this way, users control the program flow through their actions. -In the early days of ABAP, classes, methods, and events did not exist. Program flow control had to be achieved in other ways. -This is where [dynpros](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) (dynamic programs) representing a classic ABAP UI technology come into play. - -This cheat sheet provides a high-level overview of classic dynpro topics with a focus on dynpro-related statements, supported by an executable example to check the syntax in action. - -> **💡 Note**
-> - Classic dynpros are outdated for application programs. New developments should use web-based UIs, such as SAPUI5 or Web Dynpro. -> - Dynpros cannot be created in ABAP Cloud. -> - This cheat sheet ... -> - is not intended to encourage you to start creating classic dynpros for programming new applications. -> - does not cover all facets, techniques, and keywords in great detail. -> - is intended to cover a selection of dynpro-related topics and syntax that you may encounter in older ABAP code. If you need more information, always consult the ABAP Keyword Documentation. -> - Some of the statements described here - the ones used in the dynpro flow logic - are programmed in a special programming language. -> - Links to the ABAP Keyword Documentation in this cheat sheet refer to the documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm) (latest version). - -## About Dynpros - - - Stands for dynamic program, i.e. the program execution is dynmically controlled by user interactions - - Can only be defined in [function groups](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_group_glosry.htm), [module pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmodul_pool_glosry.htm) (not [class pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclass_pool_glosry.htm)) and [executable program](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexecutable_program_glosry.htm) (*reports*; the focus in the cheat sheet is on the latter) - - Can be identified by a unique, four-digit [dynpro number](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_number_glosry.htm) in an [ABAP program](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_program_glosry.htm). Note that leading zeros need not be specified when calling the dynpro. Number 1000 is reserved, as are other dynpro number ranges (e.g. used by SAP). The current dynpro can be retrieved using `sy-dynnr`. - - Is displayed in a window of [SAP GUI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_gui_glosry.htm) - - Consists of the following main aspects: - - Specific characteristics when creating the dynpro. To name a few: - - Dynpro type: Defines whether the dynpro is displayed in the full GUI window (if *Normal* is selected), in a pop-up window (*Modal Dialog Box*), or as a subscreen in a specific area within another dynpro in the same ABAP program. - - [Next dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abennext_dynpro_glosry.htm): Statically specifies the next dynpro to be displayed in a [dynpro sequence](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_sequence_glosry.htm). Setting the next dynpro to 0 or leaving the attribute blank will make the current dynpro the last dynpro in the sequence. If the next dynpro number is the same as the current dynpro, the dynpro continues to be called. The static next dynpro can be overwritten temporarily and dynamically in the ABAP program. - - [Screen layout](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_glosry.htm): - - Has [screen elements](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_element_glosry.htm) and is visible to users - - Screen elements are, for example, checkboxes, radio buttons, custom controls, dropdown list boxes, pushbuttons, input/output fields, subscreens, table controls, tabstrip controls, text fields, and status icons. - - To add screen elements, use the [layout editor](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlayout_editor_glosry.htm) of the [screen painter](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_painter_glosry.htm) tool. It is available only in the [ABAP Workbench](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_workbench_glosry.htm). - - For each screen element, you can define various static properties (attributes) that control its appearance. Double-clicking a screen element in the layout editor opens the attribute maintenance dialog box. - - Various static attributes of the screen elements can be overwritten dynamically from within the ABAP program using special statements. - - Has its own data objects, called [dynpro fields](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_glosry.htm) (see more below) - - Is called either by another dynpro (as the next dynpro), by a [transaction code](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_code_glosry.htm) ([dialog transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_transaction_glosry.htm)), or by ABAP statements (e.g. `CALL SCREEN`). Several dynpros in a single ABAP program can be called in sequence to form a dynpro sequence. - -> **💡 Note**
-> There are special dynpros ([selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_glosry.htm), [classic lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_list_glosry.htm)). They are created implicitly. - -

⬆️ back to top

- -## Dynpro Flow Logic - -- Represents the procedural part of a dynpro -- Controls the dynpro processing, fills and processes the dynpro fields -- Is defined in the *Flow Logic* tab in the screen painter -- Has its own programming language, similar to ABAP, but runs in AS ABAP -- Contains [processing blocks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenprocessing_block_glosry.htm) introduced by special keywords -- The processing blocks are executed in response to the [PAI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpai_glosry.htm), [PBO](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpbo_glosry.htm), [POH](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpoh_glosry.htm), and [POV](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpov_glosry.htm) events of the corresponding ABAP program, and call [dialog modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_module_glosry.htm): - - - `PROCESS BEFORE OUTPUT` (often also abbreviated as PBO): - - Triggered by the ABAP runtime framework and processed before the dynpro is displayed - - Dialog modules can be called at the PBO event. They are mainly used to prepare the dynpro display, for example, by pre-populating input/output fields. - - When the dynpro is presented to the user, and the user has made entries and wants to leave the dynpro, the PAI event is triggered, for example, when a button is clicked. - - - `PROCESS AFTER INPUT` (PAI): - - Processed after a user action on the dynpro - - The dialog modules called at PAI evaluate the user entries and process them. - - When the processing is complete, the processing of the current dynpro ends and the next dynpro is called. - - > **💡 Note**
- > - The PAI processing of the current dynpro and the PBO processing of the next dynpro take place one after the other in the same [work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) on the application server and together form a dialog step. - > - As soon as the screen is ready for input again, only the presentation server is active until the next user action. During this time, the ABAP program waiting for user input does not occupy a work process on the application server. - - - The other events are triggered when the user requests a field or input help for a field: - - `PROCESS ON HELP-REQUEST` (POH) - - `PROCESS ON VALUE-REQUEST` (POV) - -Example: - -```abap -PROCESS BEFORE OUTPUT. - ... "Here, for example, modules can be called. - -PROCESS AFTER INPUT. - ... - -"When you implement field or value helps, use the following processing blocks. -PROCESS ON HELP-REQUEST. - ... - -PROCESS ON VALUE-REQUEST. - ... -``` - -The following statements are among the non-ABAP statements in the dynpro flow logic. They are covered briefly below. - -- `MODULE` for calling dialog modules -- `FIELD` for controlling the data transport between dynpro fields and the ABAP program -- `CHAIN` and `ENDCHAIN` for combining module calls -- `LOOP` and `ENDLOOP` for processing lines of a table control (similar to the ABAP statement `LOOP`) -- `CALL SUBSCREEN` for calling the flow logic of a subscreen - -

⬆️ back to top

- -## Dialog Modules - -- Are processing blocks in an ABAP program -- Represent the procedural link between the dynpro and the ABAP program. -- Are implemented between the statements [`MODULE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodule.htm) and [`ENDMODULE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapendmodule.htm). -- In the [dynpro flow logic](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_flow_logic_glosry.htm), they are called using the `MODULE some_module_9000.` statement, which calls an ABAP processing block called `some_module_9000`. -- By calling dialog modules during the PBO, PAI, POH, and POV events of the dynpro, the dynpro controls the flow of the associated ABAP program. -- Do not have a parameter interface. The data transport between the dynpro fields and the ABAP program therefore takes place exclusively through the global variables of the ABAP program assigned to the dynpro fields (see below). -- Do not have a local data area. Data object declarations in dialog modules result in global variables of the program. If you really need local data declarations in this context, you can make local data declarations in a method in a local class of the program and call the method. -- Within the dynpro processing block(s) ... - - `PROCESS BEFORE OUTPUT`, the dynpro statement `MODULE` can only be used to call dialog modules that were defined with the `OUTPUT` addition. - - `PROCESS AFTER INPUT`, `PROCESS ON HELP-REQUEST`, and `PROCESS ON VALUE-REQUEST`, only the dialog modules defined with the `INPUT` addition can be called. -- Are not associated with a specific dynpro and can therefore be called from different dynpros. -- You can choose random names for the dialog modules. The name chosen in the example indicates that they are modules for a dynpro with the number 9000. - - -Calling dialog modules in the dynpro flow logic: -```abap -"Flow Logic tab in the screen painter - -PROCESS BEFORE OUTPUT. - MODULE pbo_9000. - -PROCESS AFTER INPUT. - MODULE pai_9000. -``` - -Implementation of the dialog modules in the ABAP program - -```abap -MODULE pbo_9000 OUTPUT. - ... -ENDMODULE. - -MODULE pai_9000 INPUT. - ... -ENDMODULE. -``` - -

⬆️ back to top

- -## Transporting Data between Dynpros and the ABAP Program - -### Dynpro Fields - -- The transport of data between dynpros and the ABAP program is performed using [dynpro fields](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_glosry.htm). -- Dynpro fields are the [data objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendata_object_glosry.htm) of dynpros. They are data objects in the working memory of a dynpro. -- All dynpro fields, except the [*OK field*](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenok_field_glosry.htm), are linked to a screen element. See the *Element List* tab of dynpros. -- The data types of dynpro fields are determined either by reference to built-in [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dictionary_glosry.htm) data types (except `CLNT` and `FLTP`) or by reference to global data objects of the ABAP program. An advantage of DDIC types is that additional properties are available for display on the user interface, including description texts, field help, and input help. -- The actual transport of the data is done in the following way: - - As a prerequisite, ... - - you have created a screen element, such as an input field in a dynpro. - - You have assigned a name for this screen element - which is the name of the dynpro field. - - you have created a data object with the same name as the dynpro field in the ABAP program. - - During PBO: You can assign a value to the data object, such as *demo text* for the input field, to prefill that input field. Or you can make no assignment to leave the input text blank. - - During PAI: After the PBO, the content of data objects are passed to dynpro fields of the same name. - - This is a two-way street: For example, when the user enters data in an input field, the data object in the ABAP program receives the value of the dynpro field. - - By default, all dynpro fields are transported directly to the ABAP program at the start of the PAI event (that is, at the start of a dialog step) and before the corresponding event block is processed. The reverse transport from the ABAP program to the dynpro takes place at the end of the dialog step, in the context of the PBO event. -- About declaring data objects in the ABAP program in the global declaration part: - - You can use a global variable with `DATA` or a public static attribute of a local class with `CLASS-DATA`. - - You can use a [`TABLES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaptables.htm) statement: - - Declares a [table work area](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_work_area_glosry.htm), i.e. a structure whose data type is taken from the identically named structured data type from the ABAP Dictionary - - Since it refers to a flat structure in the ABAP Dictionary, it is used to provide all the additional semantic information that is not available when you use `DATA` or `CLASS-DATA`. - - A [CDS entity](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abencds_entity_glosry.htm) cannot be specified after `TABLES`. -- Note that you can control the data transport explicitly (see below). - -Example: -```abap -PROGRAM some_program. - -"Variable declarations -DATA some_dobj TYPE abap_bool. -TABLES some_struct. - -CLASS local_class DEFINITION. - PUBLIC SECTION. - CLASS-DATA: another_dobj TYPE i. -... - -ENDCLASS. - -CLASS local_class IMPLEMENTATION. -... -ENDCLASS. -``` - -### OK Field and Function Codes - -- Each dynpro contains a twenty-character [*OK field*](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenok_field_glosry.htm), which is a dynpro field that is not associated with a screen element. -- It is implicitly declared when a dynpro is created. It is the last entry in the *Element List* tab of the dynpro. Note that the *OK field* must be given a name, for example, `ok_code`. -- The *OK field* is relevant to [function codes](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_code_glosry.htm): - - A function code (a sequence of up to 20 characters) can be assigned to specific control elements (for example, a pushbutton, a menu item, and so on) in SAP GUI. - - When a user action is performed on a control, such as clicking a button, the PAI event is triggered. If the button is linked to a function code, the function code is placed in the *OK field* and passed to a data object of the same name. - - You can then evaluate the value in the ABAP program, for example, in a [`CASE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcase.htm) control structure if you have multiple function codes for different control elements, and implement a response accordingly. -- Notes on working with the *OK field*: - - As with the other dynpro fields, a data object must be created in the ABAP program. - - The system field `sy-ucomm` automatically receives the value of the function code. However, it is recommended that you work with the *OK field* instead of `sy-ucomm`. You have full control over the fields you declare. Also, the value of an ABAP system field should not be changed. - - It is recommended that you store the function code in an auxiliary variable and initialize the *OK field* field in an ABAP program. This ensures that the function code of a dynpro is not filled with an unwanted value in the PBO event (for example, the next PAI event can be triggered with an empty function code). You can then read the function code from the auxiliary variable (for example, using a `CASE` structure) and control the program flow from there. - - The *OK field* field can have a different name on each dynpro. However, it is recommended that you use the same name for the field in each dynpro of an ABAP program. This way, you only need one field with the same name in the ABAP program, in which the function code is placed and from which you can read it. - - In addition to screen elements, function codes can also be linked to various things in the dynpro, e.g. the definition of the menu bar takes place in the GUI status. They also trigger a PAI event. - -Example: -```abap -PROGRAM zdemo_program. - -"OK field declaration and auxiliary variable, assuming the OK field is called -"ok_code in the Element List tab of the dynpro. -DATA: ok_code LIKE sy-ucomm, - save_ok LIKE ok_code. - -... - -"Dialog modules in the program - -"PBO -MODULE pbo_9000 OUTPUT. - ... - "Prefill the value for a screen element, e.g. input field - some_input_field = 'Hallo'. - ... -ENDMODULE. - -"PAI -MODULE pai_9000 INPUT. - save_ok = ok_code. - CLEAR ok_code. - - CASE save_ok. - "For example, a button is linked with a function code named PUSH - WHEN 'PUSH'. - ... - WHEN 'ENTER'. - ... - WHEN 'CANCEL'. - ... - WHEN OTHERS. - ... - ENDCASE. -ENDMODULE. -... -``` - -

⬆️ back to top

- -### Program-Controlled Data Transport - -- In addition to the automatic data transport between the dynpro and the ABAP program, that is, between the dynpro fields and the global ABAP variables of the same name, you can also use [`FIELD`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_abexa.htm) statements for program-controlled data transport in the *Flow Logic* tab. -- These statements control the data transport from the dynpro to the ABAP program during the PAI event. -- Only those dynpro fields that are not specified after a `FIELD` statement are transported directly. -- In doing so, you can specify the time of the transport from the dynpro to the ABAP program. -- One or more `FIELD` statements are possible, that is, the contents of dynpro fields specified after `FIELD` are transported to the global ABAP data object of the same name when the corresponding `FIELD` statement is executed. -- In the flow logic, the statements are implemented in the processing block `PROCESS AFTER INPUT`. - -Example: -```abap -"Note: More syntax options are possible with the FIELD statement. -"See some of them below and more details in the ABAP Keyword Documentation. - -PROCESS AFTER INPUT. - MODULE pai_9000. "neither field_a nor field_b are available - FIELD field_a. - MODULE module_a. "field_a is available, field_b is not - FIELD field_b. - MODULE module_b. "both field_a and field_b are available -``` - -

⬆️ back to top

- -### Calling Dialog Modules Conditionally - -- By combining the `FIELD` statement with the `MODULE` statement, you can make the call of PAI modules dependent on conditions. -- The following statement in the flow logic calls the dialog module `mod` only if the dynpro field `dynp_field` is not empty: - - ```abap - FIELD dynp_field MODULE mod ON INPUT. - ``` - -- To call a module `mod` only if the value of a dynpro field `dynp_field` has been changed (or just overwritten with the same value) by the user since the last PBO, use the following: - - ```abap - FIELD dynp_field MODULE mod ON REQUEST. - ``` - -- Conditional module calls can be combined into processing chains to make processing dependent on multiple dynpro fields. -- A processing chain is defined using the dynpro statements [`CHAIN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpchain.htm) and [`ENDCHAIN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpendchain.htm): - - ```abap - CHAIN. - FIELD dynp_field1. - FIELD dynp_field2. - ... - MODULE mod ON CHAIN-INPUT. - "Note: ON REQUEST is also possible - ENDCHAIN. - ``` - -

⬆️ back to top

- -## Input Checks - -- Automatic input checks - - Are performed in the PAI event before data is transported to the ABAP program and before dialog modules are called. - - If an error is detected, it is displayed in the status bar, and the affected input fields remain ready for input. - - Further PAI processing is not started until the user has successfully corrected the input. - - For example, automatic input checks are performed for required fields: Input fields marked as `required` in the screen painter must be filled in by the user. - -- Exit command - - Since the automatic input checks are implicit, the user is always forced to make a valid input before the ABAP program can react. - - This is inconvenient in cases where users have changed their minds and only want to cancel processing. For this reason, there is a special function type exit command (`E`), which allows you to bypass the automatic input checks. - - You can choose this function type in the screen painter for screen elements with function codes, or in the menu painter for function codes. - - Such a function code bypasses the automatic input checks and leads directly to the call of a special dialog module using the following statement in the screen flow logic: - - ```abap - MODULE mod AT EXIT-COMMAND. - ``` - - - Within the dialog module called in this way, you should end processing with an appropriate `LEAVE` statement. Otherwise, the normal PAI processing, which includes the automatic input checks, starts after the dialog module has been executed. - -- Self-programmed input checks - - For input checks that go beyond the automatic checks, you can program special dialog modules in which you can issue a warning (message of type `W`) or error message (`E`) using the ABAP statement [`MESSAGE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmessage.htm). - - These dialog modules are called in the flow logic using the `FIELD` and `CHAIN` statements. - - To check a single field, use the `FIELD` statement as follows: - - ```abap - FIELD dynp_field MODULE mod. - ``` - - - Within the dialog module `mod`, program your input validation and trigger a warning or error message if an error occurs. The field in question is the only field that is ready for input again, and users can (in the case of a warning) or must (in the case of an error message) correct their input before the dynpro can be successfully exited. - - - To check several semantically related input fields, define a processing chain using the `CHAIN` statement: - ```abap - CHAIN. - FIELD dynp_field1. - FIELD dynp_field2. - ... - MODULE mod. - ENDCHAIN. - ``` - - - If a warning or error message is triggered in the `mod` dialog module, all fields listed in the processing chain are ready for input again. In this way, users can correct an input that consists of several closely related individual fields, and where it is not clear from the start which of the individual fields users must change in order to create a valid input as a whole. - -

⬆️ back to top

- -## Field and Input Help - -- Field help: - - Provides an explanation of the input field that appears when the user presses *F1* on a field on a screen layout. - - When you create input fields with reference to DDIC types, you can benefit from data element documentation (which you can create yourself if it does not exist). This documentation is then automatically displayed when the user requests F1 help. - - You can program field help yourself. You can call your own dialog modules for the POH event and program any help functions there: - ```abap - PROCESS ON HELP-REQUEST - FIELD dynp_field MODULE mod. - ``` - - At this point, the `FIELD` statement does not transport any data to the ABAP program, since field help is always independent of user input. In the `mod` dialog module, you must then display the appropriate help yourself. You can do this by calling the function module `HELP_OBJECT_SHOW`, for example, or by using GUI controls. - -- Input help: - - List of values displayed when *F4* is chosen for a field on the screen layout - - This help can either come from the ABAP Dictionary or be self-programmed. - - There are several ways to create helps in the ABAP Dictionary. For more information, see the topic [Input Helps in the ABAP Dictionary](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpros_value_help_auto.htm). - - If the built-in input helps in the ABAP Dictionary and the search help exits are not sufficient for your purposes, you can program your own input helps. In this case, you can call your own dialog modules for the event POV and program input helps there. - - ```abap - PROCESS ON VALUE-REQUEST - FIELD dynp_field MODULE mod. - ``` - - - As with the POH event, the `FIELD` dynpro statement does not transport data between the dynpro field and the ABAP variable. You must therefore program the data transport yourself by calling the function modules `DYNP_VALUES_READ` and `DYNP_VALUES_UPDATE`. The function module `F4IF_INT_TABLE_VALUE_REQUEST`, which you can call in your dialog module, receives an internal table as a value list and transfers the dialog with the user and the data transport for you. - - [Dropdown list box](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendropdown_listbox_glosry.htm) - - A special form that can be linked to an input field. - - When an input field is linked to a dropdown list box, the input value can only be selected from the list. Dropdown list boxes are therefore suitable for cases where the list of values is not too extensive and no other values than those in the list are allowed. - -

⬆️ back to top

- -## Dnypro Sequence, Calling and Leaving Dynpros - -### Dynpro Sequence - -- The [dynpro sequence](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_sequence_glosry.htm) is a sequence of different dynpros that are presented to the user one after the other. -- The first dynpro in a dynpro sequence is the [initial dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninitial_dynpro_glosry.htm). -- The flow of the dynpros is determined by the next dynpro for each dynpro involved. -- Each dynpro has a next dynpro. -- The next dynpro is defined either statically (the number you enter in the dynpro properties) or in the ABAP program using statements which temporarily and dynamically overwrite the static definition of the next dynpro. -- This means that the next dynpro is automatically called when the current dynpro is exited, i.e. when the PAI processing is finished, the current dynpro is also finished and the next dynpro is called. -- A dynpro is normally exited when the end of PAI processing is reached. -- If a dynpro is connected to a next dynpro with the dynpro number 0 (this dynpro does not exist), it is the last dynpro of the dynpro sequence. -- All dynpros in a dynpro sequence are displayed in the same GUI window. -- Starting a dynpro sequence: When calling transaction codes (in a dialog transaction, the dynpro associated with the transaction code) or using a `CALL SCREEN` statement (the initial dynpro is the dynpro specified in this statement). -- Ending a dynpro sequence: As mentioned above, a dynpro sequence is terminated when the next dynpro with a dynpro number of 0 is called. -- The simplest dynpro sequence consists of a single dynpro with 0 as the next dynpro. -- When the current dynpro sequence is finished, the system returns to the previous dynpro sequence if the current dynpro sequence was nested. - -

⬆️ back to top

- -### ABAP Statements for Calling and Leaving Dynpros - -[`SET SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_screen.htm) -- Sets the next dynpro -- Dynamically and temporarily overwrites the static definition and/or a previously set next dynpro -- Can also be 0 -- The next dynpro is automatically called when the end of PAI processing for the current dynpro is reached. If the next screen number is 0, the current dynpro sequence is terminated. - -```abap -"Assumption: The static next dynpro is 9100. -"With the statement, the next dynpro is dynamically set and 9100 overwritten. - -SET SCREEN 9200. - -*************************** - -"The current dynpro sequence is terminated. -SET SCREEN 0. - -``` - -[`CALL SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_screen.htm) -- Starts a new dynpro sequence, which is embedded in the current dynpro sequence. -- The dynpro that is specified is the initial dynpro of the dynpro sequence. -- This allows nested dynpro sequences to be created, i.e. if a dynpro sequence was already running at the time of the call, the newly started dynpro sequence is embedded in the already running one. -- By default, all the dynpros of the called dynpro sequence are displayed in the current GUI window. - - ```abap - "Starting a new dynpro sequence - - CALL SCREEN 9300. - ``` - -- The `STARTING AT` and `ENDING AT` additions can be used to open a dynpro in a modal dialog box, i.e. a dynpro is displayed in a popup over the previous dynpro. - - ```abap - "Opening a dynpro in a modal dialog box - CALL SCREEN dynnr STARTING AT col_up_left line_up. - CALL SCREEN dynnr STARTING AT col_up_left line_up ENDING AT col_up_right line_low. - ``` - -- The specifications (integer values) for `STARTING AT` and `ENDING AT` define the position of the dialog box with respect to the previous dynpro and its size: - `col_up_left` and `line_up` stand for values for the column for the upper left corner and the upper line of the dialog box. The values refer to the GUI window with popup level 0 (maximum popup level is 9). The right column and lower line is set automatically or explicitly by specifying `col_up_right` and `line_low`. The values of `col_up_left` and `line_up` should be less than `col_up_right` and `line_low`, otherwise the behavior will be undefined. - -[`LEAVE SCREEN.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_screen.htm) and [`LEAVE TO SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_screen.htm) -- As mentioned earlier, a dynpro is normally exited at the end of PAI processing. -- `LEAVE SCREEN.` exits the current dynpro and enters the next dynpro. This is either statically defined in the properties of the current dynpro or was previously set with the `SET SCREEN` statement. -- `LEAVE TO SCREEN` does the same, but first sets the next dynpro to the specified dynpro number. This statement is a short form of the statements `SET SCREEN dynnr. LEAVE SCREEN.`. - -> **💡 Note**
-> - The statements do not exit the entire dynpro sequence and instead branch to another dynpro in the same sequence. Only if the number 0 is used to branch to the next dynpro does a `LEAVE` statement terminate the dynpro sequence. -> - A dialog transaction can be started from an ABAP program using the [`CALL TRANSACTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_transaction.htm) or [`LEAVE TO TRANSACTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_to_transaction.htm) statements, or directly by the user by entering the transaction code in the input field of the [standard toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_toolbar_glosry.htm). When a dialog transaction is started, the associated ABAP program is loaded and the PBO processing of the initial dynpro is called. -> - [`LEAVE PROGRAM`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_program.htm) statements terminate the program. - - ```abap - "Assumption: The next dynpro is statically defined as 9100. - "The following statement ends the processing of the current dynpro. - "Dynpro 9100 is called. - LEAVE SCREEN. - - **************************************** - - "The following statement ends the processing of the current dynpro. - "The statically defined dynpro 9100 is overwritten. Dynpro 9200 is called. - SET SCREEN 9200. - LEAVE SCREEN. - - **************************************** - - "The following statement is a shorter form of the one above. - "It has the same effect. - LEAVE TO SCREEN 9200. - - **************************************** - - "Ending the dynpro sequence - SET SCREEN 0. - LEAVE SCREEN. - ``` - -

⬆️ back to top

- -## Modifying Static Attributes of Screen Elements - -- For each screen element, you can define various static attributes that control, for example, its appearance (i.e. you can hide screen elements) or status. -- The static attributes of the screen elements can be overwritten from within the ABAP program during the PBO processing of the dynpro. -- To do this, use the ABAP statements [`LOOP AT SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaploop_at_screen.htm) and [`MODIFY SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodify_screen.htm). -- `LOOP AT SCREEN`: - - Defines a loop over all screen elements of the current dynpro to which a dynpro field is assigned. - - A work area of type `SCREEN` should be declared. - - Note: Check the ABAP Keyword Documentation for the different components. You can also check the F2 information for the work area in the `LOOP` statement below. - - After the `LOOP AT SCREEN` statement, the work area contains the properties of the corresponding screen element. -- `MODIFY SCREEN`: - - Can only be used in the statement block after `LOOP AT SCREEN` and only makes sense during PBO processing. - - Expects a work area of type `SCREEN` after `FROM`. - - Modifies the properties of the current screen element with the values from the work area. - - Note the use of the values 0 and 1 by the dynpro in contrast to Boolean values in ABAP. - -```abap -MODULE pbo_9000 OUTPUT. - "Assumption: An input field is not marked as required - "(i.e. the value of the component is 0). - "The example makes the input field required. - LOOP AT SCREEN INTO DATA(scr). - IF scr-name = 'SOME_INPUT_FIELD'. - scr-required = '1'. - MODIFY SCREEN FROM scr. - ENDIF. - ENDLOOP. -ENDMODULE. -``` - -

⬆️ back to top

- - -## Statements for the GUI Status and Title - -- [GUI status](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_status_glosry.htm) - - Groups the [menu bar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmenu_bar_glosry.htm), [standard toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_toolbar_glosry.htm), and [application toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenapplication_toolbar_glosry.htm) of a GUI window as well as the function key settings. - - A GUI status is set using the [`SET PF-STATUS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_pf-status_dynpro.htm) statement and is created using the menu painter. - - ```abap - "Setting the GUI status (in PBO) - SET PF-STATUS status. - - **************************************** - - "Setting the GUI status and excluding function codes, i.e. the - "specified function codes are deactivated. fcode expects either - "a character-like data object or an internal table with a flat - "character-like line type. - SET PF-STATUS status EXCLUDING fcode. - ``` - - The name of the current GUI status can be obtained from the `sy-pfkey` system field and from the [`GET PF-STATUS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapget_pf.htm) statement. - - ```abap - "Getting the GUI status - GET PF-STATUS status. - st = sy-pfkey. - - **************************************** - - "The following statement inserts the function codes which are - "inactive in the current GUI status line by line into the - "internal table fcode - GET PF-STATUS status EXCLUDING fcode. - ``` - -- [GUI title](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_title_glosry.htm) - - Text that can be displayed in the title bar of a GUI window. - - A GUI title is set using the statement [`SET TITLEBAR`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_titlebar_dynpro.htm) and created using the menu painter. - - ```abap - "Setting a title (in PBO) - "Here, title is not the text content itself, but the name of a GUI title, - "a further UI component of the program. - SET TITLEBAR title. - - "The name of the current GUI title is displayed in the system field sy-title. - gui_title = sy-title. - - **************************************** - - "WITH addition - "The placeholders of a GUI title can be replaced by the formatted - "content of data objects text1, and so on. - SET TITLEBAR title WITH text1 ... text9. - ``` - -> **💡 Note**
-> By separating the GUI status and title from the dynpro itself, the screen layout can remain constant when switching dynpros, and only the title and available functions can be changed. - -

⬆️ back to top

- -## Controls - -- Dynpro [controls](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abencontrol_glosry.htm) - - Complex screen elements with built-in functions that go beyond simple screen elements - - Require additional variables and a [`CONTROLS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcontrols.htm) statement in the ABAP program (note that wizards are available) - - There are two types of dynpro controls: - - [Table control](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_control_glosry.htm) for the input and output of tabular data - - [Tabstrip control](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentabstrip_control_glosry.htm) for grouping screen elements on different tab pages -- [GUI controls](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_control_glosry.htm) - - External GUI controls that are included visually in dynpros - -### Table Controls - -- Used to display screen elements in tabular form -- Allows users to display or edit not only individual values, but the contents of entire (internal) tables -- Declaring a table control in the ABAP program: - ```abap - CONTROLS contr TYPE TABLEVIEW USING SCREEN dynnr. - ``` -- Result: A structure with the name of the control is created in the ABAP program. The structure components contain the properties of the table control and allow you to process the control in the ABAP program, e.g. to change and read the properties of the corresponding table control. -- For the table controls, loops must be implemented in the dynpro flow logic using [`LOOP WITH CONTROL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynploop.htm) statements that process table controls. -- The loop sequentially processes the displayed lines of the table control by performing one loop pass for each table control line. -- The implementation of the loop must be done for each table control for both the PBO processing block and in the PAI processing block. -- In the loop, you can call dialog modules to process the relevant data objects in the ABAP program. For example, you can read data from an internal table at PBO and write it back to the table at PAI after processing it in the dynpro. - - -```abap -PROCESS BEFORE OUTPUT. -... -LOOP WITH CONTROL contr. - MODULE mod_fill_table. -ENDLOOP. -... - -PROCESS AFTER INPUT. -... -LOOP WITH CONTROL contr. - MODULE mod_read_table. -ENDLOOP. -... -``` - -> **💡 Note**
-> - In a modern program, it is more comfortable to use an ALV Grid control. -> - More additions are available for the statement. - -The ABAP statement [`REFRESH CONTROL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprefresh_control.htm) initializes the properties of a table control. - -```abap -"Code in an ABAP Program -... -REFRESH CONTROL contr FROM SCREEN dynnr. -... -``` - -

⬆️ back to top

- -### Tabstrips Controls -- Allow tab pages to be displayed on dynpros -- Represent one of several available [subscreens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensubscreen_glosry.htm) in dynpros. Users select the subscreen to be displayed using tab pages. -- Declaring a tabstrip control in the ABAP program: - ```abap - CONTROLS tabstr TYPE TABSTRIP. - ``` -- Result: A structure with the name of the control is created in the ABAP program. From this structure, only the component `activetab` is required in the program. -- For the tabstrip controls, suitable subscreens must be called using [`CALL SUBSCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpcall.htm) statements in the flow logic. -- In PBO processing, the active tab page is set by assigning the function code of a tab title to the `activetab` component. By default, the first tab page is active. -- For `CALL SUBSCREEN`, there is one variant for the PBO and one variant for the PAI event. - - PBO: `CALL SUBSCREEN sub_area INCLUDING prog dynnr.` - - Includes the subscreen dynpro of the program and the dynpro number in a subscreen area of the current dynpro. It also processes its PBO flow logic at this point. After PBO processing of the subscreen dynpro, the flow logic of the current dynpro is continued after the `CALL SUBSCREEN` statement. - - PAI: `CALL SUBSCREEN sub_area.` - - Calls the PAI flow logic of the subscreen dynpro included in the subscreen area. - -Example: -```abap -"Code in a PBO dialog module -... -"Providing a dynpro number -dynnr = '9400'. -"Assign the activetab component -tabstr-activetab = 'SOME_TAB'. -"Providing the prgram name -prog = sy-repid. -... - -****************************************************** - -"Code in the flow logic - -PROCESS BEFORE OUTPUT. - ... - CALL SUBSCREEN sub_area INCLUDING prog dynnr. - ... - -PROCESS AFTER INPUT. - ... - CALL SUBSCREEN sub_area. - ... - -``` - -

⬆️ back to top

- -### GUI Controls -- Are components of the presentation view of an AS ABAP. -- They are not directly integrated into the ABAP language and are therefore not part of the classic ABAP interfaces. However, they are part of the SAP GUI and are designed to integrate seamlessly with classic dynpros. -- Are relatively modern UI elements that are used, for example, to display different types of data (images, HTML pages, hierarchical trees, and so on) in different ways or to enable user input. -- Are integrated into a dynpro interface using container controls that provide a screen area for the actual GUI control (e.g. by a custom container). -- Examples of GUI controls - - Toolbar control (`CL_GUI_TOOLBAR`): Implements an application toolbar that is independent of the GUI status. The input elements are created by method calls (for example, `ADD_BUTTON`). User actions are signaled by raising ABAP Objects events (for example, `FUNCTION_SELECTED`). - - Picture control (`CL_GUI_PICTURE`): Allows to display images in BMP, JPG, or GIF format. The dynpro to be displayed is loaded using the `LOAD_PICTURE_FROM_URL` method. Events such as `PICTURE_DBLCLICK` signal user actions. - - Browser control (`CL_GUI_HTML_VIEWER`): A browser for HTML pages or XML documents on the dynpro. Special links in the document trigger the `SAPEVENT` event when the user clicks, which can then be evaluated in the ABAP program. - - Edit control (`CL_GUI_TEXTEDIT`): A simple text editor with the basic functions such as select, find, and replace on the dynpro. These functions can also be called in a program-controlled way using methods such as `FIND_AND_REPLACE`. - - Tree control: Are available in different versions (for example, `CL_GUI_SIMPLE_TREE`). They allow hierarchical relationships to be displayed in tree structures. - - ALV Grid control: Is the replacement for classic lists. It provides functions such as searching, sorting, and printing the content of the list. However, the associated class `CL_GUI_ALV_GRID` should no longer be used directly for new developments. Classes such as `CL_SALV_TABLE` encapsulate the use of the ALV Grid control and simplify the integration. - -

⬆️ back to top

- -## More Information - -- [SAP GUI User Dialogs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_screens.htm) in the ABAP Keyword Documentation as the entry topic for dynpro-related topics -- Documentation about the [screen painter in the Help Portal](https://help.sap.com/docs/ABAP_PLATFORM_NEW/bd833c8355f34e96a6e83096b38bf192/d1801b50454211d189710000e8322d00) -- Documentation about the [menu painter in the Help Portal](https://help.sap.com/docs/ABAP_PLATFORM_NEW/bd833c8355f34e96a6e83096b38bf192/d1801ce8454211d189710000e8322d00) -- Find more dynpro examples in the ABAP Keyword Documentation. In ADT, in your system, choose `CTRL + SHIFT + A` to open the search. Insert `demo_dynpro*` to get a list of dynpro examples. - -## Executable Example - -After the import of the repository, proceed as follows: -- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. -- Enter `zdemo_abap_dynpro` and open the program. -- Run the program by choosing `F8`. - -> **💡 Note**
-> - The executable example ... -> - covers the following topics: -> - Dynpro flow logic and related statements (`MODULE`, `FIELD`, `CHAIN`/`ENDCHAIN`, `LOOP`/`ENDLOOP`, `CALL SUBSCREEN`) -> - ABAP statements for calling and leaving dynpros (`SET SCREEN`, `CALL SCREEN`, `LEAVE SCREEN`) -> - Modifying static attributes (`LOOP AT SCREEN`, `MODIFY SCREEN`), -> - Statements related to the GUI status and title (`GET`/`SET PF-STATUS`, `SET TITLEBAR`) -> - Controls (table and tabstrip controls) -> - does not claim to include meaningful dynpros with meaningful dynpro sequences (branching to new dynpro sequences occur through using appropriate statements). -> - is not intended to be a role model for proper dynpro design. -> - is not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. -> - is only intended to demonstrate a selection of keywords and visualize dynpro-related syntax in action on a high level. -> - is explained in more detail below in the expandable section below. Click to view the details. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) - -
-
- Expand to see explanations of the executable example - -
-The example demonstrates dynpro-related statements. In the dynpros, you can select various options for checking out the effect of the syntax. -It covers the following aspects: - -- Dynpro flow logic and related statements (`MODULE`, `FIELD`, `CHAIN`/`ENDCHAIN`, `LOOP`/`ENDLOOP`, `CALL SUBSCREEN`) -- ABAP statements for calling and leaving dynpros (`SET SCREEN`, `CALL SCREEN`, `LEAVE -SCREEN`) -- Modifying static attributes (`LOOP AT SCREEN`, `MODIFY SCREEN`), -- Statements related to the GUI status and title (`GET`/`SET PF-STATUS`, `SET TITLEBAR`) -- Controls (table and tabstrip controls) - -**First dynpro** (the "home page"): -- Selection options for what can be explored in other dynpros -- Choose the *Go* button to switch to another dynpro - -**Dynpro "Example of screen elements"**: -- Demonstrates several screen elements -- Pushbuttons, input field, boxes, checkboxes, radio buttons - -**Dynpro "Statements I"**: -- Selection options for various dynpro-related ABAP statements -- When you choose a radio button and *Go*, a message is displayed providing some information. - -**Dynpro "Statements II"**: -- Covers statements in the flow logic -- The option `MODULE ... AT EXIT-COMMAND` opens another dynpro. It demonstrates the exit command. The input field is required to be filled. This denies the processing after choosing the *Close 1* and *Cancel* buttons. This is not true for the *Close 2* button. - -**Dynpro "Controls"**: -- Shows several controls: Table and tabstrip controls as well as an ALV Grid control as an example for a GUI control + + +# Dynpro + +- [Dynpro](#dynpro) + - [Introduction](#introduction) + - [About Dynpros](#about-dynpros) + - [Dynpro Flow Logic](#dynpro-flow-logic) + - [Dialog Modules](#dialog-modules) + - [Transporting Data between Dynpros and the ABAP Program](#transporting-data-between-dynpros-and-the-abap-program) + - [Dynpro Fields](#dynpro-fields) + - [OK Field and Function Codes](#ok-field-and-function-codes) + - [Program-Controlled Data Transport](#program-controlled-data-transport) + - [Calling Dialog Modules Conditionally](#calling-dialog-modules-conditionally) + - [Input Checks](#input-checks) + - [Field and Input Help](#field-and-input-help) + - [Dnypro Sequence, Calling and Leaving Dynpros](#dnypro-sequence-calling-and-leaving-dynpros) + - [Dynpro Sequence](#dynpro-sequence) + - [ABAP Statements for Calling and Leaving Dynpros](#abap-statements-for-calling-and-leaving-dynpros) + - [Modifying Static Attributes of Screen Elements](#modifying-static-attributes-of-screen-elements) + - [Statements for the GUI Status and Title](#statements-for-the-gui-status-and-title) + - [Controls](#controls) + - [Table Controls](#table-controls) + - [Tabstrips Controls](#tabstrips-controls) + - [GUI Controls](#gui-controls) + - [More Information](#more-information) + - [Executable Example](#executable-example) + +## Introduction + +⚠️ The content of this cheat sheet and the executable example are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). + +[User interfaces (UI)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_interface_glosry.htm) are not limited to displaying some information, they must also allow the user to interact with the program. +In modern UI technologies, this can be achieved through [events](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_glosry.htm), i.e. [user actions](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenuser_action_glosry.htm) on a UI trigger events, and UI methods register these events and react accordingly. In this way, users control the program flow through their actions. +In the early days of ABAP, classes, methods, and events did not exist. Program flow control had to be achieved in other ways. +This is where [dynpros](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) (dynamic programs) representing a classic ABAP UI technology come into play. + +This cheat sheet provides a high-level overview of classic dynpro topics with a focus on dynpro-related statements, supported by an executable example to check the syntax in action. + +> **💡 Note**
+> - Classic dynpros are outdated for application programs. New developments should use web-based UIs, such as SAPUI5 or Web Dynpro. +> - Dynpros cannot be created in ABAP Cloud. +> - This cheat sheet ... +> - is not intended to encourage you to start creating classic dynpros for programming new applications. +> - does not cover all facets, techniques, and keywords in great detail. +> - is intended to cover a selection of dynpro-related topics and syntax that you may encounter in older ABAP code. If you need more information, always consult the ABAP Keyword Documentation. +> - Some of the statements described here - the ones used in the dynpro flow logic - are programmed in a special programming language. +> - Links to the ABAP Keyword Documentation in this cheat sheet refer to the documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm) (latest version). + +## About Dynpros + + - Stands for dynamic program, i.e. the program execution is dynmically controlled by user interactions + - Can only be defined in [function groups](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_group_glosry.htm), [module pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmodul_pool_glosry.htm) (not [class pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclass_pool_glosry.htm)) and [executable program](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexecutable_program_glosry.htm) (*reports*; the focus in the cheat sheet is on the latter) + - Can be identified by a unique, four-digit [dynpro number](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_number_glosry.htm) in an [ABAP program](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_program_glosry.htm). Note that leading zeros need not be specified when calling the dynpro. Number 1000 is reserved, as are other dynpro number ranges (e.g. used by SAP). The current dynpro can be retrieved using `sy-dynnr`. + - Is displayed in a window of [SAP GUI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_gui_glosry.htm) + - Consists of the following main aspects: + - Specific characteristics when creating the dynpro. To name a few: + - Dynpro type: Defines whether the dynpro is displayed in the full GUI window (if *Normal* is selected), in a pop-up window (*Modal Dialog Box*), or as a subscreen in a specific area within another dynpro in the same ABAP program. + - [Next dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abennext_dynpro_glosry.htm): Statically specifies the next dynpro to be displayed in a [dynpro sequence](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_sequence_glosry.htm). Setting the next dynpro to 0 or leaving the attribute blank will make the current dynpro the last dynpro in the sequence. If the next dynpro number is the same as the current dynpro, the dynpro continues to be called. The static next dynpro can be overwritten temporarily and dynamically in the ABAP program. + - [Screen layout](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_glosry.htm): + - Has [screen elements](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_element_glosry.htm) and is visible to users + - Screen elements are, for example, checkboxes, radio buttons, custom controls, dropdown list boxes, pushbuttons, input/output fields, subscreens, table controls, tabstrip controls, text fields, and status icons. + - To add screen elements, use the [layout editor](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlayout_editor_glosry.htm) of the [screen painter](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_painter_glosry.htm) tool. It is available only in the [ABAP Workbench](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_workbench_glosry.htm). + - For each screen element, you can define various static properties (attributes) that control its appearance. Double-clicking a screen element in the layout editor opens the attribute maintenance dialog box. + - Various static attributes of the screen elements can be overwritten dynamically from within the ABAP program using special statements. + - Has its own data objects, called [dynpro fields](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_glosry.htm) (see more below) + - Is called either by another dynpro (as the next dynpro), by a [transaction code](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentransaction_code_glosry.htm) ([dialog transaction](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_transaction_glosry.htm)), or by ABAP statements (e.g. `CALL SCREEN`). Several dynpros in a single ABAP program can be called in sequence to form a dynpro sequence. + +> **💡 Note**
+> There are special dynpros ([selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_glosry.htm), [classic lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_list_glosry.htm)). They are created implicitly. + +

⬆️ back to top

+ +## Dynpro Flow Logic + +- Represents the procedural part of a dynpro +- Controls the dynpro processing, fills and processes the dynpro fields +- Is defined in the *Flow Logic* tab in the screen painter +- Has its own programming language, similar to ABAP, but runs in AS ABAP +- Contains [processing blocks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenprocessing_block_glosry.htm) introduced by special keywords +- The processing blocks are executed in response to the [PAI](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpai_glosry.htm), [PBO](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpbo_glosry.htm), [POH](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpoh_glosry.htm), and [POV](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenpov_glosry.htm) events of the corresponding ABAP program, and call [dialog modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_module_glosry.htm): + + - `PROCESS BEFORE OUTPUT` (often also abbreviated as PBO): + - Triggered by the ABAP runtime framework and processed before the dynpro is displayed + - Dialog modules can be called at the PBO event. They are mainly used to prepare the dynpro display, for example, by pre-populating input/output fields. + - When the dynpro is presented to the user, and the user has made entries and wants to leave the dynpro, the PAI event is triggered, for example, when a button is clicked. + + - `PROCESS AFTER INPUT` (PAI): + - Processed after a user action on the dynpro + - The dialog modules called at PAI evaluate the user entries and process them. + - When the processing is complete, the processing of the current dynpro ends and the next dynpro is called. + + > **💡 Note**
+ > - The PAI processing of the current dynpro and the PBO processing of the next dynpro take place one after the other in the same [work process](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwork_process_glosry.htm) on the application server and together form a dialog step. + > - As soon as the screen is ready for input again, only the presentation server is active until the next user action. During this time, the ABAP program waiting for user input does not occupy a work process on the application server. + + - The other events are triggered when the user requests a field or input help for a field: + - `PROCESS ON HELP-REQUEST` (POH) + - `PROCESS ON VALUE-REQUEST` (POV) + +Example: + +```abap +PROCESS BEFORE OUTPUT. + ... "Here, for example, modules can be called. + +PROCESS AFTER INPUT. + ... + +"When you implement field or value helps, use the following processing blocks. +PROCESS ON HELP-REQUEST. + ... + +PROCESS ON VALUE-REQUEST. + ... +``` + +The following statements are among the non-ABAP statements in the dynpro flow logic. They are covered briefly below. + +- `MODULE` for calling dialog modules +- `FIELD` for controlling the data transport between dynpro fields and the ABAP program +- `CHAIN` and `ENDCHAIN` for combining module calls +- `LOOP` and `ENDLOOP` for processing lines of a table control (similar to the ABAP statement `LOOP`) +- `CALL SUBSCREEN` for calling the flow logic of a subscreen + +

⬆️ back to top

+ +## Dialog Modules + +- Are processing blocks in an ABAP program +- Represent the procedural link between the dynpro and the ABAP program. +- Are implemented between the statements [`MODULE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodule.htm) and [`ENDMODULE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapendmodule.htm). +- In the [dynpro flow logic](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_flow_logic_glosry.htm), they are called using the `MODULE some_module_9000.` statement, which calls an ABAP processing block called `some_module_9000`. +- By calling dialog modules during the PBO, PAI, POH, and POV events of the dynpro, the dynpro controls the flow of the associated ABAP program. +- Do not have a parameter interface. The data transport between the dynpro fields and the ABAP program therefore takes place exclusively through the global variables of the ABAP program assigned to the dynpro fields (see below). +- Do not have a local data area. Data object declarations in dialog modules result in global variables of the program. If you really need local data declarations in this context, you can make local data declarations in a method in a local class of the program and call the method. +- Within the dynpro processing block(s) ... + - `PROCESS BEFORE OUTPUT`, the dynpro statement `MODULE` can only be used to call dialog modules that were defined with the `OUTPUT` addition. + - `PROCESS AFTER INPUT`, `PROCESS ON HELP-REQUEST`, and `PROCESS ON VALUE-REQUEST`, only the dialog modules defined with the `INPUT` addition can be called. +- Are not associated with a specific dynpro and can therefore be called from different dynpros. +- You can choose random names for the dialog modules. The name chosen in the example indicates that they are modules for a dynpro with the number 9000. + + +Calling dialog modules in the dynpro flow logic: +```abap +"Flow Logic tab in the screen painter + +PROCESS BEFORE OUTPUT. + MODULE pbo_9000. + +PROCESS AFTER INPUT. + MODULE pai_9000. +``` + +Implementation of the dialog modules in the ABAP program: + +```abap +MODULE pbo_9000 OUTPUT. + ... +ENDMODULE. + +MODULE pai_9000 INPUT. + ... +ENDMODULE. +``` + +

⬆️ back to top

+ +## Transporting Data between Dynpros and the ABAP Program + +### Dynpro Fields + +- The transport of data between dynpros and the ABAP program is performed using [dynpro fields](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_glosry.htm). +- Dynpro fields are the [data objects](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendata_object_glosry.htm) of dynpros. They are data objects in the working memory of a dynpro. +- All dynpro fields, except the [*OK field*](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenok_field_glosry.htm), are linked to a screen element. See the *Element List* tab of dynpros. +- The data types of dynpro fields are determined either by reference to built-in [ABAP Dictionary (DDIC)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dictionary_glosry.htm) data types (except `CLNT` and `FLTP`) or by reference to global data objects of the ABAP program. An advantage of DDIC types is that additional properties are available for display on the user interface, including description texts, field help, and input help. +- The actual transport of the data is done in the following way: + - As a prerequisite, ... + - you have created a screen element, such as an input field in a dynpro. + - You have assigned a name for this screen element - which is the name of the dynpro field. + - you have created a data object with the same name as the dynpro field in the ABAP program. + - During PBO: You can assign a value to the data object, such as *demo text* for the input field, to prefill that input field. Or you can make no assignment to leave the input text blank. + - During PAI: After the PBO, the content of data objects are passed to dynpro fields of the same name. + - This is a two-way street: For example, when the user enters data in an input field, the data object in the ABAP program receives the value of the dynpro field. + - By default, all dynpro fields are transported directly to the ABAP program at the start of the PAI event (that is, at the start of a dialog step) and before the corresponding event block is processed. The reverse transport from the ABAP program to the dynpro takes place at the end of the dialog step, in the context of the PBO event. +- About declaring data objects in the ABAP program in the global declaration part: + - You can use a global variable with `DATA` or a public static attribute of a local class with `CLASS-DATA`. + - You can use a [`TABLES`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaptables.htm) statement: + - Declares a [table work area](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_work_area_glosry.htm), i.e. a structure whose data type is taken from the identically named structured data type from the ABAP Dictionary + - Since it refers to a flat structure in the ABAP Dictionary, it is used to provide all the additional semantic information that is not available when you use `DATA` or `CLASS-DATA`. + - A [CDS entity](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abencds_entity_glosry.htm) cannot be specified after `TABLES`. +- Note that you can control the data transport explicitly (see below). + +Example: +```abap +PROGRAM some_program. + +"Variable declarations +DATA some_dobj TYPE abap_bool. +TABLES some_struct. + +CLASS local_class DEFINITION. + PUBLIC SECTION. + CLASS-DATA: another_dobj TYPE i. +... + +ENDCLASS. + +CLASS local_class IMPLEMENTATION. +... +ENDCLASS. +``` + +### OK Field and Function Codes + +- Each dynpro contains a twenty-character [*OK field*](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenok_field_glosry.htm), which is a dynpro field that is not associated with a screen element. +- It is implicitly declared when a dynpro is created. It is the last entry in the *Element List* tab of the dynpro. Note that the *OK field* must be given a name, for example, `ok_code`. +- The *OK field* is relevant to [function codes](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_code_glosry.htm): + - A function code (a sequence of up to 20 characters) can be assigned to specific control elements (for example, a pushbutton, a menu item, and so on) in SAP GUI. + - When a user action is performed on a control, such as clicking a button, the PAI event is triggered. If the button is linked to a function code, the function code is placed in the *OK field* and passed to a data object of the same name. + - You can then evaluate the value in the ABAP program, for example, in a [`CASE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcase.htm) control structure if you have multiple function codes for different control elements, and implement a response accordingly. +- Notes on working with the *OK field*: + - As with the other dynpro fields, a data object must be created in the ABAP program. + - The system field `sy-ucomm` automatically receives the value of the function code. However, it is recommended that you work with the *OK field* instead of `sy-ucomm`. You have full control over the fields you declare. Also, the value of an ABAP system field should not be changed. + - It is recommended that you store the function code in an auxiliary variable and initialize the *OK field* field in an ABAP program. This ensures that the function code of a dynpro is not filled with an unwanted value in the PBO event (for example, the next PAI event can be triggered with an empty function code). You can then read the function code from the auxiliary variable (for example, using a `CASE` structure) and control the program flow from there. + - The *OK field* field can have a different name on each dynpro. However, it is recommended that you use the same name for the field in each dynpro of an ABAP program. This way, you only need one field with the same name in the ABAP program, in which the function code is placed and from which you can read it. + - In addition to screen elements, function codes can also be linked to various things in the dynpro, e.g. the definition of the menu bar takes place in the GUI status. They also trigger a PAI event. + +Example: +```abap +PROGRAM zdemo_program. + +"OK field declaration and auxiliary variable, assuming the OK field is called +"ok_code in the Element List tab of the dynpro. +DATA: ok_code LIKE sy-ucomm, + save_ok LIKE ok_code. + +... + +"Dialog modules in the program + +"PBO +MODULE pbo_9000 OUTPUT. + ... + "Prefill the value for a screen element, e.g. input field + some_input_field = 'Hallo'. + ... +ENDMODULE. + +"PAI +MODULE pai_9000 INPUT. + save_ok = ok_code. + CLEAR ok_code. + + CASE save_ok. + "For example, a button is linked with a function code named PUSH + WHEN 'PUSH'. + ... + WHEN 'ENTER'. + ... + WHEN 'CANCEL'. + ... + WHEN OTHERS. + ... + ENDCASE. +ENDMODULE. +... +``` + +

⬆️ back to top

+ +### Program-Controlled Data Transport + +- In addition to the automatic data transport between the dynpro and the ABAP program, that is, between the dynpro fields and the global ABAP variables of the same name, you can also use [`FIELD`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_field_abexa.htm) statements for program-controlled data transport in the *Flow Logic* tab. +- These statements control the data transport from the dynpro to the ABAP program during the PAI event. +- Only those dynpro fields that are not specified after a `FIELD` statement are transported directly. +- In doing so, you can specify the time of the transport from the dynpro to the ABAP program. +- One or more `FIELD` statements are possible, that is, the contents of dynpro fields specified after `FIELD` are transported to the global ABAP data object of the same name when the corresponding `FIELD` statement is executed. +- In the flow logic, the statements are implemented in the processing block `PROCESS AFTER INPUT`. + +Example: +```abap +"Note: More syntax options are possible with the FIELD statement. +"See some of them below and more details in the ABAP Keyword Documentation. + +PROCESS AFTER INPUT. + MODULE pai_9000. "neither field_a nor field_b are available + FIELD field_a. + MODULE module_a. "field_a is available, field_b is not + FIELD field_b. + MODULE module_b. "both field_a and field_b are available +``` + +

⬆️ back to top

+ +### Calling Dialog Modules Conditionally + +- By combining the `FIELD` statement with the `MODULE` statement, you can make the call of PAI modules dependent on conditions. +- The following statement in the flow logic calls the dialog module `mod` only if the dynpro field `dynp_field` is not empty: + + ```abap + FIELD dynp_field MODULE mod ON INPUT. + ``` + +- To call a module `mod` only if the value of a dynpro field `dynp_field` has been changed (or just overwritten with the same value) by the user since the last PBO, use the following: + + ```abap + FIELD dynp_field MODULE mod ON REQUEST. + ``` + +- Conditional module calls can be combined into processing chains to make processing dependent on multiple dynpro fields. +- A processing chain is defined using the dynpro statements [`CHAIN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpchain.htm) and [`ENDCHAIN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpendchain.htm): + + ```abap + CHAIN. + FIELD dynp_field1. + FIELD dynp_field2. + ... + MODULE mod ON CHAIN-INPUT. + "Note: ON REQUEST is also possible + ENDCHAIN. + ``` + +

⬆️ back to top

+ +## Input Checks + +- Automatic input checks + - Are performed in the PAI event before data is transported to the ABAP program and before dialog modules are called. + - If an error is detected, it is displayed in the status bar, and the affected input fields remain ready for input. + - Further PAI processing is not started until the user has successfully corrected the input. + - For example, automatic input checks are performed for required fields: Input fields marked as `required` in the screen painter must be filled in by the user. + +- Exit command + - Since the automatic input checks are implicit, the user is always forced to make a valid input before the ABAP program can react. + - This is inconvenient in cases where users have changed their minds and only want to cancel processing. For this reason, there is a special function type exit command (`E`), which allows you to bypass the automatic input checks. + - You can choose this function type in the screen painter for screen elements with function codes, or in the menu painter for function codes. + - Such a function code bypasses the automatic input checks and leads directly to the call of a special dialog module using the following statement in the screen flow logic: + + ```abap + MODULE mod AT EXIT-COMMAND. + ``` + + - Within the dialog module called in this way, you should end processing with an appropriate `LEAVE` statement. Otherwise, the normal PAI processing, which includes the automatic input checks, starts after the dialog module has been executed. + +- Self-programmed input checks + - For input checks that go beyond the automatic checks, you can program special dialog modules in which you can issue a warning (message of type `W`) or error message (`E`) using the ABAP statement [`MESSAGE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmessage.htm). + - These dialog modules are called in the flow logic using the `FIELD` and `CHAIN` statements. + - To check a single field, use the `FIELD` statement as follows: + + ```abap + FIELD dynp_field MODULE mod. + ``` + + - Within the dialog module `mod`, program your input validation and trigger a warning or error message if an error occurs. The field in question is the only field that is ready for input again, and users can (in the case of a warning) or must (in the case of an error message) correct their input before the dynpro can be successfully exited. + + - To check several semantically related input fields, define a processing chain using the `CHAIN` statement: + ```abap + CHAIN. + FIELD dynp_field1. + FIELD dynp_field2. + ... + MODULE mod. + ENDCHAIN. + ``` + + - If a warning or error message is triggered in the `mod` dialog module, all fields listed in the processing chain are ready for input again. In this way, users can correct an input that consists of several closely related individual fields, and where it is not clear from the start which of the individual fields users must change in order to create a valid input as a whole. + +

⬆️ back to top

+ +## Field and Input Help + +- Field help: + - Provides an explanation of the input field that appears when the user presses *F1* on a field on a screen layout. + - When you create input fields with reference to DDIC types, you can benefit from data element documentation (which you can create yourself if it does not exist). This documentation is then automatically displayed when the user requests F1 help. + - You can program field help yourself. You can call your own dialog modules for the POH event and program any help functions there: + ```abap + PROCESS ON HELP-REQUEST + FIELD dynp_field MODULE mod. + ``` + - At this point, the `FIELD` statement does not transport any data to the ABAP program, since field help is always independent of user input. In the `mod` dialog module, you must then display the appropriate help yourself. You can do this by calling the function module `HELP_OBJECT_SHOW`, for example, or by using GUI controls. + +- Input help: + - List of values displayed when *F4* is chosen for a field on the screen layout + - This help can either come from the ABAP Dictionary or be self-programmed. + - There are several ways to create helps in the ABAP Dictionary. For more information, see the topic [Input Helps in the ABAP Dictionary](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpros_value_help_auto.htm). + - If the built-in input helps in the ABAP Dictionary and the search help exits are not sufficient for your purposes, you can program your own input helps. In this case, you can call your own dialog modules for the event POV and program input helps there. + + ```abap + PROCESS ON VALUE-REQUEST + FIELD dynp_field MODULE mod. + ``` + + - As with the POH event, the `FIELD` dynpro statement does not transport data between the dynpro field and the ABAP variable. You must therefore program the data transport yourself by calling the function modules `DYNP_VALUES_READ` and `DYNP_VALUES_UPDATE`. The function module `F4IF_INT_TABLE_VALUE_REQUEST`, which you can call in your dialog module, receives an internal table as a value list and transfers the dialog with the user and the data transport for you. + - [Dropdown list box](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendropdown_listbox_glosry.htm) + - A special form that can be linked to an input field. + - When an input field is linked to a dropdown list box, the input value can only be selected from the list. Dropdown list boxes are therefore suitable for cases where the list of values is not too extensive and no other values than those in the list are allowed. + +

⬆️ back to top

+ +## Dnypro Sequence, Calling and Leaving Dynpros + +### Dynpro Sequence + +- The [dynpro sequence](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_sequence_glosry.htm) is a sequence of different dynpros that are presented to the user one after the other. +- The first dynpro in a dynpro sequence is the [initial dynpro](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abeninitial_dynpro_glosry.htm). +- The flow of the dynpros is determined by the next dynpro for each dynpro involved. +- Each dynpro has a next dynpro. +- The next dynpro is defined either statically (the number you enter in the dynpro properties) or in the ABAP program using statements which temporarily and dynamically overwrite the static definition of the next dynpro. +- This means that the next dynpro is automatically called when the current dynpro is exited, i.e. when the PAI processing is finished, the current dynpro is also finished and the next dynpro is called. +- A dynpro is normally exited when the end of PAI processing is reached. +- If a dynpro is connected to a next dynpro with the dynpro number 0 (this dynpro does not exist), it is the last dynpro of the dynpro sequence. +- All dynpros in a dynpro sequence are displayed in the same GUI window. +- Starting a dynpro sequence: When calling transaction codes (in a dialog transaction, the dynpro associated with the transaction code) or using a `CALL SCREEN` statement (the initial dynpro is the dynpro specified in this statement). +- Ending a dynpro sequence: As mentioned above, a dynpro sequence is terminated when the next dynpro with a dynpro number of 0 is called. +- The simplest dynpro sequence consists of a single dynpro with 0 as the next dynpro. +- When the current dynpro sequence is finished, the system returns to the previous dynpro sequence if the current dynpro sequence was nested. + +

⬆️ back to top

+ +### ABAP Statements for Calling and Leaving Dynpros + +[`SET SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_screen.htm) +- Sets the next dynpro +- Dynamically and temporarily overwrites the static definition and/or a previously set next dynpro +- Can also be 0 +- The next dynpro is automatically called when the end of PAI processing for the current dynpro is reached. If the next screen number is 0, the current dynpro sequence is terminated. + +```abap +"Assumption: The static next dynpro is 9100. +"With the statement, the next dynpro is dynamically set and 9100 overwritten. + +SET SCREEN 9200. + +********************************************** + +"The current dynpro sequence is terminated. +SET SCREEN 0. + +``` + +[`CALL SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_screen.htm) +- Starts a new dynpro sequence, which is embedded in the current dynpro sequence. +- The dynpro that is specified is the initial dynpro of the dynpro sequence. +- This allows nested dynpro sequences to be created, i.e. if a dynpro sequence was already running at the time of the call, the newly started dynpro sequence is embedded in the already running one. +- By default, all the dynpros of the called dynpro sequence are displayed in the current GUI window. + + ```abap + "Starting a new dynpro sequence + + CALL SCREEN 9300. + ``` + +- The `STARTING AT` and `ENDING AT` additions can be used to open a dynpro in a modal dialog box, i.e. a dynpro is displayed in a popup over the previous dynpro. + + ```abap + "Opening a dynpro in a modal dialog box + CALL SCREEN dynnr STARTING AT col_up_left line_up. + CALL SCREEN dynnr STARTING AT col_up_left line_up ENDING AT col_up_right line_low. + ``` + +- The specifications (integer values) for `STARTING AT` and `ENDING AT` define the position of the dialog box with respect to the previous dynpro and its size: + `col_up_left` and `line_up` stand for values for the column for the upper left corner and the upper line of the dialog box. The values refer to the GUI window with popup level 0 (maximum popup level is 9). The right column and lower line is set automatically or explicitly by specifying `col_up_right` and `line_low`. The values of `col_up_left` and `line_up` should be less than `col_up_right` and `line_low`, otherwise the behavior will be undefined. + +[`LEAVE SCREEN.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_screen.htm) and [`LEAVE TO SCREEN dynnr.`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_screen.htm) +- As mentioned earlier, a dynpro is normally exited at the end of PAI processing. +- `LEAVE SCREEN.` exits the current dynpro and enters the next dynpro. This is either statically defined in the properties of the current dynpro or was previously set with the `SET SCREEN` statement. +- `LEAVE TO SCREEN` does the same, but first sets the next dynpro to the specified dynpro number. This statement is a short form of the statements `SET SCREEN dynnr. LEAVE SCREEN.`. + +> **💡 Note**
+> - The statements do not exit the entire dynpro sequence and instead branch to another dynpro in the same sequence. Only if the number 0 is used to branch to the next dynpro does a `LEAVE` statement terminate the dynpro sequence. +> - A dialog transaction can be started from an ABAP program using the [`CALL TRANSACTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_transaction.htm) or [`LEAVE TO TRANSACTION`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_to_transaction.htm) statements, or directly by the user by entering the transaction code in the input field of the [standard toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_toolbar_glosry.htm). When a dialog transaction is started, the associated ABAP program is loaded and the PBO processing of the initial dynpro is called. +> - [`LEAVE PROGRAM`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapleave_program.htm) statements terminate the program. + + ```abap + "Assumption: The next dynpro is statically defined as 9100. + "The following statement ends the processing of the current dynpro. + "Dynpro 9100 is called. + LEAVE SCREEN. + + ************************************************************************** + + "The following statement ends the processing of the current dynpro. + "The statically defined dynpro 9100 is overwritten. Dynpro 9200 is called. + SET SCREEN 9200. + LEAVE SCREEN. + + ************************************************************************** + + "The following statement is a shorter form of the one above. + "It has the same effect. + LEAVE TO SCREEN 9200. + + ************************************************************************** + + "Ending the dynpro sequence + SET SCREEN 0. + LEAVE SCREEN. + "Alternative + LEAVE TO SCREEN 0. + ``` + +

⬆️ back to top

+ +## Modifying Static Attributes of Screen Elements + +- For each screen element, you can define various static attributes that control, for example, its appearance (i.e. you can hide screen elements) or status. +- The static attributes of the screen elements can be overwritten from within the ABAP program during the PBO processing of the dynpro. +- To do this, use the ABAP statements [`LOOP AT SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaploop_at_screen.htm) and [`MODIFY SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapmodify_screen.htm). +- `LOOP AT SCREEN`: + - Defines a loop over all screen elements of the current dynpro to which a dynpro field is assigned. + - A work area of type `SCREEN` should be declared. + - Note: Check the ABAP Keyword Documentation for the different components. You can also check the F2 information for the work area in the `LOOP` statement below. + - After the `LOOP AT SCREEN` statement, the work area contains the properties of the corresponding screen element. +- `MODIFY SCREEN`: + - Can only be used in the statement block after `LOOP AT SCREEN` and only makes sense during PBO processing. + - Expects a work area of type `SCREEN` after `FROM`. + - Modifies the properties of the current screen element with the values from the work area. + - Note the use of the values 0 and 1 by the dynpro in contrast to Boolean values in ABAP. + +```abap +MODULE pbo_9000 OUTPUT. + "Assumption: An input field is not marked as required + "(i.e. the value of the component is 0). + "The example makes the input field required. + LOOP AT SCREEN INTO DATA(scr). + IF scr-name = 'SOME_INPUT_FIELD'. + scr-required = '1'. + MODIFY SCREEN FROM scr. + ENDIF. + ENDLOOP. +ENDMODULE. +``` + +

⬆️ back to top

+ + +## Statements for the GUI Status and Title + +- [GUI status](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_status_glosry.htm) + - Groups the [menu bar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmenu_bar_glosry.htm), [standard toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_toolbar_glosry.htm), and [application toolbar](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenapplication_toolbar_glosry.htm) of a GUI window as well as the function key settings. + - A GUI status is set using the [`SET PF-STATUS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_pf-status_dynpro.htm) statement and is created using the menu painter. + + ```abap + "Setting the GUI status (in PBO) + SET PF-STATUS status. + + **************************************************************************** + + "Setting the GUI status and excluding function codes, i.e. the + "specified function codes are deactivated. fcode expects either + "a character-like data object or an internal table with a flat + "character-like line type. + SET PF-STATUS status EXCLUDING fcode. + ``` + - The name of the current GUI status can be obtained from the `sy-pfkey` system field and from the [`GET PF-STATUS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapget_pf.htm) statement. + + ```abap + "Getting the GUI status + GET PF-STATUS status. + st = sy-pfkey. + + **************************************************************************** + + "The following statement inserts the function codes which are + "inactive in the current GUI status line by line into the + "internal table fcode + GET PF-STATUS status EXCLUDING fcode. + ``` + +- [GUI title](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_title_glosry.htm) + - Text that can be displayed in the title bar of a GUI window. + - A GUI title is set using the statement [`SET TITLEBAR`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_titlebar_dynpro.htm) and created using the menu painter. + + ```abap + "Setting a title (in PBO) + "Here, title is not the text content itself, but the name of a GUI title, + "a further UI component of the program. + SET TITLEBAR title. + + "The name of the current GUI title is displayed in the system field sy-title. + gui_title = sy-title. + + **************************************************************************** + + "WITH addition + "The placeholders of a GUI title can be replaced by the formatted + "content of data objects text1, and so on. + SET TITLEBAR title WITH text1 ... text9. + ``` + +> **💡 Note**
+> By separating the GUI status and title from the dynpro itself, the screen layout can remain constant when switching dynpros, and only the title and available functions can be changed. + +

⬆️ back to top

+ +## Controls + +- Dynpro [controls](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abencontrol_glosry.htm) + - Complex screen elements with built-in functions that go beyond simple screen elements + - Require additional variables and a [`CONTROLS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcontrols.htm) statement in the ABAP program (note that wizards are available) + - There are two types of dynpro controls: + - [Table control](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentable_control_glosry.htm) for the input and output of tabular data + - [Tabstrip control](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentabstrip_control_glosry.htm) for grouping screen elements on different tab pages +- [GUI controls](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abengui_control_glosry.htm) + - External GUI controls that are included visually in dynpros + +### Table Controls + +- Used to display screen elements in tabular form +- Allows users to display or edit not only individual values, but the contents of entire (internal) tables +- Declaring a table control in the ABAP program: + ```abap + CONTROLS contr TYPE TABLEVIEW USING SCREEN dynnr. + ``` +- Result: A structure with the name of the control is created in the ABAP program. The structure components contain the properties of the table control and allow you to process the control in the ABAP program, e.g. to change and read the properties of the corresponding table control. +- For the table controls, loops must be implemented in the dynpro flow logic using [`LOOP WITH CONTROL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynploop.htm) statements that process table controls. +- The loop sequentially processes the displayed lines of the table control by performing one loop pass for each table control line. +- The implementation of the loop must be done for each table control for both the PBO processing block and in the PAI processing block. +- In the loop, you can call dialog modules to process the relevant data objects in the ABAP program. For example, you can read data from an internal table at PBO and write it back to the table at PAI after processing it in the dynpro. + + +```abap +PROCESS BEFORE OUTPUT. +... +LOOP WITH CONTROL contr. + MODULE mod_fill_table. +ENDLOOP. +... + +PROCESS AFTER INPUT. +... +LOOP WITH CONTROL contr. + MODULE mod_read_table. +ENDLOOP. +... +``` + +> **💡 Note**
+> - In a modern program, it is more comfortable to use an ALV Grid control. +> - More additions are available for the statement. + +The ABAP statement [`REFRESH CONTROL`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abaprefresh_control.htm) initializes the properties of a table control. + +```abap +"Code in an ABAP Program +... +REFRESH CONTROL contr FROM SCREEN dynnr. +... +``` + +

⬆️ back to top

+ +### Tabstrips Controls +- Allow tab pages to be displayed on dynpros +- Represent one of several available [subscreens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensubscreen_glosry.htm) in dynpros. Users select the subscreen to be displayed using tab pages. +- Declaring a tabstrip control in the ABAP program: + ```abap + CONTROLS tabstr TYPE TABSTRIP. + ``` +- Result: A structure with the name of the control is created in the ABAP program. From this structure, only the component `activetab` is required in the program. +- For the tabstrip controls, suitable subscreens must be called using [`CALL SUBSCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=dynpcall.htm) statements in the flow logic. +- In PBO processing, the active tab page is set by assigning the function code of a tab title to the `activetab` component. By default, the first tab page is active. +- For `CALL SUBSCREEN`, there is one variant for the PBO and one variant for the PAI event. + - PBO: `CALL SUBSCREEN sub_area INCLUDING prog dynnr.` + - Includes the subscreen dynpro of the program and the dynpro number in a subscreen area of the current dynpro. It also processes its PBO flow logic at this point. After PBO processing of the subscreen dynpro, the flow logic of the current dynpro is continued after the `CALL SUBSCREEN` statement. + - PAI: `CALL SUBSCREEN sub_area.` + - Calls the PAI flow logic of the subscreen dynpro included in the subscreen area. + +Example: +```abap +"Code in a PBO dialog module +... +"Providing a dynpro number +dynnr = '9400'. +"Assign the activetab component +tabstr-activetab = 'SOME_TAB'. +"Providing the prgram name +prog = sy-repid. +... + +**************************************************************************** + +"Code in the flow logic + +PROCESS BEFORE OUTPUT. + ... + CALL SUBSCREEN sub_area INCLUDING prog dynnr. + ... + +PROCESS AFTER INPUT. + ... + CALL SUBSCREEN sub_area. + ... + +``` + +

⬆️ back to top

+ +### GUI Controls +- Are components of the presentation view of an AS ABAP. +- They are not directly integrated into the ABAP language and are therefore not part of the classic ABAP interfaces. However, they are part of the SAP GUI and are designed to integrate seamlessly with classic dynpros. +- Are relatively modern UI elements that are used, for example, to display different types of data (images, HTML pages, hierarchical trees, and so on) in different ways or to enable user input. +- Are integrated into a dynpro interface using container controls that provide a screen area for the actual GUI control (e.g. by a custom container). +- Examples of GUI controls + - Toolbar control (`CL_GUI_TOOLBAR`): Implements an application toolbar that is independent of the GUI status. The input elements are created by method calls (for example, `ADD_BUTTON`). User actions are signaled by raising ABAP Objects events (for example, `FUNCTION_SELECTED`). + - Picture control (`CL_GUI_PICTURE`): Allows to display images in BMP, JPG, or GIF format. The dynpro to be displayed is loaded using the `LOAD_PICTURE_FROM_URL` method. Events such as `PICTURE_DBLCLICK` signal user actions. + - Browser control (`CL_GUI_HTML_VIEWER`): A browser for HTML pages or XML documents on the dynpro. Special links in the document trigger the `SAPEVENT` event when the user clicks, which can then be evaluated in the ABAP program. + - Edit control (`CL_GUI_TEXTEDIT`): A simple text editor with the basic functions such as select, find, and replace on the dynpro. These functions can also be called in a program-controlled way using methods such as `FIND_AND_REPLACE`. + - Tree control: Are available in different versions (for example, `CL_GUI_SIMPLE_TREE`). They allow hierarchical relationships to be displayed in tree structures. + - ALV Grid control: Is the replacement for classic lists. It provides functions such as searching, sorting, and printing the content of the list. However, the associated class `CL_GUI_ALV_GRID` should no longer be used directly for new developments. Classes such as `CL_SALV_TABLE` encapsulate the use of the ALV Grid control and simplify the integration. + +

⬆️ back to top

+ +## More Information + +- [SAP GUI User Dialogs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_screens.htm) in the ABAP Keyword Documentation as the entry topic for dynpro-related topics +- Documentation about the [screen painter in the Help Portal](https://help.sap.com/docs/ABAP_PLATFORM_NEW/bd833c8355f34e96a6e83096b38bf192/d1801b50454211d189710000e8322d00) +- Documentation about the [menu painter in the Help Portal](https://help.sap.com/docs/ABAP_PLATFORM_NEW/bd833c8355f34e96a6e83096b38bf192/d1801ce8454211d189710000e8322d00) +- Find more dynpro examples in the ABAP Keyword Documentation. In ADT, in your system, choose `CTRL + SHIFT + A` to open the search. Insert `demo_dynpro*` to get a list of dynpro examples. + +## Executable Example + +After the import of the repository, proceed as follows: +- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. +- Enter `zdemo_abap_dynpro` and open the program. +- Run the program by choosing `F8`. + +> **💡 Note**
+> - The executable example ... +> - covers the following topics: +> - Dynpro flow logic and related statements (`MODULE`, `FIELD`, `CHAIN`/`ENDCHAIN`, `LOOP`/`ENDLOOP`, `CALL SUBSCREEN`) +> - ABAP statements for calling and leaving dynpros (`SET SCREEN`, `CALL SCREEN`, `LEAVE SCREEN`) +> - Modifying static attributes (`LOOP AT SCREEN`, `MODIFY SCREEN`), +> - Statements related to the GUI status and title (`GET`/`SET PF-STATUS`, `SET TITLEBAR`) +> - Controls (table and tabstrip controls) +> - does not claim to include meaningful dynpros with meaningful dynpro sequences (branching to new dynpro sequences occur through using appropriate statements). +> - is not intended to be a role model for proper dynpro design. +> - is not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. +> - is only intended to demonstrate a selection of keywords and visualize dynpro-related syntax in action on a high level. +> - is explained in more detail below in the expandable section below. Click to view the details. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) + +
+
+ Expand to see explanations of the executable example + +
+The example demonstrates dynpro-related statements. In the dynpros, you can select various options for checking out the effect of the syntax. +It covers the following aspects: + +- Dynpro flow logic and related statements (`MODULE`, `FIELD`, `CHAIN`/`ENDCHAIN`, `LOOP`/`ENDLOOP`, `CALL SUBSCREEN`) +- ABAP statements for calling and leaving dynpros (`SET SCREEN`, `CALL SCREEN`, `LEAVE +SCREEN`) +- Modifying static attributes (`LOOP AT SCREEN`, `MODIFY SCREEN`), +- Statements related to the GUI status and title (`GET`/`SET PF-STATUS`, `SET TITLEBAR`) +- Controls (table and tabstrip controls) + +**First dynpro** (the "home page"): +- Selection options for what can be explored in other dynpros +- Choose the *Go* button to switch to another dynpro + +**Dynpro "Example of screen elements"**: +- Demonstrates several screen elements +- Pushbuttons, input field, boxes, checkboxes, radio buttons + +**Dynpro "Statements I"**: +- Selection options for various dynpro-related ABAP statements +- When you choose a radio button and *Go*, a message is displayed providing some information. + +**Dynpro "Statements II"**: +- Covers statements in the flow logic +- The option `MODULE ... AT EXIT-COMMAND` opens another dynpro. It demonstrates the exit command. The input field is required to be filled. This denies the processing after choosing the *Close 1* and *Cancel* buttons. This is not true for the *Close 2* button. + +**Dynpro "Controls"**: +- Shows several controls: Table and tabstrip controls as well as an ALV Grid control as an example for a GUI control
\ No newline at end of file diff --git a/19_ABAP_for_Cloud_Development.md b/19_ABAP_for_Cloud_Development.md index a6365bc..4adb157 100644 --- a/19_ABAP_for_Cloud_Development.md +++ b/19_ABAP_for_Cloud_Development.md @@ -1,187 +1,185 @@ - - -# ABAP for Cloud Development - -- [ABAP for Cloud Development](#abap-for-cloud-development) -- [Terms](#terms) -- [Excursions](#excursions) -- [More Information](#more-information) -- [Executable Example](#executable-example) - - -This ABAP cheat sheet briefly outlines the terms ABAP Cloud and classic ABAP to get an idea about [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm). -It provides references to more detailed information on the topic. - -# Terms - -- ABAP Cloud - - Progamming paradigm for state-of-the-art, cloud-ready and upgrade-stable solutions - - Based on a usage type of the [ABAP Platform](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_platform_glosry.htm), where the following restrictions apply: - - [ABAP language version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_version_glosry.htm): - - The available ABAP language version is [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm) that presents a [restricted ABAP language version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_version_glosry.htm). - - [Released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreleased_api_glosry.htm): - - Access to SAP-delivered repository objects is restricted to objects released for ABAP for Cloud Development - - For example, most of the database tables provided by SAP cannot be read directly (although there are abstractions/CDS view entities for many that can be accessed). - - Libraries are available with predefined functionality. - - Note that repository objects can be classified by a [release contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelease_contract_glosry.htm) (e.g. C0, C1 etc.). - - Tools: - - [ABAP development tools for Eclipse (ADT)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm) are the only supported tools - - There is no access to SAP GUI (transactions `SE80`, `SE24` etc. you may know from classic ABAP) - - The [ABAP RESTful Application Programming Model (RAP)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm) is the transactional programming model for ABAP Cloud. - - Supported in both [SAP BTP ABAP Environment](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_btp_abap_env_glosry.htm) and [ABAP Platform Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_platform_cloud_glosry.htm). -- Classic ABAP - - Progamming paradigm for legacy solutions - - Based on an ABAP Platform without restrictions regarding ABAP language versions (i.e. you can use [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm) - the unrestricted ABAP language version - and also ABAP for Cloud Development there), usage of tools (ADT and/or SAP GUI) or access to repository objects (also objects provided by SAP). - - Supported in [SAP S/4HANA](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_s4hana_glosry.htm) - - -> **💡 Note**
-> - See more information in the topic [ABAP Language Versions, Release Contracts and Released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_versions_and_apis.htm). -> - See the topic [Language Elements in ABAP Versions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_abap_elements.htm) that provides a table showing which ABAP language elements are allowed in which ABAP language version - -

⬆️ back to top

- -# Excursions - -1) If available to you, you have accessed an SAP BTP ABAP environment using ADT. - - Access to SAP-provided repository objects is restricted to objects that have been released for ABAP for Cloud Development (released APIs). You can find the released repository objects in the *Project Explorer* view in ADT under *Released Objects*: - - ![Released APIs](./files/released_APIs.png) - - As an example of a released API, consider the `CL_ABAP_RANDOM_INT` class (computes random integers). In ADT, once you have opened the class, check the *Properties* tab. Click *API State* on the left to display information about the release contracts. In this case, it is C1. As mentioned above, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_versions_and_apis.htm#@@ITOC@@ABENABAP_VERSIONS_AND_APIS_2) for more information on C1, and so on. This is also true for ABAP repository objects in classic ABAP. - - ![Release contract](./files/release_contract.png) - - For deprecated and invalid syntax in ABAP for Cloud Development, see the following code. - For example, create a demo class and insert the code contained in the implementation into the `if_oo_adt_classrun~main` method. You will see several syntax errors. - - > **💡 Note**
- > - The `IF_OO_ADT_CLASSRUN` interface is a released API. As the name implies, you can implement this interface to run an ABAP class. In ADT you can do this with *F9*. Of course, the example below will not run. The class cannot be activated because of the syntax errors. Note: To output the content of data objects, you can use `out->write( ... ).` in the `main` method. - > - About the errros/warnings: - > - The first two ABAP SQL statements select from demo database tables. The first is a demo table provided by SAP. This table is not directly accessible in ABAP Cloud (unlike in classic ABAP) and therefore cannot be used as a data source to select from. The second one is a database table from the ABAP cheat sheet GitHub repository. If you have imported the repository into the system, you can use it as a data source. - > - The next set of ABAP SQL statements are dynamic statements. This is just to emphasize that you should be careful with dynamic statements. You will not get a syntax error at compile time. You can try out the following: Comment out all code except the lines with the dynamic statements, activate the code and run the class with `F9`. The result is a [runtime error](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenruntime_error_glosry.htm) because you cannot select from the data source. - > - Examples for deprecated and invalid syntax in ABAP for Cloud Development are included. Among them, the invalid statement `MOVE ... TO` and others which are just included for demonstration purposes. To set breakpoints in ADT, double-click the area to the left of the code line number. - - ```abap - CLASS zcl_demo_abap_temp DEFINITION - PUBLIC - FINAL - CREATE PUBLIC . - - PUBLIC SECTION. - INTERFACES if_oo_adt_classrun. - ENDCLASS. - - CLASS zcl_demo_abap_temp IMPLEMENTATION. - METHOD if_oo_adt_classrun~main. - "ABAP SQL statements using database tables as data sources - "Data source that cannot be accessed in ABAP Cloud - SELECT carrid, connid FROM spfli WHERE carrid = 'LH' INTO TABLE @DATA(it1). - - "Data source that can be accessed in ABAP Cloud if you have imported - "the ABAP cheat sheet repository objects - SELECT carrid, connid FROM zdemo_abap_fli WHERE carrid = 'LH' INTO TABLE @DATA(it2). - - "Dynamic ABAP SQL statements - "No syntax error will be displayed for the dynamic statements. - "However, a runtime error will occur when running the class (in ABAP Cloud). - "Note: Check out the CL_ABAP_DYN_PRG class, which supports dynamic programming - "by checking the validity of dynamic specifications. - SELECT SINGLE carrid, connid FROM ('SPFLI') WHERE carrid = 'LH' INTO NEW @DATA(ref_a). - "No runtime error if you have imported the ABAP cheat sheet repository objects. - SELECT SINGLE carrid, connid FROM ('ZDEMO_ABAP_FLI') WHERE carrid = 'LH' INTO NEW @DATA(ref_b). - - "Examples for deprecated and invalid syntax in ABAP for Cloud Development - DATA(num1) = 1. - DATA(num2) = 1. - DATA(num3) = 2. - "Invalid statement - MOVE num3 TO num1. - "Alternative that can be used - num2 = num3. - - "Note: This table type is released. - DATA(it3) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). - "Invalid statement - DESCRIBE TABLE it3 LINES DATA(num_lines1). - "Alternative that can be used - DATA(num_lines2) = lines( it3 ). - - DATA: ref1 TYPE REF TO i, - ref2 TYPE REF TO i. - "Deprecated statement - GET REFERENCE OF num1 INTO ref1. - "Alternative that can be used - ref2 = REF #( num1 ). - - DATA str_itab TYPE string_table. - "The following statements are invalid. The pointless WRITE statement here - "just represents invalid classic ABAP UI-related statements. - READ REPORT 'ZCL_DEMO_ABAP_UNIT_TEST=======CCAU' INTO str_itab. - WRITE 'hi'. - BREAK-POINT. - ENDMETHOD. - ENDCLASS. - ``` - -2) If available to you, you have accessed an on-premise ABAP system using ADT. It is assumed that the latest ABAP release is available. - - a) Checking API status information - - Choose `CTRL + SHIFT + A` to open the search in ADT. Search the class `CL_ABAP_RANDOM_INT`. Once you have opened the class, check the *Properties* tab and find the API status information. - - b) Creating an example class - - Create a global class and insert the code from above. Depending on the name of the class you created, replace the class name in the snippet. - For the example class created, check the information in the *Properties* tab. Choose *General*. The *ABAP Language Version* is maintained as *Standard ABAP*: - ![Standard ABAP](./files/standard.png) - - If you have not imported the ABAP cheat sheet GitHub repository, remove the lines of code using artifacts from that repository, i.e. remove the statements using objects starting with `Z...`. You should not see any syntax errors. Activate the class. - - Run the class with *F9*. The code should have been processed up to the `BREAK-POINT` statement and the debugger should have started. You may want to check the content of the variables in the debugger. Choose *Terminate* to exit the debugger. - - So, unlike in the case of ABAP Cloud above, you should be able to activate and run the code (which does not represent a meaningful code example). - - c) Verifying cloud-readiness of your code in classic ABAP - - You have walked through b), created a class, inserted the code from above, and activated the class. The *ABAP Language Version* is maintained as *Standard ABAP* in the *Properties* tab. - - Verifying if your code is cloud-ready - - You can use ATC check variant `ABAP_CLOUD_READINESS` for this purpose. - - For example, in your class, right-click and choose *Run As* → *4 ABAP Test Cockpit With...*. Enter `ABAP_CLOUD_READINESS` in the pop-up window and choose *Ok*. The ATC check run is started. - - As a result of the ATC check run (note that it may take a while to complete), the *ATC Problems* tab in ADT should display results. In this case, these are the errors and warnings mentioned above, indicating that the code is not cloud-ready in various places. Double-click on the findings for more detailed information. - - d) Cloud-ready development in classic ABAP - - You have walked through b), created a class, inserted the code from above, and activated the class. The *ABAP Language Version* is maintained as *Standard ABAP* in the *Properties* tab under *General*. - - Suppose you want to do cloud-ready development and use ABAP for Cloud Development, i.e. the restricted ABAP language version, in classic ABAP (e.g. an on-premise ABAP system that allows the unrestricted ABAP language version). - - Open the *Properties* tab and choose *General* for this purpose. - - Choose the *Edit...* button to the right of the *ABAP Language Version* property. - - Select *ABAP for Cloud Development* in the pop-up window and choose *Ok*. - - You will then be able to work with a repository object with the restrictions mentioned above. As a result, the example class with the code snippets will have syntax errors and cannot be activated. In more meaningful, productive development contexts, appropriate refactoring is required. - -

⬆️ back to top

- -# More Information - -- Devtoberfest sessions - - [Overview of ABAP Cloud](https://www.youtube.com/watch?v=ApZSn_t_WSo) - - [ABAP Cloud for Classic ABAP Developers](https://youtu.be/jyLoSnHa0Vo) -- Blogs - - [Steampunk is going all-in](https://blogs.sap.com/2021/09/30/steampunk-is-going-all-in/) - - [Embedded Steampunk – Some more details for ABAP developers](https://blogs.sap.com/2022/09/05/embedded-steampunk-some-more-details-for-abap-developers/) -- Documentation - - [ABAP Cloud - Technical Use Cases and Recommended Technologies](https://www.sap.com/documents/2023/05/74fc05e6-747e-0010-bca6-c68f7e60039b.html) - - [SAP Business Technology Platform](https://help.sap.com/docs/btp/sap-business-technology-platform/sap-business-technology-platform?version=Cloud) on the SAP Help Portal - - Section [Released Components and Objects](https://help.sap.com/docs/btp/sap-business-technology-platform/released-components-and-objects?version=Cloud) including the topic [XCO Library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud) - - ABAP Keyword Documentation - - [Rules for ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_strict_rules.htm) - - [Language Elements in ABAP Versions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_abap_elements.htm): A table showing which ABAP language elements are allowed in which ABAP language version - -

⬆️ back to top

- - -# Executable Example -[zcl_demo_abap_cloud_excursion](./src/zcl_demo_abap_cloud_excursion.clas.abap) - -> **💡 Note**
-> - The executable example ... -> - does not focus - unlike other ABAP cheat sheet examples - on ABAP syntax as such (the other non-Standard-ABAP cheat sheet examples focus on ABAP syntax available in ABAP for Cloud Development), but rather emphasizes released APIs and libraries that provide predefined functionality and can be used in ABAP for Cloud Development. In particular, the Extension Components Library (XCO) is used. -> - covers an arbitrary selection for you to explore. For more detailed information and code snippets, see the SAP Help Portal documentation [here](https://help.sap.com/docs/btp/sap-business-technology-platform/sap-business-technology-platform?version=Cloud) and [here about XCO](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). In most cases, the example covers a selection of classes and methods for retrieving information about repository objects. It is more of a "playground" for exploring the APIs with a few snippets of code, and should be seen as an invitation to more in-depth exploration. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). -> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) - - + + +# ABAP for Cloud Development + +- [ABAP for Cloud Development](#abap-for-cloud-development) +- [Terms](#terms) +- [Excursions](#excursions) +- [More Information](#more-information) +- [Executable Example](#executable-example) + + +This ABAP cheat sheet briefly outlines the terms ABAP Cloud and classic ABAP to get an idea about [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm). +It provides references to more detailed information on the topic. + +# Terms + +- ABAP Cloud + - Progamming paradigm for state-of-the-art, cloud-ready and upgrade-stable solutions + - Based on a usage type of the [ABAP Platform](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_platform_glosry.htm), where the following restrictions apply: + - [ABAP language version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_version_glosry.htm): + - The available ABAP language version is [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm) that presents a [restricted ABAP language version](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_version_glosry.htm). + - [Released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenreleased_api_glosry.htm): + - Access to SAP-delivered repository objects is restricted to objects released for ABAP for Cloud Development + - For example, most of the database tables provided by SAP cannot be read directly (although there are abstractions/CDS view entities for many that can be accessed). + - Libraries are available with predefined functionality. + - Note that repository objects can be classified by a [release contract](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrelease_contract_glosry.htm) (e.g. C0, C1 etc.). + - Tools: + - [ABAP development tools for Eclipse (ADT)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenadt_glosry.htm) are the only supported tools + - There is no access to SAP GUI (transactions `SE80`, `SE24` etc. you may know from classic ABAP) + - The [ABAP RESTful Application Programming Model (RAP)](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenarap_glosry.htm) is the transactional programming model for ABAP Cloud. + - Supported in both [SAP BTP ABAP Environment](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_btp_abap_env_glosry.htm) and [ABAP Platform Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_platform_cloud_glosry.htm). +- Classic ABAP + - Progamming paradigm for legacy solutions + - Based on an ABAP Platform without restrictions regarding ABAP language versions (i.e. you can use [Standard ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenstandard_abap_glosry.htm) - the unrestricted ABAP language version - and also ABAP for Cloud Development there), usage of tools (ADT and/or SAP GUI) or access to repository objects (also objects provided by SAP). + - Supported in [SAP S/4HANA](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensap_s4hana_glosry.htm) + + +> **💡 Note**
+> - See more information in the topic [ABAP Language Versions, Release Contracts and Released APIs](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_versions_and_apis.htm). +> - See the topic [Language Elements in ABAP Versions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_abap_elements.htm) that provides a table showing which ABAP language elements are allowed in which ABAP language version + +

⬆️ back to top

+ +# Excursions + +1) If available to you, you have accessed an SAP BTP ABAP environment using ADT. + + Access to SAP-provided repository objects is restricted to objects that have been released for ABAP for Cloud Development (released APIs). You can find the released repository objects in the *Project Explorer* view in ADT under *Released Objects*: + + ![Released APIs](./files/released_APIs.png) + + As an example of a released API, consider the `CL_ABAP_RANDOM_INT` class (computes random integers). In ADT, once you have opened the class, check the *Properties* tab. Click *API State* on the left to display information about the release contracts. In this case, it is C1. As mentioned above, see [here](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_versions_and_apis.htm#@@ITOC@@ABENABAP_VERSIONS_AND_APIS_2) for more information on C1, and so on. This is also true for ABAP repository objects in classic ABAP. + + ![Release contract](./files/release_contract.png) + + For deprecated and invalid syntax in ABAP for Cloud Development, see the following code. + For example, create a demo class and insert the code contained in the implementation into the `if_oo_adt_classrun~main` method. You will see several syntax errors. + + > **💡 Note**
+ > - The `IF_OO_ADT_CLASSRUN` interface is a released API. As the name implies, you can implement this interface to run an ABAP class. In ADT you can do this with *F9*. Of course, the example below will not run. The class cannot be activated because of the syntax errors. Note: To output the content of data objects, you can use `out->write( ... ).` in the `main` method. + > - About the errros/warnings: + > - The first two ABAP SQL statements select from demo database tables. The first is a demo table provided by SAP. This table is not directly accessible in ABAP Cloud (unlike in classic ABAP) and therefore cannot be used as a data source to select from. The second one is a database table from the ABAP cheat sheet GitHub repository. If you have imported the repository into the system, you can use it as a data source. + > - The next set of ABAP SQL statements are dynamic statements. This is just to emphasize that you should be careful with dynamic statements. You will not get a syntax error at compile time. You can try out the following: Comment out all code except the lines with the dynamic statements, activate the code and run the class with `F9`. The result is a [runtime error](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenruntime_error_glosry.htm) because you cannot select from the data source. + > - Examples for deprecated and invalid syntax in ABAP for Cloud Development are included. Among them, the invalid statement `MOVE ... TO` and others which are just included for demonstration purposes. To set breakpoints in ADT, double-click the area to the left of the code line number. + + ```abap + CLASS zcl_some_class DEFINITION + PUBLIC + FINAL + CREATE PUBLIC . + + PUBLIC SECTION. + INTERFACES if_oo_adt_classrun. + ENDCLASS. + + CLASS zcl_some_class IMPLEMENTATION. + METHOD if_oo_adt_classrun~main. + "ABAP SQL statements using database tables as data sources + "Data source that cannot be accessed in ABAP Cloud + SELECT carrid, connid FROM spfli WHERE carrid = 'LH' INTO TABLE @DATA(it1). + + "Data source that can be accessed in ABAP Cloud if you have imported + "the ABAP cheat sheet repository objects + SELECT carrid, connid FROM zdemo_abap_fli WHERE carrid = 'LH' INTO TABLE @DATA(it2). + + "Dynamic ABAP SQL statements + "No syntax error will be displayed for the dynamic statements. + "However, a runtime error will occur when running the class (in ABAP Cloud). + "Note: Check out the CL_ABAP_DYN_PRG class, which supports dynamic programming + "by checking the validity of dynamic specifications. + SELECT SINGLE carrid, connid FROM ('SPFLI') WHERE carrid = 'LH' INTO NEW @DATA(ref_a). + "No runtime error if you have imported the ABAP cheat sheet repository objects. + SELECT SINGLE carrid, connid FROM ('ZDEMO_ABAP_FLI') WHERE carrid = 'LH' INTO NEW @DATA(ref_b). + + "Examples for deprecated and invalid syntax in ABAP for Cloud Development + DATA(num1) = 1. + DATA(num2) = 1. + DATA(num3) = 2. + "Invalid statement + MOVE num3 TO num1. + "Alternative that can be used + num2 = num3. + + "Note: This table type is released. + DATA(it3) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ). + "Invalid statement + DESCRIBE TABLE it3 LINES DATA(num_lines1). + "Alternative that can be used + DATA(num_lines2) = lines( it3 ). + + DATA: ref1 TYPE REF TO i, + ref2 TYPE REF TO i. + "Deprecated statement + GET REFERENCE OF num1 INTO ref1. + "Alternative that can be used + ref2 = REF #( num1 ). + + DATA str_itab TYPE string_table. + "The following statements are invalid. The pointless WRITE statement here + "just represents invalid classic ABAP UI-related statements. + READ REPORT 'ZCL_DEMO_ABAP_UNIT_TEST=======CCAU' INTO str_itab. + WRITE 'hi'. + BREAK-POINT. + ENDMETHOD. + ENDCLASS. + ``` + +2) If available to you, you have accessed an on-premise ABAP system using ADT. It is assumed that the latest ABAP release is available. + + a) Checking API status information + - Choose `CTRL + SHIFT + A` to open the search in ADT. Search the class `CL_ABAP_RANDOM_INT`. Once you have opened the class, check the *Properties* tab and find the API status information. + + b) Creating an example class + - Create a global class and insert the code from above. Depending on the name of the class you created, replace the class name in the snippet. + For the example class created, check the information in the *Properties* tab. Choose *General*. The *ABAP Language Version* is maintained as *Standard ABAP*: + ![Standard ABAP](./files/standard.png) + - If you have not imported the ABAP cheat sheet GitHub repository, remove the lines of code using artifacts from that repository, i.e. remove the statements using objects starting with `Z...`. You should not see any syntax errors. Activate the class. + - Run the class with *F9*. The code should have been processed up to the `BREAK-POINT` statement and the debugger should have started. You may want to check the content of the variables in the debugger. Choose *Terminate* to exit the debugger. + - So, unlike in the case of ABAP Cloud above, you should be able to activate and run the code (which does not represent a meaningful code example). + + c) Verifying cloud-readiness of your code in classic ABAP + - You have walked through b), created a class, inserted the code from above, and activated the class. The *ABAP Language Version* is maintained as *Standard ABAP* in the *Properties* tab. + - Verifying if your code is cloud-ready + - You can use ATC check variant `ABAP_CLOUD_READINESS` for this purpose. + - For example, in your class, right-click and choose *Run As* → *4 ABAP Test Cockpit With...*. Enter `ABAP_CLOUD_READINESS` in the pop-up window and choose *Ok*. The ATC check run is started. + - As a result of the ATC check run (note that it may take a while to complete), the *ATC Problems* tab in ADT should display results. In this case, these are the errors and warnings mentioned above, indicating that the code is not cloud-ready in various places. Double-click on the findings for more detailed information. + + d) Cloud-ready development in classic ABAP + - You have walked through b), created a class, inserted the code from above, and activated the class. The *ABAP Language Version* is maintained as *Standard ABAP* in the *Properties* tab under *General*. + - Suppose you want to do cloud-ready development and use ABAP for Cloud Development, i.e. the restricted ABAP language version, in classic ABAP (e.g. an on-premise ABAP system that allows the unrestricted ABAP language version). + - Open the *Properties* tab and choose *General* for this purpose. + - Choose the *Edit...* button to the right of the *ABAP Language Version* property. + - Select *ABAP for Cloud Development* in the pop-up window and choose *Ok*. + - You will then be able to work with a repository object with the restrictions mentioned above. As a result, the example class with the code snippets will have syntax errors and cannot be activated. In more meaningful, productive development contexts, appropriate refactoring is required. + +

⬆️ back to top

+ +# More Information + +- Devtoberfest sessions + - [Overview of ABAP Cloud](https://www.youtube.com/watch?v=ApZSn_t_WSo) + - [ABAP Cloud for Classic ABAP Developers](https://youtu.be/jyLoSnHa0Vo) +- Blogs + - [Steampunk is going all-in](https://blogs.sap.com/2021/09/30/steampunk-is-going-all-in/) + - [Embedded Steampunk – Some more details for ABAP developers](https://blogs.sap.com/2022/09/05/embedded-steampunk-some-more-details-for-abap-developers/) +- Documentation + - [ABAP Cloud - Technical Use Cases and Recommended Technologies](https://www.sap.com/documents/2023/05/74fc05e6-747e-0010-bca6-c68f7e60039b.html) + - [SAP Business Technology Platform](https://help.sap.com/docs/btp/sap-business-technology-platform/sap-business-technology-platform?version=Cloud) on the SAP Help Portal + - Section [Released Components and Objects](https://help.sap.com/docs/btp/sap-business-technology-platform/released-components-and-objects?version=Cloud) including the topic [XCO Library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud) + - ABAP Keyword Documentation + - [Rules for ABAP Cloud](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_strict_rules.htm) + - [Language Elements in ABAP Versions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenrestricted_abap_elements.htm): A table showing which ABAP language elements are allowed in which ABAP language version + +

⬆️ back to top

+ + +# Executable Example +[zcl_demo_abap_cloud_excursion](./src/zcl_demo_abap_cloud_excursion.clas.abap) + +> **💡 Note**
+> - The executable example ... +> - does not focus - unlike other ABAP cheat sheet examples - on ABAP syntax as such (the other non-Standard-ABAP cheat sheet examples focus on ABAP syntax available in ABAP for Cloud Development), but rather emphasizes released APIs and libraries that provide predefined functionality and can be used in ABAP for Cloud Development. In particular, the Extension Components Library (XCO) is used. +> - covers an arbitrary selection for you to explore. For more detailed information and code snippets, see the SAP Help Portal documentation [here](https://help.sap.com/docs/btp/sap-business-technology-platform/sap-business-technology-platform?version=Cloud) and [here about XCO](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). In most cases, the example covers a selection of classes and methods for retrieving information about repository objects. It is more of a "playground" for exploring the APIs with a few snippets of code, and should be seen as an invitation to more in-depth exploration. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). +> - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file diff --git a/20_Selection_Screens_Lists.md b/20_Selection_Screens_Lists.md index 59c4976..186a061 100644 --- a/20_Selection_Screens_Lists.md +++ b/20_Selection_Screens_Lists.md @@ -1,1336 +1,1339 @@ - - -# Selection Screens and Classic Lists - -- [Selection Screens and Classic Lists](#selection-screens-and-classic-lists) - - [Introduction](#introduction) - - [Terms](#terms) - - [Selection screens](#selection-screens) - - [Classic Lists](#classic-lists) - - [ABAP Statements for Selection Screens](#abap-statements-for-selection-screens) - - [Creating Selection Screens](#creating-selection-screens) - - [PARAMETERS](#parameters) - - [SELECT-OPTIONS](#select-options) - - [SELECTION-SCREEN](#selection-screen) - - [Variants of the SELECTION-SCREEN Statement](#variants-of-the-selection-screen-statement) - - [Calling Selection Screens](#calling-selection-screens) - - [Excursion: SUBMIT](#excursion-submit) - - [ABAP Statements for Classic Lists](#abap-statements-for-classic-lists) - - [Creating Lists](#creating-lists) - - [Reading and Modifying in Lists](#reading-and-modifying-in-lists) - - [Event Blocks](#event-blocks) - - [Excursion: SAP List Viewer (ALV)](#excursion-sap-list-viewer-alv) - - [Getting Started](#getting-started) - - [Optional Layout Settings and Functionality](#optional-layout-settings-and-functionality) - - [More Information](#more-information) - - [Executable Examples](#executable-examples) - - -## Introduction - -⚠️ The content of this cheat sheet and the executable examples are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). - -[Selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_glosry.htm) and [classic lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_list_glosry.htm) are among the classic ABAP user interfaces. They are integrated into the ABAP language itself, which means that special ABAP statements are available to create and handle them. - -This cheat sheet provides a high-level overview of selection screens and classic lists, focusing on a selection of related statements, supported by executable examples to explore the syntax in action. It includes an excursion into the SAP List Viewer (ALV). - -For more detailed information and syntax options, see the topics [Selection Screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen.htm) and [Classic Lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpro_list.htm) in the ABAP Keyword Documentation. - -> **💡 Note**
-> - Although they are considered outdated for application programs, you will still find classic ABAP UIs frequently in classic ABAP. -> - Classic ABAP UIs cannot be created in [ABAP Cloud](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_cloud_glosry.htm). -> - This cheat sheet ... -> - is not intended to encourage you to start creating classic ABAP UIs for programming new applications. -> - does not cover all facets, techniques, and syntax options (there's a rich variety of keywords and additions) in great detail. -> - is intended to cover a selection of related syntax that you may encounter in older ABAP code. If you need more information, always consult the ABAP Keyword Documentation. -> - Links to the ABAP Keyword Documentation in this cheat sheet refer to the documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm) (latest version). - -

⬆️ back to top

- -## Terms - -### Selection screens -- Are special [dynpros](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) in [executable programs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexecutable_program_glosry.htm) (*"reports"*; they're also possible in [function groups](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_group_glosry.htm) and [module pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmodul_pool_glosry.htm), but the focus here is on executable programs). -- Used for data entry in an executable program, i.e. they allow users to ... - - enter parameters (for entering single values). - - provide selection criteria (complex selection options for value lists and value ranges) that can be used to supply an executable program with values to work with. -- Can be created using special ABAP statements in the global declaration part of executable programs -- Are processed by the ABAP runtime framework, which triggers [selection screen events](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_event_glosry.htm) ([see further down](#event-blocks)). -- When you create a selection screen and run an ABAP program, the dynpros are generated automatically. These generated dynpros cannot be edited directly. -- Further ways in which selections screens are different from *regular* dynpros: - - Unlike dynpros, you can create selection screens without using the [screen painter](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_painter_glosry.htm) tool. The [ABAP Editor](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_editor_glosry.htm) is the only tool you use to define a selection screen (using ABAP statements). - - They have a more limited set of features, for example, the layout of selection screens is more restricted. However, selection screens offer various types of input fields, which can also be expressed as checkboxes or radio buttons, and which can be grouped and labeled. - - Modification options are limited. For example, you can only use some predefined function codes. - - You cannot define [dialog modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_module_glosry.htm) in the ABAP program. -- There are two types of selection screens: - - [Standalone selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstand-alone_sel_screen_glosry.htm) - - Defined between the statements `SELECTION-SCREEN BEGIN OF SCREEN` and `SELECTION-SCREEN END OF SCREEN` - - Can be defined in all programs that can contain dynpros - - [Standard selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_selscreen_glosry.htm) - - Each executable program (and only there) contains a standard selection screen with the dynpro number 1000. Note: If you create a standalone selection screen, you cannot use dynpro number 1000. - - The screen elements on the standard selection screen are defined by all `PARAMETERS`, `SELECT-OPTIONS`, and `SELECTION-SCREEN` statements that are defined outside of the statements mentioned above for creating standalone selection screens. - - -### Classic Lists -- Used to output data in a structured and formatted way. -- This output can be ... - - created in the so-called [list buffer](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_buffer_glosry.htm), a memory area for storing [screen lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_list_glosry.htm), i.e. a list that is displayed on a predefined list dynpro (list dynpro that is accessed implicitly when a program is executed; note: this dynpro is not part of the executed program). - - sent to the [SAP spool system](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_spool_system_glosry.htm) as a spool list (i.e. a list that is not stored as a screen list but is intended for printing or archiving; the focus of this cheat sheet is on screen lists). -- Typical flow of executable programs that include selection screens and content to be displayed on the list dynpro: - - Programs are executed using the *Execute* button (F8). - - Selection screens are displayed, users usually make entries for whatever purpose, which are further processed in the program. - - Output result is written to the list buffer and finally displayed (on a list dynpro; note: the list processing is automatically started when running executable programs). - - The list can be further implemented to respond to user interaction, such as clicking a line in the list. -- More modern alternatives for classic lists are available, such as the classes of the SAP List Viewer (ALV), for example `CL_SALV_TABLE`. - -> **💡 Note**
-> The program is grouped into so-called [event blocks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_block_glosry.htm), which can contain implementations for various events (e.g. a [selection screen event](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_event_glosry.htm) when a user selects a radio button, or a [list event](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_event_glosry.htm) when a user double-clicks a line in the list). These event blocks are introduced by special ABAP statements. When a particular event is triggered, the corresponding event block is called and the appropriate code can be implemented there to react to the user action. See more information [here](#event-blocks). - -

⬆️ back to top

- -## ABAP Statements for Selection Screens - -### Creating Selection Screens - -Selection screens can be created by using special ABAP statements in the global declaration part of executable programs: -- [`PARAMETERS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapparameters.htm) -- [`SELECT-OPTIONS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect-options.htm) -- [`SELECTION-SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselection-screen.htm) - -### PARAMETERS -- Creates ... - - a program-global variable (similar to `DATA` statements) - - an input field on the selection screen automatically, i.e. the content of the program-global variable can be changed via the input field. -- The parameter name can be up to eight characters long. -- Multiple additions are available to define the appearance (e.g. `AS CHECKBOX`) or influence the user interface (e.g. `OBLIGATORY`). - -> **💡 Note**
-> The parameter name is a technical name. You probably do not want to display technical names on the user interface. You can define proper names ([text elements](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentext_element_glosry.htm)) in the ABAP Editor, e.g. for translation purposes. - -The following code snippets provide a commented selection of available syntax options. -Note that various combinations of multiple additions are possible, and some are not. See the ABAP Keyword Documentation for details. - -```abap -****************************** Type options ****************************** -"Referring to a built-in type with TYPE -"In this case, a variable length character string can be inserted in the -"generated input field. Note the LOWER CASE addition further down. -PARAMETERS pa TYPE string. - -"Referring to an existing data object with the LIKE addition -DATA dobj TYPE i. -PARAMETERS pb LIke dobj. - -"Reference to a data type from the ABAP Dictionary -"All screen-relvant properties of that type are adopted, -"which is the case in the following example (spfli is an SAP-delivered -"demo table). A callable field help and input help is created. -"Note that there is no automatic value check. For that, use the -"addition VALUE CHECK. -PARAMETERS pc LIKE spfli-carrid. - -"Dynamic spefication is possible, e.g. using a dynamic -"reference to a data type from the ABAP Dictionary after LIKE. -"some_dobj in the example may be the name of a component of a database table, -"provided in capital letters. -DATA some_dobj TYPE c LENGTH 50. -PARAMETERS pd LIKE (some_dobj). - -"Length specifications -"Similar to declarations with DATA, the length can be specified for data -"types with generic length (i.e. the types c, n, p, and x). -PARAMETERS pe TYPE c LENGTH 1. -PARAMETERS pf TYPE n LENGTH 5. - -"Specifications in which the length is specified in parentheses. -"For better readability, specifying LENGTH explicitly is recommended. -PARAMETERS pg(2) TYPE c. -"No length specified means LENGTH 1 by default -PARAMETERS ph TYPE c. -"No explicit type specification means TYPE c by default -PARAMETERS pi(40). -PARAMETERS pj length 40. -"No explicit type and length specification means TYPE c LENGTH 1 by default -PARAMETERS pk. - -****************************** Value options ****************************** - -"DEFAULT: Defining a start value (can also be a data object instead of a literal) -PARAMETERS pl TYPE i DEFAULT 12345. - -"LOWER CASE: Prevents the effect of capitalizing the entry made when the content -"is transported to the data object -PARAMETERS pm TYPE string DEFAULT `Hello World`. "Value you insert will be capitalized. -PARAMETERS pn TYPE string DEFAULT `Hello World` LOWER CASE. - -"Note: There are more additions available, e.g. for linking the parameter to search help, -"or checking against fixed values defined in the domain of the data type, and so on. -"You can also perform your custom input checks. See the event block section below. - -****************************** Screen options ****************************** - -"OBLIGATORY: Declaring the input field as a required field -"If there is no entry, the program cannot proceed when choosing Execute. -"A message is displayed. -PARAMETERS po TYPE string OBLIGATORY. - -"NO-DISPLAY: Hiding the input field on the selection screen -"A value can be supplied when calling the program with SUBMIT and the WITH addition. -"Note that with the NO-DISPLAY addition, the parameter can have any data types except -"for reference/enumerated types, unlike in the other additions which require flat -"types (except type string). -PARAMETERS pp TYPE string NO-DISPLAY. - -"VISIBLE LENGTH: Defining the visible length of the field -PARAMETERS pq TYPE c LENGTH 5 VISIBLE LENGTH 3. - -"AS CHECKBOX: Displaying input field as checkbox -"Type c and length 1 is expected, but the explicit length specification is not allowed. -"The checkbox is selected if the value has the value X or x. -PARAMETERS pr AS CHECKBOX. "Implicit type c -PARAMETERS ps TYPE c AS CHECKBOX. "Explicit type specification (but no explicit length) - -"RADIOBUTTON GROUP: Defining a radio button group for parameters -"Note: -"- Group name can have a maximum of four characters -"- Regarding the data type, the same applies as for AS CHECKBOX -"- Only one parameter can be defined with the DEFAULT addition -"- If DEFAULT is not specified, the first parameter of the group is set to the value X -"- Here, a chained statement is used. -PARAMETERS: prb1 RADIOBUTTON GROUP rbgr, - prb2 type c RADIOBUTTON GROUP rbgr, "Explicit type specification - prb3 RADIOBUTTON GROUP rbgr DEFAULT 'X'. "Select this radiobutton by default - -"AS LISTBOX VISIBLE LENGTH: Creating a dropdown list box -"You can use the function module VRM_SET_VALUES by passing a suitable list at the -"events AT SELECTION-SCREEN OUTPUT or AT SELECTION-SCREEN ON VALUE-REQUEST. -"See the executable example. -PARAMETERS pt TYPE i AS LISTBOX VISIBLE LENGTH 10. - -*********************** Assigning function codes *********************** - -"The AS CHECKBOX, RADIOBUTTON GROUP, AS LISTBOX additions can be combined -"with the addition USER-COMMAND. That means, on selection, the event -"AT SELECTION-SCREEN is raised and you can evaluate the function code there. -"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. -"When the button is clicked, the event AT SELECTION-SCREEN is raised and the -"function code ('cmd', 'rbcm' in the example) is passed to the 'ucomm' component -"in the interface work area 'sscrfields' which can be evaluated and reacted upon -"accordingly. See the executable example. -PARAMETERS pu AS CHECKBOX USER-COMMAND cmd. -"For radio buttons, the addition can be specified for the first selection -"parameter in a radio button group. -PARAMETERS: pv RADIOBUTTON GROUP grp USER-COMMAND rbcm, - pw RADIOBUTTON GROUP grp. - -"Note: The MODIF ID addition is possible for PARAMETERS and -"SELECT-OPTIONS. This is also true for SELECTION-SCREEN statements. See -"the details there. -``` - -

⬆️ back to top

- -### SELECT-OPTIONS - -- Declares selection criteria for a data object -- Unlike the `PARAMETERS` statement, which specifies a single value for a variable, the `SELECT-OPTIONS` statement allows you to specify complex criteria, such as an value range or a list of single values, to include or exclude values, that can be evaluated. -- The selection criteria are assigned to a selection table (see [ranges table](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenranges_table_glosry.htm) and the type `TYPE RANGE OF`). - - Such a table type contains four columns - low, high, option, sign - for determining range conditions. Each line of such a table represents a condition. - - Typically, the content of the selection table can be evaluated in `SELECT` statements using the `IN` operator in the `WHERE` clause. - - If the selection table is empty, all lines are respected. - -Example: - -```abap -DATA wa TYPE some_tab. - -SELECT-OPTIONS sel FOR some_tab-some_comp. - -SELECT * - FROM some_tab - WHERE some_comp IN @sel - INTO @wa. - ... -ENDSELECT. - -"Multiple additions and combinations are possible. - -"The following statement creates two input fields that can be -"used to specify selection criteria on the selection screen. -"In addition, the Multiple Selection button is available to -"further specify the selection criteria, e.g. what to include, -"exclude, etc.. As in all examples, the variable is an internal -"table of type TYPE RANGE OF whose contents can be evaluated. -"The FOR addition is followed by an already declared data object. -SELECT-OPTIONS a FOR some_dobj. -"As mentioned above, NO-DISPLAY hides. -SELECT-OPTIONS b FOR some_dobj NO-DISPLAY. -"NO-EXTENSION: The Multiple Selection button is not created on the -"selection screen -SELECT-OPTIONS c FOR some_dobj NO-EXTENSION. -"NO INTERVALS: Only one input field. Intervals can still be selected -"using the Multiple Selection button. -SELECT-OPTIONS d FOR some_dobj NO INTERVALS. -"DEFAULT ... TO ...: Providing start values for the columns in the -"first line of the selection table (low and high values) -SELECT-OPTIONS e FOR some_dobj DEFAULT 3 TO 10. -"DEFAULT ... OPTION ... SIGN ...: Providing further start values. -"See details further down. -SELECT-OPTIONS f FOR some_dobj DEFAULT 4 TO 8 OPTION NB SIGN I. -``` - -> **💡 Note**
-> Notes on the `OPTION` and `SIGN` additions: -> - `OPTION` -> - Start value for the `option` column for the condition in the form of comparison operators -> - `TO` not specified: `EQ` (equal), `NE` (not equals), `GE` (greater than or equals), `GT` (greater than), `LE` (less than or equals), `LT` (less than), `CP` (conforms to pattern), or `NP` (does not conform to pattern) must be specified -> - `TO` specified: Either `BT` (between) or `NB` (not between) must be specified -> - `OPTION` not specified: `EQ`/`BT` is used -> - For `CP` and `NP`, wildcard characters `*` or `+` must be specified. -> - `SIGN` -> - Start value for the `sign` column -> - Either `I` or `E` must be specified to include/exclude the result of the condition -> - `SIGN` not specified: `I` by default -> - For historical reasons, the selection table is a table with [header line](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenheader_line_glosry.htm). Therefore, if you want to address the table content (beyond the use in a `SELECT ... WHERE ... IN ...` statement), use the syntax `a[]`. - - -

⬆️ back to top

- - -### SELECTION-SCREEN - -- `SELECTION-SCREEN` statements can be used to create and modify the layout of standalone selection screens. -- Note: The standard selection screen for executable programs is created automatically. That is, each executable program contains a standard selection screen with dynpro number 1000. -- Selection screens can be created as regular dynpros or as subscreen dynpros. - -```abap -******************************** Pattern *********************************** - -SELECTION-SCREEN BEGIN OF SCREEN ... - - ... - "Here go all PARAMETERS, SELECT-OPTIONS, and SELECTION-SCREEN statements - "to define the screen elements of the standalone selection screen. - -SELECTION-SCREEN END OF SCREEN ... - - -****************************** Regular dynpros ****************************** - -"Creating a selection screen as regular dynpro -"Note that the dynpro number must be unique in the program. Do not use 1000. -SELECTION-SCREEN BEGIN OF SCREEN 9000. - ... -SELECTION-SCREEN END OF SCREEN 9000. - -"Note: The following additions can also be combined. -"TITLE: Defining a title (e.g. the name of a text symbol) for the title bar -SELECTION-SCREEN BEGIN OF SCREEN 9001 TITLE some_title. - ... -SELECTION-SCREEN END OF SCREEN 9001. - -"AS WINDOW: Displaying the selection screen in a modal dialog box -SELECTION-SCREEN BEGIN OF SCREEN 9002 AS WINDOW. - ... -SELECTION-SCREEN END OF SCREEN 9002. - -****************************** Subscreen dynpros ****************************** - -"Can be included in other dynpros or selection screens, or in subscreen areas -"or tab pages. But they cannot be called explicitly. -SELECTION-SCREEN BEGIN OF SCREEN 9003 AS SUBSCREEN. -... -SELECTION-SCREEN END OF SCREEN 9003. - -"Note: There are more additions available regarding display adjustment, among others. -``` - -

⬆️ back to top

- -#### Variants of the SELECTION-SCREEN Statement - -- The variants do not create selection screens, but are used to change the layout of selection screens, create additional screen elements, and so on. -- Example: The `PARAMETERS` and `SELECT-OPTIONS` statements create input fields on an individual line. Using the variants of the `SELECTION-SCREEN` statement, you can arrange the layout differently. -- However, the selection screen cannot be generated if there are conflicts with existing screen elements. - - See the effect with the following snippet. Run a program with the code snippet and comment in the third line. The program terminates. The text to be created (in the same line as the first text) interferes with the first text. However, the fourth line would be possible because there is no overlap. - ```abap - PARAMETERS pa TYPE string. - SELECTION-SCREEN COMMENT /5(10) t1. - "SELECTION-SCREEN COMMENT 10(20) t2. - "SELECTION-SCREEN COMMENT 20(20) t3. - ``` - -Syntax examples: - -```abap -"Note: More optional additions are available for the the following statements. -"For the details, check the ABAP Keyword Documentation. - -"Adding blank lines -SELECTION-SCREEN SKIP. "1 blank line by default -SELECTION-SCREEN SKIP 5. "5 blank lines - -"Creating a horizontal line -"Line accross the whole screen below the lines that are already filled -SELECTION-SCREEN ULINE. -"/: Line in a new line, 5: position, (10): length -SELECTION-SCREEN ULINE /5(10). -"Note: The following statement commented out can only be specified -"inside a BEGIN/END OF LINE statement. Outside, specifying a position -"is required. -"SELECTION-SCREEN ULINE (10). - -"Providing text content on the selection screen (e.g. using a text symbol) -"Also here, note the use outside of BEGIN/END OF LINE regarding the additions. -"The optional FOR FIELD addition is, among others, used in the context of -"input/field help. -SELECTION-SCREEN COMMENT /1(20) txt. - -"Creating a pushbutton -"The pushbutton is assigned a function code. -"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. -"When the button is clicked, the event AT SELECTION-SCREEN is raised and the -"function code ('com' in the example) is passed to the 'ucomm' component in the -"interface work area 'sscrfields' which can be evaluated and reacted upon -"accordingly. See the executable example. -SELECTION-SCREEN PUSHBUTTON /5(10) pb USER-COMMAND com. - -"Defining a new line with multiple elements -SELECTION-SCREEN BEGIN OF LINE. - "The following statement with the POSITION addition is only possible here. - "It specifies the output position of a screen element. - SELECTION-SCREEN POSITION 10. - ... -SELECTION-SCREEN END OF LINE. - -"Chained statements come in handy -"Watch out that there are no positioning conflicts with other screen elements. -SELECTION-SCREEN: BEGIN OF LINE, - PUSHBUTTON 2(5) button USER-COMMAND fc, - POSITION 10. "The statement specifies the position in which the - "next element (PARAMETERS) is put. -PARAMETERS para TYPE c LENGTH 10. -SELECTION-SCREEN: COMMENT 25(10) txt, - END OF LINE. - -"Creating blocks -"More additions available, e.g. WITH FRAME (to draw a frame around a block) -"and TITLE (to define a block title). -SELECTION-SCREEN BEGIN OF BLOCK bl. - ... -SELECTION-SCREEN END OF BLOCK bl. - -"Creating tabbed blocks (other optional additions are available) -SELECTION-SCREEN BEGIN OF TABBED BLOCK tabbl FOR 5 LINES. "Specifies number of lines covered - ... - "In such a TABBED BLOCK statement, only TAB statements are allowed to integrate - "subscreen dynpros. - "USER-COMMAND addition specifies a function code. When a tab is selected by users, - "the function code can be evaluated using the the component ucomm of the structure - "'sscrfields' after the AT SELECTION-SCREEN event. See the executable example. - SELECTION-SCREEN TAB (10) tab USER-COMMAND cmd. -... -SELECTION-SCREEN END OF BLOCK tabbl. - -"MODIF ID addition for some of the previous statements (ULINE, COMMENT, -"PUSHBUTTON, TAB, and also for PARAMETERS and SELECT-OPTIONS) -"An identifier can be specified to assign a screen element to a modification group. -"This identifier is assigned to the component 'group1' of the SCREEN structure. -"Using MODIFY SCREEN statements, the elements can be modified before displaying -"in the AT SELECTION-SCREEN OUTPUT event block. -"In the following example, a radio button group consists of 4 radio buttons. -"Two of them have the addition MODIF ID. -SELECTION-SCREEN BEGIN OF BLOCK bl WITH FRAME. -PARAMETERS: pa1 RADIOBUTTON GROUP gr MODIF ID mbl, - pa2 RADIOBUTTON GROUP gr MODIF ID mbl, - pa3 RADIOBUTTON GROUP gr, - pa4 RADIOBUTTON GROUP gr. -SELECTION-SCREEN END OF BLOCK bl. - -"Suppose you want to modify the elements before displaying, e.g. make the -"two radio buttons with the identifier invisible. In the AT SELECTION-SCREEN -"OUTPUT event block, you might implement it as follows. -... -AT SELECTION-SCREEN OUTPUT. - LOOP AT SCREEN INTO DATA(wa). - IF wa-group1 = 'MBL'. - wa-invisible = '1'. - MODIFY SCREEN FROM wa. - ENDIF. - ENDLOOP. -... - -"Adding pushbuttons in the application toolbar -"There are five inactive pushbuttons to which the function codes FC01, FC02 up to FC05 -"are assigned. The ... FUNCTION KEY ... statement activates the pushbuttons for -"the specified codes. -"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. -"When the button is clicked, the event AT SELECTION-SCREEN is raised and the -"function code is passed to the 'ucomm' component in the interface -"work area 'sscrfields' which can be evaluated and reacted upon accordingly, e.g. -"in a CASE control structure. -"In the following example, three pushbuttons are added to the toolbar. To -"provide text for the buttons, assign values to the component functxt_0n (while -"n stands for the numbers 1 - 5). Otherwise, there won't be any button text. -TABLES sscrfields. -PARAMETERS pa TYPE c LENGTH 10. -SELECTION-SCREEN: FUNCTION KEY 1, "Stands for FC01 - FUNCTION KEY 2, "FC02 - FUNCTION KEY 3. "FC03 - -INITIALIZATION. - sscrfields-functxt_01 = 'Button 1'. - sscrfields-functxt_02 = 'Button 2'. - sscrfields-functxt_03 = 'Button 3'. - -AT SELECTION-SCREEN. - CASE sscrfields-ucomm. - WHEN 'FC01'. - ... - WHEN 'FC02'. - ... - WHEN 'FC03'. - ... - ENDCASE. -... -``` - -`INCLUDE` addition for reusing already created elements of the same program: - -```abap -"Note: More optional additions are available. - -SELECTION-SCREEN BEGIN OF SCREEN ... -... -SELECTION-SCREEN INCLUDE PARAMETERS param. -SELECTION-SCREEN INCLUDE SELECT-OPTIONS sel. -SELECTION-SCREEN INCLUDE COMMENT (10) txt. -SELECTION-SCREEN INCLUDE PUSHBUTTON (10) rb. -SELECTION-SCREEN INCLUDE BLOCKS blck. -... -SELECTION-SCREEN END OF SCREEN ... -``` - -

⬆️ back to top

- -### Calling Selection Screens - -- There are several ways of how to call selection screens (see [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_call.htm)), among them [`CALL SELECTION-SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_selection_screen.htm) statements. -- These statements call selection screens by specifying the dynpro number. -- Any selection screen of the main program (and only from there; including 1000) can be called. - -```abap -CALL SELECTION-SCREEN 9876. - -"STARTING AT/ENDING AT additions for creating a modal dialog box -"The numbers determine how it should be displayed. -"STARTING AT: upper left corner (column and line); ENDING AT: bottom right -"corner (if not specified, it is set automatically) -CALL SELECTION-SCREEN 9345 STARTING AT 10 10. -CALL SELECTION-SCREEN 9345 STARTING AT a b ENDING AT c d. - -"You can also predefine selection criteria for a selection screen using -"the addition USING SELECTION-SET. -``` - -

⬆️ back to top

- -### Excursion: SUBMIT -- [`SUBMIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapsubmit.htm) statements call executable programs and, therefore, selection screens. -- In general, every executable program is started implicitly with `SUBMIT`. -- Selection screens can be considered a parameter interface if the program containing them is executed using `SUBMIT`. - -```abap -"The calling program is ended -SUBMIT some_program. "Direct specification of the program name - -"Dynamic call -"Note the security risks and consequences a program submitted from outside can cause; -"you may use the class CL_ABAP_DYN_PRG to tackle security risks -SUBMIT ('SOME_PROGRAM'). "Character-like data object in a pair of parentheses - -"AND RETURN: The calling program is interrupted -SUBMIT some_program AND RETURN. - -"Selection screen-related options for the SUBMIT statement -"Specifies a particular selection screen to be called (but it's not displayed) -SUBMIT some_program USING SELECTION-SCREEN 9123. - -"Specifies that the selection screen to be called is displayed -SUBMIT some_program VIA SELECTION-SCREEN. -SUBMIT some_program USING SELECTION-SCREEN 9123 VIA SELECTION-SCREEN. - -"You can pass values to the selection screen. There are a several options. -"Check the ABAP Keyword Documentation. The following examples cover a selection. - -"In the followig example, it is assumed that the called program only has 1 -"parameter with name par, type i. The addition USING SELECTION-SCREEN is -"omitted, i.e. the standard selection screen is called (but you can also call -"the dynpro 1000 explicitly). -SUBMIT some_program WITH par = 1. "Specifying EQ is also possible - -"Displaying the selection screen, only interrupt the current program -SUBMIT some_program VIA SELECTION-SCREEN WITH par = 1 AND RETURN. - -"You can also pass multiple values, e.g. consider a program having multiple -"PARAMETERS statements (you may also have multiple WITH additions), or SELECT-OPTIONS -"statements. -SUBMIT some_program VIA SELECTION-SCREEN WITH SELECTION-TABLE tab. -``` - -

⬆️ back to top

- -## ABAP Statements for Classic Lists - -### Creating Lists - -- Lists consist of consecutive list lines that are filled one after the other using the statement [`WRITE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapwrite-.htm). -- This way, you can output mostly flat data objects and strings/xstrings, types converted to a character-like value (i.e. no internal table content or structures directly). -- Each time a data object is output, an output length is defined, either implicitly or explicitly (see [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwrite_output_length.htm)). -- The following snippets show a selection of additions to `WRITE` statements, covering positioning, creating special list elements, and formatting options. - -```abap -"WRITE using an unnamed data object -WRITE 'Hello ABAP.'. -"Named data objects -DATA some_text TYPE string VALUE `Hi, `. -"Note: The text is written right after the previous text in one line. -WRITE some_text && sy-uname. -"/: Writes to a new line -WRITE / 'new line'. - -*********** Positioning output *********** -"Specifying the output position (and output in new line) -WRITE /5 'positioned'. -"Specifying the length, no position specified means the output is -"written from the first column on -WRITE /(3) 'not displayed completely'. -"Specifying both length and position -WRITE /5(30) 'this is displayed completely'. -"Position/length only specified as numeric literals as above, then the -"addition AT can be omitted -WRITE AT /3(12) 'lorem ipsum'. -"Length specifications with * or **. In that case, the output length -"depends on the data type of the data object. There are special rules. -"See the ABAP Keyword Documentation for the details. -DATA dc34 TYPE decfloat34 VALUE ' 1.2345 '. -WRITE /(*) dc34. -WRITE /1(**) dc34. - -*********** Further specification options *********** -"Various examples for further specification options, among them function -"calls, string expressions, method calls -DATA txt TYPE string VALUE `abap`. -"String template -WRITE / |{ txt WIDTH = 20 ALIGN = RIGHT CASE = UPPER }|. -"The following statement uses a chained statement with colon. -WRITE: / |{ 1 + 2 }|, "String template includes an arithmetic calculation - to_upper( txt ). "Function call -"Concatenation using && -WRITE / `conc` && `atenated`. -"Method call (returns a random integer between 1 and 10) -"Note the * specification. The returned value is of type i. Specifying * -"for the length means the length required to output the current value -"is used. You may want to try the following code snippet by removing (*). -WRITE /(*) cl_abap_random_int=>create( - seed = cl_abap_random=>seed( ) - min = 1 - max = 10 )->get_next( ). - -"UNDER: Output in the position of previous output -"Note: If the output is written in the same line in which the previous output -"is displayed, this output is overwritten. -DATA abc TYPE c LENGTH 5 VALUE 'abcde'. -WRITE /5(5) abc. -WRITE / 'fghij' UNDER abc. - -"NO-GAP -WRITE / 'g'. -WRITE 'ap1'. "Output: g ap1 -WRITE: / 'g' NO-GAP, 'ap2'. "Output: gap2 - -"QUICKINFO: Creates a tooltip for the output -WRITE / 'Place the mouse on the following output and check the tooltip:'. -WRITE: (*) sy-uname QUICKINFO 'User name', - '/', - (*) sy-datum QUICKINFO 'Current date', - '/', - (*) sy-uzeit QUICKINFO 'Current time'. - -*********** Special list elements *********** -"INPUT: Enabling fields for input -"You can overwrite the output and further evaluate the overwritten -"content in a list event. -WRITE / ' Enter your name here ' INPUT. - -"AS CHECKBOX -"The value (blank, X) is stored in the list buffer and can be -"evaluated during a list event. -DATA: chck1 TYPE c LENGTH 1 VALUE 'X', - chck2 TYPE c LENGTH 1 VALUE ' '. -WRITE: / chck1 AS CHECKBOX, 'A checkbox', - / chck2 AS CHECKBOX, 'Another checkbox'. - -"AS ICON: Outputting icons -"Check the type pool ICON for names of predefined icons. -WRITE / icon_green_light AS ICON. -WRITE / icon_red_light AS ICON. -WRITE / icon_yellow_light AS ICON. -WRITE / icon_activate AS ICON. - -"AS SYMBOL: Outputting symbols -"Check the type pool SYM for names of predefined icons. -WRITE / sym_left_hand AS SYMBOL. -WRITE / sym_caution AS SYMBOL. - -"AS LINE: Outputting corners, crosses, lines, and T sections -"Check the type pool LINE for names of predefined icons. -WRITE: /10 line_horizontal_line AS LINE NO-GAP, - line_space AS LINE NO-GAP, - line_vertical_line AS LINE NO-GAP. -``` - -

⬆️ back to top

- -Formatting options with `WRITE` and `FORMAT`: - -```abap -"The following examples show a selection. Various other additions are -"available that deal with currency, unit, date and time-related formatting, -"among others. See the ABAP Keyword Documentation. -WRITE /(10) 'X' RIGHT-JUSTIFIED. "' X' -WRITE /(10) 'X' CENTERED. "' X ' -WRITE /(10) 'X' LEFT-JUSTIFIED. "'X ' -DATA dc TYPE decfloat34 VALUE '1.2345'. -WRITE /(*) dc DECIMALS 2. "1,23 - -"COLOR addition -"The commented out value stands for the value that can also -"be directly specified in the syntax (except 0) or contained in -"a data object. There are several additions with many options. -WRITE / 'COL_BACKGROUND (0)' COLOR COL_BACKGROUND. "0 (GUI dependent) -WRITE / 'COL_HEADING (1)' COLOR COL_HEADING. "1 (gray-blue) -WRITE / 'COL_HEADING (1)' COLOR 1. -WRITE / 'COL_NORMAL (2)' COLOR COL_NORMAL. "2 (light gray) -WRITE / 'COL_TOTAL (3)' COLOR COL_TOTAL. "3 (yellow) -WRITE / 'COL_KEY (4)' COLOR COL_KEY. "4 (blue-green) -WRITE / 'COL_POSITIVE (5)' COLOR COL_POSITIVE. "5 (green) -WRITE / 'COL_NEGATIVE (6)' COLOR COL_NEGATIVE. "6 (red) -WRITE / 'COL_GROUP (7)' COLOR COL_GROUP. "7 (orange) -WRITE / 'COLOR 7 OFF' COLOR 7 OFF. "default color - -"Setting the intensity of the background color. -"Note that many of the following additions can specify further -"additions such as ON and OFF. See the details in the documentation. -WRITE / 'COLOR 7 INTENSIFIED OFF' COLOR 7 INTENSIFIED OFF. -"INVERSE: When ON, the foreground, i.e. the output is displayed -"in the selected color -WRITE / 'COLOR 7 INVERSE ON' COLOR 7 INVERSE ON. - -"FORMAT: You can use FORMAT statements for applying settings on the following -"output statements up to a definition with new settings or ... OFF. -"Note: Many of the additions that are also possible for WRITE (e.g. COLOR, -"INTENSIFIED, INVERSE ...) are possible. The following example uses the already -"mentioned COLOR addition. -FORMAT COLOR COL_POSITIVE. -WRITE / 'ABC'. -WRITE / 'DEF'. -WRITE / 'GHI'. -FORMAT COLOR OFF. - -"HOTSPOT addition: Displays the mouse pointer when hovering over an element. -"Here, a single click has then the same effect as a double click (i.e. the -"selection of function key F2). -FORMAT HOTSPOT ON. -DO 5 TIMES. - WRITE / sy-index. -ENDDO. -FORMAT HOTSPOT OFF. - -"FRAMES addition: Defines whether the - and | characters are converted to line elements, -"producing continuous lines. -FORMAT FRAMES ON. -WRITE: / '----', - / '| |', - / '----'. -FORMAT FRAMES OFF. - -"RESET addition: Resetting the formatting settings -"This addition sets all formatting settings for which the corresponding addition is -"not specified in the same FORMAT statement to the state OFF (exception: FRAMES). -"In the following example, all settings are reset without specifying concrete -"additions (e.g. INVERSE OFF). Note the effects of such a statement (e.g. INTENSIFIED -"is ON by default at program start; now it is set to OFF). See the ABAP Keyword -"Documentation for more information. -FORMAT COLOR 7 INVERSE ON. -WRITE / 'ABC'. -FORMAT RESET. -WRITE / 'DEF'. -``` - -

⬆️ back to top

- -More list-related ABAP keywords: - -```abap -"Creating a horizontal line -ULINE. -"More additions are available e.g. for position and length -ULINE AT 5(20). - -"SET BLANK LINES: Specifying if blank lines created using WRITE are displayed -"In the example, the content of a string table that contains blank lines -"is output. -DATA(itab) = VALUE string_table( ( `a` ) ( `b` ) ( `` ) ( `` ) ( `c` ) ). - -"... OFF is set by default. Here it is explicitly specified. -"In this case, the blank lines are not output. -SET BLANK LINES OFF. -LOOP AT itab INTO DATA(wa). - WRITE / wa. -ENDLOOP. - -"... ON: The blank lines are output. -SET BLANK LINES ON. -LOOP AT itab INTO wa. - WRITE / wa. -ENDLOOP. - -"Setting the list cursor explicitly (more statements are -"available such as POSITION or BACK) -"SKIP: Positions the list cursor in another line (creating blank lines) -SKIP. "Skips 1 line -SKIP 3. "Specifying the number of lines to be skipped - -"SKIP TO LINE -"In the example, the list cursor is explicitly set to -"a particular number. Here, B and C are not output (i.e. -"overwritten with the output that follows). -WRITE / 'Text A'. -WRITE / 'Text B'. -DATA(line) = sy-linno. "The line number of the previous WRITE is retrieved. -WRITE / 'Text C'. -SKIP TO LINE line. -WRITE / 'Text D'. -WRITE / 'Text E'. - -"NEW-LINE: Setting list cursor to the first position of the next line -"Additions are available to affect the scrolling behavior -WRITE / 'Next statement is NEW-LINE'. -NEW-LINE. -WRITE 'WRITE statement without /'. "Output is in new line - -"HIDE: Storing the content of a flat variable together with the current list line. -"Example: a (3) is the result of b (1) + c (2). Suppose you click the line -"where a is output. You may e.g. output then b and c (e.g. another WRITE in the -"AT LIST-SELECTION event block), then getting the correct context of the list line. -... -a = b + c. -WRITE / a. -HIDE: b, c. -... - -"RESERVE: Creating a page break if there is not enough space left on the current list -"page between the last output and the page end or page footer, as specified with the number. -RESERVE 3 LINES. -"Consider the 3 lines defined as block. When you use BACK after RESERVE, e.g. after a loop, you -"can put the suqsequent output to the first line of this block of lines. See the effect in the -"executable example. -... -BACK. -WRITE ... -``` - -

⬆️ back to top

- -### Reading and Modifying in Lists - -`READ LINE` statements: -- Assign the content of a line stored in the list buffer to the system field `sy-lisel`. -- Plus, it allows other target fields to be specified. -- `sy-subrc` is set: 0 (line was read), other than 0 (line does not exist) - -```abap -"More additions than those covered are available (e.g. for -"list level and list page) -"sy-lisel contains the entire line content of the specified line -READ LINE 1. -"sy-lisel contains the entire line content of the current line -READ CURRENT LINE. -"Assigning the output of individual data objects -"Here, it is the entire line content. -DATA wa TYPE c LENGTH 50. -READ CURRENT LINE LINE VALUE INTO wa. -"Here, specific field values (val1/val2) are assigned to individual data objects -DATA dobj1 TYPE c LENGTH 10. -DATA dobj2 TYPE c LENGTH 10. -READ CURRENT LINE FIELD VALUE val1 INTO dobj1 val2 INTO dobj2. -``` - -`MODIFY LINE` statements: -- Overwrites a line stored in the list buffer with the content of the `sy-lisel` system field -- Plus, it allows additional modifications - -```abap -"Overwrites line stored in sy-lisel (which is filled e.g. using a previous -"READ LINE statement) -MODIFY CURRENT LINE. -MODIFY LINE 2. -"Specifying content to overwrite an existing line; the following examples -"only use the addition CURRENT LINE -"Overwrites the entire list line with the content -MODIFY CURRENT LINE LINE VALUE FROM 'hi'. -"Overwrite a specific field with specified content -MODIFY CURRENT LINE FIELD VALUE a FROM b. -"Mutliple fields specified -MODIFY CURRENT LINE FIELD VALUE a FROM b c FROM d. -"Change the format (here using COLOR) -"... of a specific field -MODIFY CURRENT LINE FIELD FORMAT a COLOR 3. -"... of the line -MODIFY CURRENT LINE LINE FORMAT COLOR 4. -"Note: Multiple additions and combinations are possible, using COLOR here -MODIFY CURRENT LINE FIELD FORMAT a COLOR 5 b COLOR 6 LINE FORMAT COLOR 7. -``` - -> **💡 Note**
-> - [Relevant sy components in the context of lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_systemfields.htm) -> - You can interact with a list by double-clicking a line (or pressing F2; the default `PICK` function code raises the `AT LINE-SELECTION` event). Other function codes usually trigger the `AT USER-COMMAND` event. See the event blocks below. In your ABAP program, you can react to the user action by implementing the individual event blocks. Regarding the function code, you can use the `sy-ucomm` system field for evaluation (unlike dynpros, there's no `OK_CODE` field to be filled). - -

⬆️ back to top

- -## Event Blocks -- Notes - - Introduced by an [event keyword](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_keyword_glosry.htm). - - Ended by the next processing block (there's no closing statement). - - Should not contain separate declarations, i.e. you should put all data object declarations in the global declaration part (except for `AT SELECTION-SCREEN ...`) - - It is recommended that you use ABAP Objects and methods consistently for data encapsulation - - Should not be specified more than once in a program - - Called depending on the user action and the program state (even if not explicitly specified) -- `LOAD-OF-PROGRAM` - - Program constructor - - Called when a program is loaded into the internal session - - Can be used to initialize the global data of a program. However, for executable programs, it is recommended that you use the event block `INITIALIZATION` for this task since the start values for parameters and selection criteria are set after `LOAD-OF-PROGRAM`. -- Reporting events related to executable programs in particular (and occur in predefined order). - - `INITIALIZATION` - - Used to initialize executable programs and provide start values (that cannot be statically expressed using `DEFAULT`) - - Called directly after `LOAD-OF-PROGRAM` and before selection screen processing - - `START-OF-SELECTION` - - Called after selection screen processing (see the following event blocks) - - If an executable program does not contain selection screens, this block is called automatically and implicitly. - - All statements are implicitly assigned to this block unless they are explicitly assigned to another block. - - Although it is optional, it is recommended that you specify the statement explicitly to improve readability. -- Selection screen events - - Used to individually evaluate selection screen elements, e.g. a specific parameter. - - In many cases, the events can be used for input validation (this should not wait until `START-OF-SELECTION`). If your custom input validation fails on an input, you can raise a message (e.g. a message of type `E`: `MESSAGE 'Error' TYPE 'E'.`) and allow users to edit the input again. - - `AT SELECTION-SCREEN OUTPUT`
Called by the dynpro event PBO of a selection screen after `INITIALIZATION`; can be used for modifying screen elements (e.g. using `MODIFY SCREEN`) - - `AT SELECTION-SCREEN ON par`
Called when values for a parameter or selection criteria were passed to the program; note: the syntax is also available for selection criteria; an additional variant `... ON END OF ...` is available (this event block is called when the selection table is passed completely allowing to check the entire selection table content) - - `AT SELECTION-SCREEN ON BLOCK bl`
Called when all input for a block is passed to the program - - `AT SELECTION-SCREEN ON RADIOBUTTON GROUP gr`
Called when the values for a radio button group were passed - - `AT SELECTION-SCREEN ON EXIT-COMMAND`
Called by *Back*, *Exit*, or *Cancel* (e.g. used for cleanup tasks) - - `AT SELECTION-SCREEN ON HELP-REQUEST | VALUE-REQUEST`
Relates to field (F1) and input (F4) help - - `AT SELECTION-SCREEN.`
Called as last event in the selection screen processing when all input values are passed to the program -- List events - - Are triggered during the list creation and after certain user actions on a displayed list. - - During list creation: - - `TOP-OF-PAGE`
For definining page headers; called when a [basic list](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbasic_list_glosry.htm) is created and when a new page begins (`... DURING LINE-SELECTION` is called when [details lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendetails_list_glosry.htm) are created) - - `END-OF-PAGE`
For definining page footers; called when the end of a page is reached, for example, when the specified number of lines in the `LINE-COUNT` addition (e.g. `PROGRAM LINE-COUNT 20(3).`) has been reached - - After user actions: - - `AT LINE-SELECTION`
Called when a screen list is displayed, the screen cursor is on a list line and a function is selected using the function code `PICK`; when specified, the function key F2 is enabled and, therefore, double click functionality; F2 and a double click are linked with the function code `PICK`. - - [`AT USER-COMMAND`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapat_user-command.htm)
Called when a function with a user-defined function code is selected when a screen list is displayed; the function codes can be evaluated using `sy-ucomm`; you can set a list event programmatically using [`SET USER-COMMAND`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_user-command.htm) - - -

⬆️ back to top

- -## Excursion: SAP List Viewer (ALV) - -- Provides an object-oriented API for displaying and formatting lists -- Allows you to specify layout settings and functionality -- Classes such as `CL_SALV_TABLE` encapsulate the use of the ALV grid control and simplify the integration into ABAP programs. Note: The older class `CL_GUI_ALV_GRID` should no longer be used directly for new developments. -- Other classes are available to handle hierarchical lists and tree structures. The focus of the code snippets is on simple, non-nested tables and the use of the `CL_SALV_TABLE` class. - -### Getting Started -- To get started quickly, you only need to ... - - instantiate an ALV table object using the `factory` method. - - define the display type for the ALV output. By default, full-screen display is enabled. - - display the ALV output using the `display` method. - -> **💡 Note**
-> - When working with ALV, make sure that you implement appropriate error handling. -> - The `factory` method also has optional exporting parameters. You can use the optional `list_display` parameter to specify whether you want to display the ALV output as classic list. It is set to false by default. There are also exporting parameters to display the ALV output in containers (e.g. see the dynpro cheat sheet example). The exporting parameters are not relevant in this example. Here, the ALV output is displayed on the entire screen (however, it is also possible to display the ALV output in a dialog box). - -The following code snippet shows a simple example to get you started quickly with the necessary method calls. It includes a demo internal table with content. - -```abap -TYPES: BEGIN OF demo_struct, - col1 TYPE string, - col2 TYPE i, - col3 TYPE c LENGTH 1, - END OF demo_struct. - -DATA itab TYPE TABLE OF demo_struct WITH EMPTY KEY. -itab = VALUE #( ( col1 = `abc` col2 = 1 col3 = 'X' ) - ( col1 = `def` col2 = 2 col3 = 'Y' ) - ( col1 = `ghi` col2 = 3 col3 = 'Z' ) ). - -TRY. - cl_salv_table=>factory( IMPORTING r_salv_table = DATA(alv) - CHANGING t_table = itab ). - - alv->display( ). - CATCH cx_salv_msg INTO DATA(err). - MESSAGE err->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. -ENDTRY. -``` - -### Optional Layout Settings and Functionality - -- The following commented code snippet covers a selection of the many setting and functionality options. -- For simplicity of the snippet, the code only uses the root exception class. Make sure that you implement appropriate error handling and exception classes. -- You can copy and paste the code into your own test program to explore the ALV output and the effect of the method calls. - -> **💡 Note**
-> Check the comments for the custom functions. If there are errors in your test program, replace the relevant code section and enable the generic ALV functions. - -```abap -TYPES: BEGIN OF demo_struct, - col1 TYPE string, - col2 TYPE i, - col3 TYPE string, - col4 TYPE icon_d, - col5 TYPE string, - END OF demo_struct. -DATA itab TYPE TABLE OF demo_struct WITH EMPTY KEY. -DATA alv TYPE REF TO cl_salv_table. -DATA cnt4evt TYPE i VALUE 6. - -"Local class to handle events -CLASS lcl_events DEFINITION. - PUBLIC SECTION. - CLASS-METHODS single_click - FOR EVENT link_click OF cl_salv_events_table - IMPORTING row column. - CLASS-METHODS double_click - FOR EVENT double_click OF cl_salv_events_table - IMPORTING row column. - CLASS-METHODS func_click - FOR EVENT added_function OF cl_salv_events - IMPORTING e_salv_function. -ENDCLASS. -CLASS lcl_events IMPLEMENTATION. - METHOD single_click. - "Both single and double click events trigger messages. - READ TABLE itab INDEX row REFERENCE INTO DATA(sc_ref). - IF sy-subrc = 0. - ASSIGN sc_ref->(column) TO FIELD-SYMBOL(). - MESSAGE `Single click event. ` && - |Row: { row } { COND #( WHEN column IS NOT INITIAL THEN `Column: ` && column ) } | && - |{ COND #( WHEN IS ASSIGNED THEN `Value: ` && ) }| TYPE 'I'. - ELSE. - MESSAGE `Single click event` TYPE 'I'. - ENDIF. - ENDMETHOD. - METHOD double_click. - READ TABLE itab INDEX row REFERENCE INTO DATA(dc_ref). - IF sy-subrc = 0. - ASSIGN dc_ref->(column) TO FIELD-SYMBOL(). - MESSAGE `Double click event. ` && - |Row: { row } { COND #( WHEN column IS NOT INITIAL THEN `Column: ` && column ) } | && - |{ COND #( WHEN IS ASSIGNED THEN `Value: ` && ) }| TYPE 'I'. - ELSE. - MESSAGE `Double click event` TYPE 'I'. - ENDIF. - ENDMETHOD. - METHOD func_click. - "Handling custom functions - CASE e_salv_function. - WHEN 'DATA'. - MESSAGE `Custom function DATA. Do something ...` TYPE 'I'. - WHEN 'TEST'. - IF cnt4evt = 6. - MESSAGE `A table row will be added, demonstrating the 'refresh' ` && - `method that rebuilds the output table.` TYPE 'I'. - ENDIF. - cnt4evt += 1. - itab = VALUE #( BASE itab ( col1 = `fffff` col2 = cnt4evt - col3 = `ttttt` col4 = icon_green_light ) ). - "Rebuilding the output table - alv->refresh( ). - WHEN 'QUIT'. - MESSAGE `Custom function QUIT. Do something ...` TYPE 'I'. - WHEN OTHERS. - MESSAGE `Some other function` TYPE 'I'. - ENDCASE. - ENDMETHOD. -ENDCLASS. -START-OF-SELECTION. -"Populating internal table that is output -itab = VALUE #( ( col1 = `aaaaa` col2 = 1 col3 = `zzzzz` col4 = icon_green_light ) - ( col1 = `bbbbb` col2 = 2 col3 = 'yyyyy' col4 = icon_green_light ) - ( col1 = `ccccc` col2 = 3 col3 = 'xxxxx' col4 = icon_green_light ) ). -TRY. - "----------- Instantiating an ALV table object ----------- - cl_salv_table=>factory( IMPORTING r_salv_table = alv - CHANGING t_table = itab ). - "----------- Creating a new instance with new data ----------- - "Notes on the set_data method: - "- All objects that were referred to previously are removed. - "- Not to be used in event handlers. - "In the example, new lines are added to the existing internal table. - itab = VALUE #( BASE itab ( col1 = `ddddd` col2 = 4 - col3 = `wwwww` col4 = icon_green_light ) - ( col1 = `ddddd` col2 = 5 - col3 = `vvvvv` col4 = icon_green_light ) - ( col1 = `eeeee` col2 = 6 - col3 = `uuuuu` col4 = icon_green_light ) ). - alv->set_data( CHANGING t_table = itab ). - "----------- Layout-related settings ----------- - "Changing the list header title - CAST cl_salv_display_settings( - alv->get_display_settings( ) )->set_list_header( 'Demo Title' ). - "There are several methods to retrieve column-specific information. - "The following examples show a selection. You can check the variable - "content in the debugger. - DATA(col1obj) = alv->get_columns( )->get_column( 'COL1' ). - DATA(col1alignment) = col1obj->get_alignment( ). - DATA(col1type) = col1obj->get_ddic_inttype( ). - DATA(col1colname) = col1obj->get_columnname( ). - DATA(is_col1_visible) = col1obj->is_visible( ). - "Settings for the column header - "This example uses the get method, which returns all column objects of - "the output table. The table is processed in a loop. - "Settings covered: - "- Specifying the column header titles (long, medium, and short - " column header) - "- Specifying a tooltip for the column header - LOOP AT alv->get_columns( )->get( ) REFERENCE INTO DATA(colref). - "Specifying the column header titles - "The example sets the texts based on the columname value. - "Note: The column width is optimized further down. You may want to - "manually adjust the width in the ALV output to see the column header - "name change. - colref->r_column->set_long_text( |{ colref->columnname }| ). - colref->r_column->set_medium_text( |{ colref->columnname+2(3) }| ). - colref->r_column->set_short_text( |{ colref->columnname+3(3) }| ). - "Specifying a tooltip for the column headers - colref->r_column->set_tooltip( - |Demo tooltip { colref->columnname+3(3) }| ). - ENDLOOP. - "Displaying/Hiding the column headers - "In the example, the value is set to abap_true. Set it to abap_false - "to hide the column header. - "Note: In this and the following examples, the settings are - "intentionally done using separate casts for each example. You can also - "create object reference variables, such as for 'col1obj' to avoid having - "to specify the casts explicitly each time. - CAST cl_salv_columns_list( - alv->get_columns( ) )->set_headers_visible( abap_true ). - "Setting key columns - "Note: The key columns have a default color setting. There, you can only - "change the color in individual cells. - CAST cl_salv_column_table( - alv->get_columns( )->get_column( 'COL1' ) )->set_key( abap_true ). - - "Setting column color - "Note: The executable example includes examples of coloring entire rows and - "specific cells. - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL2' ) - )->set_color( VALUE lvc_s_colo( col = col_positive ) ). - - "Hiding columns - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL5' ) - )->set_visible( abap_false ). - - "Setting text alignment - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL2' ) - )->set_alignment( if_salv_c_alignment=>left ). - - "Optimizing column width, i.e. automatically adjusting the column width - "to display values completely (can also be done for individual columns) - alv->get_columns( )->set_optimize( abap_true ). - - "Setting output width explicitly (for an individual column) - "Note: Just to demonstrate the method call. This setting has no effect in - "the example due to the column width optimization above, and the column is - "hidden anyway. - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL5' ) - )->set_output_length( '100' ). - - "Setting table rows to a striped pattern - alv->get_display_settings( )->set_striped_pattern( abap_true ). - - "Displaying/hiding horizontal and vertical grid lines (here, they're hidden) - alv->get_display_settings( )->set_horizontal_lines( abap_false ). - alv->get_display_settings( )->set_vertical_lines( abap_false ). - - "With the following method call, the ALV output is displayed in a dialog box. - "Demo coordinates are provided. You can comment it in to see the effect. -* alv->set_screen_popup( start_column = 10 -* end_column = 100 -* start_line = 4 -* end_line = 15 ). - - "------ Adding functionality/user interaction options to the ALV output ------ - "Specifying the selection type - "The following specification allows you to select multiple rows/columns (a column - "is added on the left for selections). Check the other options in the - "if_salv_c_selection_mode interface. - alv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ). - - "Setting the sorting - "In the example, a particular column is sorted in descending order. - alv->get_sorts( )->add_sort( 'COL1' )->set_sequence( if_salv_c_sort=>sort_down ). - - "Applying a filter - "The example is implemented to exculed one entry from the demo table. - alv->get_filters( )->add_filter( 'COL2' )->add_selopt( sign = 'E' - option = 'EQ' - low = '6' ). - - "Making a calculation/aggregation - "In this example, an aggregation is added for a specific column. - "In this case, the average value is calculated. It is displayed in a row added - "at the bottom of the table. - alv->get_aggregations( )->add_aggregation( - columnname = 'COL2' - aggregation = if_salv_c_aggregation=>average ). - - "Generic and custom ALV functions - "Note: - "- By default, ALV functions (such as sorting or filtering) are not available - " to users. You must explicitly enable them. - "- Depending on whether the display is full-screen (as it is here) or in a - " container, restrictions apply. In the first case, you can use your own GUI status - " to integrate custom functions. - - "This (self-contained, ready-to-use) code snippet is intended so that you can simply - "copy & paste the code into a test program. For this purpose, and to be able to - "demonstrate custom functions in this full-screen ALV example using a GUI status, the - "example uses a demo GUI status that is included in another sample program (in a - "subpackage of SALV). For your own GUI status, you can check the SALV_TABLE_STANDARD - "status contained in the SALV_METADATA_STATUS function group, which you can copy and - "use as a template, for example. - "*********************************** NOTE *********************************** - "- The GUI status used here is just reused to have a copyable and self-contained example. - "- The GUI status of the sample program (specified for the report parameter below) - " contains generic and additional functions. For the additional functions, a simple - " implementation is included in this snippet. The GUI status should include the - " functions TEST, DATA, QUIT. - "- The implementations in the event handler class here do not match the implementations - " there, the button texts do not make sense for the implementations here, and so on. - "- So even though it (the button names, icons, implementations, etc.) does not make much - " sense for this snippet, you should get an idea about custom functions and be able to - " explore the event handling by clicking on the buttons. - "- The TEST function demonstrates adding new rows to the table and the 'refresh' method. - "- If this particular program, the GUI status and/or the custom functions are not available - " in your system, or if you insert the code into your own test program, run it, and - " encounter problems setting the status, remove the TRY control structure that contains - " the set_screen_status method call, and comment in the code below to use the standard - " ALV functions. In this case, the custom functions cannot be checked out with this - " snippet. - "- Check out the executable example of the cheat sheet that includes a GUI status. - TRY. - alv->set_screen_status( - pfstatus = 'SALV_TABLE_STANDARD' - report = 'SALV_TEST_REFRESH' - set_functions = alv->c_functions_all ). - - "In this GUI status, the custom functions TEST, DATA, and QUIT are specified. You can - "check the results of the following method calls in the debugger. - DATA(getfunc) = alv->get_functions( ). - "Checking the activation status - DATA(is_enabled) = getfunc->is_enabled( 'TEST' ). - "Checking the visibility - DATA(is_visible) = getfunc->is_visible( 'TEST' ). - - "Registering an event handler for the custom functions - "The added_function event is raised. In the implementation of the event handler method, - "you can then implement your code based on the value of the e_salv_function parameter - "(which contains the specified function name), for example, using a CASE statement. - "The implementation in this code snippet is different from the original program. - SET HANDLER lcl_events=>func_click FOR alv->get_event( ). - - CATCH cx_salv_object_not_found. - MESSAGE `GUI status error. Instead, use the set_default method, for example.` - TYPE 'I'. - ENDTRY. - - "If you remove the TRY control structure above, you can comment in the following - "code to use the generic ALV functions. Use the set_all method for all generic - "functions. You can also enable generic ALV functions individually. Check the - "set_* methods. - "alv->get_functions( )->set_default( abap_true ). - - "Hotspot/single click functionality - "You can define the content of a cell as a clickable area. You can do this by - "specifying the cell type hotspot. When a user clicks the cell content, - "the link_click event is raised. - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL1' ) - )->set_cell_type( if_salv_c_cell_type=>hotspot ). - - "You can set icon columns and make the icon cells clickable areas. To do this, - "use the set_icon method. As above, the cell type of the column is set to hotspot. - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL4' ) - )->set_icon( if_salv_c_bool_sap=>true ). - CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL4' ) - )->set_cell_type( if_salv_c_cell_type=>hotspot ). - - "An event handler is registered for the clickable areas (the link_click event - "is raised). The get_event method returns the required event object. In the - "example, a message is displayed. - SET HANDLER lcl_events=>single_click FOR alv->get_event( ). - - "Double click functionality - "Registering an event handler for the double click event. In the example, a message - "is displayed. Double-click cells in columns for which the cell type is not set to hotspot. - SET HANDLER lcl_events=>double_click FOR alv->get_event( ). - - "Adding tooltips to the icon column cells - alv->get_functional_settings( )->get_tooltips( )->add_tooltip( - type = cl_salv_tooltip=>c_type_icon - value = CONV lvc_value( icon_green_light ) - tooltip = `This is a tooltip for an icon` ). - - "----------- Displaying the ALV output ----------- - alv->display( ). - CATCH cx_root INTO DATA(error). - "For simplicity, this example uses the root exception class. - "Always make sure that you use appropriate exception classes. Check the F2 - "information for the methods in ADT. - MESSAGE error->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. -ENDTRY. -``` - -

⬆️ back to top

- -## More Information -- ABAP Keyword Documentation: - - [Selection Screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen.htm) - - [Classic Lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpro_list.htm) -- ALV: - - [SAP List Viewer (ALV)](https://help.sap.com/docs/SAP_NETWEAVER_731_BW_ABAP/b1c834a22d05483b8a75710743b5ff26/4ec38f8788d22b90e10000000a42189d.html?locale=en-US) on the SAP Help Portal - - Find more demonstration examples in package `SALV` and its subpackages. - -## Executable Examples - -After the import of the repository, proceed as follows: -- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. -- Enter `ZDEMO_ABAP_SELSCR_LISTS_INTRO` and open the program. This program serves as an entry point for all selection screen and list examples. Program names of the individual examples: - - `ZDEMO_ABAP_SELSCR_PARAMETERS`: Demonstrates `PARAMETERS` statements - - `ZDEMO_ABAP_SELSCR_SELECT_OPT`: Demonstrates `SELECT-OPTIONS` statements - - `ZDEMO_ABAP_SELSCR_STANDALONE`: Demonstrates the creation (`SELECTION-SCREEN` statements) and calling of standalone selection screens - - `ZDEMO_ABAP_SELSCR_STMTS_VAR`: Demonstrates variants of the `SELECTION-SCREEN` statements that do not create selection screens - - `ZDEMO_ABAP_LISTS`: Demonstrates various ABAP statements to create and handle classic lists - - `ZDEMO_ABAP_EVENT_BLOCKS`: Demonstrates event blocks - - `ZDEMO_ABAP_ALV`: Demonstrates the SAP List Viewer (ALV) -- Run the program by choosing `F8`. - -> **💡 Note**
-> - The executable examples ... -> - do not claim to include meaningful selection screens and lists. -> - are not intended to be role models for proper selection screen and list design. -> - are not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. -> - are only intended to demonstrate a selection of keywords and visualize related syntax in action on a high level. -> - include comments in the program code. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). + + +# Selection Screens and Classic Lists + +- [Selection Screens and Classic Lists](#selection-screens-and-classic-lists) + - [Introduction](#introduction) + - [Terms](#terms) + - [Selection screens](#selection-screens) + - [Classic Lists](#classic-lists) + - [ABAP Statements for Selection Screens](#abap-statements-for-selection-screens) + - [Creating Selection Screens](#creating-selection-screens) + - [PARAMETERS](#parameters) + - [SELECT-OPTIONS](#select-options) + - [SELECTION-SCREEN](#selection-screen) + - [Variants of the SELECTION-SCREEN Statement](#variants-of-the-selection-screen-statement) + - [Calling Selection Screens](#calling-selection-screens) + - [Excursion: SUBMIT](#excursion-submit) + - [ABAP Statements for Classic Lists](#abap-statements-for-classic-lists) + - [Creating Lists](#creating-lists) + - [Reading and Modifying in Lists](#reading-and-modifying-in-lists) + - [Event Blocks](#event-blocks) + - [Excursion: SAP List Viewer (ALV)](#excursion-sap-list-viewer-alv) + - [Getting Started](#getting-started) + - [Optional Layout Settings and Functionality](#optional-layout-settings-and-functionality) + - [More Information](#more-information) + - [Executable Examples](#executable-examples) + + +## Introduction + +⚠️ The content of this cheat sheet and the executable examples are only relevant to [classic ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_abap_glosry.htm). + +[Selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_glosry.htm) and [classic lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenclassic_list_glosry.htm) are among the classic ABAP user interfaces. They are integrated into the ABAP language itself, which means that special ABAP statements are available to create and handle them. + +This cheat sheet provides a high-level overview of selection screens and classic lists, focusing on a selection of related statements, supported by executable examples to explore the syntax in action. It includes an excursion into the SAP List Viewer (ALV). + +For more detailed information and syntax options, see the topics [Selection Screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen.htm) and [Classic Lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpro_list.htm) in the ABAP Keyword Documentation. + +> **💡 Note**
+> - Although they are considered outdated for application programs, you will still find classic ABAP UIs frequently in classic ABAP. +> - Classic ABAP UIs cannot be created in [ABAP Cloud](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_cloud_glosry.htm). +> - This cheat sheet ... +> - is not intended to encourage you to start creating classic ABAP UIs for programming new applications. +> - does not cover all facets, techniques, and syntax options (there's a rich variety of keywords and additions) in great detail. +> - is intended to cover a selection of related syntax that you may encounter in older ABAP code. If you need more information, always consult the ABAP Keyword Documentation. +> - Links to the ABAP Keyword Documentation in this cheat sheet refer to the documentation for [Standard ABAP](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_abap_glosry.htm) (latest version). + +

⬆️ back to top

+ +## Terms + +### Selection screens +- Are special [dynpros](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendynpro_glosry.htm) in [executable programs](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenexecutable_program_glosry.htm) (*"reports"*; they're also possible in [function groups](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenfunction_group_glosry.htm) and [module pools](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenmodul_pool_glosry.htm), but the focus here is on executable programs). +- Used for data entry in an executable program, i.e. they allow users to ... + - enter parameters (for entering single values). + - provide selection criteria (complex selection options for value lists and value ranges) that can be used to supply an executable program with values to work with. +- Can be created using special ABAP statements in the global declaration part of executable programs +- Are processed by the ABAP runtime framework, which triggers [selection screen events](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_event_glosry.htm) ([see further down](#event-blocks)). +- When you create a selection screen and run an ABAP program, the dynpros are generated automatically. These generated dynpros cannot be edited directly. +- Further ways in which selections screens are different from *regular* dynpros: + - Unlike dynpros, you can create selection screens without using the [screen painter](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_painter_glosry.htm) tool. The [ABAP Editor](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_editor_glosry.htm) is the only tool you use to define a selection screen (using ABAP statements). + - They have a more limited set of features, for example, the layout of selection screens is more restricted. However, selection screens offer various types of input fields, which can also be expressed as checkboxes or radio buttons, and which can be grouped and labeled. + - Modification options are limited. For example, you can only use some predefined function codes. + - You cannot define [dialog modules](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendialog_module_glosry.htm) in the ABAP program. +- There are two types of selection screens: + - [Standalone selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstand-alone_sel_screen_glosry.htm) + - Defined between the statements `SELECTION-SCREEN BEGIN OF SCREEN` and `SELECTION-SCREEN END OF SCREEN` + - Can be defined in all programs that can contain dynpros + - [Standard selection screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenstandard_selscreen_glosry.htm) + - Each executable program (and only there) contains a standard selection screen with the dynpro number 1000. Note: If you create a standalone selection screen, you cannot use dynpro number 1000. + - The screen elements on the standard selection screen are defined by all `PARAMETERS`, `SELECT-OPTIONS`, and `SELECTION-SCREEN` statements that are defined outside of the statements mentioned above for creating standalone selection screens. + + +### Classic Lists +- Used to output data in a structured and formatted way. +- This output can be ... + - created in the so-called [list buffer](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_buffer_glosry.htm), a memory area for storing [screen lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenscreen_list_glosry.htm), i.e. a list that is displayed on a predefined list dynpro (list dynpro that is accessed implicitly when a program is executed; note: this dynpro is not part of the executed program). + - sent to the [SAP spool system](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abensap_spool_system_glosry.htm) as a spool list (i.e. a list that is not stored as a screen list but is intended for printing or archiving; the focus of this cheat sheet is on screen lists). +- Typical flow of executable programs that include selection screens and content to be displayed on the list dynpro: + - Programs are executed using the *Execute* button (F8). + - Selection screens are displayed, users usually make entries for whatever purpose, which are further processed in the program. + - Output result is written to the list buffer and finally displayed (on a list dynpro; note: the list processing is automatically started when running executable programs). + - The list can be further implemented to respond to user interaction, such as clicking a line in the list. +- More modern alternatives for classic lists are available, such as the classes of the SAP List Viewer (ALV), for example `CL_SALV_TABLE`. + +> **💡 Note**
+> The program is grouped into so-called [event blocks](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_block_glosry.htm), which can contain implementations for various events (e.g. a [selection screen event](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_event_glosry.htm) when a user selects a radio button, or a [list event](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_event_glosry.htm) when a user double-clicks a line in the list). These event blocks are introduced by special ABAP statements. When a particular event is triggered, the corresponding event block is called and the appropriate code can be implemented there to react to the user action. See more information [here](#event-blocks). + +

⬆️ back to top

+ +## ABAP Statements for Selection Screens + +### Creating Selection Screens + +Selection screens can be created by using special ABAP statements in the global declaration part of executable programs: +- [`PARAMETERS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapparameters.htm) +- [`SELECT-OPTIONS`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselect-options.htm) +- [`SELECTION-SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapselection-screen.htm) + +### PARAMETERS +- Creates ... + - a program-global variable (similar to `DATA` statements) + - an input field on the selection screen automatically, i.e. the content of the program-global variable can be changed via the input field. +- The parameter name can be up to eight characters long. +- Multiple additions are available to define the appearance (e.g. `AS CHECKBOX`) or influence the user interface (e.g. `OBLIGATORY`). + +> **💡 Note**
+> The parameter name is a technical name. You probably do not want to display technical names on the user interface. You can define proper names ([text elements](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abentext_element_glosry.htm)) in the ABAP Editor, e.g. for translation purposes. + +The following code snippets provide a commented selection of available syntax options. +Note that various combinations of multiple additions are possible, and some are not. See the ABAP Keyword Documentation for details. + +```abap +"-------------------------- Type options -------------------------- + +"Referring to a built-in type with TYPE +"In this case, a variable length character string can be inserted in the +"generated input field. Note the LOWER CASE addition further down. +PARAMETERS pa TYPE string. + +"Referring to an existing data object with the LIKE addition +DATA dobj TYPE i. +PARAMETERS pb LIke dobj. + +"Reference to a data type from the ABAP Dictionary +"All screen-relvant properties of that type are adopted, +"which is the case in the following example (spfli is an SAP-delivered +"demo table). A callable field help and input help is created. +"Note that there is no automatic value check. For that, use the +"addition VALUE CHECK. +PARAMETERS pc LIKE spfli-carrid. + +"Dynamic spefication is possible, e.g. using a dynamic +"reference to a data type from the ABAP Dictionary after LIKE. +"some_dobj in the example may be the name of a component of a database table, +"provided in capital letters. +DATA some_dobj TYPE c LENGTH 50. +PARAMETERS pd LIKE (some_dobj). + +"Length specifications +"Similar to declarations with DATA, the length can be specified for data +"types with generic length (i.e. the types c, n, p, and x). +PARAMETERS pe TYPE c LENGTH 1. +PARAMETERS pf TYPE n LENGTH 5. + +"Specifications in which the length is specified in parentheses. +"For better readability, specifying LENGTH explicitly is recommended. +PARAMETERS pg(2) TYPE c. +"No length specified means LENGTH 1 by default +PARAMETERS ph TYPE c. +"No explicit type specification means TYPE c by default +PARAMETERS pi(40). +PARAMETERS pj length 40. +"No explicit type and length specification means TYPE c LENGTH 1 by default +PARAMETERS pk. + +"-------------------------- Value options -------------------------- + +"DEFAULT: Defining a start value (can also be a data object instead of a literal) +PARAMETERS pl TYPE i DEFAULT 12345. + +"LOWER CASE: Prevents the effect of capitalizing the entry made when the content +"is transported to the data object +PARAMETERS pm TYPE string DEFAULT `Hello World`. "Value you insert will be capitalized. +PARAMETERS pn TYPE string DEFAULT `Hello World` LOWER CASE. + +"Note: There are more additions available, e.g. for linking the parameter to search help, +"or checking against fixed values defined in the domain of the data type, and so on. +"You can also perform your custom input checks. See the event block section below. + +"-------------------------- Screen options -------------------------- + +"OBLIGATORY: Declaring the input field as a required field +"If there is no entry, the program cannot proceed when choosing Execute. +"A message is displayed. +PARAMETERS po TYPE string OBLIGATORY. + +"NO-DISPLAY: Hiding the input field on the selection screen +"A value can be supplied when calling the program with SUBMIT and the WITH addition. +"Note that with the NO-DISPLAY addition, the parameter can have any data types except +"for reference/enumerated types, unlike in the other additions which require flat +"types (except type string). +PARAMETERS pp TYPE string NO-DISPLAY. + +"VISIBLE LENGTH: Defining the visible length of the field +PARAMETERS pq TYPE c LENGTH 5 VISIBLE LENGTH 3. + +"AS CHECKBOX: Displaying input field as checkbox +"Type c and length 1 is expected, but the explicit length specification is not allowed. +"The checkbox is selected if the value has the value X or x. +PARAMETERS pr AS CHECKBOX. "Implicit type c +PARAMETERS ps TYPE c AS CHECKBOX. "Explicit type specification (but no explicit length) + +"RADIOBUTTON GROUP: Defining a radio button group for parameters +"Note: +"- Group name can have a maximum of four characters +"- Regarding the data type, the same applies as for AS CHECKBOX +"- Only one parameter can be defined with the DEFAULT addition +"- If DEFAULT is not specified, the first parameter of the group is set to the value X +"- Here, a chained statement is used. +PARAMETERS: prb1 RADIOBUTTON GROUP rbgr, + prb2 type c RADIOBUTTON GROUP rbgr, "Explicit type specification + prb3 RADIOBUTTON GROUP rbgr DEFAULT 'X'. "Select this radiobutton by default + +"AS LISTBOX VISIBLE LENGTH: Creating a dropdown list box +"You can use the function module VRM_SET_VALUES by passing a suitable list at the +"events AT SELECTION-SCREEN OUTPUT or AT SELECTION-SCREEN ON VALUE-REQUEST. +"See the executable example. +PARAMETERS pt TYPE i AS LISTBOX VISIBLE LENGTH 10. + +"-------------------------- Assigning function codes -------------------------- + +"The AS CHECKBOX, RADIOBUTTON GROUP, AS LISTBOX additions can be combined +"with the addition USER-COMMAND. That means, on selection, the event +"AT SELECTION-SCREEN is raised and you can evaluate the function code there. +"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. +"When the button is clicked, the event AT SELECTION-SCREEN is raised and the +"function code ('cmd', 'rbcm' in the example) is passed to the 'ucomm' component +"in the interface work area 'sscrfields' which can be evaluated and reacted upon +"accordingly. See the executable example. +PARAMETERS pu AS CHECKBOX USER-COMMAND cmd. +"For radio buttons, the addition can be specified for the first selection +"parameter in a radio button group. +PARAMETERS: pv RADIOBUTTON GROUP grp USER-COMMAND rbcm, + pw RADIOBUTTON GROUP grp. + +"Note: The MODIF ID addition is possible for PARAMETERS and +"SELECT-OPTIONS. This is also true for SELECTION-SCREEN statements. See +"the details there. +``` + +

⬆️ back to top

+ +### SELECT-OPTIONS + +- Declares selection criteria for a data object +- Unlike the `PARAMETERS` statement, which specifies a single value for a variable, the `SELECT-OPTIONS` statement allows you to specify complex criteria, such as an value range or a list of single values, to include or exclude values, that can be evaluated. +- The selection criteria are assigned to a selection table (see [ranges table](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenranges_table_glosry.htm) and the type `TYPE RANGE OF`). + - Such a table type contains four columns - low, high, option, sign - for determining range conditions. Each line of such a table represents a condition. + - Typically, the content of the selection table can be evaluated in `SELECT` statements using the `IN` operator in the `WHERE` clause. + - If the selection table is empty, all lines are respected. + +Example: + +```abap +DATA wa TYPE some_tab. + +SELECT-OPTIONS sel FOR some_tab-some_comp. + +SELECT * + FROM some_tab + WHERE some_comp IN @sel + INTO @wa. + ... +ENDSELECT. + +"Multiple additions and combinations are possible. + +"The following statement creates two input fields that can be +"used to specify selection criteria on the selection screen. +"In addition, the Multiple Selection button is available to +"further specify the selection criteria, e.g. what to include, +"exclude, etc.. As in all examples, the variable is an internal +"table of type TYPE RANGE OF whose contents can be evaluated. +"The FOR addition is followed by an already declared data object. +SELECT-OPTIONS a FOR some_dobj. +"As mentioned above, NO-DISPLAY hides. +SELECT-OPTIONS b FOR some_dobj NO-DISPLAY. +"NO-EXTENSION: The Multiple Selection button is not created on the +"selection screen +SELECT-OPTIONS c FOR some_dobj NO-EXTENSION. +"NO INTERVALS: Only one input field. Intervals can still be selected +"using the Multiple Selection button. +SELECT-OPTIONS d FOR some_dobj NO INTERVALS. +"DEFAULT ... TO ...: Providing start values for the columns in the +"first line of the selection table (low and high values) +SELECT-OPTIONS e FOR some_dobj DEFAULT 3 TO 10. +"DEFAULT ... OPTION ... SIGN ...: Providing further start values. +"See details further down. +SELECT-OPTIONS f FOR some_dobj DEFAULT 4 TO 8 OPTION NB SIGN I. +``` + +> **💡 Note**
+> Notes on the `OPTION` and `SIGN` additions: +> - `OPTION` +> - Start value for the `option` column for the condition in the form of comparison operators +> - `TO` not specified: `EQ` (equal), `NE` (not equals), `GE` (greater than or equals), `GT` (greater than), `LE` (less than or equals), `LT` (less than), `CP` (conforms to pattern), or `NP` (does not conform to pattern) must be specified +> - `TO` specified: Either `BT` (between) or `NB` (not between) must be specified +> - `OPTION` not specified: `EQ`/`BT` is used +> - For `CP` and `NP`, wildcard characters `*` or `+` must be specified. +> - `SIGN` +> - Start value for the `sign` column +> - Either `I` or `E` must be specified to include/exclude the result of the condition +> - `SIGN` not specified: `I` by default +> - For historical reasons, the selection table is a table with [header line](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenheader_line_glosry.htm). Therefore, if you want to address the table content (beyond the use in a `SELECT ... WHERE ... IN ...` statement), use the syntax `a[]`. + + +

⬆️ back to top

+ + +### SELECTION-SCREEN + +- `SELECTION-SCREEN` statements can be used to create and modify the layout of standalone selection screens. +- Note: The standard selection screen for executable programs is created automatically. That is, each executable program contains a standard selection screen with dynpro number 1000. +- Selection screens can be created as regular dynpros or as subscreen dynpros. + +```abap +"-------------------------- Pattern -------------------------- + +SELECTION-SCREEN BEGIN OF SCREEN ... + + ... + "Here go all PARAMETERS, SELECT-OPTIONS, and SELECTION-SCREEN statements + "to define the screen elements of the standalone selection screen. + +SELECTION-SCREEN END OF SCREEN ... + + +"-------------------------- Regular dynpros -------------------------- + +"Creating a selection screen as regular dynpro +"Note that the dynpro number must be unique in the program. Do not use 1000. +SELECTION-SCREEN BEGIN OF SCREEN 9000. + ... +SELECTION-SCREEN END OF SCREEN 9000. + +"Note: The following additions can also be combined. +"TITLE: Defining a title (e.g. the name of a text symbol) for the title bar +SELECTION-SCREEN BEGIN OF SCREEN 9001 TITLE some_title. + ... +SELECTION-SCREEN END OF SCREEN 9001. + +"AS WINDOW: Displaying the selection screen in a modal dialog box +SELECTION-SCREEN BEGIN OF SCREEN 9002 AS WINDOW. + ... +SELECTION-SCREEN END OF SCREEN 9002. + +"-------------------------- Subscreen dynpros -------------------------- + +"Can be included in other dynpros or selection screens, or in subscreen areas +"or tab pages. But they cannot be called explicitly. +SELECTION-SCREEN BEGIN OF SCREEN 9003 AS SUBSCREEN. +... +SELECTION-SCREEN END OF SCREEN 9003. + +"Note: There are more additions available regarding display adjustment, among others. +``` + +

⬆️ back to top

+ +#### Variants of the SELECTION-SCREEN Statement + +- The variants do not create selection screens, but are used to change the layout of selection screens, create additional screen elements, and so on. +- Example: The `PARAMETERS` and `SELECT-OPTIONS` statements create input fields on an individual line. Using the variants of the `SELECTION-SCREEN` statement, you can arrange the layout differently. +- However, the selection screen cannot be generated if there are conflicts with existing screen elements. + - See the effect with the following snippet. Run a program with the code snippet and comment in the third line. The program terminates. The text to be created (in the same line as the first text) interferes with the first text. However, the fourth line would be possible because there is no overlap. + ```abap + PARAMETERS pa TYPE string. + SELECTION-SCREEN COMMENT /5(10) t1. + "SELECTION-SCREEN COMMENT 10(20) t2. + "SELECTION-SCREEN COMMENT 20(20) t3. + ``` + +Syntax examples: + +```abap +"Note: More optional additions are available for the the following statements. +"For the details, check the ABAP Keyword Documentation. + +"Adding blank lines +SELECTION-SCREEN SKIP. "1 blank line by default +SELECTION-SCREEN SKIP 5. "5 blank lines + +"Creating a horizontal line +"Line accross the whole screen below the lines that are already filled +SELECTION-SCREEN ULINE. +"/: Line in a new line, 5: position, (10): length +SELECTION-SCREEN ULINE /5(10). +"Note: The following statement commented out can only be specified +"inside a BEGIN/END OF LINE statement. Outside, specifying a position +"is required. +"SELECTION-SCREEN ULINE (10). + +"Providing text content on the selection screen (e.g. using a text symbol) +"Also here, note the use outside of BEGIN/END OF LINE regarding the additions. +"The optional FOR FIELD addition is, among others, used in the context of +"input/field help. +SELECTION-SCREEN COMMENT /1(20) txt. + +"Creating a pushbutton +"The pushbutton is assigned a function code. +"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. +"When the button is clicked, the event AT SELECTION-SCREEN is raised and the +"function code ('com' in the example) is passed to the 'ucomm' component in the +"interface work area 'sscrfields' which can be evaluated and reacted upon +"accordingly. See the executable example. +SELECTION-SCREEN PUSHBUTTON /5(10) pb USER-COMMAND com. + +"Defining a new line with multiple elements +SELECTION-SCREEN BEGIN OF LINE. + "The following statement with the POSITION addition is only possible here. + "It specifies the output position of a screen element. + SELECTION-SCREEN POSITION 10. + ... +SELECTION-SCREEN END OF LINE. + +"Chained statements come in handy +"Watch out that there are no positioning conflicts with other screen elements. +SELECTION-SCREEN: BEGIN OF LINE, + PUSHBUTTON 2(5) button USER-COMMAND fc, + POSITION 10. "The statement specifies the position in which the + "next element (PARAMETERS) is put. +PARAMETERS para TYPE c LENGTH 10. +SELECTION-SCREEN: COMMENT 25(10) txt, + END OF LINE. + +"Creating blocks +"More additions available, e.g. WITH FRAME (to draw a frame around a block) +"and TITLE (to define a block title). +SELECTION-SCREEN BEGIN OF BLOCK bl. + ... +SELECTION-SCREEN END OF BLOCK bl. + +"Creating tabbed blocks (other optional additions are available) +SELECTION-SCREEN BEGIN OF TABBED BLOCK tabbl FOR 5 LINES. "Specifies number of lines covered + ... + "In such a TABBED BLOCK statement, only TAB statements are allowed to integrate + "subscreen dynpros. + "USER-COMMAND addition specifies a function code. When a tab is selected by users, + "the function code can be evaluated using the the component ucomm of the structure + "'sscrfields' after the AT SELECTION-SCREEN event. See the executable example. + SELECTION-SCREEN TAB (10) tab USER-COMMAND cmd. +... +SELECTION-SCREEN END OF BLOCK tabbl. + +"MODIF ID addition for some of the previous statements (ULINE, COMMENT, +"PUSHBUTTON, TAB, and also for PARAMETERS and SELECT-OPTIONS) +"An identifier can be specified to assign a screen element to a modification group. +"This identifier is assigned to the component 'group1' of the SCREEN structure. +"Using MODIFY SCREEN statements, the elements can be modified before displaying +"in the AT SELECTION-SCREEN OUTPUT event block. +"In the following example, a radio button group consists of 4 radio buttons. +"Two of them have the addition MODIF ID. +SELECTION-SCREEN BEGIN OF BLOCK bl WITH FRAME. +PARAMETERS: pa1 RADIOBUTTON GROUP gr MODIF ID mbl, + pa2 RADIOBUTTON GROUP gr MODIF ID mbl, + pa3 RADIOBUTTON GROUP gr, + pa4 RADIOBUTTON GROUP gr. +SELECTION-SCREEN END OF BLOCK bl. + +"Suppose you want to modify the elements before displaying, e.g. make the +"two radio buttons with the identifier invisible. In the AT SELECTION-SCREEN +"OUTPUT event block, you might implement it as follows. +... +AT SELECTION-SCREEN OUTPUT. + LOOP AT SCREEN INTO DATA(wa). + IF wa-group1 = 'MBL'. + wa-invisible = '1'. + MODIFY SCREEN FROM wa. + ENDIF. + ENDLOOP. +... + +"Adding pushbuttons in the application toolbar +"There are five inactive pushbuttons to which the function codes FC01, FC02 up to FC05 +"are assigned. The ... FUNCTION KEY ... statement activates the pushbuttons for +"the specified codes. +"Note: To enable it, include the statement 'TABLES sscrfields.' in the code. +"When the button is clicked, the event AT SELECTION-SCREEN is raised and the +"function code is passed to the 'ucomm' component in the interface +"work area 'sscrfields' which can be evaluated and reacted upon accordingly, e.g. +"in a CASE control structure. +"In the following example, three pushbuttons are added to the toolbar. To +"provide text for the buttons, assign values to the component functxt_0n (while +"n stands for the numbers 1 - 5). Otherwise, there won't be any button text. +TABLES sscrfields. +PARAMETERS pa TYPE c LENGTH 10. +SELECTION-SCREEN: FUNCTION KEY 1, "Stands for FC01 + FUNCTION KEY 2, "FC02 + FUNCTION KEY 3. "FC03 + +INITIALIZATION. + sscrfields-functxt_01 = 'Button 1'. + sscrfields-functxt_02 = 'Button 2'. + sscrfields-functxt_03 = 'Button 3'. + +AT SELECTION-SCREEN. + CASE sscrfields-ucomm. + WHEN 'FC01'. + ... + WHEN 'FC02'. + ... + WHEN 'FC03'. + ... + ENDCASE. +... +``` + +`INCLUDE` addition for reusing already created elements of the same program: + +```abap +"Note: More optional additions are available. + +SELECTION-SCREEN BEGIN OF SCREEN ... +... +SELECTION-SCREEN INCLUDE PARAMETERS param. +SELECTION-SCREEN INCLUDE SELECT-OPTIONS sel. +SELECTION-SCREEN INCLUDE COMMENT (10) txt. +SELECTION-SCREEN INCLUDE PUSHBUTTON (10) rb. +SELECTION-SCREEN INCLUDE BLOCKS blck. +... +SELECTION-SCREEN END OF SCREEN ... +``` + +

⬆️ back to top

+ +### Calling Selection Screens + +- There are several ways of how to call selection screens (see [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen_call.htm)), among them [`CALL SELECTION-SCREEN`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapcall_selection_screen.htm) statements. +- These statements call selection screens by specifying the dynpro number. +- Any selection screen of the main program (and only from there; including 1000) can be called. + +```abap +CALL SELECTION-SCREEN 9876. + +"STARTING AT/ENDING AT additions for creating a modal dialog box +"The numbers determine how it should be displayed. +"STARTING AT: upper left corner (column and line); ENDING AT: bottom right +"corner (if not specified, it is set automatically) +CALL SELECTION-SCREEN 9345 STARTING AT 10 10. +CALL SELECTION-SCREEN 9345 STARTING AT a b ENDING AT c d. + +"You can also predefine selection criteria for a selection screen using +"the addition USING SELECTION-SET. +``` + +

⬆️ back to top

+ +### Excursion: SUBMIT +- [`SUBMIT`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapsubmit.htm) statements call executable programs and, therefore, selection screens. +- In general, every executable program is started implicitly with `SUBMIT`. +- Selection screens can be considered a parameter interface if the program containing them is executed using `SUBMIT`. + +```abap +"The calling program is ended +SUBMIT some_program. "Direct specification of the program name + +"Dynamic call +"Note the security risks and consequences a program submitted from outside can cause; +"you may use the class CL_ABAP_DYN_PRG to tackle security risks +SUBMIT ('SOME_PROGRAM'). "Character-like data object in a pair of parentheses + +"AND RETURN: The calling program is interrupted +SUBMIT some_program AND RETURN. + +"Selection screen-related options for the SUBMIT statement +"Specifies a particular selection screen to be called (but it's not displayed) +SUBMIT some_program USING SELECTION-SCREEN 9123. + +"Specifies that the selection screen to be called is displayed +SUBMIT some_program VIA SELECTION-SCREEN. +SUBMIT some_program USING SELECTION-SCREEN 9123 VIA SELECTION-SCREEN. + +"You can pass values to the selection screen. There are a several options. +"Check the ABAP Keyword Documentation. The following examples cover a selection. + +"In the followig example, it is assumed that the called program only has 1 +"parameter with name par, type i. The addition USING SELECTION-SCREEN is +"omitted, i.e. the standard selection screen is called (but you can also call +"the dynpro 1000 explicitly). +SUBMIT some_program WITH par = 1. "Specifying EQ is also possible + +"Displaying the selection screen, only interrupt the current program +SUBMIT some_program VIA SELECTION-SCREEN WITH par = 1 AND RETURN. + +"You can also pass multiple values, e.g. consider a program having multiple +"PARAMETERS statements (you may also have multiple WITH additions), or SELECT-OPTIONS +"statements. +SUBMIT some_program VIA SELECTION-SCREEN WITH SELECTION-TABLE tab. +``` + +

⬆️ back to top

+ +## ABAP Statements for Classic Lists + +### Creating Lists + +- Lists consist of consecutive list lines that are filled one after the other using the statement [`WRITE`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapwrite-.htm). +- This way, you can output mostly flat data objects and strings/xstrings, types converted to a character-like value (i.e. no internal table content or structures directly). +- Each time a data object is output, an output length is defined, either implicitly or explicitly (see [here](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenwrite_output_length.htm)). +- The following snippets show a selection of additions to `WRITE` statements, covering positioning, creating special list elements, and formatting options. + +```abap +"WRITE using an unnamed data object +WRITE 'Hello ABAP.'. +"Named data objects +DATA some_text TYPE string VALUE `Hi, `. +"Note: The text is written right after the previous text in one line. +WRITE some_text && sy-uname. +"/: Writes to a new line +WRITE / 'new line'. + +"-------------------------- Positioning output -------------------------- +"Specifying the output position (and output in new line) +WRITE /5 'positioned'. +"Specifying the length, no position specified means the output is +"written from the first column on +WRITE /(3) 'not displayed completely'. +"Specifying both length and position +WRITE /5(30) 'this is displayed completely'. +"Position/length only specified as numeric literals as above, then the +"addition AT can be omitted +WRITE AT /3(12) 'lorem ipsum'. +"Length specifications with * or **. In that case, the output length +"depends on the data type of the data object. There are special rules. +"See the ABAP Keyword Documentation for the details. +DATA dc34 TYPE decfloat34 VALUE ' 1.2345 '. +WRITE /(*) dc34. +WRITE /1(**) dc34. + +"--------------------- Further specification options ---------------------- + +"Various examples for further specification options, among them function +"calls, string expressions, method calls +DATA txt TYPE string VALUE `abap`. +"String template +WRITE / |{ txt WIDTH = 20 ALIGN = RIGHT CASE = UPPER }|. +"The following statement uses a chained statement with colon. +WRITE: / |{ 1 + 2 }|, "String template includes an arithmetic calculation + to_upper( txt ). "Function call +"Concatenation using && +WRITE / `conc` && `atenated`. +"Method call (returns a random integer between 1 and 10) +"Note the * specification. The returned value is of type i. Specifying * +"for the length means the length required to output the current value +"is used. You may want to try the following code snippet by removing (*). +WRITE /(*) cl_abap_random_int=>create( + seed = cl_abap_random=>seed( ) + min = 1 + max = 10 )->get_next( ). + +"UNDER: Output in the position of previous output +"Note: If the output is written in the same line in which the previous output +"is displayed, this output is overwritten. +DATA abc TYPE c LENGTH 5 VALUE 'abcde'. +WRITE /5(5) abc. +WRITE / 'fghij' UNDER abc. + +"NO-GAP +WRITE / 'g'. +WRITE 'ap1'. "Output: g ap1 +WRITE: / 'g' NO-GAP, 'ap2'. "Output: gap2 + +"QUICKINFO: Creates a tooltip for the output +WRITE / 'Place the mouse on the following output and check the tooltip:'. +WRITE: (*) sy-uname QUICKINFO 'User name', + '/', + (*) sy-datum QUICKINFO 'Current date', + '/', + (*) sy-uzeit QUICKINFO 'Current time'. + +"--------------------- Special list elements ---------------------- + +"INPUT: Enabling fields for input +"You can overwrite the output and further evaluate the overwritten +"content in a list event. +WRITE / ' Enter your name here ' INPUT. + +"AS CHECKBOX +"The value (blank, X) is stored in the list buffer and can be +"evaluated during a list event. +DATA: chck1 TYPE c LENGTH 1 VALUE 'X', + chck2 TYPE c LENGTH 1 VALUE ' '. +WRITE: / chck1 AS CHECKBOX, 'A checkbox', + / chck2 AS CHECKBOX, 'Another checkbox'. + +"AS ICON: Outputting icons +"Check the type pool ICON for names of predefined icons. +WRITE / icon_green_light AS ICON. +WRITE / icon_red_light AS ICON. +WRITE / icon_yellow_light AS ICON. +WRITE / icon_activate AS ICON. + +"AS SYMBOL: Outputting symbols +"Check the type pool SYM for names of predefined icons. +WRITE / sym_left_hand AS SYMBOL. +WRITE / sym_caution AS SYMBOL. + +"AS LINE: Outputting corners, crosses, lines, and T sections +"Check the type pool LINE for names of predefined icons. +WRITE: /10 line_horizontal_line AS LINE NO-GAP, + line_space AS LINE NO-GAP, + line_vertical_line AS LINE NO-GAP. +``` + +

⬆️ back to top

+ +Formatting options with `WRITE` and `FORMAT`: + +```abap +"The following examples show a selection. Various other additions are +"available that deal with currency, unit, date and time-related formatting, +"among others. See the ABAP Keyword Documentation. +WRITE /(10) 'X' RIGHT-JUSTIFIED. "' X' +WRITE /(10) 'X' CENTERED. "' X ' +WRITE /(10) 'X' LEFT-JUSTIFIED. "'X ' +DATA dc TYPE decfloat34 VALUE '1.2345'. +WRITE /(*) dc DECIMALS 2. "1,23 + +"COLOR addition +"The commented out value stands for the value that can also +"be directly specified in the syntax (except 0) or contained in +"a data object. There are several additions with many options. +WRITE / 'COL_BACKGROUND (0)' COLOR COL_BACKGROUND. "0 (GUI dependent) +WRITE / 'COL_HEADING (1)' COLOR COL_HEADING. "1 (gray-blue) +WRITE / 'COL_HEADING (1)' COLOR 1. +WRITE / 'COL_NORMAL (2)' COLOR COL_NORMAL. "2 (light gray) +WRITE / 'COL_TOTAL (3)' COLOR COL_TOTAL. "3 (yellow) +WRITE / 'COL_KEY (4)' COLOR COL_KEY. "4 (blue-green) +WRITE / 'COL_POSITIVE (5)' COLOR COL_POSITIVE. "5 (green) +WRITE / 'COL_NEGATIVE (6)' COLOR COL_NEGATIVE. "6 (red) +WRITE / 'COL_GROUP (7)' COLOR COL_GROUP. "7 (orange) +WRITE / 'COLOR 7 OFF' COLOR 7 OFF. "default color + +"Setting the intensity of the background color. +"Note that many of the following additions can specify further +"additions such as ON and OFF. See the details in the documentation. +WRITE / 'COLOR 7 INTENSIFIED OFF' COLOR 7 INTENSIFIED OFF. +"INVERSE: When ON, the foreground, i.e. the output is displayed +"in the selected color +WRITE / 'COLOR 7 INVERSE ON' COLOR 7 INVERSE ON. + +"FORMAT: You can use FORMAT statements for applying settings on the following +"output statements up to a definition with new settings or ... OFF. +"Note: Many of the additions that are also possible for WRITE (e.g. COLOR, +"INTENSIFIED, INVERSE ...) are possible. The following example uses the already +"mentioned COLOR addition. +FORMAT COLOR COL_POSITIVE. +WRITE / 'ABC'. +WRITE / 'DEF'. +WRITE / 'GHI'. +FORMAT COLOR OFF. + +"HOTSPOT addition: Displays the mouse pointer when hovering over an element. +"Here, a single click has then the same effect as a double click (i.e. the +"selection of function key F2). +FORMAT HOTSPOT ON. +DO 5 TIMES. + WRITE / sy-index. +ENDDO. +FORMAT HOTSPOT OFF. + +"FRAMES addition: Defines whether the - and | characters are converted to line elements, +"producing continuous lines. +FORMAT FRAMES ON. +WRITE: / '----', + / '| |', + / '----'. +FORMAT FRAMES OFF. + +"RESET addition: Resetting the formatting settings +"This addition sets all formatting settings for which the corresponding addition is +"not specified in the same FORMAT statement to the state OFF (exception: FRAMES). +"In the following example, all settings are reset without specifying concrete +"additions (e.g. INVERSE OFF). Note the effects of such a statement (e.g. INTENSIFIED +"is ON by default at program start; now it is set to OFF). See the ABAP Keyword +"Documentation for more information. +FORMAT COLOR 7 INVERSE ON. +WRITE / 'ABC'. +FORMAT RESET. +WRITE / 'DEF'. +``` + +

⬆️ back to top

+ +More list-related ABAP keywords: + +```abap +"Creating a horizontal line +ULINE. +"More additions are available e.g. for position and length +ULINE AT 5(20). + +"SET BLANK LINES: Specifying if blank lines created using WRITE are displayed +"In the example, the content of a string table that contains blank lines +"is output. +DATA(itab) = VALUE string_table( ( `a` ) ( `b` ) ( `` ) ( `` ) ( `c` ) ). + +"... OFF is set by default. Here it is explicitly specified. +"In this case, the blank lines are not output. +SET BLANK LINES OFF. +LOOP AT itab INTO DATA(wa). + WRITE / wa. +ENDLOOP. + +"... ON: The blank lines are output. +SET BLANK LINES ON. +LOOP AT itab INTO wa. + WRITE / wa. +ENDLOOP. + +"Setting the list cursor explicitly (more statements are +"available such as POSITION or BACK) +"SKIP: Positions the list cursor in another line (creating blank lines) +SKIP. "Skips 1 line +SKIP 3. "Specifying the number of lines to be skipped + +"SKIP TO LINE +"In the example, the list cursor is explicitly set to +"a particular number. Here, B and C are not output (i.e. +"overwritten with the output that follows). +WRITE / 'Text A'. +WRITE / 'Text B'. +DATA(line) = sy-linno. "The line number of the previous WRITE is retrieved. +WRITE / 'Text C'. +SKIP TO LINE line. +WRITE / 'Text D'. +WRITE / 'Text E'. + +"NEW-LINE: Setting list cursor to the first position of the next line +"Additions are available to affect the scrolling behavior +WRITE / 'Next statement is NEW-LINE'. +NEW-LINE. +WRITE 'WRITE statement without /'. "Output is in new line + +"HIDE: Storing the content of a flat variable together with the current list line. +"Example: a (3) is the result of b (1) + c (2). Suppose you click the line +"where a is output. You may e.g. output then b and c (e.g. another WRITE in the +"AT LIST-SELECTION event block), then getting the correct context of the list line. +... +a = b + c. +WRITE / a. +HIDE: b, c. +... + +"RESERVE: Creating a page break if there is not enough space left on the current list +"page between the last output and the page end or page footer, as specified with the number. +RESERVE 3 LINES. +"Consider the 3 lines defined as block. When you use BACK after RESERVE, e.g. after a loop, you +"can put the suqsequent output to the first line of this block of lines. See the effect in the +"executable example. +... +BACK. +WRITE ... +``` + +

⬆️ back to top

+ +### Reading and Modifying in Lists + +`READ LINE` statements: +- Assign the content of a line stored in the list buffer to the system field `sy-lisel`. +- Plus, it allows other target fields to be specified. +- `sy-subrc` is set: 0 (line was read), other than 0 (line does not exist) + +```abap +"More additions than those covered are available (e.g. for +"list level and list page) +"sy-lisel contains the entire line content of the specified line +READ LINE 1. +"sy-lisel contains the entire line content of the current line +READ CURRENT LINE. +"Assigning the output of individual data objects +"Here, it is the entire line content. +DATA wa TYPE c LENGTH 50. +READ CURRENT LINE LINE VALUE INTO wa. +"Here, specific field values (val1/val2) are assigned to individual data objects +DATA dobj1 TYPE c LENGTH 10. +DATA dobj2 TYPE c LENGTH 10. +READ CURRENT LINE FIELD VALUE val1 INTO dobj1 val2 INTO dobj2. +``` + +`MODIFY LINE` statements: +- Overwrites a line stored in the list buffer with the content of the `sy-lisel` system field +- Plus, it allows additional modifications + +```abap +"Overwrites line stored in sy-lisel (which is filled e.g. using a previous +"READ LINE statement) +MODIFY CURRENT LINE. +MODIFY LINE 2. +"Specifying content to overwrite an existing line; the following examples +"only use the addition CURRENT LINE +"Overwrites the entire list line with the content +MODIFY CURRENT LINE LINE VALUE FROM 'hi'. +"Overwrite a specific field with specified content +MODIFY CURRENT LINE FIELD VALUE a FROM b. +"Mutliple fields specified +MODIFY CURRENT LINE FIELD VALUE a FROM b c FROM d. +"Change the format (here using COLOR) +"... of a specific field +MODIFY CURRENT LINE FIELD FORMAT a COLOR 3. +"... of the line +MODIFY CURRENT LINE LINE FORMAT COLOR 4. +"Note: Multiple additions and combinations are possible, using COLOR here +MODIFY CURRENT LINE FIELD FORMAT a COLOR 5 b COLOR 6 LINE FORMAT COLOR 7. +``` + +> **💡 Note**
+> - [Relevant sy components in the context of lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenlist_systemfields.htm) +> - You can interact with a list by double-clicking a line (or pressing F2; the default `PICK` function code raises the `AT LINE-SELECTION` event). Other function codes usually trigger the `AT USER-COMMAND` event. See the event blocks below. In your ABAP program, you can react to the user action by implementing the individual event blocks. Regarding the function code, you can use the `sy-ucomm` system field for evaluation (unlike dynpros, there's no `OK_CODE` field to be filled). + +

⬆️ back to top

+ +## Event Blocks +- Notes + - Introduced by an [event keyword](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenevent_keyword_glosry.htm). + - Ended by the next processing block (there's no closing statement). + - Should not contain separate declarations, i.e. you should put all data object declarations in the global declaration part (except for `AT SELECTION-SCREEN ...`) + - It is recommended that you use ABAP Objects and methods consistently for data encapsulation + - Should not be specified more than once in a program + - Called depending on the user action and the program state (even if not explicitly specified) +- `LOAD-OF-PROGRAM` + - Program constructor + - Called when a program is loaded into the internal session + - Can be used to initialize the global data of a program. However, for executable programs, it is recommended that you use the event block `INITIALIZATION` for this task since the start values for parameters and selection criteria are set after `LOAD-OF-PROGRAM`. +- Reporting events related to executable programs in particular (and occur in predefined order). + - `INITIALIZATION` + - Used to initialize executable programs and provide start values (that cannot be statically expressed using `DEFAULT`) + - Called directly after `LOAD-OF-PROGRAM` and before selection screen processing + - `START-OF-SELECTION` + - Called after selection screen processing (see the following event blocks) + - If an executable program does not contain selection screens, this block is called automatically and implicitly. + - All statements are implicitly assigned to this block unless they are explicitly assigned to another block. + - Although it is optional, it is recommended that you specify the statement explicitly to improve readability. +- Selection screen events + - Used to individually evaluate selection screen elements, e.g. a specific parameter. + - In many cases, the events can be used for input validation (this should not wait until `START-OF-SELECTION`). If your custom input validation fails on an input, you can raise a message (e.g. a message of type `E`: `MESSAGE 'Error' TYPE 'E'.`) and allow users to edit the input again. + - `AT SELECTION-SCREEN OUTPUT`
Called by the dynpro event PBO of a selection screen after `INITIALIZATION`; can be used for modifying screen elements (e.g. using `MODIFY SCREEN`) + - `AT SELECTION-SCREEN ON par`
Called when values for a parameter or selection criteria were passed to the program; note: the syntax is also available for selection criteria; an additional variant `... ON END OF ...` is available (this event block is called when the selection table is passed completely allowing to check the entire selection table content) + - `AT SELECTION-SCREEN ON BLOCK bl`
Called when all input for a block is passed to the program + - `AT SELECTION-SCREEN ON RADIOBUTTON GROUP gr`
Called when the values for a radio button group were passed + - `AT SELECTION-SCREEN ON EXIT-COMMAND`
Called by *Back*, *Exit*, or *Cancel* (e.g. used for cleanup tasks) + - `AT SELECTION-SCREEN ON HELP-REQUEST | VALUE-REQUEST`
Relates to field (F1) and input (F4) help + - `AT SELECTION-SCREEN.`
Called as last event in the selection screen processing when all input values are passed to the program +- List events + - Are triggered during the list creation and after certain user actions on a displayed list. + - During list creation: + - `TOP-OF-PAGE`
For definining page headers; called when a [basic list](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenbasic_list_glosry.htm) is created and when a new page begins (`... DURING LINE-SELECTION` is called when [details lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abendetails_list_glosry.htm) are created) + - `END-OF-PAGE`
For definining page footers; called when the end of a page is reached, for example, when the specified number of lines in the `LINE-COUNT` addition (e.g. `PROGRAM LINE-COUNT 20(3).`) has been reached + - After user actions: + - `AT LINE-SELECTION`
Called when a screen list is displayed, the screen cursor is on a list line and a function is selected using the function code `PICK`; when specified, the function key F2 is enabled and, therefore, double click functionality; F2 and a double click are linked with the function code `PICK`. + - [`AT USER-COMMAND`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapat_user-command.htm)
Called when a function with a user-defined function code is selected when a screen list is displayed; the function codes can be evaluated using `sy-ucomm`; you can set a list event programmatically using [`SET USER-COMMAND`](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abapset_user-command.htm) + + +

⬆️ back to top

+ +## Excursion: SAP List Viewer (ALV) + +- Provides an object-oriented API for displaying and formatting lists +- Allows you to specify layout settings and functionality +- Classes such as `CL_SALV_TABLE` encapsulate the use of the ALV grid control and simplify the integration into ABAP programs. Note: The older class `CL_GUI_ALV_GRID` should no longer be used directly for new developments. +- Other classes are available to handle hierarchical lists and tree structures. The focus of the code snippets is on simple, non-nested tables and the use of the `CL_SALV_TABLE` class. + +### Getting Started +- To get started quickly, you only need to ... + - instantiate an ALV table object using the `factory` method. + - define the display type for the ALV output. By default, full-screen display is enabled. + - display the ALV output using the `display` method. + +> **💡 Note**
+> - When working with ALV, make sure that you implement appropriate error handling. +> - The `factory` method also has optional exporting parameters. You can use the optional `list_display` parameter to specify whether you want to display the ALV output as classic list. It is set to false by default. There are also exporting parameters to display the ALV output in containers (e.g. see the dynpro cheat sheet example). The exporting parameters are not relevant in this example. Here, the ALV output is displayed on the entire screen (however, it is also possible to display the ALV output in a dialog box). + +The following code snippet shows a simple example to get you started quickly with the necessary method calls. It includes a demo internal table with content. + +```abap +TYPES: BEGIN OF demo_struct, + col1 TYPE string, + col2 TYPE i, + col3 TYPE c LENGTH 1, + END OF demo_struct. + +DATA itab TYPE TABLE OF demo_struct WITH EMPTY KEY. +itab = VALUE #( ( col1 = `abc` col2 = 1 col3 = 'X' ) + ( col1 = `def` col2 = 2 col3 = 'Y' ) + ( col1 = `ghi` col2 = 3 col3 = 'Z' ) ). + +TRY. + cl_salv_table=>factory( IMPORTING r_salv_table = DATA(alv) + CHANGING t_table = itab ). + + alv->display( ). + CATCH cx_salv_msg INTO DATA(err). + MESSAGE err->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. +ENDTRY. +``` + +### Optional Layout Settings and Functionality + +- The following commented code snippet covers a selection of the many setting and functionality options. +- For simplicity of the snippet, the code only uses the root exception class. Make sure that you implement appropriate error handling and exception classes. +- You can copy and paste the code into your own test program to explore the ALV output and the effect of the method calls. + +> **💡 Note**
+> Check the comments for the custom functions. If there are errors in your test program, replace the relevant code section and enable the generic ALV functions. + +```abap +TYPES: BEGIN OF demo_struct, + col1 TYPE string, + col2 TYPE i, + col3 TYPE string, + col4 TYPE icon_d, + col5 TYPE string, + END OF demo_struct. +DATA itab TYPE TABLE OF demo_struct WITH EMPTY KEY. +DATA alv TYPE REF TO cl_salv_table. +DATA cnt4evt TYPE i VALUE 6. + +"Local class to handle events +CLASS lcl_events DEFINITION. + PUBLIC SECTION. + CLASS-METHODS single_click + FOR EVENT link_click OF cl_salv_events_table + IMPORTING row column. + CLASS-METHODS double_click + FOR EVENT double_click OF cl_salv_events_table + IMPORTING row column. + CLASS-METHODS func_click + FOR EVENT added_function OF cl_salv_events + IMPORTING e_salv_function. +ENDCLASS. +CLASS lcl_events IMPLEMENTATION. + METHOD single_click. + "Both single and double click events trigger messages. + READ TABLE itab INDEX row REFERENCE INTO DATA(sc_ref). + IF sy-subrc = 0. + ASSIGN sc_ref->(column) TO FIELD-SYMBOL(). + MESSAGE `Single click event. ` && + |Row: { row } { COND #( WHEN column IS NOT INITIAL THEN `Column: ` && column ) } | && + |{ COND #( WHEN IS ASSIGNED THEN `Value: ` && ) }| TYPE 'I'. + ELSE. + MESSAGE `Single click event` TYPE 'I'. + ENDIF. + ENDMETHOD. + METHOD double_click. + READ TABLE itab INDEX row REFERENCE INTO DATA(dc_ref). + IF sy-subrc = 0. + ASSIGN dc_ref->(column) TO FIELD-SYMBOL(). + MESSAGE `Double click event. ` && + |Row: { row } { COND #( WHEN column IS NOT INITIAL THEN `Column: ` && column ) } | && + |{ COND #( WHEN IS ASSIGNED THEN `Value: ` && ) }| TYPE 'I'. + ELSE. + MESSAGE `Double click event` TYPE 'I'. + ENDIF. + ENDMETHOD. + METHOD func_click. + "Handling custom functions + CASE e_salv_function. + WHEN 'DATA'. + MESSAGE `Custom function DATA. Do something ...` TYPE 'I'. + WHEN 'TEST'. + IF cnt4evt = 6. + MESSAGE `A table row will be added, demonstrating the 'refresh' ` && + `method that rebuilds the output table.` TYPE 'I'. + ENDIF. + cnt4evt += 1. + itab = VALUE #( BASE itab ( col1 = `fffff` col2 = cnt4evt + col3 = `ttttt` col4 = icon_green_light ) ). + "Rebuilding the output table + alv->refresh( ). + WHEN 'QUIT'. + MESSAGE `Custom function QUIT. Do something ...` TYPE 'I'. + WHEN OTHERS. + MESSAGE `Some other function` TYPE 'I'. + ENDCASE. + ENDMETHOD. +ENDCLASS. +START-OF-SELECTION. +"Populating internal table that is output +itab = VALUE #( ( col1 = `aaaaa` col2 = 1 col3 = `zzzzz` col4 = icon_green_light ) + ( col1 = `bbbbb` col2 = 2 col3 = 'yyyyy' col4 = icon_green_light ) + ( col1 = `ccccc` col2 = 3 col3 = 'xxxxx' col4 = icon_green_light ) ). +TRY. + "----------- Instantiating an ALV table object ----------- + cl_salv_table=>factory( IMPORTING r_salv_table = alv + CHANGING t_table = itab ). + "----------- Creating a new instance with new data ----------- + "Notes on the set_data method: + "- All objects that were referred to previously are removed. + "- Not to be used in event handlers. + "In the example, new lines are added to the existing internal table. + itab = VALUE #( BASE itab ( col1 = `ddddd` col2 = 4 + col3 = `wwwww` col4 = icon_green_light ) + ( col1 = `ddddd` col2 = 5 + col3 = `vvvvv` col4 = icon_green_light ) + ( col1 = `eeeee` col2 = 6 + col3 = `uuuuu` col4 = icon_green_light ) ). + alv->set_data( CHANGING t_table = itab ). + "----------- Layout-related settings ----------- + "Changing the list header title + CAST cl_salv_display_settings( + alv->get_display_settings( ) )->set_list_header( 'Demo Title' ). + "There are several methods to retrieve column-specific information. + "The following examples show a selection. You can check the variable + "content in the debugger. + DATA(col1obj) = alv->get_columns( )->get_column( 'COL1' ). + DATA(col1alignment) = col1obj->get_alignment( ). + DATA(col1type) = col1obj->get_ddic_inttype( ). + DATA(col1colname) = col1obj->get_columnname( ). + DATA(is_col1_visible) = col1obj->is_visible( ). + "Settings for the column header + "This example uses the get method, which returns all column objects of + "the output table. The table is processed in a loop. + "Settings covered: + "- Specifying the column header titles (long, medium, and short + " column header) + "- Specifying a tooltip for the column header + LOOP AT alv->get_columns( )->get( ) REFERENCE INTO DATA(colref). + "Specifying the column header titles + "The example sets the texts based on the columname value. + "Note: The column width is optimized further down. You may want to + "manually adjust the width in the ALV output to see the column header + "name change. + colref->r_column->set_long_text( |{ colref->columnname }| ). + colref->r_column->set_medium_text( |{ colref->columnname+2(3) }| ). + colref->r_column->set_short_text( |{ colref->columnname+3(3) }| ). + "Specifying a tooltip for the column headers + colref->r_column->set_tooltip( + |Demo tooltip { colref->columnname+3(3) }| ). + ENDLOOP. + "Displaying/Hiding the column headers + "In the example, the value is set to abap_true. Set it to abap_false + "to hide the column header. + "Note: In this and the following examples, the settings are + "intentionally done using separate casts for each example. You can also + "create object reference variables, such as for 'col1obj' to avoid having + "to specify the casts explicitly each time. + CAST cl_salv_columns_list( + alv->get_columns( ) )->set_headers_visible( abap_true ). + "Setting key columns + "Note: The key columns have a default color setting. There, you can only + "change the color in individual cells. + CAST cl_salv_column_table( + alv->get_columns( )->get_column( 'COL1' ) )->set_key( abap_true ). + + "Setting column color + "Note: The executable example includes examples of coloring entire rows and + "specific cells. + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL2' ) + )->set_color( VALUE lvc_s_colo( col = col_positive ) ). + + "Hiding columns + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL5' ) + )->set_visible( abap_false ). + + "Setting text alignment + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL2' ) + )->set_alignment( if_salv_c_alignment=>left ). + + "Optimizing column width, i.e. automatically adjusting the column width + "to display values completely (can also be done for individual columns) + alv->get_columns( )->set_optimize( abap_true ). + + "Setting output width explicitly (for an individual column) + "Note: Just to demonstrate the method call. This setting has no effect in + "the example due to the column width optimization above, and the column is + "hidden anyway. + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL5' ) + )->set_output_length( '100' ). + + "Setting table rows to a striped pattern + alv->get_display_settings( )->set_striped_pattern( abap_true ). + + "Displaying/hiding horizontal and vertical grid lines (here, they're hidden) + alv->get_display_settings( )->set_horizontal_lines( abap_false ). + alv->get_display_settings( )->set_vertical_lines( abap_false ). + + "With the following method call, the ALV output is displayed in a dialog box. + "Demo coordinates are provided. You can comment it in to see the effect. +* alv->set_screen_popup( start_column = 10 +* end_column = 100 +* start_line = 4 +* end_line = 15 ). + + "------ Adding functionality/user interaction options to the ALV output ------ + "Specifying the selection type + "The following specification allows you to select multiple rows/columns (a column + "is added on the left for selections). Check the other options in the + "if_salv_c_selection_mode interface. + alv->get_selections( )->set_selection_mode( if_salv_c_selection_mode=>row_column ). + + "Setting the sorting + "In the example, a particular column is sorted in descending order. + alv->get_sorts( )->add_sort( 'COL1' )->set_sequence( if_salv_c_sort=>sort_down ). + + "Applying a filter + "The example is implemented to exculed one entry from the demo table. + alv->get_filters( )->add_filter( 'COL2' )->add_selopt( sign = 'E' + option = 'EQ' + low = '6' ). + + "Making a calculation/aggregation + "In this example, an aggregation is added for a specific column. + "In this case, the average value is calculated. It is displayed in a row added + "at the bottom of the table. + alv->get_aggregations( )->add_aggregation( + columnname = 'COL2' + aggregation = if_salv_c_aggregation=>average ). + + "Generic and custom ALV functions + "Note: + "- By default, ALV functions (such as sorting or filtering) are not available + " to users. You must explicitly enable them. + "- Depending on whether the display is full-screen (as it is here) or in a + " container, restrictions apply. In the first case, you can use your own GUI status + " to integrate custom functions. + + "This (self-contained, ready-to-use) code snippet is intended so that you can simply + "copy & paste the code into a test program. For this purpose, and to be able to + "demonstrate custom functions in this full-screen ALV example using a GUI status, the + "example uses a demo GUI status that is included in another sample program (in a + "subpackage of SALV). For your own GUI status, you can check the SALV_TABLE_STANDARD + "status contained in the SALV_METADATA_STATUS function group, which you can copy and + "use as a template, for example. + "*********************************** NOTE *********************************** + "- The GUI status used here is just reused to have a copyable and self-contained example. + "- The GUI status of the sample program (specified for the report parameter below) + " contains generic and additional functions. For the additional functions, a simple + " implementation is included in this snippet. The GUI status should include the + " functions TEST, DATA, QUIT. + "- The implementations in the event handler class here do not match the implementations + " there, the button texts do not make sense for the implementations here, and so on. + "- So even though it (the button names, icons, implementations, etc.) does not make much + " sense for this snippet, you should get an idea about custom functions and be able to + " explore the event handling by clicking on the buttons. + "- The TEST function demonstrates adding new rows to the table and the 'refresh' method. + "- If this particular program, the GUI status and/or the custom functions are not available + " in your system, or if you insert the code into your own test program, run it, and + " encounter problems setting the status, remove the TRY control structure that contains + " the set_screen_status method call, and comment in the code below to use the standard + " ALV functions. In this case, the custom functions cannot be checked out with this + " snippet. + "- Check out the executable example of the cheat sheet that includes a GUI status. + TRY. + alv->set_screen_status( + pfstatus = 'SALV_TABLE_STANDARD' + report = 'SALV_TEST_REFRESH' + set_functions = alv->c_functions_all ). + + "In this GUI status, the custom functions TEST, DATA, and QUIT are specified. You can + "check the results of the following method calls in the debugger. + DATA(getfunc) = alv->get_functions( ). + "Checking the activation status + DATA(is_enabled) = getfunc->is_enabled( 'TEST' ). + "Checking the visibility + DATA(is_visible) = getfunc->is_visible( 'TEST' ). + + "Registering an event handler for the custom functions + "The added_function event is raised. In the implementation of the event handler method, + "you can then implement your code based on the value of the e_salv_function parameter + "(which contains the specified function name), for example, using a CASE statement. + "The implementation in this code snippet is different from the original program. + SET HANDLER lcl_events=>func_click FOR alv->get_event( ). + + CATCH cx_salv_object_not_found. + MESSAGE `GUI status error. Instead, use the set_default method, for example.` + TYPE 'I'. + ENDTRY. + + "If you remove the TRY control structure above, you can comment in the following + "code to use the generic ALV functions. Use the set_all method for all generic + "functions. You can also enable generic ALV functions individually. Check the + "set_* methods. + "alv->get_functions( )->set_default( abap_true ). + + "Hotspot/single click functionality + "You can define the content of a cell as a clickable area. You can do this by + "specifying the cell type hotspot. When a user clicks the cell content, + "the link_click event is raised. + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL1' ) + )->set_cell_type( if_salv_c_cell_type=>hotspot ). + + "You can set icon columns and make the icon cells clickable areas. To do this, + "use the set_icon method. As above, the cell type of the column is set to hotspot. + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL4' ) + )->set_icon( if_salv_c_bool_sap=>true ). + CAST cl_salv_column_table( alv->get_columns( )->get_column( 'COL4' ) + )->set_cell_type( if_salv_c_cell_type=>hotspot ). + + "An event handler is registered for the clickable areas (the link_click event + "is raised). The get_event method returns the required event object. In the + "example, a message is displayed. + SET HANDLER lcl_events=>single_click FOR alv->get_event( ). + + "Double click functionality + "Registering an event handler for the double click event. In the example, a message + "is displayed. Double-click cells in columns for which the cell type is not set to hotspot. + SET HANDLER lcl_events=>double_click FOR alv->get_event( ). + + "Adding tooltips to the icon column cells + alv->get_functional_settings( )->get_tooltips( )->add_tooltip( + type = cl_salv_tooltip=>c_type_icon + value = CONV lvc_value( icon_green_light ) + tooltip = `This is a tooltip for an icon` ). + + "----------- Displaying the ALV output ----------- + alv->display( ). + CATCH cx_root INTO DATA(error). + "For simplicity, this example uses the root exception class. + "Always make sure that you use appropriate exception classes. Check the F2 + "information for the methods in ADT. + MESSAGE error->get_text( ) TYPE 'I' DISPLAY LIKE 'E'. +ENDTRY. +``` + +

⬆️ back to top

+ +## More Information +- ABAP Keyword Documentation: + - [Selection Screens](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenselection_screen.htm) + - [Classic Lists](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_dynpro_list.htm) +- ALV: + - [SAP List Viewer (ALV)](https://help.sap.com/docs/SAP_NETWEAVER_731_BW_ABAP/b1c834a22d05483b8a75710743b5ff26/4ec38f8788d22b90e10000000a42189d.html?locale=en-US) on the SAP Help Portal + - Find more demonstration examples in package `SALV` and its subpackages. + +## Executable Examples + +After the import of the repository, proceed as follows: +- Find the program in ADT using the search by choosing `CTRL + SHIFT + A`. +- Enter `ZDEMO_ABAP_SELSCR_LISTS_INTRO` and open the program. This program serves as an entry point for all selection screen and list examples. Program names of the individual examples: + - `ZDEMO_ABAP_SELSCR_PARAMETERS`: Demonstrates `PARAMETERS` statements + - `ZDEMO_ABAP_SELSCR_SELECT_OPT`: Demonstrates `SELECT-OPTIONS` statements + - `ZDEMO_ABAP_SELSCR_STANDALONE`: Demonstrates the creation (`SELECTION-SCREEN` statements) and calling of standalone selection screens + - `ZDEMO_ABAP_SELSCR_STMTS_VAR`: Demonstrates variants of the `SELECTION-SCREEN` statements that do not create selection screens + - `ZDEMO_ABAP_LISTS`: Demonstrates various ABAP statements to create and handle classic lists + - `ZDEMO_ABAP_EVENT_BLOCKS`: Demonstrates event blocks + - `ZDEMO_ABAP_ALV`: Demonstrates the SAP List Viewer (ALV) +- Run the program by choosing `F8`. + +> **💡 Note**
+> - The executable examples ... +> - do not claim to include meaningful selection screens and lists. +> - are not intended to be role models for proper selection screen and list design. +> - are not intended to solve concrete programming tasks. You should always work out your own solution for each individual case. +> - are only intended to demonstrate a selection of keywords and visualize related syntax in action on a high level. +> - include comments in the program code. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). > - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file diff --git a/21_XML_JSON.md b/21_XML_JSON.md index 1f99e63..7da6e7f 100644 --- a/21_XML_JSON.md +++ b/21_XML_JSON.md @@ -1,749 +1,750 @@ - - -# Working with XML and JSON in ABAP - -- [Working with XML and JSON in ABAP](#working-with-xml-and-json-in-abap) - - [Introduction](#introduction) - - [Processing XML Using Class Libraries](#processing-xml-using-class-libraries) - - [iXML](#ixml) - - [sXML](#sxml) - - [XML Transformations](#xml-transformations) - - [CALL TRANSFORMATION Syntax](#call-transformation-syntax) - - [Dealing with JSON](#dealing-with-json) - - [Excursions](#excursions) - - [Converting string \<-\> xstring](#converting-string---xstring) - - [Compressing and Decompressing Binary Data](#compressing-and-decompressing-binary-data) - - [More Information](#more-information) - - [Executable Example](#executable-example) - -## Introduction - -This cheat sheet provides a high-level overview of working with XML and JSON in ABAP. It covers the following topics: -- Processing XML using class libraries (iXML, sXML) -- XML Transformations using XSLT and Simple Transformations (ST), i.e. serializations (ABAP to XML) and deserializations (XML to ABAP) -- `CALL TRANSFORMATION` syntax -- Dealing with JSON data - -> **💡 Note**
-> - The cheat sheet snippets and the executable example cover simple cases. Find more executable examples of the ABAP Keyword Documentation following the links in the [More Information](#more-information) section. -> - For more detailed information, such as documentation on ST syntax, what asXML is, etc., also see the links in the [More Information](#more-information) section. -> - In addition to the options covered in the cheat sheet, there are other ways to work with XML/JSON (for example, the `/ui2/cl_json` class). - -

⬆️ back to top

- -## Processing XML Using Class Libraries - -### iXML -- *Integrated* XML Library -- Provides methods for ... - - validating and parsing (i.e. reading) XML data in 1.0 format into a DOM representation (Document Object Model, which is a tree-like representation of the documents in the memory) - - processing the DOM representation (you can create or edit XML data) - - rendering (i.e. writing) the DOM representation -- To access XML data, you need input and output streams that are created using iXML methods. -- Advantages: Easy access to the individual parts of an XML document possible, DTDs (Document Type Definitions) are possible -- Disadvantages: High memory consumption of the DOM (if the complete DOM is created) - -The following code snippets demonstrate a selection of iXML methods for handling XML data. Note that the snippets use classes available for [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm). Find documentation on the classes for [classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm) [here (F1 documentation for Standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_ixml_lib.htm). - -Creating XML data using iXML: - -```abap -"Creating one factory object of the access class cl_ixml_core using the -"create method. It is used to access the iXML library. -DATA(ixml_cr) = cl_ixml_core=>create( ). - -"Creating an XML document stored in DOM format in the memory -DATA(document_cr) = ixml_cr->create_document( ). - -"Creating DOM nodes step by step. Here, elements, attributes, and content are -"and inserted into the XML. Using an appropriate attribute setting, the result -"represents XML data in the asXML format (see more information further down). - -"Creating a root node -DATA(root) = document_cr->create_element_ns( name = 'abap' - prefix = 'asx' ). -root->set_attribute_ns( name = 'asx' - prefix = 'xmlns' - value = 'http://www.sap.com/abapxml' ). -root->set_attribute_ns( name = 'version' - value = '1.0' ). -document_cr->append_child( root ). - -DATA(xml_node1) = document_cr->create_element_ns( prefix = 'asx' - name = 'values' ). -root->append_child( xml_node1 ). -DATA(xml_node2) = document_cr->create_element_ns( name = 'STRING' ). -xml_node1->append_child( xml_node2 ). -xml_node2->append_child( document_cr->create_text( 'Hello World' ) ). - -"Creating a renderer for rendering the XML document into an output stream -"that is used to pass XML data from the renderer. -DATA xml_doc TYPE xstring. -ixml_cr->create_renderer( document = document_cr - ostream = ixml_cr->create_stream_factory( )->create_ostream_xstring( string = xml_doc ) - )->render( ). - -"Result (xstring converted to string): -" -"Hello World -``` - -Parsing XML data using iXML: - -```abap -"Creating demo XML data to be used in the example as string. Using the cl_abap_conv_codepage -"class, you can convert the string to xstring which is required for the example. -DATA(some_xml) = cl_abap_conv_codepage=>create_out( )->convert( - `` && - ` hallo` && - ` how` && - ` are` && - `` ). - -"Creating one factory object of the access class cl_ixml_core using the -"create method. It is used to access the iXML library. -DATA(ixml_pa) = cl_ixml_core=>create( ). -"Creaing an input stream that is used for the input of XML data -DATA(stream_factory_pa) = ixml_pa->create_stream_factory( ). -"Creating an XML document stored in DOM format in the memory -DATA(document_pa) = ixml_pa->create_document( ). -"Creating a parser. It requires the following input parameters: input stream to be parsed, -"the XML document to which the stream is parsed, a factory required to create a stream -DATA(parser_pa) = ixml_pa->create_parser( - istream = stream_factory_pa->create_istream_xstring( string = some_xml ) - document = document_pa - stream_factory = stream_factory_pa ). - -"Parsing XML data to a DOM representation in one go. It is put in the memory. -"Note: You can also parse sequentially, and not in one go. -DATA(parsing_check) = parser_pa->parse( ). -IF parsing_check = 0. "Parsing was successful - - "************* Directly reading nodes ************* - - "Accessing the root element of the DOM. It can be used as the initial node - "for accessing subnodes. - "Note: Multiple methods are available to further process the nodes. - DATA(root_element) = document_pa->get_root_element( ). - "First subnode - DATA(child_element) = root_element->get_first_child( ). - "Gettng the value of that node - DATA(child_element_value) = child_element->get_value( ). "hallo - "Next adjacent node/getting the value - DATA(next_element_value) = child_element->get_next( )->get_value( ). "how - "Direct access using element names - "Result: First element searched for - DATA(element_by_name) = document_pa->find_from_name( name = `word3` )->get_value( ). "are - - "************* Reading using iterators ************* - "i.e. going over the XML nodes one after another - - "Creating an iterator - DATA(iterator_pa) = document_pa->create_iterator( ). - DO. - "For the iteration, you can use the get_next method to process the nodes one after another. - "Note: Here, all nodes are respected. You can also create filters to go over specific nodes. - DATA(node_i) = iterator_pa->get_next( ). - IF node_i IS INITIAL. - "Exiting the loop when there are no more nodes to process. - EXIT. - ELSE. - ... "Do something, e.g. modify values - ENDIF. - ENDDO. - - "Creating a renderer. It renders the XML document into an output stream - "that is used to pass XML data from the renderer. - DATA xml_pa TYPE xstring. - ixml_pa->create_renderer( document = document_pa - ostream = ixml_pa->create_stream_factory( )->create_ostream_xstring( string = xml_pa ) - )->render( ). - ... -ELSE. - "Parsing was not successful. - ... -ENDIF. -``` - -

⬆️ back to top

- -### sXML -- *Serial* XML Library -- Provides XML readers and writers for different sources and targets -- Processes XML data sequentially -- Allows you to parse and render XML data in a token-based (iterating across all nodes, i.e. tokens, in the tree structure of the XML data) and object-oriented way (wrapping methods of the token-based access; providing an object-oriented way to access XML nodes) -- Unlike iXML, ... - - more formats are possible (standard XML 1.0, but also XOP, binary XML, and JSON). - - no document is created in DOM format (if you do not need a DOM representation and DTDs, sXML is a more performant alternative to iXML). - -Creating XML data using sXML: - -```abap -"************** Token-based rendering ************** - -"For sXML, there are specialized writer classes, such as CL_SXML_STRING_WRITE. -"Writers created with this class render XML data to a byte string. -"The XML 1.0 format and UTF-8 are used by default in the create method. -"Here, the parameters are specified explicitly. -"Note: The interface IF_SXML_WRITER contains the components that are valid -"for all readers (the abstract super class CL_SXML_WRITER includes this -"interface as well as implementations for all readers). In the example below, -"a cast is required so as to access special methods (such as open_element). - -DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 - encoding = 'UTF-8' ) ). - -"Creating/Rendering XML data using token-based rendering -"The example shows shows how XML data can be created using various available methods. -"Here, token-based rendering is used, i.e. each node is added to the XML data using -"a method. There is a method for each node type. -TRY. - "Creating nodes (the order of the nodes is crucial) - writer->open_element( name = 'flights' ). - writer->open_element( name = 'flight' ). - writer->open_element( name = 'carrier' ). - writer->write_value( 'LH' ). - writer->close_element( ). - writer->open_element( name = 'flightnumber' ). - writer->write_value( '400' ). - writer->close_element( ). - writer->close_element( ). - writer->open_element( name = 'flight' ). - writer->open_element( name = 'carrier' ). - writer->write_value( 'DL' ). - writer->close_element( ). - writer->open_element( name = 'flightnumber' ). - writer->write_value( '1984' ). - writer->close_element( ). - writer->close_element( ). - writer->close_element( ). - CATCH cx_sxml_state_error. - ... -ENDTRY. - -"The XML data can be retrieved with the GET_OUTPUT method. -"Also here, a cast is required. -"The result is of type xstring. -DATA(xml) = CAST cl_sxml_string_writer( writer )->get_output( ). - -"The result looks like this (when converted to string and indented): -" -" -" -" LH -" 400 -" -" -" DL -" 1984 -" -" - -"************** Object-oriented rendering ************** - -DATA(writer_oo) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 - encoding = 'UTF-8' ) ). - -TRY. - writer_oo->write_node( writer_oo->new_open_element( name = 'flights' ) ). - - writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). - DATA(val) = writer_oo->new_value( ). - val->set_value( 'AZ' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). - val = writer_oo->new_value( ). - val->set_value( '788' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - - writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). - val = writer_oo->new_value( ). - val->set_value( 'JL' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). - val = writer_oo->new_value( ). - val->set_value( '407' ). - writer_oo->write_node( val ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - writer_oo->write_node( writer_oo->new_close_element( ) ). - - writer_oo->write_node( writer_oo->new_close_element( ) ). - CATCH cx_sxml_state_error. - ... -ENDTRY. - -DATA(xml_oo) = CAST cl_sxml_string_writer( writer_oo )->get_output( ). - -"The result looks like this (when converted to string and indented): -" -" -" AZ -" 788 -" -" -" JL -" 407 -" -" -``` - -Parsing XML data using sXML: - -```abap -"************** Token-based parsing ************** - -"Creating reader -"Note: See the comments for the writer above. It is similar here. For readers, -"the interface IF_SXML_READER exists. In this example, no special methods -"are used. Therefore, a cast is not carried out. -"The example uses the XML data from above. -DATA(reader) = cl_sxml_string_reader=>create( xml_oo ). -"DATA(reader_cast) = CAST if_sxml_reader( cl_sxml_string_reader=>create( xml_oo ) ). - -"To iterate accros all nodes, you can call the NEXT_NODE method. -TRY. - DO. - "Check out other available methods in ADT by placing the cursor behind '...->' - "and choose CTRL + Space. - reader->next_node( ). - - "Exiting the loop when reaching the end of the XML data. - IF reader->node_type = if_sxml_node=>co_nt_final. - EXIT. - ENDIF. - - "You can access the properties of the node directly. - DATA(node_type) = reader->node_type. "Node type, see the interface if_sxml_node - DATA(prefix) = reader->prefix. "Namespace prefix - DATA(name) = reader->name. "Name of the element - DATA(value_type) = reader->value_type. "Value type, see the interface if_sxml_value - DATA(value) = reader->value. "Character-like value (if it is textual data) - DATA(value_raw) = reader->value_raw. "Byte-like value (if it is raw data) - - ... - - ENDDO. - CATCH cx_sxml_parse_error. - ... -ENDTRY. - -"************** Object-oriented parsing ************** - -"Creating demo XML data to be used in the example. -DATA(xml_oo_read) = cl_abap_conv_codepage=>create_out( )->convert( - `` && - `` && - ` ` && - ` A` && - ` 01-01-2024` && - ` ` && - ` ` && - ` abc` && - ` def` && - ` ghi` && - ` ` && - `` ). - -"Creating reader -DATA(reader_oo) = cl_sxml_string_reader=>create( xml_oo_read ). -TRY. - DO. - "To iterate accros all nodes, you can call the READ_NEXT_NODE method. - "When the end of the XML data is reached, the returned value is initial. - DATA(node_oo) = reader_oo->read_next_node( ). - IF node_oo IS INITIAL. - EXIT. - ENDIF. - - "In object-oriented parsing, methods for token-based parsing are wrapped. - "An object-oriented access to the node is provided. - "References to objects that represent the current node are returned. - - "Getting the node type - DATA(n_type) = node_oo->type. - - "When the parser is currently on the node of an element opening, - "the node object has the class CL_SXML_OPEN_ELEMENT that implements the - "interface IF_SXML_OPEN_ELEMENT. With the methods included, you can - "access the XML attributes of the element, e.g. using the GET_ATTRIBUTES - "method to put the references for all attributes into an internal table. - "To access the attributes, a downcast is required. - IF n_type = if_sxml_node=>co_nt_element_open. - DATA(attributes) = CAST if_sxml_open_element( node_oo )->get_attributes( ). - ... - ENDIF. - ... - ENDDO. - CATCH cx_sxml_parse_error. - ... -ENDTRY. -``` - -

⬆️ back to top

- -## XML Transformations - -To perform transformations in ABAP, you can use: - -- XSL Transformations (XSLT) - - Repository objects written in XSLT - - XSLT can process ABAP data because ABAP data is first implicitly transformed into the asXML format. The result of this implicit transformation (the asXML format) is then used as the actual source for the XSL transformation. -- Identity transformations - - SAP-delivered and predefined XSL transformation with the name `ID` - - Used to read and write the asXML (and also asJSON) format. - - When the transformation ID is called, the resulting intermediate formats (asXML, asJSON) are the direct output. - - When used, for example, to transform ABAP data, such as a structure, to XML, the transformation does not change the structure itself. You can, however, change the structure by implementing your own XSLT. -- Simple Transformation (ST) - - Repository objects written in an SAP-specific programming language for transformations between XML formats and ABAP data - -The tranformations are called using `CALL TRANSFORMATION` statements. - -Possible transformations, some of which are covered in the example: - -| Transformation | XSLT | ST | -|---|---|---| -| XML <-> XML | X | - | -| ABAP <-> XML | X | X | -| ABAP <-> ABAP | X | - | - -> **💡 Note**
-> asXML: -> - *ABAP Serialization XML* -> - Describes a format of XML data created when serializing ABAP data (ABAP -> XML) with the identity transformation -> - This format is a prerequisite for deserializations (XML -> ABAP) using identity transformations. -> - Used as an intermediate format that defines a mapping between ABAP data and XML -> - Therefore, if you want to deserialize XML data in ABAP, you must first transform it to the asXML format. -> Make sure that you use appropriate exception classes for potential errors in transformations. See the section [Catchable Exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) in the `CALL TRANSFORMATION` topic. - -

⬆️ back to top

- -## CALL TRANSFORMATION Syntax - -The following code snippets demonstrate a selection of possible syntax options when using [`CALL TRANSFORMATION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) statements. - -**Specifying transformations** - -```abap -"Specifying the name of an XSL or Simple Transformation statically -CALL TRANSFORMATION zsome_transformation SOURCE ... - RESULT ... - -"Specifying the identity transformation with the predefined name ID -CALL TRANSFORMATION id SOURCE ... - RESULT ... - -"Dynamic specifiation of the transformation -"If the transformation does not exist, an exception is raised. -TRY. - CALL TRANSFORMATION ('ID') SOURCE ... - RESULT ... -CATCH cx_invalid_transformation. - ... -ENDTRY. -``` - -**Specifying the source of the transformation** - -There are multiple options. Check the executable example to explore them. - -```abap -"**************** Transforming XML data **************** -"Options for src: -"- Data object of type string or xstring containing XML data in XML 1.0 format -"- Standard table with flat character-like or byte-like line type -"- Some references to iXML and sXML libraries are possible. For example, an -" interface reference variable of type if_sxml_reader. -CALL TRANSFORMATION ... SOURCE XML src - RESULT ... - -"**************** Transforming ABAP data **************** -"No XML specified after SOURCE -"Options for src: -"- One or multiple ABAP data objects (abap1 in the snippet) can be specified as -" static parameter list, e.g. z1 = abap1 z2 = abap2 ... -"- When XSLT is used (such as ID), the data is serialized to asXML depending on -" the target -"- z1 etc. stands for names of XML elements -CALL TRANSFORMATION ... SOURCE z1 = abap1 ... - RESULT ... - -"Dynamic specification of ABAP data objects in an internal table of type -"abap_trans_srcbind_tab -DATA(srctab) = VALUE abap_trans_srcbind_tab( ( name = 'A' value = REF #( b ) ) ( ... ) ). -CALL TRANSFORMATION ... SOURCE (srctab) - RESULT ... -``` - -**Specifying the result of the transformation** - -There are multiple options. Check the executable example to see them in action. - -```abap -"**************** Transforming to XML data **************** -"Options for res: -"- Data object of type string or xstring -"- Data object declared inline (e.g. DATA(a) or FINAL(b)), which has then the type xstring -"- Standard table with flat character-like or byte-like line type -"- References for objects in iXML and sXML (e.g. sXML writers) -CALL TRANSFORMATION ... SOURCE ... - RESULT XML res. - -"**************** Transforming to ABAP data **************** -"No XML specified after RESULT -"Similar to above, multiple ABAP data objects can be specified as a static parameter list. -CALL TRANSFORMATION ... SOURCE ... - RESULT y1 = abap1 ... - -"An internal table of type abap_trans_resbind_tab can be specified. -DATA(restab) = VALUE abap_trans_resbind_tab( ( name = 'A' value = REF #( b ) ) ( ... ) ). -CALL TRANSFORMATION ... SOURCE ... - RESULT (restab). -``` - -> **💡 Note**
-> More additions are available such as `PARAMETERS` (for parameter binding) and `OPTIONS` (for predefined transformation options). See the details in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm). - -

⬆️ back to top

- -## Dealing with JSON -- You can .. - - create and read JSON data in ABAP using the readers and writers in the sXML ibrary. See the processing of XML data in the sXML section above. Parsing and rendering JSON data works in a similar way. However, instead of using XML readers/writers, you use JSON readers/writers. - - transform ABAP to and from JSON data using transformations. You can directly transform ABAP <-> JSON using identity transformation (ID). In this context, note the intermediate format asJSON (see the notes on asXML above). - - create and handle JSON data using the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). - -The following code snippets show a selection of transformation options using the predefined identity transformation. Here, a JSON writer is specified as the target. - -```abap -"ABAP (elementary type) -> JSON -DATA str_a TYPE string VALUE `Hello`. -"Creating a JSON writer (see the type specification; you can also specify other -"types, e.g. if_sxml=>co_xt_xml10 for an XML writer) -DATA(writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). - -CALL TRANSFORMATION id SOURCE hi = str_a - RESULT XML writer. - -"Getting the output and converting to string -DATA(json) = cl_abap_conv_codepage=>create_in( )->convert( writer->get_output( ) ). -"json: {"HI":"Hello"} - -"JSON -> ABAP -DATA str_b TYPE string. -"Note: CALL TRANSFORMATION handles JSON sources implicitly. -CALL TRANSFORMATION id SOURCE XML json - RESULT hi = str_b. -"str_b: Hello - -"ABAP -> formatted JSON -"In this example, an internal table is transformed to JSON. -"A cast is included for the writer (if_sxml_writer) to access special methods. -"See comments in the sXML section. -DATA(str_table) = value string_table( ( `abc` ) ( `def` ) ( `ghi` ) ). -DATA(json_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). -DATA(json_wr_cast) = CAST if_sxml_writer( json_wr ). - -"With the following method calls, the result is formatted. -json_wr_cast->set_option( option = if_sxml_writer=>co_opt_linebreaks ). -json_wr_cast->set_option( option = if_sxml_writer=>co_opt_indent ). - -CALL TRANSFORMATION id SOURCE itab = str_table - RESULT XML json_wr. - -DATA(json_formatted) = cl_abap_conv_codepage=>create_in( )->convert( json_wr->get_output( ) ). - -*json_formatted: -*{ -* "ITAB": -* [ -* "abc", -* "def", -* "ghi" -* ] -*} -``` - -The following snippets demonstrate creating and handling JSON data using the XCO library. - -```abap -"Creating and populating a demo structure and internal table -DATA: BEGIN OF carrier_struc, - carrier_id TYPE c length 3, - connection_id TYPE n length 4, - city_from TYPE c length 20, - city_to TYPE c length 20, - END OF carrier_struc. - -DATA carriers_tab LIKE TABLE OF carrier_struc WITH EMPTY KEY. - -carrier_struc = VALUE #( carrier_id = 'AA' connection_id = '17' city_from = 'New York' city_to = 'San Francisco' ). -carriers_tab = VALUE #( ( carrier_id = 'AZ' connection_id = '788' city_from = 'Rome' city_to = 'Tokyo' ) - ( carrier_id = 'JL' connection_id = '408' city_from = 'Frankfurt' city_to = 'Tokyo' ) ). - -"ABAP (structure) -> JSON using XCO -DATA(struc2json_xco) = xco_cp_json=>data->from_abap( carrier_struc )->to_string( ). -"Result: {"CARRIER_ID":"AA","CONNECTION_ID":"0017","CITY_FROM":"New York","CITY_TO":"San Francisco"} - -"ABAP (internal table) -> JSON using XCO -DATA(itab2json_xco) = xco_cp_json=>data->from_abap( carriers_tab )->to_string( ). -"Result: [{"CARRIER_ID":"AZ","CONNECTION_ID":"0788","CITY_FROM":"Rome","CITY_TO":"Tokyo"}, -" {"CARRIER_ID":"JL","CONNECTION_ID":"0408","CITY_FROM":"Frankfurt","CITY_TO":"Tokyo"}] - -"JSON -> ABAP (structure) using XCO -DATA json2struc_xco LIKE carrier_struc. -xco_cp_json=>data->from_string( struc2json_xco )->write_to( REF #( json2struc_xco ) ). -"Result: -"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO -"AA 0017 New York San Francisco - -"JSON -> ABAP (internal table) using XCO -DATA json2itab_xco LIKE carriers_tab. -xco_cp_json=>data->from_string( itab2json_xco )->write_to( REF #( json2itab_xco ) ). -"Result: -"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO -"AZ 0788 Rome Tokyo -"JL 0408 Frankfurt Tokyo - -"Creating JSON using XCO -"You can check out more methods that offer various options to build -"the JSON by clicking CTRL + Space after '->' in ADT. -"In the following example, JSON data similar to above is created. -"First, a JSON data builder is created. Then, using different methods, -"JSON data is created. -DATA(json_builder_xco) = xco_cp_json=>data->builder( ). -json_builder_xco->begin_object( - )->add_member( 'CarrierId' )->add_string( 'DL' - )->add_member( 'ConnectionId' )->add_string( '1984' - )->add_member( 'CityFrom' )->add_string( 'San Francisco' - )->add_member( 'CityTo' )->add_string( 'New York' - )->end_object( ). - -"Getting JSON data -DATA(json_created_xco) = json_builder_xco->get_data( )->to_string( ). -"Result: {"CarrierId":"DL","ConnectionId":"1984","CityFrom":"San Francisco","CityTo":"New York"} - -"Transforming the created JSON to ABAP (structure) -"Note: The JSON was intentionally created without the underscores in the -"name to demonstrate the 'apply' method. The following example demonstrates -"a transformation of camel case and underscore notation. As above, check out -"more options by clicking CTRL + Space after '...transformation->'. -CLEAR json2struc_xco. -xco_cp_json=>data->from_string( json_created_xco )->apply( VALUE #( - ( xco_cp_json=>transformation->pascal_case_to_underscore ) ) )->write_to( REF #( json2struc_xco ) ). -"Result -"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO -"DL 1984 San Francisco New York -``` - -

⬆️ back to top

- -## Excursions -### Converting string <-> xstring -In the code snippets above and in the executable example, many operations are performed using binary data. -This excursion shows the conversion of string <-> xstring using a codepage. The examples use UTF-8. -For example, you can use the `cl_abap_conv_codepage` class and the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). - -```abap -DATA(xml_string) = `ABAP`. - -"string -> xstring -"Note: UTF-8 is used by default. Here, it is specified explicitly. -"Exception class that can be used: cx_sy_conversion_codepage -TRY. - DATA(conv_xstring) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( xml_string ). - CATCH cx_sy_conversion_codepage. -ENDTRY. -"conv_xstring: 3C5458543E414241503C2F5458543E - -"xstring -> string -DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( conv_xstring ). -"conv_string: ABAP - -"As an alternative, you can use methods of the XCO library. More methods are available -"in this context. Check the options when choosing CTRL + Space after '->' -"string -> xstring -DATA(conv_xstring_xco) = xco_cp=>string( xml_string - )->as_xstring( xco_cp_character=>code_page->utf_8 - )->value. - -"xstring -> string -DATA(conv_string_xco) = xco_cp=>xstring( conv_xstring_xco - )->as_string( xco_cp_character=>code_page->utf_8 - )->value. -``` - -

⬆️ back to top

- -### Compressing and Decompressing Binary Data -You may want to process or store binary data. The data may be very large. You can compress the data in gzip format and decompress it for further processing using the `cl_abap_gzip` class. - -```abap -DATA(str) = `This is a data object of type string. It should be converted to xstring, compressed and decompressed.`. -DATA(xstr) = cl_abap_conv_codepage=>create_out( )->convert( str ). -DATA xstr_comp TYPE xstring. - -"Compressing binary data -TRY. - cl_abap_gzip=>compress_binary( EXPORTING raw_in = xstr - IMPORTING gzip_out = xstr_comp ). - CATCH cx_parameter_invalid_range cx_sy_buffer_overflow cx_sy_compression_error. -ENDTRY. - -"Comparing the length of the data objects -DATA(len_xstr) = xstrlen( xstr ). "101 -DATA(len_xstr_comp) = xstrlen( xstr_comp ). "81 - -"Decompressing binary data -DATA xstr_decomp TYPE xstring. -TRY. - cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = xstr_comp - IMPORTING raw_out = xstr_decomp ). - CATCH cx_parameter_invalid_range cx_sy_buffer_overflow cx_sy_compression_error. -ENDTRY. - -DATA(len_xstr_decomp) = xstrlen( xstr_decomp ). "101 -DATA(conv_str) = cl_abap_conv_codepage=>create_in( )->convert( xstr_decomp ). - -DATA(is_equal) = COND #( WHEN len_xstr = len_xstr_decomp - AND str = conv_str - THEN 'X' - ELSE '' ). "Result: X -``` - -## 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) -- [sXML](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sxml_lib.htm) -- [XSLT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_xslt.htm) -- [SAP XSLT Processor Reference](https://help.sap.com/docs/ABAP_PLATFORM_NEW/31bfc625c2674acdb9aa7547b62db9cc/3cb7463c32a3fe13e10000000a114084.html) -- [ST](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_st.htm) - - [ST Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenst_abexas.htm) -- [asXML](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_xslt_asxml.htm) -- [asJSON](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_asjson.htm) - - [JSON Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_json_abexas.htm) -- [`CALL TRANSFORMATION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) - - [`CALL TRANSFORMATION` Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencall_transformation_abexas.htm) - -

⬆️ back to top

- -## Executable Example -[zcl_demo_abap_xml_json](./src/zcl_demo_abap_xml_json.clas.abap) - -> **💡 Note**
-> - The executable example ... -> - covers the following topics: -> - Creating/Parsing XML Data Using iXML -> - Creating/Parsing XML Data Using sXML -> - XML Transformations using XSLT and Simple Transformations -> - Serializations (ABAP -> XML) and Deserialization (XML -> ABAP) using the identity transformation ID (elementary types, structures, internal tables, data and object references) -> - `CALL TRANSFORMATION` syntax options, sources and targets of transformations -> - Dealing with JSON data, XCO classes for JSON -> - Excursions: Converting string <-> xstring, compressing and decompressing binary data -> - uses, apart from the predefined identity transformation (ID), demo XSLT and ST programs. They are not intended to be role models for proper XSLT/ST design. -> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). + + +# Working with XML and JSON in ABAP + +- [Working with XML and JSON in ABAP](#working-with-xml-and-json-in-abap) + - [Introduction](#introduction) + - [Processing XML Using Class Libraries](#processing-xml-using-class-libraries) + - [iXML](#ixml) + - [sXML](#sxml) + - [XML Transformations](#xml-transformations) + - [CALL TRANSFORMATION Syntax](#call-transformation-syntax) + - [Dealing with JSON](#dealing-with-json) + - [Excursions](#excursions) + - [Converting string \<-\> xstring](#converting-string---xstring) + - [Compressing and Decompressing Binary Data](#compressing-and-decompressing-binary-data) + - [More Information](#more-information) + - [Executable Example](#executable-example) + +## Introduction + +This cheat sheet provides a high-level overview of working with XML and JSON in ABAP. It covers the following topics: +- Processing XML using class libraries (iXML, sXML) +- XML Transformations using XSLT and Simple Transformations (ST), i.e. serializations (ABAP to XML) and deserializations (XML to ABAP) +- `CALL TRANSFORMATION` syntax +- Dealing with JSON data + +> **💡 Note**
+> - The cheat sheet snippets and the executable example cover simple cases. Find more executable examples of the ABAP Keyword Documentation following the links in the [More Information](#more-information) section. +> - For more detailed information, such as documentation on ST syntax, what asXML is, etc., also see the links in the [More Information](#more-information) section. +> - In addition to the options covered in the cheat sheet, there are other ways to work with XML/JSON (for example, the `/ui2/cl_json` class). + +

⬆️ back to top

+ +## Processing XML Using Class Libraries + +### iXML +- *Integrated* XML Library +- Provides methods for ... + - validating and parsing (i.e. reading) XML data in 1.0 format into a DOM representation (Document Object Model, which is a tree-like representation of the documents in the memory) + - processing the DOM representation (you can create or edit XML data) + - rendering (i.e. writing) the DOM representation +- To access XML data, you need input and output streams that are created using iXML methods. +- Advantages: Easy access to the individual parts of an XML document possible, DTDs (Document Type Definitions) are possible +- Disadvantages: High memory consumption of the DOM (if the complete DOM is created) + +The following code snippets demonstrate a selection of iXML methods for handling XML data. Note that the snippets use classes available for [ABAP for Cloud Development](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_for_cloud_dev_glosry.htm). Find documentation on the classes for [classic ABAP](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenclassic_abap_glosry.htm) [here (F1 documentation for Standard ABAP)](https://help.sap.com/doc/abapdocu_latest_index_htm/latest/en-US/index.htm?file=abenabap_ixml_lib.htm). + +Creating XML data using iXML: + +```abap +"Creating one factory object of the access class cl_ixml_core using the +"create method. It is used to access the iXML library. +DATA(ixml_cr) = cl_ixml_core=>create( ). + +"Creating an XML document stored in DOM format in the memory +DATA(document_cr) = ixml_cr->create_document( ). + +"Creating DOM nodes step by step. Here, elements, attributes, and content are +"and inserted into the XML. Using an appropriate attribute setting, the result +"represents XML data in the asXML format (see more information further down). + +"Creating a root node +DATA(root) = document_cr->create_element_ns( name = 'abap' + prefix = 'asx' ). +root->set_attribute_ns( name = 'asx' + prefix = 'xmlns' + value = 'http://www.sap.com/abapxml' ). +root->set_attribute_ns( name = 'version' + value = '1.0' ). +document_cr->append_child( root ). + +DATA(xml_node1) = document_cr->create_element_ns( prefix = 'asx' + name = 'values' ). +root->append_child( xml_node1 ). +DATA(xml_node2) = document_cr->create_element_ns( name = 'STRING' ). +xml_node1->append_child( xml_node2 ). +xml_node2->append_child( document_cr->create_text( 'Hello World' ) ). + +"Creating a renderer for rendering the XML document into an output stream +"that is used to pass XML data from the renderer. +DATA xml_doc TYPE xstring. +ixml_cr->create_renderer( document = document_cr + ostream = ixml_cr->create_stream_factory( )->create_ostream_xstring( string = xml_doc ) + )->render( ). + +"Result (xstring converted to string): +" +"Hello World +``` + +Parsing XML data using iXML: + +```abap +"Creating demo XML data to be used in the example as string. Using the cl_abap_conv_codepage +"class, you can convert the string to xstring which is required for the example. +DATA(some_xml) = cl_abap_conv_codepage=>create_out( )->convert( + `` && + ` hallo` && + ` how` && + ` are` && + `` ). + +"Creating one factory object of the access class cl_ixml_core using the +"create method. It is used to access the iXML library. +DATA(ixml_pa) = cl_ixml_core=>create( ). +"Creaing an input stream that is used for the input of XML data +DATA(stream_factory_pa) = ixml_pa->create_stream_factory( ). +"Creating an XML document stored in DOM format in the memory +DATA(document_pa) = ixml_pa->create_document( ). +"Creating a parser. It requires the following input parameters: input stream to be parsed, +"the XML document to which the stream is parsed, a factory required to create a stream +DATA(parser_pa) = ixml_pa->create_parser( + istream = stream_factory_pa->create_istream_xstring( string = some_xml ) + document = document_pa + stream_factory = stream_factory_pa ). + +"Parsing XML data to a DOM representation in one go. It is put in the memory. +"Note: You can also parse sequentially, and not in one go. +DATA(parsing_check) = parser_pa->parse( ). +IF parsing_check = 0. "Parsing was successful + + "--------------------- Directly reading nodes ---------------------- + + "Accessing the root element of the DOM. It can be used as the initial node + "for accessing subnodes. + "Note: Multiple methods are available to further process the nodes. + DATA(root_element) = document_pa->get_root_element( ). + "First subnode + DATA(child_element) = root_element->get_first_child( ). + "Gettng the value of that node + DATA(child_element_value) = child_element->get_value( ). "hallo + "Next adjacent node/getting the value + DATA(next_element_value) = child_element->get_next( )->get_value( ). "how + "Direct access using element names + "Result: First element searched for + DATA(element_by_name) = document_pa->find_from_name( name = `word3` )->get_value( ). "are + + "--------------------- Reading using iterators ---------------------- + + "i.e. going over the XML nodes one after another + + "Creating an iterator + DATA(iterator_pa) = document_pa->create_iterator( ). + DO. + "For the iteration, you can use the get_next method to process the nodes one after another. + "Note: Here, all nodes are respected. You can also create filters to go over specific nodes. + DATA(node_i) = iterator_pa->get_next( ). + IF node_i IS INITIAL. + "Exiting the loop when there are no more nodes to process. + EXIT. + ELSE. + ... "Do something, e.g. modify values + ENDIF. + ENDDO. + + "Creating a renderer. It renders the XML document into an output stream + "that is used to pass XML data from the renderer. + DATA xml_pa TYPE xstring. + ixml_pa->create_renderer( document = document_pa + ostream = ixml_pa->create_stream_factory( )->create_ostream_xstring( string = xml_pa ) + )->render( ). + ... +ELSE. + "Parsing was not successful. + ... +ENDIF. +``` + +

⬆️ back to top

+ +### sXML +- *Serial* XML Library +- Provides XML readers and writers for different sources and targets +- Processes XML data sequentially +- Allows you to parse and render XML data in a token-based (iterating across all nodes, i.e. tokens, in the tree structure of the XML data) and object-oriented way (wrapping methods of the token-based access; providing an object-oriented way to access XML nodes) +- Unlike iXML, ... + - more formats are possible (standard XML 1.0, but also XOP, binary XML, and JSON). + - no document is created in DOM format (if you do not need a DOM representation and DTDs, sXML is a more performant alternative to iXML). + +Creating XML data using sXML: + +```abap +"--------------------- Token-based rendering ---------------------- + +"For sXML, there are specialized writer classes, such as CL_SXML_STRING_WRITE. +"Writers created with this class render XML data to a byte string. +"The XML 1.0 format and UTF-8 are used by default in the create method. +"Here, the parameters are specified explicitly. +"Note: The interface IF_SXML_WRITER contains the components that are valid +"for all readers (the abstract super class CL_SXML_WRITER includes this +"interface as well as implementations for all readers). In the example below, +"a cast is required so as to access special methods (such as open_element). + +DATA(writer) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 + encoding = 'UTF-8' ) ). + +"Creating/Rendering XML data using token-based rendering +"The example shows shows how XML data can be created using various available methods. +"Here, token-based rendering is used, i.e. each node is added to the XML data using +"a method. There is a method for each node type. +TRY. + "Creating nodes (the order of the nodes is crucial) + writer->open_element( name = 'flights' ). + writer->open_element( name = 'flight' ). + writer->open_element( name = 'carrier' ). + writer->write_value( 'LH' ). + writer->close_element( ). + writer->open_element( name = 'flightnumber' ). + writer->write_value( '400' ). + writer->close_element( ). + writer->close_element( ). + writer->open_element( name = 'flight' ). + writer->open_element( name = 'carrier' ). + writer->write_value( 'DL' ). + writer->close_element( ). + writer->open_element( name = 'flightnumber' ). + writer->write_value( '1984' ). + writer->close_element( ). + writer->close_element( ). + writer->close_element( ). + CATCH cx_sxml_state_error. + ... +ENDTRY. + +"The XML data can be retrieved with the GET_OUTPUT method. +"Also here, a cast is required. +"The result is of type xstring. +DATA(xml) = CAST cl_sxml_string_writer( writer )->get_output( ). + +"The result looks like this (when converted to string and indented): +" +" +" +" LH +" 400 +" +" +" DL +" 1984 +" +" + +"--------------------- Object-oriented rendering ---------------------- + +DATA(writer_oo) = CAST if_sxml_writer( cl_sxml_string_writer=>create( type = if_sxml=>co_xt_xml10 + encoding = 'UTF-8' ) ). + +TRY. + writer_oo->write_node( writer_oo->new_open_element( name = 'flights' ) ). + + writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). + DATA(val) = writer_oo->new_value( ). + val->set_value( 'AZ' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). + val = writer_oo->new_value( ). + val->set_value( '788' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + + writer_oo->write_node( writer_oo->new_open_element( name = 'flight' ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'carrier' ) ). + val = writer_oo->new_value( ). + val->set_value( 'JL' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_open_element( name = 'flightnumber' ) ). + val = writer_oo->new_value( ). + val->set_value( '407' ). + writer_oo->write_node( val ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + writer_oo->write_node( writer_oo->new_close_element( ) ). + + writer_oo->write_node( writer_oo->new_close_element( ) ). + CATCH cx_sxml_state_error. + ... +ENDTRY. + +DATA(xml_oo) = CAST cl_sxml_string_writer( writer_oo )->get_output( ). + +"The result looks like this (when converted to string and indented): +" +" +" AZ +" 788 +" +" +" JL +" 407 +" +" +``` + +Parsing XML data using sXML: + +```abap +"--------------------- Token-based parsing ---------------------- + +"Creating reader +"Note: See the comments for the writer above. It is similar here. For readers, +"the interface IF_SXML_READER exists. In this example, no special methods +"are used. Therefore, a cast is not carried out. +"The example uses the XML data from above. +DATA(reader) = cl_sxml_string_reader=>create( xml_oo ). +"DATA(reader_cast) = CAST if_sxml_reader( cl_sxml_string_reader=>create( xml_oo ) ). + +"To iterate accros all nodes, you can call the NEXT_NODE method. +TRY. + DO. + "Check out other available methods in ADT by placing the cursor behind '...->' + "and choose CTRL + Space. + reader->next_node( ). + + "Exiting the loop when reaching the end of the XML data. + IF reader->node_type = if_sxml_node=>co_nt_final. + EXIT. + ENDIF. + + "You can access the properties of the node directly. + DATA(node_type) = reader->node_type. "Node type, see the interface if_sxml_node + DATA(prefix) = reader->prefix. "Namespace prefix + DATA(name) = reader->name. "Name of the element + DATA(value_type) = reader->value_type. "Value type, see the interface if_sxml_value + DATA(value) = reader->value. "Character-like value (if it is textual data) + DATA(value_raw) = reader->value_raw. "Byte-like value (if it is raw data) + + ... + + ENDDO. + CATCH cx_sxml_parse_error. + ... +ENDTRY. + +"--------------------- Object-oriented parsing ---------------------- + +"Creating demo XML data to be used in the example. +DATA(xml_oo_read) = cl_abap_conv_codepage=>create_out( )->convert( + `` && + `` && + ` ` && + ` A` && + ` 01-01-2024` && + ` ` && + ` ` && + ` abc` && + ` def` && + ` ghi` && + ` ` && + `` ). + +"Creating reader +DATA(reader_oo) = cl_sxml_string_reader=>create( xml_oo_read ). +TRY. + DO. + "To iterate accros all nodes, you can call the READ_NEXT_NODE method. + "When the end of the XML data is reached, the returned value is initial. + DATA(node_oo) = reader_oo->read_next_node( ). + IF node_oo IS INITIAL. + EXIT. + ENDIF. + + "In object-oriented parsing, methods for token-based parsing are wrapped. + "An object-oriented access to the node is provided. + "References to objects that represent the current node are returned. + + "Getting the node type + DATA(n_type) = node_oo->type. + + "When the parser is currently on the node of an element opening, + "the node object has the class CL_SXML_OPEN_ELEMENT that implements the + "interface IF_SXML_OPEN_ELEMENT. With the methods included, you can + "access the XML attributes of the element, e.g. using the GET_ATTRIBUTES + "method to put the references for all attributes into an internal table. + "To access the attributes, a downcast is required. + IF n_type = if_sxml_node=>co_nt_element_open. + DATA(attributes) = CAST if_sxml_open_element( node_oo )->get_attributes( ). + ... + ENDIF. + ... + ENDDO. + CATCH cx_sxml_parse_error. + ... +ENDTRY. +``` + +

⬆️ back to top

+ +## XML Transformations + +To perform transformations in ABAP, you can use: + +- XSL Transformations (XSLT) + - Repository objects written in XSLT + - XSLT can process ABAP data because ABAP data is first implicitly transformed into the asXML format. The result of this implicit transformation (the asXML format) is then used as the actual source for the XSL transformation. +- Identity transformations + - SAP-delivered and predefined XSL transformation with the name `ID` + - Used to read and write the asXML (and also asJSON) format. + - When the transformation ID is called, the resulting intermediate formats (asXML, asJSON) are the direct output. + - When used, for example, to transform ABAP data, such as a structure, to XML, the transformation does not change the structure itself. You can, however, change the structure by implementing your own XSLT. +- Simple Transformation (ST) + - Repository objects written in an SAP-specific programming language for transformations between XML formats and ABAP data + +The tranformations are called using `CALL TRANSFORMATION` statements. + +Possible transformations, some of which are covered in the example: + +| Transformation | XSLT | ST | +|---|---|---| +| XML <-> XML | X | - | +| ABAP <-> XML | X | X | +| ABAP <-> ABAP | X | - | + +> **💡 Note**
+> asXML: +> - *ABAP Serialization XML* +> - Describes a format of XML data created when serializing ABAP data (ABAP -> XML) with the identity transformation +> - This format is a prerequisite for deserializations (XML -> ABAP) using identity transformations. +> - Used as an intermediate format that defines a mapping between ABAP data and XML +> - Therefore, if you want to deserialize XML data in ABAP, you must first transform it to the asXML format. +> Make sure that you use appropriate exception classes for potential errors in transformations. See the section [Catchable Exceptions](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) in the `CALL TRANSFORMATION` topic. + +

⬆️ back to top

+ +## CALL TRANSFORMATION Syntax + +The following code snippets demonstrate a selection of possible syntax options when using [`CALL TRANSFORMATION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) statements. + +**Specifying transformations** + +```abap +"Specifying the name of an XSL or Simple Transformation statically +CALL TRANSFORMATION zsome_transformation SOURCE ... + RESULT ... + +"Specifying the identity transformation with the predefined name ID +CALL TRANSFORMATION id SOURCE ... + RESULT ... + +"Dynamic specifiation of the transformation +"If the transformation does not exist, an exception is raised. +TRY. + CALL TRANSFORMATION ('ID') SOURCE ... + RESULT ... +CATCH cx_invalid_transformation. + ... +ENDTRY. +``` + +**Specifying the source of the transformation** + +There are multiple options. Check the executable example to explore them. + +```abap +"--------------------- Transforming XML data ---------------------- +"Options for src: +"- Data object of type string or xstring containing XML data in XML 1.0 format +"- Standard table with flat character-like or byte-like line type +"- Some references to iXML and sXML libraries are possible. For example, an +" interface reference variable of type if_sxml_reader. +CALL TRANSFORMATION ... SOURCE XML src + RESULT ... + +"--------------------- Transforming ABAP data ---------------------- +"No XML specified after SOURCE +"Options for src: +"- One or multiple ABAP data objects (abap1 in the snippet) can be specified as +" static parameter list, e.g. z1 = abap1 z2 = abap2 ... +"- When XSLT is used (such as ID), the data is serialized to asXML depending on +" the target +"- z1 etc. stands for names of XML elements +CALL TRANSFORMATION ... SOURCE z1 = abap1 ... + RESULT ... + +"Dynamic specification of ABAP data objects in an internal table of type +"abap_trans_srcbind_tab +DATA(srctab) = VALUE abap_trans_srcbind_tab( ( name = 'A' value = REF #( b ) ) ( ... ) ). +CALL TRANSFORMATION ... SOURCE (srctab) + RESULT ... +``` + +**Specifying the result of the transformation** + +There are multiple options. Check the executable example to see them in action. + +```abap +"--------------------- Transforming to XML data ---------------------- +"Options for res: +"- Data object of type string or xstring +"- Data object declared inline (e.g. DATA(a) or FINAL(b)), which has then the type xstring +"- Standard table with flat character-like or byte-like line type +"- References for objects in iXML and sXML (e.g. sXML writers) +CALL TRANSFORMATION ... SOURCE ... + RESULT XML res. + +"--------------------- Transforming to ABAP data ---------------------- +"No XML specified after RESULT +"Similar to above, multiple ABAP data objects can be specified as a static parameter list. +CALL TRANSFORMATION ... SOURCE ... + RESULT y1 = abap1 ... + +"An internal table of type abap_trans_resbind_tab can be specified. +DATA(restab) = VALUE abap_trans_resbind_tab( ( name = 'A' value = REF #( b ) ) ( ... ) ). +CALL TRANSFORMATION ... SOURCE ... + RESULT (restab). +``` + +> **💡 Note**
+> More additions are available such as `PARAMETERS` (for parameter binding) and `OPTIONS` (for predefined transformation options). See the details in the [ABAP Keyword Documentation](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm). + +

⬆️ back to top

+ +## Dealing with JSON +- You can .. + - create and read JSON data in ABAP using the readers and writers in the sXML ibrary. See the processing of XML data in the sXML section above. Parsing and rendering JSON data works in a similar way. However, instead of using XML readers/writers, you use JSON readers/writers. + - transform ABAP to and from JSON data using transformations. You can directly transform ABAP <-> JSON using identity transformation (ID). In this context, note the intermediate format asJSON (see the notes on asXML above). + - create and handle JSON data using the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). + +The following code snippets show a selection of transformation options using the predefined identity transformation. Here, a JSON writer is specified as the target. + +```abap +"ABAP (elementary type) -> JSON +DATA str_a TYPE string VALUE `Hello`. +"Creating a JSON writer (see the type specification; you can also specify other +"types, e.g. if_sxml=>co_xt_xml10 for an XML writer) +DATA(writer) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). + +CALL TRANSFORMATION id SOURCE hi = str_a + RESULT XML writer. + +"Getting the output and converting to string +DATA(json) = cl_abap_conv_codepage=>create_in( )->convert( writer->get_output( ) ). +"json: {"HI":"Hello"} + +"JSON -> ABAP +DATA str_b TYPE string. +"Note: CALL TRANSFORMATION handles JSON sources implicitly. +CALL TRANSFORMATION id SOURCE XML json + RESULT hi = str_b. +"str_b: Hello + +"ABAP -> formatted JSON +"In this example, an internal table is transformed to JSON. +"A cast is included for the writer (if_sxml_writer) to access special methods. +"See comments in the sXML section. +DATA(str_table) = value string_table( ( `abc` ) ( `def` ) ( `ghi` ) ). +DATA(json_wr) = cl_sxml_string_writer=>create( type = if_sxml=>co_xt_json ). +DATA(json_wr_cast) = CAST if_sxml_writer( json_wr ). + +"With the following method calls, the result is formatted. +json_wr_cast->set_option( option = if_sxml_writer=>co_opt_linebreaks ). +json_wr_cast->set_option( option = if_sxml_writer=>co_opt_indent ). + +CALL TRANSFORMATION id SOURCE itab = str_table + RESULT XML json_wr. + +DATA(json_formatted) = cl_abap_conv_codepage=>create_in( )->convert( json_wr->get_output( ) ). + +*json_formatted: +*{ +* "ITAB": +* [ +* "abc", +* "def", +* "ghi" +* ] +*} +``` + +The following snippets demonstrate creating and handling JSON data using the XCO library. + +```abap +"Creating and populating a demo structure and internal table +DATA: BEGIN OF carrier_struc, + carrier_id TYPE c length 3, + connection_id TYPE n length 4, + city_from TYPE c length 20, + city_to TYPE c length 20, + END OF carrier_struc. + +DATA carriers_tab LIKE TABLE OF carrier_struc WITH EMPTY KEY. + +carrier_struc = VALUE #( carrier_id = 'AA' connection_id = '17' city_from = 'New York' city_to = 'San Francisco' ). +carriers_tab = VALUE #( ( carrier_id = 'AZ' connection_id = '788' city_from = 'Rome' city_to = 'Tokyo' ) + ( carrier_id = 'JL' connection_id = '408' city_from = 'Frankfurt' city_to = 'Tokyo' ) ). + +"ABAP (structure) -> JSON using XCO +DATA(struc2json_xco) = xco_cp_json=>data->from_abap( carrier_struc )->to_string( ). +"Result: {"CARRIER_ID":"AA","CONNECTION_ID":"0017","CITY_FROM":"New York","CITY_TO":"San Francisco"} + +"ABAP (internal table) -> JSON using XCO +DATA(itab2json_xco) = xco_cp_json=>data->from_abap( carriers_tab )->to_string( ). +"Result: [{"CARRIER_ID":"AZ","CONNECTION_ID":"0788","CITY_FROM":"Rome","CITY_TO":"Tokyo"}, +" {"CARRIER_ID":"JL","CONNECTION_ID":"0408","CITY_FROM":"Frankfurt","CITY_TO":"Tokyo"}] + +"JSON -> ABAP (structure) using XCO +DATA json2struc_xco LIKE carrier_struc. +xco_cp_json=>data->from_string( struc2json_xco )->write_to( REF #( json2struc_xco ) ). +"Result: +"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO +"AA 0017 New York San Francisco + +"JSON -> ABAP (internal table) using XCO +DATA json2itab_xco LIKE carriers_tab. +xco_cp_json=>data->from_string( itab2json_xco )->write_to( REF #( json2itab_xco ) ). +"Result: +"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO +"AZ 0788 Rome Tokyo +"JL 0408 Frankfurt Tokyo + +"Creating JSON using XCO +"You can check out more methods that offer various options to build +"the JSON by clicking CTRL + Space after '->' in ADT. +"In the following example, JSON data similar to above is created. +"First, a JSON data builder is created. Then, using different methods, +"JSON data is created. +DATA(json_builder_xco) = xco_cp_json=>data->builder( ). +json_builder_xco->begin_object( + )->add_member( 'CarrierId' )->add_string( 'DL' + )->add_member( 'ConnectionId' )->add_string( '1984' + )->add_member( 'CityFrom' )->add_string( 'San Francisco' + )->add_member( 'CityTo' )->add_string( 'New York' + )->end_object( ). + +"Getting JSON data +DATA(json_created_xco) = json_builder_xco->get_data( )->to_string( ). +"Result: {"CarrierId":"DL","ConnectionId":"1984","CityFrom":"San Francisco","CityTo":"New York"} + +"Transforming the created JSON to ABAP (structure) +"Note: The JSON was intentionally created without the underscores in the +"name to demonstrate the 'apply' method. The following example demonstrates +"a transformation of camel case and underscore notation. As above, check out +"more options by clicking CTRL + Space after '...transformation->'. +CLEAR json2struc_xco. +xco_cp_json=>data->from_string( json_created_xco )->apply( VALUE #( + ( xco_cp_json=>transformation->pascal_case_to_underscore ) ) )->write_to( REF #( json2struc_xco ) ). +"Result +"CARRIER_ID CONNECTION_ID CITY_FROM CITY_TO +"DL 1984 San Francisco New York +``` + +

⬆️ back to top

+ +## Excursions +### Converting string <-> xstring +In the code snippets above and in the executable example, many operations are performed using binary data. +This excursion shows the conversion of string <-> xstring using a codepage. The examples use UTF-8. +For example, you can use the `cl_abap_conv_codepage` class and the [XCO library](https://help.sap.com/docs/btp/sap-business-technology-platform/xco-library?version=Cloud). + +```abap +DATA(xml_string) = `ABAP`. + +"string -> xstring +"Note: UTF-8 is used by default. Here, it is specified explicitly. +"Exception class that can be used: cx_sy_conversion_codepage +TRY. + DATA(conv_xstring) = cl_abap_conv_codepage=>create_out( codepage = `UTF-8` )->convert( xml_string ). + CATCH cx_sy_conversion_codepage. +ENDTRY. +"conv_xstring: 3C5458543E414241503C2F5458543E + +"xstring -> string +DATA(conv_string) = cl_abap_conv_codepage=>create_in( )->convert( conv_xstring ). +"conv_string: ABAP + +"As an alternative, you can use methods of the XCO library. More methods are available +"in this context. Check the options when choosing CTRL + Space after '->' +"string -> xstring +DATA(conv_xstring_xco) = xco_cp=>string( xml_string + )->as_xstring( xco_cp_character=>code_page->utf_8 + )->value. + +"xstring -> string +DATA(conv_string_xco) = xco_cp=>xstring( conv_xstring_xco + )->as_string( xco_cp_character=>code_page->utf_8 + )->value. +``` + +

⬆️ back to top

+ +### Compressing and Decompressing Binary Data +You may want to process or store binary data. The data may be very large. You can compress the data in gzip format and decompress it for further processing using the `cl_abap_gzip` class. + +```abap +DATA(str) = `This is a data object of type string. It should be converted to xstring, compressed and decompressed.`. +DATA(xstr) = cl_abap_conv_codepage=>create_out( )->convert( str ). +DATA xstr_comp TYPE xstring. + +"Compressing binary data +TRY. + cl_abap_gzip=>compress_binary( EXPORTING raw_in = xstr + IMPORTING gzip_out = xstr_comp ). + CATCH cx_parameter_invalid_range cx_sy_buffer_overflow cx_sy_compression_error. +ENDTRY. + +"Comparing the length of the data objects +DATA(len_xstr) = xstrlen( xstr ). "101 +DATA(len_xstr_comp) = xstrlen( xstr_comp ). "81 + +"Decompressing binary data +DATA xstr_decomp TYPE xstring. +TRY. + cl_abap_gzip=>decompress_binary( EXPORTING gzip_in = xstr_comp + IMPORTING raw_out = xstr_decomp ). + CATCH cx_parameter_invalid_range cx_sy_buffer_overflow cx_sy_compression_error. +ENDTRY. + +DATA(len_xstr_decomp) = xstrlen( xstr_decomp ). "101 +DATA(conv_str) = cl_abap_conv_codepage=>create_in( )->convert( xstr_decomp ). + +DATA(is_equal) = COND #( WHEN len_xstr = len_xstr_decomp + AND str = conv_str + THEN 'X' + ELSE '' ). "Result: X +``` + +## 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) +- [sXML](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_sxml_lib.htm) +- [XSLT](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_xslt.htm) +- [SAP XSLT Processor Reference](https://help.sap.com/docs/ABAP_PLATFORM_NEW/31bfc625c2674acdb9aa7547b62db9cc/3cb7463c32a3fe13e10000000a114084.html) +- [ST](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_st.htm) + - [ST Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenst_abexas.htm) +- [asXML](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_xslt_asxml.htm) +- [asJSON](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_asjson.htm) + - [JSON Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenabap_json_abexas.htm) +- [`CALL TRANSFORMATION`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abapcall_transformation.htm) + - [`CALL TRANSFORMATION` Examples](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abencall_transformation_abexas.htm) + +

⬆️ back to top

+ +## Executable Example +[zcl_demo_abap_xml_json](./src/zcl_demo_abap_xml_json.clas.abap) + +> **💡 Note**
+> - The executable example ... +> - covers the following topics: +> - Creating/Parsing XML Data Using iXML +> - Creating/Parsing XML Data Using sXML +> - XML Transformations using XSLT and Simple Transformations +> - Serializations (ABAP -> XML) and Deserialization (XML -> ABAP) using the identity transformation ID (elementary types, structures, internal tables, data and object references) +> - `CALL TRANSFORMATION` syntax options, sources and targets of transformations +> - Dealing with JSON data, XCO classes for JSON +> - Excursions: Converting string <-> xstring, compressing and decompressing binary data +> - uses, apart from the predefined identity transformation (ID), demo XSLT and ST programs. They are not intended to be role models for proper XSLT/ST design. +> - The steps to import and run the code are outlined [here](README.md#-getting-started-with-the-examples). > - [Disclaimer](README.md#%EF%B8%8F-disclaimer) \ No newline at end of file