-r_column->set_visible( abap_true ).
+ ENDIF.
+ ENDLOOP.
+ alv->display( ).
+ CATCH cx_salv_msg cx_salv_not_found.
+ MESSAGE 'ALV display not possible' TYPE 'I'
+ DISPLAY LIKE 'E'.
+ ENDTRY.
+
+ ELSE.
+
+ SELECT id, context, name, details, timestamp
+ FROM zdemo_abap_logt
+ INTO CORRESPONDING FIELDS OF TABLE @log_entries
+ ORDER BY id.
+
+ TRY.
+ cl_salv_table=>factory( EXPORTING r_container = cont
+ container_name = CONV string( container )
+ IMPORTING r_salv_table = alv
+ CHANGING t_table = log_entries ).
+
+ columns = alv->get_columns( ).
+ col_tab = columns->get( ).
+ LOOP AT col_tab ASSIGNING FIELD-SYMBOL().
+ column = columns->get_column( -columnname ).
+ column->set_medium_text( CONV scrtext_m( -columnname ) ).
+
+ IF -columnname = `DETAILS`.
+ column->set_output_length( 70 ).
+ ENDIF.
+
+ IF -columnname = 'CLIENT'.
+ -r_column->set_visible( abap_false ).
+ ELSE.
+ -r_column->set_visible( abap_true ).
+ ENDIF.
+ ENDLOOP.
+ alv->display( ).
+ CATCH cx_salv_msg cx_salv_not_found.
+ MESSAGE 'ALV display not possible' TYPE 'I'
+ DISPLAY LIKE 'E'.
+ ENDTRY.
+ ENDIF.
+ ENDMETHOD.
+
+
+ METHOD checking_transaction_state.
+ tx_state = `Tx state: ` &&
+ `Update task (` && SWITCH #( cl_system_transaction_state=>get_in_update_task( ) WHEN 1 THEN `1)` ELSE `0)` ) &&
+ ` Local update (` && SWITCH #( cl_system_transaction_state=>get_update_task_local( ) WHEN 1 THEN `1)` ELSE `0)` ) &&
+ ` Perf. on commit (` && SWITCH #( cl_system_transaction_state=>get_on_commit( ) WHEN 1 THEN `1)` ELSE `0)` ) &&
+ ` Perf. on rollback (` && SWITCH #( cl_system_transaction_state=>get_on_rollback( ) WHEN 1 THEN `1)` ELSE `0)` ).
+ ENDMETHOD.
+
+
+ METHOD create_log_entries.
+ INSERT zdemo_abap_logt FROM TABLE @log.
+ ENDMETHOD.
+
+
+ METHOD get_work_process_info.
+ CALL FUNCTION 'TH_GET_OWN_WP_NO'
+ IMPORTING
+ wp_pid = wp_pid
+ wp_index = wp_index.
+
+ id_no = |Work process ID: { wp_pid } / work process index: { wp_index }|.
+ ENDMETHOD.
+
+
+ METHOD subr_delete.
+ DELETE FROM zdemo_abap_luw_t.
+ ENDMETHOD.
+
+
+ METHOD subr_insert.
+ INSERT zdemo_abap_luw_t FROM @values.
+ ENDMETHOD.
+
+
+ METHOD subr_update_log.
+ INSERT zdemo_abap_logt FROM TABLE @log.
+ ENDMETHOD.
+ENDCLASS.
diff --git a/src/test_abap_cheat_sheets_classic/zcl_demo_abap_sap_luw_helper.clas.xml b/src/test_abap_cheat_sheets_classic/zcl_demo_abap_sap_luw_helper.clas.xml
new file mode 100644
index 0000000..cad0596
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zcl_demo_abap_sap_luw_helper.clas.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ZCL_DEMO_ABAP_SAP_LUW_HELPER
+ E
+ Helper class for SAP LUW example
+ 1
+ X
+ X
+ X
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_dbluw.tabl.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_dbluw.tabl.xml
new file mode 100644
index 0000000..991a690
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_dbluw.tabl.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+ ZDEMO_ABAP_DBLUW
+ E
+ TRANSP
+ X
+ Demo database table
+ E
+ X
+ A
+ 1
+
+
+ ZDEMO_ABAP_DBLUW
+ A
+ 0
+ APPL0
+ N
+
+
+
+ CLIENT
+ X
+ 0
+ C
+ 000006
+ X
+ CLNT
+ 000003
+ CLNT
+
+
+ KEY_FIELD
+ X
+ 0
+ X
+ 000004
+ X
+ INT4
+ 000010
+ INT4
+
+
+ CH
+ 0
+ C
+ 000020
+ CHAR
+ 000010
+ CHAR
+
+
+ NUM
+ 0
+ X
+ 000004
+ INT4
+ 000010
+ INT4
+
+
+ TIME_STAMP
+ 0
+ p
+ 000008
+ UTCL
+ 000027
+ UTCL
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.abap
new file mode 100644
index 0000000..e7af612
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.abap
@@ -0,0 +1,826 @@
+*&---------------------------------------------------------------------*
+*& ABAP cheat sheet: Dynpro
+*&
+*&-------------------------- PURPOSE ----------------------------------*
+*& - Example to demonstrate dynpro-related statements
+*& - Topics covered: 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)
+*&
+*&----------------------- GETTING STARTED -----------------------------*
+*& - Open the program with the ABAP development tools for Eclipse (ADT).
+*& - Choose F8 to run the program.
+*& - Select the radio buttons and/or provide input in input fields etc.
+*& to check out dynpro-related syntax in action.
+*&
+*&----------------------------- NOTE -----------------------------------*
+*& The code presented in this class is intended only to support the ABAP
+*& cheat sheets. It is not intended for direct use in a production system
+*& environment. The code examples in the ABAP cheat sheets are primarily
+*& intended to provide a better explanation and visualization of the
+*& syntax and semantics of ABAP statements, not to solve concrete
+*& programming tasks. For production application programs, you should
+*& always work out your own solution for each individual case. There is
+*& no guarantee for the correctness or completeness of the code.
+*& Furthermore, there is no legal responsibility or liability for any
+*& errors or their consequences that may occur when using the the example
+*& code.
+*&---------------------------------------------------------------------*
+REPORT zdemo_abap_dynpro.
+
+DATA:
+ "OK field
+ ok_code LIKE sy-ucomm,
+ "Auxiliary variable for storing the value of the OK field
+ save_ok LIKE ok_code,
+ dyn_num LIKE sy-dynnr,
+ dyn_title LIKE sy-title.
+
+"Note: This demo database table does not have any semantic information
+"that may be used for input helps etc.
+TABLES zdemo_abap_flsch.
+
+"----- Related to dynpro 9850 (Home page) -----
+DATA: screen_elements TYPE abap_bool,
+ stmts TYPE abap_bool,
+ stmts2 TYPE abap_bool,
+ controls TYPE abap_bool.
+
+"----- Related to dynpro 9860 (Screen elements) -----
+
+DATA: "Icons
+ icon TYPE icons-text,
+ icon_name TYPE c LENGTH 20,
+ icon_text TYPE c LENGTH 10,
+ "check boxes
+ ch_a TYPE abap_bool,
+ ch_b TYPE abap_bool,
+ ch_c TYPE abap_bool,
+ checkbox_msg TYPE c LENGTH 4,
+ input_field TYPE c LENGTH 20,
+ "radio buttons
+ rb_x TYPE abap_bool,
+ rb_y TYPE abap_bool,
+ rb_z TYPE abap_bool,
+ radiobutton_msg TYPE c LENGTH 1.
+
+"----- Related to dynpro 9870 (Statements I) -----
+
+DATA: call_screen TYPE abap_bool,
+ call_screen_starting TYPE abap_bool,
+ call_screen_st_end TYPE abap_bool,
+ set_screen TYPE abap_bool,
+ leave_screen_next TYPE abap_bool,
+ leave_screen_set TYPE abap_bool,
+ leave_to_screen TYPE abap_bool,
+ set_pfstatus TYPE abap_bool,
+ set_pf_excluding TYPE abap_bool,
+ get_pfstatus TYPE abap_bool,
+ get_pfstatsus_excl TYPE abap_bool,
+ set_titlebar TYPE abap_bool,
+ set_titlebar_with TYPE abap_bool,
+ with_title TYPE c LENGTH 15,
+ col1 TYPE i,
+ lin1 TYPE i,
+ col2 TYPE i,
+ lin2 TYPE i,
+ col3 TYPE i,
+ lin3 TYPE i,
+ pf TYPE c LENGTH 1,
+ pfkey TYPE syst_pfkey,
+ title TYPE c LENGTH 1.
+
+"Data type and objects for the EXCLUDING addition of GET/SET PF-STATUS
+"statements
+TYPES fu_key_tab TYPE TABLE OF sy-ucomm WITH NON-UNIQUE KEY table_line.
+DATA: excl_list1 TYPE fu_key_tab,
+ excl_list2 TYPE fu_key_tab,
+ excl_list3 TYPE fu_key_tab.
+
+"----- Related to dynpro 9880 (Statements II) -----
+
+DATA: loop_modify TYPE abap_bool,
+ field_stmt TYPE abap_bool,
+ mod_at_exit TYPE abap_bool,
+ selected TYPE abap_bool,
+ set TYPE abap_bool,
+ field_a TYPE c LENGTH 1,
+ field_b TYPE c LENGTH 1,
+ field_c TYPE c LENGTH 1,
+ field_d TYPE c LENGTH 1,
+ field_e TYPE c LENGTH 1,
+ field_f TYPE c LENGTH 1,
+ output_field_1 TYPE c LENGTH 100,
+ output_field_2 TYPE c LENGTH 100,
+ output_field_3 TYPE c LENGTH 100,
+ field_help TYPE c LENGTH 30,
+ input_help TYPE c LENGTH 30,
+ "For GET/SET CURSOR statements
+ fld TYPE c LENGTH 20,
+ off TYPE i,
+ val TYPE string,
+ len TYPE i.
+
+"For field and input help
+TYPES: BEGIN OF values,
+ carrid TYPE zdemo_abap_flsch-carrid,
+ connid TYPE zdemo_abap_flsch-connid,
+ END OF values.
+
+DATA: progname TYPE sy-repid,
+ dynnum TYPE sy-dynnr,
+ dynpro_values TYPE TABLE OF dynpread,
+ field_value LIKE LINE OF dynpro_values,
+ values_tab TYPE TABLE OF values,
+ tab TYPE TABLE OF zdemo_abap_flsch-carrid,
+ carr TYPE zdemo_abap_flsch-carrid,
+ conn TYPE zdemo_abap_flsch-connid.
+
+DATA itab_flsch TYPE TABLE OF zdemo_abap_flsch-carrid.
+
+TYPES: BEGIN OF carrid_line,
+ carrid TYPE zdemo_abap_flsch-carrid,
+ END OF carrid_line.
+
+DATA carrid_list TYPE STANDARD TABLE OF carrid_line.
+
+"----- Related to dynpro 9890 (Exit command) -----
+
+"For demonstration purposes, implementations for the
+"related dialog modules are done in methods of a local
+"class.
+
+"----- Related to dynpro 9990 (Controls) -----
+
+"For table controls
+DATA lines TYPE i.
+DATA fill TYPE i.
+CONTROLS flights TYPE TABLEVIEW USING SCREEN 9900.
+
+"Internal table to hold data that is to be displayed.
+DATA itab_flights TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
+
+"Filling the internal table
+SELECT *
+ FROM zdemo_abap_flsch
+ ORDER BY carrid, connid
+ INTO TABLE @itab_flights.
+
+"For tabstrip controls
+CONTROLS tabstr TYPE TABSTRIP.
+DATA number LIKE sy-dynnr.
+
+"For ALV Grid control
+TYPES: BEGIN OF flight_struc,
+ carrid TYPE zdemo_abap_flsch-carrid,
+ connid TYPE zdemo_abap_flsch-connid,
+ countryfr TYPE zdemo_abap_flsch-countryfr,
+ cityfrom TYPE zdemo_abap_flsch-cityfrom,
+ airpfrom TYPE zdemo_abap_flsch-airpfrom,
+ countryto TYPE zdemo_abap_flsch-countryto,
+ cityto TYPE zdemo_abap_flsch-cityto,
+ airpto TYPE zdemo_abap_flsch-airpto,
+ fltime TYPE zdemo_abap_flsch-fltime,
+ END OF flight_struc.
+
+DATA itab4alv TYPE TABLE OF flight_struc WITH EMPTY KEY.
+
+"----- For other dialog modules -----
+
+DATA: links TYPE TABLE OF tline,
+ field_tab TYPE TABLE OF dfies WITH EMPTY KEY.
+
+"----- Local class -----
+
+CLASS local_class DEFINITION.
+ PUBLIC SECTION.
+ CLASS-METHODS: provide_fu_keys IMPORTING example TYPE i
+ RETURNING VALUE(fu_keys) TYPE fu_key_tab,
+
+ cc_alv_display IMPORTING container TYPE c,
+ "Implementations for dialog modules for dynpro 9890
+ pbo9890,
+ pai9890,
+ cancel.
+
+ "Variable declarations for dialog modules for dynpro 9890
+ CLASS-DATA: mandatory_field TYPE c LENGTH 20,
+ btn_exit_1 TYPE abap_bool,
+ btn_exit_2 TYPE abap_bool.
+ENDCLASS.
+
+CLASS local_class IMPLEMENTATION.
+
+ METHOD provide_fu_keys.
+ CASE example.
+ WHEN 1.
+ fu_keys = VALUE #( ( 'CANCEL' ) ( 'SAP' ) ).
+ WHEN 2.
+ fu_keys = VALUE #( ( 'CANCEL' ) ).
+ WHEN OTHERS.
+ ENDCASE.
+ ENDMETHOD.
+ METHOD cc_alv_display.
+ DATA(cont) = NEW cl_gui_custom_container( container_name = container ).
+
+ SELECT carrid, connid, countryfr, cityfrom, airpfrom, countryto, cityto, airpto, fltime
+ FROM zdemo_abap_flsch
+ ORDER BY carrid, connid
+ INTO CORRESPONDING FIELDS OF TABLE @itab4alv.
+
+ TRY.
+ cl_salv_table=>factory( EXPORTING r_container = cont
+ container_name = CONV string( container )
+ IMPORTING r_salv_table = DATA(alv)
+ CHANGING t_table = itab4alv ).
+ alv->get_columns( )->set_optimize( abap_true ).
+ alv->get_display_settings( )->set_list_header( 'Flights' ).
+ LOOP AT alv->get_columns( )->get( ) ASSIGNING FIELD-SYMBOL().
+ DATA(column) = -r_column.
+ column->set_long_text( |{ column->get_columnname( ) }| ).
+ ENDLOOP.
+ alv->display( ).
+ CATCH cx_salv_msg cx_salv_not_found.
+ MESSAGE `ALV display not possible` TYPE 'I'
+ DISPLAY LIKE 'E'.
+ ENDTRY.
+ ENDMETHOD.
+ METHOD pai9890.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'CLOSE1'.
+ MESSAGE `Processing continues. It does so only after the input field is filled.` TYPE 'I'.
+ SET SCREEN 0.
+ LEAVE SCREEN.
+ WHEN 'CLOSE2'.
+ MESSAGE `Superfluouse message :)` TYPE 'I'.
+ WHEN OTHERS.
+ MESSAGE `Processing continues. It does so only after the input field is filled.` TYPE 'I'.
+ LEAVE PROGRAM.
+ ENDCASE.
+ ENDMETHOD.
+
+ METHOD pbo9890.
+ SET PF-STATUS 'STATUS9890'.
+ SET TITLEBAR 'TITLE9890'.
+
+ dyn_num = sy-dynnr.
+ ENDMETHOD.
+
+ METHOD cancel.
+ MESSAGE `Module "cancel" was called. The dynpro will be left without the need to fill in the mandatory input field.` TYPE 'I'.
+
+ IF ok_code = 'CLOSE2'.
+ CLEAR: ok_code, mandatory_field.
+ SET SCREEN 0.
+ LEAVE SCREEN.
+ ENDIF.
+ ENDMETHOD.
+
+ENDCLASS.
+
+END-OF-SELECTION.
+
+ "Filling demo database tables
+ zcl_demo_abap_flight_tables=>fill_dbtabs( ).
+
+ CALL SCREEN 9850.
+
+**********************************************************************
+
+***************** Dialog modules for 9850 ****************************
+
+MODULE status_9850 OUTPUT.
+ SET PF-STATUS 'STATUS9850'.
+ SET TITLEBAR 'TITLE9850'.
+
+ CLEAR: screen_elements, stmts, stmts2.
+ dyn_num = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9850 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'ENTER' OR 'GO'.
+ CASE abap_true.
+ WHEN screen_elements.
+ CALL SCREEN 9860.
+ WHEN stmts.
+ CALL SCREEN 9870.
+ WHEN stmts2.
+ CALL SCREEN 9880.
+ WHEN controls.
+ CALL SCREEN 9900.
+ ENDCASE.
+ WHEN OTHERS.
+ LEAVE PROGRAM.
+ ENDCASE.
+ENDMODULE.
+
+***************** Dialog modules for 9860 ****************************
+
+MODULE status_9860 OUTPUT.
+ SET PF-STATUS 'STATUS9860'.
+ SET TITLEBAR 'TITLE9860'.
+
+ "Modifying static attributes
+ IF loop_modify = 'X'.
+ LOOP AT SCREEN INTO DATA(scr).
+ IF scr-name = 'ICON3'.
+ scr-invisible = '1'.
+ MODIFY SCREEN FROM scr.
+ ENDIF.
+ IF scr-name = 'INPUT_FIELD'.
+ scr-length = 10.
+ scr-intensified = '1'.
+ "scr-required = '1'.
+ MODIFY SCREEN FROM scr.
+ ENDIF.
+ IF scr-name = 'RB_Z'.
+ scr-active = '0'.
+ MODIFY SCREEN FROM scr.
+ ENDIF.
+ IF scr-name = 'CH_B'.
+ scr-input = '0'.
+ MODIFY SCREEN FROM scr.
+ ENDIF.
+ ENDLOOP.
+ ENDIF.
+
+ dyn_num = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9860 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ "Icons
+ WHEN 'ICON1'.
+ icon_name = 'ICON_GREEN_LIGHT'.
+ icon_text = `green`.
+ WHEN 'ICON2'.
+ icon_name = 'ICON_YELLOW_LIGHT'.
+ icon_text = `yellow`.
+ WHEN 'ICON3'.
+ icon_name = 'ICON_RED_LIGHT'.
+ icon_text = `red`.
+ "Input field
+ WHEN 'BTN_NO'.
+ MESSAGE |The text "{ input_field }" in the input field has { numofchar( input_field ) } characters. Trailing blanks are ignored.| TYPE 'I'.
+ "Check boxes
+ WHEN 'CH_BTN'.
+ IF ch_a = abap_true.
+ checkbox_msg = 'A'.
+ ENDIF.
+ IF ch_b = abap_true.
+ checkbox_msg = checkbox_msg && 'B'.
+ ENDIF.
+ IF ch_c = abap_true.
+ checkbox_msg = checkbox_msg && 'C'.
+ ENDIF.
+ IF checkbox_msg IS INITIAL.
+ checkbox_msg = 'None'.
+ ENDIF.
+ checkbox_msg = checkbox_msg.
+ MESSAGE checkbox_msg TYPE 'I'.
+ CLEAR checkbox_msg.
+ "Radio buttons
+ WHEN 'RB_BTN'.
+ CASE abap_true.
+ WHEN rb_x.
+ radiobutton_msg = 'X'.
+ WHEN rb_y.
+ radiobutton_msg = 'Y'.
+ WHEN rb_z.
+ radiobutton_msg = 'Z'.
+ WHEN OTHERS.
+ radiobutton_msg = ' '.
+ ENDCASE.
+ MESSAGE radiobutton_msg TYPE 'I'.
+ CLEAR radiobutton_msg.
+ WHEN 'HOME'.
+ SET SCREEN 0.
+ LEAVE SCREEN.
+ WHEN OTHERS.
+ LEAVE PROGRAM.
+ ENDCASE.
+
+ IF save_ok = 'ICON1' OR save_ok = 'ICON2' OR save_ok = 'ICON3'.
+ CALL FUNCTION 'ICON_CREATE'
+ EXPORTING
+ name = icon_name
+ text = icon_text
+ info = 'Status'
+ add_stdinf = 'X'
+ IMPORTING
+ result = icon
+ EXCEPTIONS
+ icon_not_found = 1
+ outputfield_too_short = 2
+ OTHERS = 3.
+ IF sy-subrc <> 0.
+ MESSAGE `Issue.` TYPE 'I' DISPLAY LIKE 'E'.
+ ENDIF.
+ ENDIF.
+
+ENDMODULE.
+
+***************** Dialog modules for 9870 ****************************
+
+MODULE status_9870 OUTPUT.
+
+ "Control structures in case of calling the dynpro again
+ IF set_pfstatus IS NOT INITIAL AND pfkey = 'STATUS9870'.
+ SET PF-STATUS 'DEMOSTATUS'.
+ ELSEIF set_pfstatus IS NOT INITIAL AND pfkey = 'DEMOSTATUS'.
+ SET PF-STATUS 'STATUS9870'.
+ ELSEIF set_pf_excluding IS NOT INITIAL AND pfkey = 'STATUS9870'.
+ excl_list1 = local_class=>provide_fu_keys( 1 ).
+ SET PF-STATUS 'DEMOSTATUS' EXCLUDING excl_list1.
+ ELSEIF set_pf_excluding IS NOT INITIAL AND pfkey = 'DEMOSTATUS'.
+ excl_list2 = local_class=>provide_fu_keys( 2 ).
+ SET PF-STATUS 'STATUS9870' EXCLUDING excl_list2.
+ ELSE.
+ SET PF-STATUS 'STATUS9870'.
+ ENDIF.
+
+ IF set_titlebar IS NOT INITIAL.
+ IF dyn_title CS 'Demo title'.
+ SET TITLEBAR 'TITLE9870'.
+ ELSE.
+ SET TITLEBAR 'DEMOTITLE'.
+ ENDIF.
+ ELSEIF SET_TITLEBAR_with IS NOT INITIAL.
+ SET TITLEBAR 'DEMOTITLE' WITH '"' with_title '"'.
+ ELSE.
+ SET TITLEBAR 'TITLE9870'.
+ ENDIF.
+
+ "Prepopulating values
+ col1 = 5.
+ lin1 = 10.
+ col2 = 1.
+ lin2 = 1.
+ col3 = 80.
+ lin3 = 20.
+ dyn_num = sy-dynnr.
+ dyn_title = sy-title.
+ENDMODULE.
+
+MODULE user_command_9870 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'ENTER' OR 'GO'.
+ CASE abap_true.
+ WHEN set_screen.
+ MESSAGE |A SET SCREEN statement is about to get called. The static next dynpro of dynpro { sy-dynnr } is 0.| &&
+ ` It is dynamically overwritten. Another dynpro will be displayed. A new dynpro sequence is not started.` TYPE 'I'.
+ SET SCREEN 9860.
+ WHEN call_screen.
+ MESSAGE `A CALL SCREEN statement is about to get called. You will switch to another dynpro. A new dynpro sequence is started.` TYPE 'I'.
+ CALL SCREEN 9860.
+ WHEN call_screen_starting.
+ IF col1 < 0 OR lin1 < 0.
+ MESSAGE `Only positive integers can be specified.` TYPE 'E'.
+ ELSE.
+ MESSAGE |The statement "CALL SCREEN ... STARTING AT { col1 } { lin1 }." is about to get called. | &&
+ `Note: In the dialog box that opens, click the icon in the popup footer to remain in the program. Clicking the X leaves the program.` TYPE 'I'.
+ CALL SCREEN 9860 STARTING AT col1 lin1.
+ ENDIF.
+ WHEN call_screen_st_end.
+ IF col2 < 0 OR lin2 < 0
+ OR col3 < 0 OR lin3 < 0.
+ MESSAGE `Only positive integers can be specified.`
+ TYPE 'E'.
+ ELSE.
+ MESSAGE |The statement "CALL SCREEN ... STARTING AT { col2 } { lin2 } ENDING AT { col3 } { lin3 }| &&
+ `." is about to get called. Note: In the dialog box that opens, click the icon in the popup footer ` &&
+ `to remain in the program. Clicking the X leaves the program.` TYPE 'I'.
+ CALL SCREEN 9860 STARTING AT col2 lin2 ENDING AT col3 lin3.
+ ENDIF.
+ WHEN leave_screen_next.
+ MESSAGE `A LEAVE SCREEN statement is about to get called. The current dynpro is exited, and the statically ` &&
+ `defined next dynpro is called, which is 0 in this case. Hence, the current dynpro sequence is terminated. ` &&
+ `Since the dynpro sequence is nested, you return to the home page and the parent dynpro sequence.` TYPE 'I'.
+ LEAVE SCREEN.
+ WHEN leave_screen_set.
+ MESSAGE `A LEAVE SCREEN statement is about to get called. In this case, a SET SCREEN statement before the LEAVE ` &&
+ `SCREEN statement overwrites the next dynpro (0 here). A new dynpro sequence is not started, instead the statement ` &&
+ `branches to another dynpro in the same sequence.` TYPE 'I'.
+ SET SCREEN 9900.
+ LEAVE SCREEN.
+ WHEN leave_to_screen.
+ MESSAGE `A LEAVE TO SCREEN statement is about to get called. A new dynpro sequence is not started, instead the ` &&
+ `statement branches to another dynpro in the same sequence. It has the same effect as the previous example.` TYPE 'I'.
+ LEAVE TO SCREEN 9900.
+ WHEN set_pfstatus.
+ pfkey = sy-pfkey.
+ MESSAGE |The current GUI status is { pfkey }. The current dynpro { sy-dynnr } will be set as the next dynpro.| &&
+ ` It will have a different GUI status.` TYPE 'I'.
+ SET SCREEN 9870.
+ WHEN set_pf_excluding.
+ GET PF-STATUS pfkey.
+ MESSAGE |The current GUI status is { pfkey }. The current dynpro will be set as the next dynpro.| &&
+ ` It will have a different GUI status (set at PBO) but excluding function codes (for example, the CANCEL button).` TYPE 'I'.
+ SET SCREEN 9870.
+ WHEN get_pfstatus.
+ GET PF-STATUS pfkey.
+ MESSAGE |The current GUI status is { pfkey }, which was retrieved using GET-PF-STATUS. Value of sy-pfkey: { sy-pfkey }.| TYPE 'I'.
+ SET SCREEN 9870.
+ WHEN get_pfstatsus_excl.
+ GET PF-STATUS pfkey EXCLUDING excl_list3.
+ MESSAGE |The current GUI status is { pfkey }. The exluded function codes are: {
+ COND #( WHEN excl_list3 IS INITIAL THEN `None are excluded. Try to run SET PF-STATUS ... EXCLUDING ... first before this one.`
+ ELSE concat_lines_of( table = excl_list3 sep = `, ` ) ) }| TYPE 'I'.
+ SET SCREEN 9870.
+ CLEAR excl_list3.
+ WHEN set_titlebar.
+ MESSAGE |The current title is "{ dyn_title }". The current dynpro is set as the next dynpro.| &&
+ `The text in the title bar should change.` TYPE 'I'.
+ SET SCREEN 9870.
+ WHEN set_titlebar_with.
+ MESSAGE |The current title is "{ dyn_title }". The current dynpro is set as the next dynpro.| &&
+ `The text in the title bar should change according to your input in the input field.` TYPE 'I'.
+ SET SCREEN 9870.
+ ENDCASE.
+ WHEN 'SAP'.
+ cl_gui_frontend_services=>execute( document = 'https://www.sap.com' ).
+ SET SCREEN 9870.
+ WHEN 'SAYHI'.
+ MESSAGE `Hallo ` && sy-uname && `.` TYPE 'I'.
+ SET SCREEN 9870.
+ WHEN 'HOME'.
+ LEAVE TO SCREEN 9850.
+ WHEN 'LEAVE' OR 'CANCEL'.
+ LEAVE PROGRAM.
+ WHEN OTHERS.
+ ENDCASE.
+ENDMODULE.
+
+***************** Dialog modules for 9880 ****************************
+
+MODULE status_9880 OUTPUT.
+ SET PF-STATUS 'STATUS9880'.
+ SET TITLEBAR 'TITLE9880'.
+
+ "Clearing variables in case the dynpro is called again
+ IF field_stmt IS INITIAL.
+ CLEAR: output_field_1, output_field_2, output_field_3,
+ field_a, field_b, field_c, field_d, field_e, field_f.
+ ENDIF.
+ IF field_d IS INITIAL.
+ CLEAR output_field_2.
+ ENDIF.
+ IF field_e IS INITIAL OR field_f IS INITIAL.
+ CLEAR output_field_3.
+ ENDIF.
+
+ "Prepopulating fields for input help
+ progname = sy-repid.
+ dynnum = sy-dynnr.
+ CLEAR: field_value, dynpro_values.
+ field_value-fieldname = 'CARR'.
+ APPEND field_value TO dynpro_values.
+
+ "Setting the cursor field
+ IF set = abap_true.
+ SET CURSOR FIELD 'CONN'.
+ CLEAR set.
+ ENDIF.
+
+ dyn_num = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9880 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'ENTER' OR 'GO'.
+ CASE abap_true.
+ WHEN loop_modify.
+ MESSAGE `Another dynpro will be set as the next dynpro. This dynpro includes a LOOP AT SCREEN ` &&
+ ` and MODIFY SCREEN statements in the PBO dialog module. Some screen elements have their static ` &&
+ `attributes changed. For example, they are made invisible or inactive, or the length is changed.` TYPE 'I'.
+ SET SCREEN 9860.
+ LEAVE SCREEN.
+ WHEN field_stmt.
+ MESSAGE `The current dynpro will be set as the next dynpro. Depending on which checkboxes you ` &&
+ `have selected, text is displayed in the fields below showing the effect of FIELD statements.` TYPE 'I'.
+ SET SCREEN 9880.
+ WHEN mod_at_exit.
+ SET SCREEN 9890.
+ ENDCASE.
+ WHEN 'SELECTED'.
+ CLEAR conn.
+ SET SCREEN 9880.
+ WHEN 'GET'.
+ GET CURSOR FIELD fld OFFSET off VALUE val LENGTH len.
+ MESSAGE |Current position of cursor: Field: "{ fld }", value: "{ val }", offset: "{ off }", length "{ len }"| TYPE 'I'.
+ SET SCREEN 9880.
+ WHEN 'SET'.
+ set = abap_true.
+ MESSAGE `Clicking the pushbutton triggers a SET CURSOR statement to be called at PBO. This sets the cursor on ` &&
+ `a specific input field (the one in the lower left corner).` TYPE 'I'.
+ SET SCREEN 9880.
+ WHEN 'HOME'.
+ LEAVE TO SCREEN 9850.
+ WHEN 'LEAVE' OR 'CANCEL'.
+ LEAVE PROGRAM.
+ WHEN OTHERS.
+ ENDCASE.
+ENDMODULE.
+
+***************** Dialog modules for 9890 ****************************
+"For demonstration purposes, the dialog module implementations are
+"done in methods of a local class.
+
+MODULE status_9890 OUTPUT.
+ local_class=>pbo9890( ).
+ENDMODULE.
+
+MODULE user_command_9890 INPUT.
+ local_class=>pai9890( ).
+ENDMODULE.
+
+***************** Dialog modules for 9900 ****************************
+
+MODULE status_9900 OUTPUT.
+ SET PF-STATUS 'STATUS9900'.
+ SET TITLEBAR 'TITLE9900'.
+
+ "For vertically scrolling in the table control
+ "To do this, the LINES component of the scxtab_control structure is set
+ "to the correct line number. Each time the scroll bar is scrolled, the
+ "PAI event is triggered with an empty function code, and the top_line
+ "component of the cxtab_control structure is automatically set to the
+ "new top line before PBO.
+ flights-lines = lines( itab_flights ).
+
+ "Setting a tab to be active by default in case of calling the
+ "dynpro again after leaving it.
+ IF tabstr-activetab IS INITIAL
+ OR number IS INITIAL.
+ number = '9920'.
+ tabstr-activetab = 'TAB2'.
+ ENDIF.
+ local_class=>cc_alv_display( 'ALVCONT' ).
+ dyn_num = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9900 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'TAB1'.
+ number = '9910'.
+ tabstr-activetab = save_ok.
+ WHEN 'TAB2'.
+ number = '9920'.
+ tabstr-activetab = save_ok.
+ WHEN 'HOME'.
+ "REFRESH statement: You can check out the effect, for example, by setting
+ "the vertical scroll bar somewhere. If you then go back and call the dynpro
+ "again, the control is refreshed (the scroll bar is again at the top).
+ REFRESH CONTROL 'FLIGHTS' FROM SCREEN sy-dynnr.
+ CLEAR: number, tabstr-activetab.
+ SET SCREEN 0.
+ LEAVE SCREEN.
+ WHEN 'CANCEL' OR 'LEAVE'.
+ LEAVE PROGRAM.
+ ENDCASE.
+ENDMODULE.
+
+***************** Further dialog modules to support the example ****************************
+
+MODULE module_1 INPUT.
+ output_field_1 = 'Available in module_1:' && ` ` &&
+ COND #( WHEN field_a = abap_true THEN 'A' ELSE '' ) &&
+ COND #( WHEN field_b = abap_true THEN 'B' ELSE '' ) &&
+ COND #( WHEN field_c = abap_true THEN 'C' ELSE '' ) &&
+ ' /'.
+ENDMODULE.
+
+MODULE module_2 INPUT.
+ output_field_1 = output_field_1 &&
+ ' Available in module_2:' && ` ` &&
+ COND #( WHEN field_a = abap_true THEN 'A' ELSE '' ) &&
+ COND #( WHEN field_b = abap_true THEN 'B' ELSE '' ) &&
+ COND #( WHEN field_c = abap_true THEN 'C' ELSE '' ) &&
+ ' /'.
+ENDMODULE.
+
+MODULE module_3 INPUT.
+ output_field_1 = output_field_1 &&
+ ' Available in module_3:' && ` ` &&
+ COND #( WHEN field_a = abap_true THEN 'A' ELSE '' ) &&
+ COND #( WHEN field_b = abap_true THEN 'B' ELSE '' ) &&
+ COND #( WHEN field_c = abap_true THEN 'C' ELSE '' ).
+ CLEAR: field_a, field_b, field_c.
+ENDMODULE.
+
+MODULE module_4 INPUT.
+ output_field_2 = 'module_4 was called because field_d was selected.'.
+ENDMODULE.
+
+MODULE module_5 INPUT.
+ output_field_3 = 'module_5 was called because field_e and field_f were selected.'.
+ENDMODULE.
+
+MODULE module_f1 INPUT.
+ "In this example, a demo object from the ABAP Keyword
+ "Documentation examples is used.
+ CALL FUNCTION 'HELP_OBJECT_SHOW'
+ EXPORTING
+ dokclass = 'TX'
+ doklangu = sy-langu
+ dokname = 'DEMO_FOR_F1_HELP'
+ TABLES
+ links = links.
+ENDMODULE.
+
+MODULE module_f4 INPUT.
+ CALL FUNCTION 'DYNP_VALUES_READ'
+ EXPORTING
+ dyname = progname
+ dynumb = dynnum
+ translate_to_upper = 'X'
+ TABLES
+ dynpfields = dynpro_values.
+
+ field_value = dynpro_values[ 1 ].
+
+ SELECT carrid, connid
+ FROM zdemo_abap_flsch
+ WHERE carrid = @( CONV #( field_value-fieldvalue ) )
+ INTO CORRESPONDING FIELDS OF TABLE @values_tab.
+
+ "Note: To save extra artifacts, this example goes without a dedicated DDIC
+ "structure with which input help can be created comfortably. Hence, creating
+ "a table manually for the field_tab parameter of the function module below.
+ field_tab = VALUE #(
+ ( tabname = 'ZDEMO_ABAP_FLSCH' fieldname = 'CARRID' langu = 'E' position = '1'
+ offset = '0' leng = '3' intlen = '6' outputlen = '3' datatype = 'CHAR' inttype = 'C' )
+ ( tabname = 'ZDEMO_ABAP_FLSCH' fieldname = 'CONNID' langu = 'E' position = '2'
+ offset = '6' leng = '4' intlen = '8' outputlen = '4' datatype = 'NUMC' inttype = 'N' ) ).
+
+ CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
+ EXPORTING
+ retfield = 'CONNID'
+ dynpprog = progname
+ dynpnr = dynnum
+ dynprofield = 'CONN'
+ value_org = 'S'
+ window_title = 'Selection'
+ TABLES
+ value_tab = values_tab
+ field_tab = field_tab.
+ENDMODULE.
+
+MODULE module_dropdown INPUT.
+ SELECT DISTINCT carrid
+ FROM zdemo_abap_flsch
+ INTO CORRESPONDING FIELDS OF TABLE @carrid_list.
+
+ CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
+ EXPORTING
+ retfield = 'CARRID'
+ value_org = 'S'
+ TABLES
+ value_tab = carrid_list
+ EXCEPTIONS
+ parameter_error = 1
+ no_values_found = 2
+ OTHERS = 3.
+ IF sy-subrc <> 0.
+ carr = 'LH'.
+ ENDIF.
+ENDMODULE.
+
+MODULE module_fill_table OUTPUT.
+ TRY.
+ zdemo_abap_flsch = itab_flights[ flights-current_line ].
+ CATCH cx_sy_itab_line_not_found.
+ RETURN.
+ ENDTRY.
+ENDMODULE.
+
+MODULE module_read_table INPUT.
+ lines = sy-loopc.
+ MODIFY itab_flights FROM zdemo_abap_flsch INDEX flights-current_line.
+ENDMODULE.
+
+MODULE cancel INPUT.
+ local_class=>cancel( ).
+ENDMODULE.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.xml
new file mode 100644
index 0000000..ffa8ed9
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_dynpro.prog.xml
@@ -0,0 +1,2793 @@
+
+
+
+
+
+ ZDEMO_ABAP_DYNPRO
+ S
+ 1
+ X
+ D$S
+ X
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9850
+ E
+ Demo dynpro
+ N
+ 9850
+ 027
+ 128
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_SCREEN_ELEMENTS
+ SCREEN
+ 003
+ 006
+ 029
+ 004
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT1
+ Dynpro_Number:
+ 010
+ 006
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _______
+ 010
+ 021
+ 007
+ 007
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_SCREEN_ELEMENTS
+ RADIO
+ SCREEN_ELEMENTS
+ Examples_of_screen_elements
+ 003
+ 006
+ 029
+ 029
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SCREEN_ELEMENTS
+ RADIO
+ STMTS
+ Statements_I
+ 004
+ 006
+ 014
+ 014
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SCREEN_ELEMENTS
+ RADIO
+ STMTS2
+ Statements_II
+ 005
+ 006
+ 015
+ 015
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SCREEN_ELEMENTS
+ RADIO
+ CONTROLS
+ Controls
+ 006
+ 006
+ 010
+ 010
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9850.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9850.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9860
+ E
+ Screen elements
+ N
+ 9860
+ 027
+ 123
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_RB_X
+ SCREEN
+ 009
+ 041
+ 003
+ 003
+
+
+
+
+ SCREEN
+ SCREEN
+ FRAME
+ %#AUTOTEXT001
+ ________________________________________________________________________
+ 002
+ 003
+ 073
+ 073
+ 006
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ ICON
+ __________________
+ X
+ 004
+ 005
+ 023
+ 021
+ 001
+ CHAR
+ X
+ N
+ <_--32_DIMENS>X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ INPUT_FIELD
+ ____________________
+ 004
+ 034
+ 020
+ 020
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ ICON1
+ green
+ 006
+ 005
+ 005
+ 005
+ 001
+ ICON1
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ ICON2
+ yellow
+ 006
+ 012
+ 006
+ 006
+ 001
+ ICON2
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ ICON3
+ red
+ 006
+ 020
+ 003
+ 003
+ 001
+ ICON3
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ BTN_OUTPUT
+ Number_of_characters?
+ 006
+ 034
+ 021
+ 021
+ 001
+ BTN_NO
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ FRAME
+ %#AUTOTEXT002
+ ________________________________________________________________________
+ 008
+ 003
+ 073
+ 073
+ 007
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ CH_A
+ A
+ 009
+ 005
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ CH_B
+ B
+ 010
+ 005
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ CH_C
+ C
+ 011
+ 005
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ CHECKBOX_BTN
+ Which_checkboxes_are_selected?
+ 013
+ 005
+ 030
+ 030
+ 001
+ CH_BTN
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ RADIOBUTTON_BTN
+ Which_radio_button_is_selected?
+ 013
+ 041
+ 031
+ 031
+ 001
+ RB_BTN
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT2
+ Dynpro_Number:
+ 017
+ 004
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _________
+ 017
+ 019
+ 009
+ 009
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_RB_X
+ RADIO
+ RB_X
+ X
+ 009
+ 041
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_RB_X
+ RADIO
+ RB_Y
+ Y
+ 010
+ 041
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_RB_X
+ RADIO
+ RB_Z
+ Z
+ 011
+ 041
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9860.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9860.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9870
+ E
+ Statements I
+ N
+ 0000
+ 027
+ 129
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ SCREEN
+ 002
+ 004
+ 047
+ 015
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT3
+ Dynpro_Number:
+ 002
+ 089
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _________
+ 002
+ 104
+ 009
+ 009
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ %#AUTOTEXT001
+ CALL_SCREEN_dynpro_STARTING_AT
+ 005
+ 006
+ 030
+ 030
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ COL1
+ ___
+ 005
+ 038
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ LIN1
+ ___
+ 005
+ 043
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ %#AUTOTEXT002
+ CALL_SCREEN_dynpro_STARTING_AT
+ 007
+ 006
+ 030
+ 030
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ COL2
+ ___
+ 007
+ 038
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ LIN2
+ ___
+ 007
+ 043
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ %#AUTOTEXT003
+ ENDING_AT
+ 007
+ 048
+ 009
+ 009
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ COL3
+ ___
+ 007
+ 059
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ LIN3
+ ___
+ 007
+ 064
+ 003
+ 003
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ WITH_TITLE
+ _______________
+ 016
+ 033
+ 015
+ 015
+ 001
+ CHAR
+ X
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ SET_SCREEN
+ SET_SCREEN
+ 002
+ 004
+ 012
+ 012
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ CALL_SCREEN
+ CALL_SCREEN
+ 003
+ 004
+ 013
+ 013
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ CALL_SCREEN_STARTING
+ Insert_values:
+ 004
+ 004
+ 016
+ 016
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ CALL_SCREEN_ST_END
+ Insert_values:
+ 006
+ 004
+ 016
+ 016
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ LEAVE_SCREEN_NEXT
+ LEAVE_SCREEN_(statically_defined_next_dynpro)
+ 008
+ 004
+ 047
+ 047
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ LEAVE_SCREEN_SET
+ LEAVE_SCREEN_(dynpro_set_beforehand)
+ 009
+ 004
+ 038
+ 038
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ LEAVE_TO_SCREEN
+ LEAVE_TO_SCREEN
+ 010
+ 004
+ 017
+ 017
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ SET_PFSTATUS
+ SET_PF-STATUS
+ 011
+ 004
+ 015
+ 015
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ SET_PF_EXCLUDING
+ SET_PF-STATUS_..._EXCLUDING_...
+ 012
+ 004
+ 033
+ 033
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ GET_PFSTATUS
+ GET_PF-STATUS
+ 013
+ 004
+ 015
+ 015
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ GET_PFSTATSUS_EXCL
+ GET_PF-STATUS_..._EXCLUDING_...
+ 014
+ 004
+ 033
+ 033
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ SET_TITLEBAR
+ SET_TITLEBAR
+ 015
+ 004
+ 014
+ 014
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_SET_SCREEN
+ RADIO
+ SET_TITLEBAR_WITH
+ SET_TITLEBAR_..._WITH_...
+ 016
+ 004
+ 027
+ 027
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9870.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9870.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9880
+ E
+ Statements II
+ N
+ 0000
+ 027
+ 139
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_LOOP_MODIFY
+ SCREEN
+ 002
+ 004
+ 037
+ 016
+
+
+
+
+ SCREEN
+ SCREEN
+ FRAME
+ %#AUTOTEXT001
+ ___________________________________________________________________________________________________________________________
+ 001
+ 002
+ 124
+ 124
+ 018
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT4
+ Dynpro_Number:
+ 002
+ 099
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _________
+ 002
+ 114
+ 009
+ 009
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT2
+ 1)_FIELD_statement_(select_all_3_checkboxes)
+ 005
+ 007
+ 044
+ 044
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_A
+ A
+ 006
+ 007
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_B
+ B
+ 006
+ 011
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_C
+ C
+ 006
+ 016
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ OUTPUT_FIELD_1
+ _____________________________________________________________________________________________________________
+ 007
+ 007
+ 109
+ 109
+ 001
+ CHAR
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT1
+ 2)_FIELD_..._MODULE_..._ON_INPUT_(Conditional_dialog_module_call)
+ 009
+ 007
+ 065
+ 065
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_D
+ D
+ 010
+ 007
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ OUTPUT_FIELD_2
+ _____________________________________________________________________________________________________________
+ 011
+ 007
+ 109
+ 109
+ 001
+ CHAR
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT3
+ 3)_CHAIN_/_MODULE_..._ON_CHAIN-INPUT
+ 013
+ 007
+ 036
+ 036
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_E
+ E
+ 014
+ 007
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ CHECK
+ FIELD_F
+ F
+ 014
+ 012
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ OUTPUT_FIELD_3
+ _____________________________________________________________________________________________________________
+ 015
+ 007
+ 109
+ 109
+ 001
+ CHAR
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ FRAME
+ %#AUTOTEXT002
+ ___________________________________________________________________________________________________________________________
+ 019
+ 002
+ 124
+ 124
+ 008
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT5
+ Field_help_(choose_F1_for_the_input_field)
+ 020
+ 007
+ 042
+ 042
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ FIELD_HELP
+ ______________________________
+ 021
+ 007
+ 030
+ 030
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ GET_CURSOR
+ Get_cursor_position
+ 021
+ 071
+ 019
+ 019
+ 001
+ GET
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT6
+ Input_help_
+ 023
+ 007
+ 011
+ 011
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ SET_CURSOR
+ Set_cursor_position
+ 023
+ 071
+ 019
+ 019
+ 001
+ SET
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ CARR
+ ___
+ L
+ 024
+ 007
+ 003
+ 005
+ 001
+ SELECTED
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_DD
+ Dropdown_list_box
+ 024
+ 014
+ 017
+ 017
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ CONN
+ ____
+ 025
+ 007
+ 004
+ 004
+ 001
+ NUMC
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_F4
+ Choose_F4_or_the_icon
+ 025
+ 014
+ 021
+ 021
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_LOOP_MODIFY
+ RADIO
+ LOOP_MODIFY
+ LOOP_AT_SCREEN_/_MODIFY_SCREEN_FROM
+ 002
+ 004
+ 037
+ 037
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_LOOP_MODIFY
+ RADIO
+ FIELD_STMT
+ FIELD,_MODULE_and_CHAIN_statements
+ 003
+ 004
+ 036
+ 036
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_LOOP_MODIFY
+ RADIO
+ MOD_AT_EXIT
+ MODULE_..._AT_EXIT-COMMAND.
+ 017
+ 005
+ 029
+ 029
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9880.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9880.
+
+
+ "Field statement
+
+
+ MODULE module_1.
+
+
+ FIELD field_a.
+
+
+ MODULE module_2.
+
+
+ FIELD field_b.
+
+
+ MODULE module_3.
+
+
+
+ "FIELD statement, conditional dialog module call
+
+
+ FIELD field_d MODULE module_4 ON INPUT.
+
+
+
+ "CHAIN/FIELD statements
+
+
+ CHAIN.
+
+
+ FIELD field_e.
+
+
+ FIELD field_f.
+
+
+ MODULE module_5 ON CHAIN-INPUT.
+
+
+ ENDCHAIN.
+
+
+
+ PROCESS ON HELP-REQUEST.
+
+
+ FIELD field_help MODULE module_f1.
+
+
+
+ PROCESS ON VALUE-REQUEST.
+
+
+ FIELD conn MODULE module_f4.
+
+
+ FIELD carr MODULE module_dropdown.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9890
+ E
+ Exit command
+ N
+ 0000
+ 027
+ 125
+
+
+
+ SCREEN
+ SCREEN
+
+
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ LOCAL_CLASS=>MANDATORY_FIELD
+ ?___________________
+ 002
+ 006
+ 020
+ 020
+ 001
+ CHAR
+ X
+ X
+ O
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ LOCAL_CLASS=>BTN_EXIT_1
+ Close_1
+ 004
+ 006
+ 007
+ 007
+ 001
+ CLOSE1
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ PUSH
+ LOCAL_CLASS=>BTN_EXIT_2
+ Close_2
+ 004
+ 016
+ 007
+ 007
+ 001
+ CLOSE2
+ E
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT5
+ Dynpro_Number:
+ 009
+ 006
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _________
+ 009
+ 021
+ 009
+ 009
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9890.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+
+ MODULE USER_COMMAND_9890.
+
+
+ MODULE CANCEL AT EXIT-COMMAND.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9900
+ E
+ Controls
+ N
+ 9900
+ 027
+ 126
+
+
+
+ SCREEN
+ SCREEN
+
+
+ TABLE_CTRL
+ FLIGHTS
+ SCREEN
+ 003
+ 002
+ 056
+ 010
+ X
+ X
+ X
+ X
+ ENTRY
+ X
+ X
+ X
+ X
+ X
+ MULTIPLE
+ SINGLE
+ 002
+
+
+ STRIP_CTRL
+ TABSTR
+ SCREEN
+ 003
+ 063
+ 053
+ 010
+
+
+ SUBSCREEN
+ SUB
+ TABSTR
+ 005
+ 064
+ 049
+ 007
+ X
+ X
+
+
+ CUST_CTRL
+ ALVCONT
+ SCREEN
+ 016
+ 002
+ 057
+ 010
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_TC
+ Table_control
+ 001
+ 002
+ 013
+ 013
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_TSC
+ Tabstrip_control
+ 001
+ 063
+ 016
+ 016
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_ALV
+ ALV_Grid_as_example_for_a_GUI_control
+ 014
+ 002
+ 037
+ 037
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ DYNNR_TEXT6
+ Dynpro_Number:
+ 016
+ 092
+ 014
+ 014
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYN_NUM
+ _________
+ 016
+ 107
+ 009
+ 009
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEXT
+ TAB
+ Flights__
+ 001
+ 009
+ 053
+ 001
+ CHAR
+ N
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEXT
+ ZDEMO_ABAP_FLSCH-CARRID
+ ID
+ 001
+ 001
+ 002
+ 003
+ 001
+ CHAR
+ X
+ F
+ X
+ N
+ X
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEXT
+ ZDEMO_ABAP_FLSCH-CONNID
+ Num
+ 001
+ 002
+ 003
+ 004
+ 001
+ CHAR
+ X
+ F
+ X
+ N
+ X
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEXT
+ ZDEMO_ABAP_FLSCH-CITYFROM
+ From_
+ 001
+ 003
+ 005
+ 020
+ 001
+ CHAR
+ X
+ F
+ N
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEXT
+ ZDEMO_ABAP_FLSCH-CITYTO
+ To_
+ 001
+ 004
+ 003
+ 020
+ 001
+ CHAR
+ X
+ F
+ N
+ X
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEMPLATE
+ ZDEMO_ABAP_FLSCH-CARRID
+ 001
+ 001
+ 003
+ 003
+ 001
+ CHAR
+ X
+ X
+ X
+ X
+ N
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEMPLATE
+ ZDEMO_ABAP_FLSCH-CONNID
+ 001
+ 002
+ 004
+ 004
+ 001
+ NUMC
+ X
+ X
+ X
+ X
+ N
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEMPLATE
+ ZDEMO_ABAP_FLSCH-CITYFROM
+ 001
+ 003
+ 020
+ 020
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ TABLE_CTRL
+ FLIGHTS
+ TEMPLATE
+ ZDEMO_ABAP_FLSCH-CITYTO
+ 001
+ 004
+ 020
+ 020
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ STRIP_CTRL
+ TABSTR
+ PUSH
+ TAB1
+ Tab_1__
+ 001
+ 001
+ 007
+ 005
+ 001
+ TAB1
+ CHAR
+ N
+ SUB
+
+
+ STRIP_CTRL
+ TABSTR
+ PUSH
+ TAB2
+ Tab_2__
+ 001
+ 002
+ 007
+ 005
+ 001
+ TAB2
+ CHAR
+ N
+ SUB
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9900.
+
+
+ LOOP WITH CONTROL flights.
+
+
+ MODULE module_fill_table.
+
+
+ ENDLOOP.
+
+
+
+ CALL SUBSCREEN sub INCLUDING sy-repid number.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ CALL SUBSCREEN sub.
+
+
+
+ LOOP WITH CONTROL FLIGHTS.
+
+
+ MODULE module_read_table.
+
+
+ ENDLOOP.
+
+
+
+ MODULE USER_COMMAND_9900.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9910
+ E
+ Subscreen 1
+ I
+ 9910
+ 027
+ 122
+
+
+
+ SCREEN
+ SCREEN
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_SC_1
+ This_is_subscreen_1.
+ 002
+ 003
+ 020
+ 020
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+
+ -
+
+ ZDEMO_ABAP_DYNPRO
+ 9920
+ E
+ Subscreen 2
+ I
+ 9920
+ 027
+ 122
+
+
+
+ SCREEN
+ SCREEN
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TEXT_SC_2
+ This_is_subscreen_2.
+ 007
+ 003
+ 020
+ 020
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+
+
+
+
+ 000007
+ 000011
+ 000007
+
+
+
+ DEMOSTATUS
+ D
+ 000004
+ 000004
+ 0001
+ Demo status
+
+
+ STATUS9850
+ D
+ 000001
+ 000001
+ 0001
+ Demo dynpro
+
+
+ STATUS9860
+ D
+ 000002
+ 000002
+ 0001
+ Demo
+
+
+ STATUS9870
+ D
+ 000003
+ 000003
+ 0001
+ STATUS9870
+
+
+ STATUS9880
+ D
+ 000005
+ 000005
+ 0001
+ Demo status
+
+
+ STATUS9890
+ D
+ 000006
+ 000006
+ 0001
+ STATUS9890
+
+
+ STATUS9900
+ D
+ 000007
+ 000007
+ 0001
+ STATUS9900
+
+
+
+
+ BACK
+ 001
+ S
+ Back
+ Home
+ Home
+
+
+ CANCEL
+ 001
+ S
+ ICON_CANCEL
+ @0W@
+ Cancel
+
+
+ ENTER
+ 001
+ S
+ Enter
+
+
+ GO
+ 001
+ S
+ ICON_EXECUTE_OBJECT
+ @15@
+ Go
+ Go
+
+
+ GOBACK
+ 001
+ S
+ ICON_COLUMN_LEFT
+ @0D@
+ Go back
+ Go back
+
+
+ HOME
+ 001
+ S
+ @B9@
+ Home
+
+
+ LEAVE
+ 001
+ S
+ Exit
+
+
+ SAP
+ 001
+ S
+ Open sap.com
+
+
+ SAYHI
+ 001
+ S
+ Say hi
+
+
+ START
+ 001
+ S
+ ICON_PREVIOUS_STEP
+ @B9@
+ Go to first dynpro
+
+
+ STARTPAGE
+ 001
+ S
+ ICON_PREVIOUS_STEP
+ @B9@
+ STARTPAGE
+ Go to start
+
+
+ SWITCH
+ 001
+ S
+ ICON_COLUMN_RIGHT
+ @0E@
+ Switch
+ Go to other dynpro
+
+
+
+
+ 000011
+ S
+ Go
+
+
+
+
+ 000001
+ 0001
+ 01
+ 08
+
+
+ 000002
+ 0001
+ 01
+ 05
+
+
+ 000003
+ 0001
+ 01
+ 08
+
+
+ 000003
+ 0001
+ 02
+ 05
+
+
+ 000004
+ 0001
+ 01
+ 08
+
+
+ 000004
+ 0001
+ 02
+ 05
+
+
+ 000004
+ 0001
+ 03
+ 06
+
+
+ 000004
+ 0001
+ 04
+ 07
+
+
+ 000005
+ 0001
+ 01
+ 08
+
+
+ 000005
+ 0001
+ 02
+ 05
+
+
+ 000007
+ 0001
+ 01
+ 05
+
+
+
+
+ 000001
+ 00
+ ENTER
+ 001
+
+
+ 000001
+ 08
+ GO
+ 001
+
+
+ 000001
+ 12
+ CANCEL
+ 001
+
+
+ 000001
+ 15
+ LEAVE
+ 001
+
+
+ 000002
+ 05
+ HOME
+ 001
+
+
+ 000002
+ 12
+ CANCEL
+ 001
+
+
+ 000002
+ 15
+ LEAVE
+ 001
+
+
+ 000003
+ 00
+ ENTER
+ 001
+
+
+ 000003
+ 05
+ HOME
+ 001
+
+
+ 000003
+ 08
+ GO
+ 001
+
+
+ 000003
+ 12
+ CANCEL
+ 001
+
+
+ 000003
+ 15
+ LEAVE
+ 001
+
+
+ 000004
+ 00
+ ENTER
+ 001
+
+
+ 000004
+ 05
+ HOME
+ 001
+
+
+ 000004
+ 06
+ SAYHI
+ 001
+
+
+ 000004
+ 07
+ SAP
+ 001
+
+
+ 000004
+ 08
+ GO
+ 001
+
+
+ 000004
+ 12
+ CANCEL
+ 001
+
+
+ 000004
+ 15
+ LEAVE
+ 001
+
+
+ 000005
+ 00
+ ENTER
+ 001
+
+
+ 000005
+ 05
+ HOME
+ 001
+
+
+ 000005
+ 08
+ GO
+ 001
+
+
+ 000005
+ 12
+ CANCEL
+ 001
+
+
+ 000005
+ 15
+ LEAVE
+ 001
+
+
+ 000006
+ 12
+ CANCEL
+ 001
+
+
+ 000007
+ 05
+ HOME
+ 001
+
+
+ 000007
+ 12
+ CANCEL
+ 001
+
+
+ 000007
+ 15
+ LEAVE
+ 001
+
+
+
+
+ DEMOSTATUS
+ BACK
+
+
+ DEMOSTATUS
+ CANCEL
+
+
+ DEMOSTATUS
+ ENTER
+
+
+ DEMOSTATUS
+ GO
+
+
+ DEMOSTATUS
+ HOME
+
+
+ DEMOSTATUS
+ LEAVE
+
+
+ DEMOSTATUS
+ SAP
+
+
+ DEMOSTATUS
+ SAYHI
+
+
+ DEMOSTATUS
+ SWITCH
+
+
+ STATUS9850
+ CANCEL
+
+
+ STATUS9850
+ ENTER
+
+
+ STATUS9850
+ GO
+
+
+ STATUS9850
+ LEAVE
+
+
+ STATUS9860
+ BACK
+
+
+ STATUS9860
+ CANCEL
+
+
+ STATUS9860
+ HOME
+
+
+ STATUS9860
+ LEAVE
+
+
+ STATUS9860
+ START
+
+
+ STATUS9870
+ BACK
+
+
+ STATUS9870
+ CANCEL
+
+
+ STATUS9870
+ ENTER
+
+
+ STATUS9870
+ GO
+
+
+ STATUS9870
+ HOME
+
+
+ STATUS9870
+ LEAVE
+
+
+ STATUS9870
+ START
+
+
+ STATUS9880
+ BACK
+
+
+ STATUS9880
+ CANCEL
+
+
+ STATUS9880
+ ENTER
+
+
+ STATUS9880
+ GO
+
+
+ STATUS9880
+ HOME
+
+
+ STATUS9880
+ LEAVE
+
+
+ STATUS9890
+ CANCEL
+
+
+ STATUS9900
+ BACK
+
+
+ STATUS9900
+ CANCEL
+
+
+ STATUS9900
+ HOME
+
+
+ STATUS9900
+ LEAVE
+
+
+
+
+ A
+ 000001
+ D
+ STATUS9850
+
+
+ P
+ 000001
+ D
+ STATUS9850
+
+
+ B
+ 000001
+ 0001
+ D
+ STATUS9850
+
+
+ A
+ 000002
+ D
+ STATUS9860
+
+
+ P
+ 000002
+ D
+ STATUS9860
+
+
+ B
+ 000002
+ 0001
+ D
+ STATUS9860
+
+
+ A
+ 000003
+ D
+ STATUS9870
+
+
+ P
+ 000003
+ D
+ STATUS9870
+
+
+ B
+ 000003
+ 0001
+ D
+ STATUS9870
+
+
+ A
+ 000004
+ D
+ Demo status
+
+
+ P
+ 000004
+ D
+ Demo status
+
+
+ B
+ 000004
+ 0001
+ D
+ Demo status
+
+
+ A
+ 000005
+ D
+ Demo status
+
+
+ P
+ 000005
+ D
+ Demo status
+
+
+ B
+ 000005
+ 0001
+ D
+ Demo status
+
+
+ A
+ 000006
+ D
+ STATUS9890
+
+
+ P
+ 000006
+ D
+ STATUS9890
+
+
+ B
+ 000006
+ 0001
+ D
+ STATUS9890
+
+
+ A
+ 000007
+ D
+ STATUS9900
+
+
+ P
+ 000007
+ D
+ STATUS9900
+
+
+ B
+ 000007
+ 0001
+ D
+ STATUS9900
+
+
+
+
+ DEMOTITLE
+ Demo title &1&2&3
+
+
+ TITLE9850
+ Dynpro Demo
+
+
+ TITLE9860
+ Screen Elements
+
+
+ TITLE9870
+ Statements I
+
+
+ TITLE9880
+ Statements II
+
+
+ TITLE9890
+ Exit command
+
+
+ TITLE9900
+ Controls
+
+
+
+
+ -
+ R
+ Demo example
+ 12
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.abap
new file mode 100644
index 0000000..e3f3880
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.abap
@@ -0,0 +1,3 @@
+FUNCTION-POOL ZDEMO_ABAP_FUGR. "MESSAGE-ID ..
+
+* INCLUDE LZDEMO_ABAP_FUGRD... " Local class definition
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.xml
new file mode 100644
index 0000000..14f4f7e
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.lzdemo_abap_fugrtop.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ LZDEMO_ABAP_FUGRTOP
+ S
+ D$
+ I
+ S
+ X
+ D$S
+ X
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.abap
new file mode 100644
index 0000000..e6a2dc9
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.abap
@@ -0,0 +1,15 @@
+*******************************************************************
+* System-defined Include-files. *
+*******************************************************************
+ INCLUDE LZDEMO_ABAP_FUGRTOP. " Global Declarations
+ INCLUDE LZDEMO_ABAP_FUGRUXX. " Function Modules
+
+*******************************************************************
+* User-defined Include-files (if necessary). *
+*******************************************************************
+* INCLUDE LZDEMO_ABAP_FUGRF... " Subroutines
+* INCLUDE LZDEMO_ABAP_FUGRO... " PBO-Modules
+* INCLUDE LZDEMO_ABAP_FUGRI... " PAI-Modules
+* INCLUDE LZDEMO_ABAP_FUGRE... " Events
+* INCLUDE LZDEMO_ABAP_FUGRP... " Local class implement.
+* INCLUDE LZDEMO_ABAP_FUGRT99. " ABAP Unit tests
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.xml
new file mode 100644
index 0000000..422bb97
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.saplzdemo_abap_fugr.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+ SAPLZDEMO_ABAP_FUGR
+ S
+ D$
+ F
+ S
+ E
+ X
+ D$S
+ X
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.xml
new file mode 100644
index 0000000..1beb82e
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.xml
@@ -0,0 +1,63 @@
+
+
+
+
+ Demo function group
+
+ LZDEMO_ABAP_FUGRTOP
+ SAPLZDEMO_ABAP_FUGR
+
+
+ -
+ ZDEMO_ABAP_DELETE_FU
+ 1
+ Demo update function module
+
+ -
+ ZDEMO_ABAP_LOG_FU
+ 1
+ Demo update function module
+
+
+ LOG
+ ZCL_DEMO_ABAP_SAP_LUW_HELPER=>LOG_TYPE
+
+
+ CAUSE_ERROR
+ ABAP_FALSE
+ X
+ ABAP_BOOL
+
+
+
+
+ LOG
+ P
+
+
+ CAUSE_ERROR
+ P
+
+
+
+ -
+ ZDEMO_ABAP_MODIFY_FU
+ 1
+ Demo update function module
+
+
+ VALUES
+ ZDEMO_ABAP_LUW_T
+
+
+
+
+ VALUES
+ P
+
+
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_delete_fu.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_delete_fu.abap
new file mode 100644
index 0000000..75820c6
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_delete_fu.abap
@@ -0,0 +1,34 @@
+FUNCTION zdemo_abap_delete_fu.
+*"----------------------------------------------------------------------
+*"*"Update Function Module:
+*"
+*"*"Local Interface:
+*"----------------------------------------------------------------------
+
+
+ DELETE FROM zdemo_abap_luw_t.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 70
+ context = 'Function module'
+ name = 'zdemo_abap_delete_fu'
+ details = `Function module called`
+ timestamp = utclong_current( ) )
+ ( id = 71
+ context = 'Function module'
+ name = 'zdemo_abap_delete_fu'
+ details = zcl_demo_abap_sap_luw_helper=>get_work_process_info( )
+ timestamp = utclong_current( ) )
+ ( id = 72
+ context = 'Function module'
+ name = 'zdemo_abap_delete_fu'
+ details = `SAP LUW Key: ` && cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( ) )
+ ( id = 73
+ context = 'Function module'
+ name = 'zdemo_abap_delete_fu'
+ details = zcl_demo_abap_sap_luw_helper=>checking_transaction_state( )
+ timestamp = utclong_current( ) ) ) ).
+
+
+ENDFUNCTION.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_log_fu.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_log_fu.abap
new file mode 100644
index 0000000..011cb70
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_log_fu.abap
@@ -0,0 +1,41 @@
+FUNCTION ZDEMO_ABAP_LOG_FU.
+*"----------------------------------------------------------------------
+*"*"Update Function Module:
+*"
+*"*"Local Interface:
+*" IMPORTING
+*" VALUE(LOG) TYPE ZCL_DEMO_ABAP_SAP_LUW_HELPER=>LOG_TYPE
+*" VALUE(CAUSE_ERROR) TYPE ABAP_BOOL DEFAULT ABAP_FALSE
+*"----------------------------------------------------------------------
+
+
+ MODIFY zdemo_abap_logt FROM TABLE @log.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 90
+ context = `Function module`
+ name = `zdemo_abap_log_fu`
+ details = `Function module called`
+ timestamp = utclong_current( ) )
+ ( id = 91
+ context = `Function module`
+ name = `zdemo_abap_log_fu`
+ details = zcl_demo_abap_sap_luw_helper=>get_work_process_info( )
+ timestamp = utclong_current( ) )
+ ( id = 92
+ context = `Function module`
+ name = `zdemo_abap_log_fu`
+ details = `SAP LUW Key: ` && cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( ) )
+ ( id = 93
+ context = `Function module`
+ name = `zdemo_abap_log_fu`
+ details = zcl_demo_abap_sap_luw_helper=>checking_transaction_state( )
+ timestamp = utclong_current( ) ) ) ).
+
+ IF cause_error = abap_true.
+ DATA(error_not_caught) = 1 / 0.
+ ENDIF.
+
+
+ENDFUNCTION.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_modify_fu.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_modify_fu.abap
new file mode 100644
index 0000000..86fe044
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_fugr.fugr.zdemo_abap_modify_fu.abap
@@ -0,0 +1,38 @@
+FUNCTION ZDEMO_ABAP_MODIFY_FU.
+*"----------------------------------------------------------------------
+*"*"Update Function Module:
+*"
+*"*"Local Interface:
+*" IMPORTING
+*" VALUE(VALUES) TYPE ZDEMO_ABAP_LUW_T
+*"----------------------------------------------------------------------
+
+ values-time_stamp = utclong_current( ).
+
+ MODIFY zdemo_abap_luw_t FROM @values.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 80
+ context = 'Function module'
+ name = 'zdemo_abap_modify_fu'
+ details = `Function module called`
+ timestamp = utclong_current( ) )
+ ( id = 81
+ context = 'Function module'
+ name = 'zdemo_abap_modify_fu'
+ details = zcl_demo_abap_sap_luw_helper=>get_work_process_info( )
+ timestamp = utclong_current( ) )
+ ( id = 82
+ context = 'Function module'
+ name = 'zdemo_abap_modify_fu'
+ details = `SAP LUW Key: ` && cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( ) )
+ ( id = 83
+ context = 'Function module'
+ name = 'zdemo_abap_modify_fu'
+ details = zcl_demo_abap_sap_luw_helper=>checking_transaction_state( )
+ timestamp = utclong_current( ) ) ) ).
+
+
+
+ENDFUNCTION.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_logt.tabl.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_logt.tabl.xml
new file mode 100644
index 0000000..b6a96ad
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_logt.tabl.xml
@@ -0,0 +1,83 @@
+
+
+
+
+
+ ZDEMO_ABAP_LOGT
+ E
+ TRANSP
+ X
+ Log table
+ E
+ A
+ 1
+
+
+ ZDEMO_ABAP_LOGT
+ A
+ 0
+ APPL0
+ N
+
+
+
+ CLIENT
+ X
+ 0
+ C
+ 000006
+ X
+ CLNT
+ 000003
+ CLNT
+
+
+ ID
+ X
+ 0
+ X
+ 000004
+ X
+ INT4
+ 000010
+ INT4
+
+
+ CONTEXT
+ 0
+ C
+ 000030
+ CHAR
+ 000015
+ CHAR
+
+
+ NAME
+ 0
+ C
+ 000040
+ CHAR
+ 000020
+ CHAR
+
+
+ DETAILS
+ 0
+ g
+ 000008
+ STRG
+ STRG
+
+
+ TIMESTAMP
+ 0
+ p
+ 000008
+ UTCL
+ 000027
+ UTCL
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_luw_t.tabl.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_luw_t.tabl.xml
new file mode 100644
index 0000000..9ac5344
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_luw_t.tabl.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+ ZDEMO_ABAP_LUW_T
+ E
+ TRANSP
+ X
+ Demo database table
+ E
+ A
+ 1
+
+
+ ZDEMO_ABAP_LUW_T
+ A
+ 0
+ APPL0
+ N
+
+
+
+ CLIENT
+ X
+ 0
+ C
+ 000006
+ X
+ CLNT
+ 000003
+ CLNT
+
+
+ KEY_FIELD
+ X
+ 0
+ X
+ 000004
+ X
+ INT4
+ 000010
+ INT4
+
+
+ CH
+ 0
+ C
+ 000020
+ CHAR
+ 000010
+ CHAR
+
+
+ NUM
+ 0
+ X
+ 000004
+ INT4
+ 000010
+ INT4
+
+
+ TIME_STAMP
+ 0
+ p
+ 000008
+ UTCL
+ 000027
+ UTCL
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.abap
new file mode 100644
index 0000000..3745aaa
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.abap
@@ -0,0 +1,513 @@
+*&---------------------------------------------------------------------*
+*& ABAP cheat sheet: SAP LUW
+*&
+*&-------------------------- PURPOSE ----------------------------------*
+*& - Example to demonstrate ABAP syntax in the context of the SAP LUW.
+*& - Topics covered: Using update function modules and subroutines as
+*& bundling techniques, synchronous/asynchronous/local updates
+*&
+*&----------------------- GETTING STARTED -----------------------------*
+*& - Open the program with the ABAP development tools for Eclipse (ADT).
+*& - Choose F8 to run the program.
+*& - Select the radio buttons and choose 'Go' to progress with the program.
+*&
+*&----------------------------- NOTE -----------------------------------*
+*&* The code presented in this class is intended only to support the ABAP
+*&* cheat sheets. It is not intended for direct use in a production system
+*&* environment. The code examples in the ABAP cheat sheets are primarily
+*&* intended to provide a better explanation and visualization of the
+*&* syntax and semantics of ABAP statements, not to solve concrete
+*&* programming tasks. For production application programs, you should
+*&* always work out your own solution for each individual case. There is
+*&* no guarantee for the correctness or completeness of the code.
+*&* Furthermore, there is no legal responsibility or liability for any
+*&* errors or their consequences that may occur when using the the example
+*&* code.
+*&---------------------------------------------------------------------*
+REPORT zdemo_abap_sap_luw.
+
+DATA: tab_struc TYPE zdemo_abap_luw_t,
+ ok_code LIKE sy-ucomm,
+ save_ok LIKE sy-ucomm,
+ del_insert TYPE abap_bool,
+ perform TYPE abap_bool,
+ commit TYPE abap_bool,
+ commit_wait TYPE abap_bool,
+ local_update TYPE abap_bool,
+ err TYPE abap_bool,
+ rollback TYPE abap_bool,
+ terminate TYPE abap_bool,
+ dynnr TYPE sy-dynnr,
+ counter TYPE i,
+ log_itab TYPE zcl_demo_abap_sap_luw_helper=>log_type.
+
+CLASS lcl DEFINITION.
+ PUBLIC SECTION.
+
+ TYPES: BEGIN OF request4log,
+ log TYPE zdemo_abap_logt,
+ called TYPE abap_bool,
+ wp_info TYPE abap_bool,
+ luw_key TYPE abap_bool,
+ tx_state TYPE abap_bool,
+ END OF request4log.
+
+ CLASS-METHODS: prep,
+ create_log_entries IMPORTING req TYPE request4log.
+ENDCLASS.
+
+CLASS lcl IMPLEMENTATION.
+
+ METHOD prep.
+ DELETE FROM zdemo_abap_luw_t.
+
+ INSERT zdemo_abap_luw_t FROM TABLE @( VALUE #(
+ ( key_field = 1
+ ch = 'DEMO DATA'
+ num = 11
+ time_stamp = utclong_current( ) )
+ ( key_field = 2
+ ch = 'THAT WAS'
+ num = 22
+ time_stamp = utclong_current( ) )
+ ( key_field = 3
+ ch = 'CREATED'
+ num = 33
+ time_stamp = utclong_current( ) )
+ ( key_field = 4
+ ch = 'IN ADVANCE'
+ num = 44
+ time_stamp = utclong_current( ) ) ) ).
+
+ DELETE FROM zdemo_abap_logt.
+ ENDMETHOD.
+
+ METHOD create_log_entries.
+
+ IF req-called = abap_true.
+ counter += 1.
+ INSERT VALUE #( id = counter
+ context = req-log-context
+ name = req-log-name
+ details = `Called!`
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+ ENDIF.
+
+ IF req-luw_key = abap_true.
+ counter += 1.
+ INSERT VALUE #( id = counter
+ context = req-log-context
+ name = req-log-name
+ details = `SAP LUW key: ` &&
+ cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+
+ ENDIF.
+
+ IF req-wp_info = abap_true.
+ counter += 1.
+ INSERT VALUE #( id = counter
+ context = req-log-context
+ name = req-log-name
+ details =
+ zcl_demo_abap_sap_luw_helper=>get_work_process_info( )
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+ ENDIF.
+
+ IF req-tx_state = abap_true.
+ counter += 1.
+ INSERT VALUE #(
+ id = counter
+ context = req-log-context
+ name = req-log-name
+ details =
+ zcl_demo_abap_sap_luw_helper=>checking_transaction_state( )
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+ ENDIF.
+ ENDMETHOD.
+ENDCLASS.
+
+FORM delete.
+ zcl_demo_abap_sap_luw_helper=>subr_delete( ).
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'Subroutine'
+ name = 'delete' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+ENDFORM.
+
+FORM insert.
+
+ DATA values TYPE zdemo_abap_luw_t.
+ IMPORT values = values FROM MEMORY ID 'DEMO_INSERT'.
+ IF sy-subrc = 0.
+ values-time_stamp = utclong_current( ).
+ zcl_demo_abap_sap_luw_helper=>subr_insert( values ).
+ ENDIF.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'Subroutine'
+ name = 'insert' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+ENDFORM.
+
+FORM update_log.
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'Subroutine'
+ name = 'update_log' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ zcl_demo_abap_sap_luw_helper=>subr_update_log( log_itab ).
+ENDFORM.
+
+FORM call_on_rollback.
+
+ "No implementation here. Only to demonstrate that the
+ "subroutine is called in the event of triggering a
+ "rollback.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'Subroutine'
+ name = 'call_on_rollback' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true ) ).
+ENDFORM.
+
+END-OF-SELECTION.
+
+ lcl=>prep( ).
+
+ counter += 1.
+ INSERT VALUE #(
+ id = counter
+ context = '-'
+ name = '-'
+ details = |Program { sy-repid } has been started.| &&
+ `The first dynpro is about to be called.`
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+
+ counter += 1.
+ INSERT VALUE #( id = counter
+ context = '-'
+ name = '-'
+ details = `SAP LUW Key: ` &&
+ cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( )
+ ) INTO TABLE log_itab.
+
+ CALL SCREEN 9750.
+
+**********************************************************************
+
+***************** Dialog modules for 9750 ****************************
+
+MODULE status_9750 OUTPUT.
+ SET PF-STATUS 'STATUS9750'.
+ SET TITLEBAR 'TITLE9750'.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PBO'
+ name = 'status_9750' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ zcl_demo_abap_sap_luw_helper=>cc_alv_display( 'DBENTRIES' ).
+ dynnr = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9750 INPUT.
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PAI'
+ name = 'user_command_9750' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'GO' OR 'ENTER'.
+
+ IF del_insert = abap_true.
+ CALL FUNCTION 'ZDEMO_ABAP_DELETE_FU' IN UPDATE TASK.
+
+ MESSAGE `A function module has been registered ` &&
+ `that clears the database table.` TYPE 'I'.
+
+ ELSEIF local_update = abap_true.
+
+ SET UPDATE TASK LOCAL.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PAI'
+ name = 'user_command_9750' )
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ CALL FUNCTION 'ZDEMO_ABAP_DELETE_FU' IN UPDATE TASK.
+
+ MESSAGE `Local update has been activated. A function ` &&
+ `module has been registered that clears the database table.` &&
+ ` No matter if you choose COMMIT WORK or COMMIT WORK AND ` &&
+ `WAIT in the next step, it will be a synchronous update.` TYPE 'I'.
+
+ ELSEIF perform = abap_true.
+
+ PERFORM delete ON COMMIT.
+ PERFORM call_on_rollback ON ROLLBACK.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PAI'
+ name = 'user_command_9750' )
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ MESSAGE `Subroutines have been registered for commit ` &&
+ `and rollback.` TYPE 'I'.
+
+ ENDIF.
+
+ WHEN OTHERS.
+ LEAVE PROGRAM.
+ ENDCASE.
+ENDMODULE.
+
+***************** Dialog modules for 9760 ****************************
+
+MODULE status_9760 OUTPUT.
+ SET PF-STATUS 'STATUS9760'.
+ SET TITLEBAR 'TITLE9760'.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PBO'
+ name = 'status_9760' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ dynnr = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9760 INPUT.
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PAI'
+ name = 'user_command_9760' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'GO' OR 'ENTER'.
+
+ IF perform = abap_true.
+ "Registered subroutines cannot have any parameter interface.
+ "Therefore, data can only be passed through external interfaces,
+ "for example, the ABAP memory.
+ EXPORT values = tab_struc TO MEMORY ID 'DEMO_INSERT'.
+ PERFORM insert ON COMMIT.
+
+ MESSAGE `A subroutine that inserts the entries in the ` &&
+ `database table has been registered. ` &&
+ `When you select a commit option in the next step, ` &&
+ `COMMIT WORK and COMMIT WORK AND WAIT have ` &&
+ `the same effect. The subroutines are executed in ` &&
+ `the current work process in this case.` TYPE 'I'.
+ ELSE.
+ CALL FUNCTION 'ZDEMO_ABAP_MODIFY_FU' IN UPDATE TASK
+ EXPORTING
+ values = tab_struc.
+ MESSAGE `An update function module that inserts the ` &&
+ `entries in the database table has ` &&
+ `been registered.` TYPE 'I'.
+ ENDIF.
+ WHEN OTHERS.
+ LEAVE PROGRAM.
+ ENDCASE.
+ENDMODULE.
+
+***************** Dialog modules for 9770 ****************************
+
+MODULE status_9770 OUTPUT.
+ SET PF-STATUS 'STATUS9770'.
+ SET TITLEBAR 'TITLE9770'.
+
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PBO'
+ name = 'status_9770' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ dynnr = sy-dynnr.
+
+ IF perform = 'X'.
+ LOOP AT SCREEN INTO DATA(scr).
+ IF scr-name = 'EXCURSION_WP'
+ OR scr-name = 'WAIT'
+ OR scr-name = 'FAIL_LUW'
+ OR scr-name = 'ERR'
+ OR scr-name = 'TERMINATE'
+ OR scr-name = 'ERROR_A'.
+ scr-invisible = '1'.
+ MODIFY SCREEN FROM scr.
+ ENDIF.
+ ENDLOOP.
+ ENDIF.
+ENDMODULE.
+
+MODULE user_command_9770 INPUT.
+ lcl=>create_log_entries(
+ VALUE #( log = VALUE #( context = 'PAI'
+ name = 'user_command_9770' )
+ called = abap_true
+ luw_key = abap_true
+ tx_state = abap_true
+ wp_info = abap_true ) ).
+
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+
+ WHEN 'GO' OR 'ENTER' OR 'OK'.
+
+ CASE 'X'.
+
+ WHEN commit.
+ IF perform = abap_false.
+ CALL FUNCTION 'ZDEMO_ABAP_LOG_FU' IN UPDATE TASK
+ EXPORTING
+ log = log_itab.
+ MESSAGE `An update function module that inserts ` &&
+ `entries for the log has been registered. ` &&
+ `COMMIT WORK is about to be executed.` TYPE 'I'.
+ ELSE.
+ PERFORM update_log ON COMMIT.
+
+ MESSAGE `A subroutine that inserts entries for the ` &&
+ `log has been registered ` &&
+ `COMMIT WORK is about to be executed.` TYPE 'I'.
+ ENDIF.
+
+ COMMIT WORK.
+
+ SELECT COUNT(*) FROM zdemo_abap_luw_t INTO @DATA(entries).
+
+ MESSAGE `COMMIT WORK has been executed. Current ` &&
+ `number of database table entries: ` &&
+ entries &&
+ `. If it is 4 and not 1, the update will be done ` &&
+ `asynchronously.` TYPE 'I'.
+ WHEN commit_wait.
+ IF perform = abap_false.
+ CALL FUNCTION 'ZDEMO_ABAP_LOG_FU' IN UPDATE TASK
+ EXPORTING
+ log = log_itab.
+ MESSAGE `An update function module that inserts ` &&
+ `entries for the log has been registered. ` &&
+ `COMMIT WORK AND WAIT is about to be executed.` TYPE 'I'.
+ ELSE.
+ PERFORM update_log ON COMMIT.
+
+ MESSAGE `A subroutine that inserts entries for the ` &&
+ `log has been registered ` &&
+ `COMMIT WORK AND WAIT is about to be executed.` TYPE 'I'.
+ ENDIF.
+
+ COMMIT WORK AND WAIT.
+
+ SELECT COUNT(*) FROM zdemo_abap_luw_t INTO @entries.
+
+ MESSAGE `COMMIT WORK AND WAIT has been executed. Current ` &&
+ `number of database table entries: ` &&
+ entries &&
+ `. If it is 1, the update has been done synchronously.` TYPE 'I'.
+ WHEN rollback.
+ ROLLBACK WORK.
+
+ MESSAGE `ROLLBACK WORK has been executed. A rollback has ` &&
+ `been triggered. The original database table content ` &&
+ `should be displayed.`
+ TYPE 'I'.
+
+ MESSAGE `Note: As an exception, and only for this demo ` &&
+ `example, the sample implementation includes a ` &&
+ `database update to the log table after the ` &&
+ `table after the rollback, just to show the progress of the ` &&
+ `execution up to that point.` TYPE 'I' DISPLAY LIKE 'E'.
+
+ "Update log table
+ zcl_demo_abap_sap_luw_helper=>create_log_entries( log_itab ).
+
+ "Log information for triggering a rollback
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 99
+ context = '-'
+ name = '-'
+ details = `Rollback triggered`
+ timestamp = utclong_current( ) ) ) ).
+ WHEN err.
+ CALL FUNCTION 'ZDEMO_ABAP_LOG_FU' IN UPDATE TASK
+ EXPORTING
+ log = log_itab
+ cause_error = abap_true.
+
+ IF local_update = abap_true.
+ MESSAGE `A function module has been registered that ` &&
+ `causes an error (zero division). COMMIT WORK AND WAIT ` &&
+ `is about to be executed. You are directly informed ` &&
+ `about the error and the program is terminated. All ` &&
+ `changes are implicitly rolled back. You can check ` &&
+ `transaction ST22 for the error caused.` TYPE 'I'.
+ ELSE.
+ MESSAGE `Function module was registered that ` &&
+ `causes an error (zero division). COMMIT WORK AND WAIT` &&
+ ` will be excetued. All changes are implicitly rolled back.` &&
+ ` When you start over or leave the example in the next dynpro, ` &&
+ `you should be informed about the issue in the Business Workplace. ` &&
+ `Also check ST22.` TYPE 'I'.
+ ENDIF.
+
+ COMMIT WORK AND WAIT.
+
+ WHEN terminate.
+ MESSAGE `This is an error message of type A. ` &&
+ `It termiantes the program. All changes are ` &&
+ `implicitly rolled back. ` &&
+ `You may want to check the database table entries of ` &&
+ `the example that remain unchanged.` TYPE 'A'.
+ ENDCASE.
+
+ WHEN OTHERS.
+ LEAVE PROGRAM.
+ ENDCASE.
+
+ SUBMIT ('ZDEMO_ABAP_SAP_LUW_DISPL').
+ENDMODULE.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.xml
new file mode 100644
index 0000000..ea8c7f2
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw.prog.xml
@@ -0,0 +1,864 @@
+
+
+
+
+
+ ZDEMO_ABAP_SAP_LUW
+ S
+ 1
+ X
+ D$S
+ X
+
+
+ -
+
+ ZDEMO_ABAP_SAP_LUW
+ 9750
+ E
+ Delete database table entries
+ N
+ 9760
+ 027
+ 121
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_DEL_INSERT
+ SCREEN
+ 006
+ 004
+ 076
+ 003
+
+
+ CUST_CTRL
+ DBENTRIES
+ SCREEN
+ 012
+ 005
+ 068
+ 007
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX1
+ The_SAP_LUW_is_started._In_this_example,_all_the_entries_in_a_database_table_(see_below)_are_to_be_deleted.
+ 002
+ 004
+ 107
+ 107
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX2
+ The_ABAP_SQL_statement_is_implemented_in_an_update_function_module_and_a_subroutine._
+ 003
+ 004
+ 085
+ 085
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX3
+ Choose_one_of_the_following_options:
+ 004
+ 004
+ 036
+ 036
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX4
+ Current_database_table_entries:
+ 010
+ 004
+ 031
+ 031
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX5
+ Dynpro_number:
+ 021
+ 005
+ 014
+ 014
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYNNR
+ ___________
+ 021
+ 021
+ 011
+ 011
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_DEL_INSERT
+ RADIO
+ DEL_INSERT
+ Use_update_task_(CALL_FUNCTION_..._IN_UPDATE_TASK_statement)
+ 006
+ 004
+ 062
+ 062
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_DEL_INSERT
+ RADIO
+ LOCAL_UPDATE
+ Use_update_task_and_perform_local_update_(SET_UPDATE_TASK_LOCAL_statement)
+ 007
+ 004
+ 076
+ 076
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_DEL_INSERT
+ RADIO
+ PERFORM
+ Use_subroutines_(PERFORM_statement)
+ 008
+ 004
+ 037
+ 037
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9750.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9750.
+
+
+
+ -
+
+ ZDEMO_ABAP_SAP_LUW
+ 9760
+ E
+ Create database table entry
+ N
+ 9770
+ 027
+ 121
+
+
+
+ SCREEN
+ SCREEN
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX7
+ To_create_a_database_table_entry,_make_entries_in_the_following_input_fields:
+ 002
+ 003
+ 077
+ 077
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX8
+ KEY_FIELD
+ 004
+ 003
+ 009
+ 009
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ TAB_STRUC-KEY_FIELD
+ _______.__
+ 004
+ 015
+ 010
+ 010
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX11
+ Type_i
+ 004
+ 028
+ 006
+ 006
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX9
+ CH
+ 006
+ 003
+ 002
+ 002
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ TAB_STRUC-CH
+ __________
+ 006
+ 015
+ 010
+ 010
+ 001
+ CHAR
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX12
+ Type_c_length_10
+ 006
+ 028
+ 016
+ 016
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX10
+ NUM
+ 008
+ 003
+ 003
+ 003
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ TAB_STRUC-NUM
+ _______.__
+ 008
+ 015
+ 010
+ 010
+ 001
+ INT4
+ X
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX13
+ Type_i
+ 008
+ 028
+ 006
+ 006
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX14
+ Dynpro_number:
+ 011
+ 003
+ 014
+ 014
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYNNR
+ ___________
+ 011
+ 019
+ 011
+ 011
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9760.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9760.
+
+
+
+ -
+
+ ZDEMO_ABAP_SAP_LUW
+ 9770
+ E
+ End SAP LUW
+ N
+ 0000
+ 027
+ 121
+
+
+
+ SCREEN
+ SCREEN
+
+
+ RADIOGROUP
+ %A_COMMIT
+ SCREEN
+ 004
+ 003
+ 048
+ 005
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX6
+ Select_one_of_the_following_options_to_proceed:
+ 002
+ 003
+ 047
+ 047
+ 001
+ CHAR
+ N
+ X
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ %#AUTOTEXT009
+ Dynpro_number:
+ 012
+ 003
+ 014
+ 014
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYNNR
+ ___________
+ 012
+ 018
+ 011
+ 011
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+ RADIOGROUP
+ %A_COMMIT
+ RADIO
+ COMMIT
+ Asynchronous_update_with_COMMIT_WORK
+ 004
+ 003
+ 038
+ 038
+ 001
+ 1
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_COMMIT
+ RADIO
+ COMMIT_WAIT
+ Synchronous_update_with_COMMIT_WORK_AND_WAIT
+ 005
+ 003
+ 046
+ 046
+ 001
+ 1
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_COMMIT
+ RADIO
+ ROLLBACK
+ Rollback_changes_using_ROLLBACK_WORK
+ 006
+ 003
+ 038
+ 038
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_COMMIT
+ RADIO
+ ERR
+ Cause_a_failure_in_the_current_SAP_LUW
+ 007
+ 003
+ 040
+ 040
+ 001
+ CHAR
+ X
+ X
+
+
+ RADIOGROUP
+ %A_COMMIT
+ RADIO
+ TERMINATE
+ Terminate_program_with_error_message_of_type_A
+ 008
+ 003
+ 048
+ 048
+ 001
+ CHAR
+ X
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9770.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9770.
+
+
+
+
+
+
+ 000003
+ 000003
+
+
+
+ STATUS9750
+ D
+ 000001
+ 000001
+ 0001
+ Delete database table entries
+
+
+ STATUS9760
+ D
+ 000002
+ 000002
+ 0001
+ Create database table entry
+
+
+ STATUS9770
+ D
+ 000003
+ 000003
+ 0001
+ End SAP LUW
+
+
+
+
+ ENTER
+ 001
+ S
+ Enter
+
+
+ GO
+ 001
+ S
+ ICON_MAPPED_RELATION
+ @EY@
+ Go
+ Go
+ Go
+
+
+ LEAVE
+ 001
+ S
+ Exit
+
+
+
+
+ 000001
+ 0001
+ 01
+ 08
+
+
+ 000002
+ 0001
+ 01
+ 08
+
+
+ 000003
+ 0001
+ 01
+ 08
+
+
+
+
+ 000001
+ 00
+ ENTER
+ 001
+
+
+ 000001
+ 08
+ GO
+ 001
+
+
+ 000001
+ 15
+ LEAVE
+ 001
+
+
+ 000002
+ 00
+ ENTER
+ 001
+
+
+ 000002
+ 08
+ GO
+ 001
+
+
+ 000002
+ 15
+ LEAVE
+ 001
+
+
+ 000003
+ 00
+ ENTER
+ 001
+
+
+ 000003
+ 08
+ GO
+ 001
+
+
+ 000003
+ 15
+ LEAVE
+ 001
+
+
+
+
+ STATUS9750
+ ENTER
+
+
+ STATUS9750
+ GO
+
+
+ STATUS9750
+ LEAVE
+
+
+ STATUS9760
+ ENTER
+
+
+ STATUS9760
+ GO
+
+
+ STATUS9760
+ LEAVE
+
+
+ STATUS9770
+ ENTER
+
+
+ STATUS9770
+ GO
+
+
+ STATUS9770
+ LEAVE
+
+
+
+
+ A
+ 000001
+ D
+ Delete database table entries
+
+
+ P
+ 000001
+ D
+ Delete database table entries
+
+
+ B
+ 000001
+ 0001
+ D
+ Delete database table entries
+
+
+ A
+ 000002
+ D
+ Create database table entry
+
+
+ P
+ 000002
+ D
+ Create database table entry
+
+
+ B
+ 000002
+ 0001
+ D
+ Create database table entry
+
+
+ A
+ 000003
+ D
+ End SAP LUW
+
+
+ P
+ 000003
+ D
+ End SAP LUW
+
+
+ B
+ 000003
+ 0001
+ D
+ End SAP LUW
+
+
+
+
+ TITLE9750
+ Delete database table entries
+
+
+ TITLE9760
+ Create database table entry
+
+
+ TITLE9770
+ End SAP LUW
+
+
+
+
+ -
+ R
+ Demonstrating SAP LUW
+ 21
+
+
+
+
+
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.abap b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.abap
new file mode 100644
index 0000000..7071994
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.abap
@@ -0,0 +1,139 @@
+*&---------------------------------------------------------------------*
+*& Demo program used in the context of the SAP LUW ABAP cheat sheet
+*&
+*&----------------------------- NOTE -----------------------------------*
+*& The code presented in this class is intended only to support the ABAP
+*& cheat sheets. It is not intended for direct use in a production system
+*& environment. The code examples in the ABAP cheat sheets are primarily
+*& intended to provide a better explanation and visualization of the
+*& syntax and semantics of ABAP statements, not to solve concrete
+*& programming tasks. For production application programs, you should
+*& always work out your own solution for each individual case. There is
+*& no guarantee for the correctness or completeness of the code.
+*& Furthermore, there is no legal responsibility or liability for any
+*& errors or their consequences that may occur when using the the example
+*& code.
+*&---------------------------------------------------------------------*
+REPORT zdemo_abap_sap_luw_displ.
+
+DATA: ok_code LIKE sy-ucomm,
+ save_ok LIKE sy-ucomm,
+ dynnr LIKE sy-dynnr.
+
+END-OF-SELECTION.
+
+ "Checks if program is started separately
+ SELECT COUNT(*)
+ FROM zdemo_abap_logt
+ INTO @DATA(entries).
+
+ SELECT SINGLE id
+ FROM zdemo_abap_logt
+ WHERE id = 100
+ INTO @DATA(exists).
+
+ IF sy-subrc = 0 OR entries = 0.
+ DELETE FROM zdemo_abap_logt.
+
+ DATA(check) = abap_true.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 97
+ context = '-'
+ name = '-'
+ details = `Choose Start over from the menu.`
+ timestamp = utclong_current( ) ) ) ).
+ ENDIF.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #( ( id = 100
+ context = '-'
+ name = '-'
+ details = |New program executed: { sy-repid }|
+ timestamp = utclong_current( ) ) ) ).
+
+ CALL SCREEN 9780.
+
+**********************************************************************
+
+***************** Dialog modules for 9780 ****************************
+
+MODULE status_9780 OUTPUT.
+ SET PF-STATUS 'STATUS9780'.
+ SET TITLEBAR 'TITLE9780'.
+
+ "Checks for asynchronous update
+ IF check = abap_false.
+ DATA(idx) = 0.
+
+ DO 5 TIMES. "A maximum of 5 seconds of waiting time
+ SELECT SINGLE id, context
+ FROM zdemo_abap_logt
+ WHERE
+ "Entry inserted ...
+ id = 93 "by the final update function module
+ OR id = 99 "in case of ROLLBACK WORK
+ OR id = 96 "in case of the intended failure in SAP LUW
+ OR context = 'Subroutine' "if subroutines are used
+ INTO @DATA(wa). "#EC CI_CMPLX_WHERE
+
+ IF sy-subrc = 0.
+ EXIT.
+ ELSE.
+ idx = sy-index.
+ WAIT UP TO 1 SECONDS.
+ ENDIF.
+ ENDDO.
+
+ IF idx = 5.
+ MESSAGE `The asynchronous update takes too long. ` &&
+ `You may want to restart the example and try again.`
+ TYPE 'I'.
+ ENDIF.
+
+ ENDIF.
+
+ zcl_demo_abap_sap_luw_helper=>create_log_entries(
+ VALUE #(
+ ( id = 101
+ context = 'PBO'
+ name = 'status_9780'
+ details = `Module called`
+ timestamp = utclong_current( ) )
+ ( id = 102
+ context = 'PBO'
+ name = 'status_9780'
+ details = zcl_demo_abap_sap_luw_helper=>get_work_process_info( )
+ timestamp = utclong_current( ) )
+ ( id = 103
+ context = 'PBO'
+ name = 'status_9780'
+ details = `SAP LUW Key: ` &&
+ cl_system_transaction_state=>get_sap_luw_key( )
+ timestamp = utclong_current( ) )
+ ( id = 104
+ context = 'PBO'
+ name = 'status_9780'
+ details = zcl_demo_abap_sap_luw_helper=>checking_transaction_state( )
+ timestamp = utclong_current( ) ) ) ).
+
+ zcl_demo_abap_sap_luw_helper=>cc_alv_display( 'CC_DB_FINAL' ).
+ zcl_demo_abap_sap_luw_helper=>cc_alv_display( container = 'CC_WP'
+ log = abap_true ).
+ dynnr = sy-dynnr.
+ENDMODULE.
+
+MODULE user_command_9780 INPUT.
+ save_ok = ok_code.
+ CLEAR ok_code.
+
+ CASE save_ok.
+ WHEN 'STARTOVER'.
+ ROLLBACK WORK.
+ DELETE FROM zdemo_abap_logt.
+ SUBMIT ('ZDEMO_ABAP_SAP_LUW').
+ WHEN OTHERS.
+ DELETE FROM zdemo_abap_logt.
+ LEAVE PROGRAM.
+ ENDCASE.
+ENDMODULE.
diff --git a/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.xml b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.xml
new file mode 100644
index 0000000..5466da3
--- /dev/null
+++ b/src/test_abap_cheat_sheets_classic/zdemo_abap_sap_luw_displ.prog.xml
@@ -0,0 +1,240 @@
+
+
+
+
+
+ ZDEMO_ABAP_SAP_LUW_DISPL
+ S
+ 1
+ X
+ D$S
+ X
+
+
+ -
+
+ ZDEMO_ABAP_SAP_LUW_DISPL
+ 9780
+ E
+ Display database table and log
+ N
+ 9780
+ 027
+ 186
+
+
+
+ SCREEN
+ SCREEN
+
+
+ CUST_CTRL
+ CC_DB_FINAL
+ SCREEN
+ 003
+ 002
+ 074
+ 007
+
+
+ CUST_CTRL
+ CC_WP
+ SCREEN
+ 013
+ 002
+ 156
+ 014
+
+
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX15
+ Database_table_entries:
+ 001
+ 002
+ 023
+ 023
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ %#AUTOTEXT003
+ Dynpro_number:
+ 001
+ 130
+ 014
+ 014
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ TEMPLATE
+ DYNNR
+ ___________
+ 001
+ 146
+ 011
+ 011
+ 001
+ CHAR
+ X
+ X
+ N
+
+
+ SCREEN
+ SCREEN
+ TEXT
+ TX16
+ Log_database_table_entries:
+ 011
+ 002
+ 027
+ 027
+ 001
+ CHAR
+ N
+
+
+ SCREEN
+ SCREEN
+ OKCODE
+ OK_CODE
+ ____________________
+ 020
+ 020
+ 001
+ CHAR
+ X
+
+
+
+
+ PROCESS BEFORE OUTPUT.
+
+
+ MODULE STATUS_9780.
+
+
+
+ PROCESS AFTER INPUT.
+
+
+ MODULE USER_COMMAND_9780.
+
+
+
+
+
+
+ 000001
+ 000001
+
+
+
+ STATUS9780
+ D
+ 000001
+ 000001
+ 0001
+ Display database table and log
+
+
+
+
+ LEAVE
+ 001
+ S
+ Exit
+
+
+ STARTOVER
+ 001
+ S
+ ICON_SYSTEM_UNDO
+ @2W@
+ STARTOVER
+ Start over
+ Start over
+
+
+
+
+ 000001
+ 0001
+ 01
+ 08
+
+
+
+
+ 000001
+ 08
+ STARTOVER
+ 001
+
+
+ 000001
+ 15
+ LEAVE
+ 001
+
+
+
+
+ STATUS9780
+ LEAVE
+
+
+ STATUS9780
+ STARTOVER
+
+
+
+
+ A
+ 000001
+ D
+ Display database table and log
+
+
+ P
+ 000001
+ D
+ Display database table and log
+
+
+ B
+ 000001
+ 0001
+ D
+ Display database table and log
+
+
+
+
+ TITLE9780
+ Display database table and log
+
+
+
+
+ -
+ R
+ Demonstrating SAP LUW - Display
+ 31
+
+
+
+
+
diff --git a/src/zcl_demo_abap_amdp.clas.abap b/src/zcl_demo_abap_amdp.clas.abap
new file mode 100644
index 0000000..96be432
--- /dev/null
+++ b/src/zcl_demo_abap_amdp.clas.abap
@@ -0,0 +1,377 @@
+***********************************************************************
+*
+* ABAP cheat sheet: AMDP
+*
+* -------------------------- PURPOSE ----------------------------------
+* - Example to demonstrate AMDP procedures and functions. It includes
+* a CDS table function.
+* - NOTE:
+* - The example covers basics regarding AMDP method declarations
+* and implementations.
+* - The purpose is to give you a rough idea about AMDP. Therefore,
+* the SQLScript code used in the method implementations is
+* fairly simple. AMDP is not needed in simple cases like these.
+* - The example is primarily intended for the SAP BTP ABAP
+* environment. For example, in SAP BTP ABAP environment only
+* read-only operations are possible. In general, there are more
+* syntax options available in the unrestricted ABAP language scope
+* in on-premise ABAP systems. Check the ABAP Keyword Documentation
+* for more details and examples.
+*
+* ----------------------- GETTING STARTED -----------------------------
+* - Open the class with the ABAP development tools for Eclipse (ADT).
+* - Choose F9 to run the class.
+* - Check the console output.
+* - To understand the context and the ABAP syntax used, check the notes
+* included in the class as comments or refer to the respective topic
+* in the ABAP Keyword Documentation.
+* - Due to the amount of output in the console, the examples include
+* numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example
+* sections. Plus, the variable name is displayed in most cases. Hence,
+* to easier and faster find the relevant output in the console, just
+* search in the console for the number/variable name (CTRL+F in the
+* console) or use the debugger.
+*
+* ----------------------------- NOTE -----------------------------------
+* The code presented in this class is intended only to support the ABAP
+* cheat sheets. It is not intended for direct use in a production system
+* environment. The code examples in the ABAP cheat sheets are primarily
+* intended to provide a better explanation and visualization of the
+* syntax and semantics of ABAP statements, not to solve concrete
+* programming tasks. For production application programs, you should
+* always work out your own solution for each individual case. There is
+* no guarantee for the correctness or completeness of the code.
+* Furthermore, there is no legal responsibility or liability for any
+* errors or their consequences that may occur when using the the example
+* code.
+*
+***********************************************************************
+"! ABAP cheat sheet: AMDP
+"! Example to demonstrate AMDP procedures and functions.
Choose F9 in ADT to run the class.
+CLASS zcl_demo_abap_amdp DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ INTERFACES:
+ if_oo_adt_classrun, "Interface for displaying output
+ if_amdp_marker_hdb. "This interface specification is mandatory for an AMDP class
+
+ "Various internal table type specifications for the parameters of AMDP methods
+ "Note: Only table and elementary data types are possible for the parameters.
+ TYPES carr_tab TYPE STANDARD TABLE OF zdemo_abap_carr WITH EMPTY KEY.
+
+ TYPES fli_tab TYPE STANDARD TABLE OF zdemo_abap_fli WITH EMPTY KEY.
+
+ TYPES:
+ "Structured data type as basis for the table type below
+ BEGIN OF carr_fli_struc,
+ carrname TYPE zdemo_abap_carr-carrname,
+ connid TYPE zdemo_abap_flsch-connid,
+ cityfrom TYPE zdemo_abap_flsch-cityfrom,
+ cityto TYPE zdemo_abap_flsch-cityto,
+ END OF carr_fli_struc,
+
+ "Internal table type
+ carr_fli_tab TYPE STANDARD TABLE OF carr_fli_struc WITH EMPTY KEY,
+
+ "Structured data type as basis for the table type below
+ BEGIN OF fli_struc,
+ carrid TYPE zdemo_abap_flsch-carrid,
+ connid TYPE zdemo_abap_flsch-connid,
+ cityfrom TYPE zdemo_abap_flsch-cityfrom,
+ cityto TYPE zdemo_abap_flsch-cityto,
+ fltime TYPE zdemo_abap_flsch-fltime,
+ END OF fli_struc,
+
+ "Internal table type
+ flsch_tab TYPE STANDARD TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
+
+ "Various instance method declarations
+ "The selection for instance and static methods is irrelevant for the example.
+ "It is just meant to visualize that AMDP methods can be declared as either of them.
+
+ "AMDP procedure
+ "It's a simple AMDP procedure having only an output parameter with tabular type.
+ "Note the parameter declaration that includes the mandatory passing by value.
+ "This is true for all of the AMDP method declarations.
+ METHODS select_carriers
+ EXPORTING VALUE(carr_tab) TYPE carr_tab.
+
+ "AMDP procedure to call an AMDP table function
+ "As can be seen in the implementation part, this example method calls the
+ "AMDP table function get_carr_fli. AMDP table functions can only be called
+ "by other AMDP methods.
+ METHODS select_get_carr_fli
+ IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
+ EXPORTING VALUE(carr_fli_tab) TYPE carr_fli_tab.
+
+ "Various static method declarations
+
+ "The purpose of the implementation of the static constructor in this example is to
+ "fill a demo database table to have data to work with in the example.
+ CLASS-METHODS class_constructor.
+
+ "AMDP procedure
+ "This method demonstrates the calling of an AMDP procedure from SQLScript.
+ "In this example, the selection of data is 'delegated' to another AMDP method get_flights_amdp
+ "in the same AMDP class. The method declaration includes the addition RAISING with an
+ "exception class for AMDP-specific exceptions.
+ CLASS-METHODS get_flights
+ IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
+ EXPORTING VALUE(fli_tab) TYPE fli_tab
+ RAISING cx_amdp_execution_error.
+
+ "AMDP Table Function for CDS Table Function
+ "Note that, in this case, a static method declaration is required along with the special
+ "syntax FOR TABLE FUNCTION. Plus, there are no parameters specified and the declaration
+ "is made in the PUBLIC visibility section.
+ CLASS-METHODS flight_analysis FOR TABLE FUNCTION zdemo_abap_table_function.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+
+ "AMDP procedure
+ "This method demonstrates the calling of an AMDP procedure from SQLScript as mentioned above.
+ CLASS-METHODS get_flights_amdp
+ IMPORTING VALUE(carrid) TYPE zdemo_abap_fli-carrid
+ EXPORTING VALUE(fli_tab) TYPE fli_tab
+ RAISING cx_amdp_execution_error.
+
+ "AMDP table function
+ "AMDP table functions can only be called by other AMDP methods. In this example,
+ "the AMDP procedure select_get_carr_fli calls this AMDP table function.
+ METHODS get_carr_fli
+ IMPORTING VALUE(carrid) TYPE zdemo_abap_flsch-carrid
+ RETURNING VALUE(carr_fli_tab) TYPE carr_fli_tab.
+
+ CONSTANTS nl TYPE string value cl_abap_char_utilities=>newline.
+ENDCLASS.
+
+
+
+CLASS zcl_demo_abap_amdp IMPLEMENTATION.
+
+
+ METHOD class_constructor.
+ "Filling demo database tables.
+ zcl_demo_abap_flight_tables=>fill_dbtabs( ).
+ ENDMETHOD.
+
+
+ METHOD flight_analysis
+ BY DATABASE FUNCTION
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zdemo_abap_flsch "Two database tables are used and must both be specified here.
+ zdemo_abap_carr.
+* Reading data from two database tables
+ itab_cities =
+ select DISTINCT
+ zdemo_abap_flsch.mandt as client,
+ zdemo_abap_flsch.carrid as carrier_id,
+ zdemo_abap_flsch.airpfrom as airport_from,
+ zdemo_abap_flsch.airpto as airport_to,
+ zdemo_abap_flsch.fltime as flight_time,
+ zdemo_abap_flsch.distance as flight_distance,
+ zdemo_abap_flsch.distid as unit
+ from zdemo_abap_flsch;
+
+ itab_carrier_names =
+ select distinct
+ zdemo_abap_carr.mandt as client,
+ zdemo_abap_carr.carrid as carrier_id,
+ zdemo_abap_carr.carrname as carrier_name
+ from zdemo_abap_carr;
+
+* Returning joined data using an inner join
+ return
+ select fl.client, fl.carrier_id, ca.carrier_name,
+* Departure and destination airports are concatenated; then all results are joined by string aggregation
+ string_agg( concat(concat(fl.airport_from,' -> '),fl.airport_to), ', ' ORDER BY fl.airport_from) AS connections,
+* Retrieving the average flight time of all flights by carrier
+ AVG( fl.flight_time ) as avg_flight_time,
+* Retrieving the average flight distance of all flights by carrier; miles are converted to kilometers
+ avg( case 'MI'
+ when fl.unit then fl.flight_distance * 1.609
+ ELSE fl.flight_distance
+ END ) AS avg_distance
+ FROM :itab_cities AS fl
+ INNER JOIN :itab_carrier_names AS ca
+ ON ca.client = fl.client
+ AND ca.carrier_id = fl.carrier_id
+ WHERE fl.client = ca.client AND fl.carrier_id = ca.carrier_id
+ GROUP BY fl.client, ca.carrier_name, fl.carrier_id;
+ ENDMETHOD.
+
+
+ METHOD get_carr_fli
+ BY DATABASE FUNCTION
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zdemo_abap_carr zdemo_abap_flsch.
+* AMDP table function to be called by other AMDP methods only.
+* In the example, joined data from two database table are returned.
+ RETURN
+ SELECT ca.carrname, fl.connid, fl.cityfrom, fl.cityto
+ FROM zdemo_abap_carr as ca
+ INNER JOIN zdemo_abap_flsch as fl
+ ON ca.carrid = fl.carrid
+ WHERE fl.carrid = :carrid
+ ORDER BY ca.mandt, ca.carrname, fl.connid;
+ ENDMETHOD.
+
+
+ METHOD get_flights
+ BY DATABASE PROCEDURE
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zcl_demo_abap_amdp=>get_flights_amdp.
+* Another AMDP procedure is called from SQLScript
+ CALL "ZCL_DEMO_ABAP_AMDP=>GET_FLIGHTS_AMDP"(
+ carrid => :carrid,
+ fli_tab => :fli_tab );
+ ENDMETHOD.
+
+
+ METHOD get_flights_amdp
+ BY DATABASE PROCEDURE
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zdemo_abap_fli.
+* Simple data selection
+ fli_tab = SELECT *
+ FROM "ZDEMO_ABAP_FLI"
+ WHERE carrid = :carrid
+ ORDER BY carrid;
+ ENDMETHOD.
+
+
+ METHOD if_oo_adt_classrun~main.
+
+ DATA(output) = NEW zcl_demo_abap_display( out ).
+
+ output->display( `ABAP Cheat Sheet Example: ABAP AMDP` ).
+
+ output->display( `1) AMDP procedure` ).
+
+ "Declaring an internal table to store the data that are
+ "returned by the following method.
+ "You could also choose to create the internal table inline
+ "within the method call,
+ "i. e. like ... IMPORTING carr_tab = DATA(tab) ).
+ DATA amdp_proc_res TYPE zcl_demo_abap_amdp=>carr_tab.
+
+ "Since the method is declared as an instance method, an instance
+ "has to be created. Here, the instance constructor NEW is used
+ "in a standalone method call that includes a chained method call.
+ NEW zcl_demo_abap_amdp( )->select_carriers(
+ IMPORTING carr_tab = amdp_proc_res ).
+
+ output->display( input = amdp_proc_res name = `amdp_proc_res` ).
+
+**********************************************************************
+
+ output->next_section( `2) Calling an AMDP Procedure from SQLScript` ).
+
+ "As can be seen in the method implementation part, this AMDP procedure
+ "includes an AMDP procedure call from SQLScript.
+ "In this example, the AMDP procedure get_flights_amdp is called by
+ "get_flights which is meant to select data from a database table.
+ "The returned result is displayed.
+ TRY.
+
+ zcl_demo_abap_amdp=>get_flights( EXPORTING carrid = 'LH'
+ IMPORTING fli_tab = DATA(call_amdp_res) ).
+
+ CATCH cx_amdp_execution_error INTO DATA(error1).
+
+ output->display( error1->get_text( ) ).
+
+ ENDTRY.
+
+ output->display( input = call_amdp_res name = `call_amdp_res` ).
+
+
+**********************************************************************
+
+ output->next_section( `3) AMDP Table Function for AMDP Method` ).
+
+ "The AMDP procedure select_get_carr_fli calls the AMDP table function
+ "get_carr_fli in the implementation part. AMDP table functions can
+ "only be called by other AMDP methods.
+ TRY.
+
+ NEW zcl_demo_abap_amdp( )->select_get_carr_fli(
+ EXPORTING carrid = 'LH'
+ IMPORTING carr_fli_tab = DATA(amdp_tab_func) ).
+
+ CATCH cx_amdp_execution_error INTO DATA(error2).
+
+ out->write( error2->get_text( ) ).
+
+ ENDTRY.
+
+ output->display( input = amdp_tab_func name = `amdp_tab_func` ).
+
+ "Note: When commented in, the following code results in a runtime
+ "error since you cannot call an AMDP function in ABAP directly.
+* NEW zcl_demo_abap_amdp( )->get_carr_fli(
+* EXPORTING carrid = 'LH' ).
+
+**********************************************************************
+
+ output->next_section( `4) AMDP Table Function for CDS Table Function` ).
+
+
+ "The example demonstrates that a CDS table function can be used as a
+ "data source of ABAP SQL read statements.
+ "You might want to navigate to the DDL source after FROM by holding
+ "CTRL and clicking the DDL source name in ADT to see the details.
+ "Or, just check out the F2 help.
+ "In this example, the CDS table function is implemented in a way to
+ "return accumulated data.
+ "In the method implementation for flight_analysis, first two kinds of
+ "data sets from two database tables are gathered. These data sets are
+ "joined using an inner join. There, some expressions are included
+ "(strings are aggregated, average values are determined).
+
+ SELECT * FROM zdemo_abap_table_function
+ INTO TABLE @DATA(cds_tab_func).
+
+ output->display( input = cds_tab_func name = `cds_tab_func` ).
+
+ ENDMETHOD.
+
+
+ METHOD select_carriers
+ BY DATABASE PROCEDURE
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zdemo_abap_carr.
+* Simple data selection
+ carr_tab = SELECT *
+ FROM "ZDEMO_ABAP_CARR"
+ ORDER BY carrid;
+ ENDMETHOD.
+
+
+ METHOD select_get_carr_fli
+ BY DATABASE PROCEDURE
+ FOR HDB
+ LANGUAGE SQLSCRIPT
+ OPTIONS READ-ONLY
+ USING zcl_demo_abap_amdp=>get_carr_fli.
+* AMDP procedure to call an AMDP table function as specified after USING
+ carr_fli_tab = SELECT *
+ FROM "ZCL_DEMO_ABAP_AMDP=>GET_CARR_FLI"(
+ carrid => :carrid );
+ ENDMETHOD.
+ENDCLASS.
+
diff --git a/src/zcl_demo_abap_amdp.clas.xml b/src/zcl_demo_abap_amdp.clas.xml
new file mode 100644
index 0000000..f24acab
--- /dev/null
+++ b/src/zcl_demo_abap_amdp.clas.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ZCL_DEMO_ABAP_AMDP
+ E
+ ABAP cheat sheet: AMDP
+ 1
+ X
+ X
+ X
+
+
+
+
diff --git a/src/zcl_demo_abap_constructor_expr.clas.abap b/src/zcl_demo_abap_constructor_expr.clas.abap
new file mode 100644
index 0000000..d9f89b7
--- /dev/null
+++ b/src/zcl_demo_abap_constructor_expr.clas.abap
@@ -0,0 +1,1387 @@
+***********************************************************************
+*
+* ABAP cheat sheet: Constructor expressions
+*
+* -------------------------- PURPOSE ----------------------------------
+* - Example to demonstrate the use of constructor expressions.
+* - Topics covered: Operators VALUE, CORRESPONDING, NEW, CONV, EXACT, REF,
+* CAST, COND, SWITCH, FILTER, REDUCE, iteration expressions with FOR,
+* LET expressions
+*
+* ----------------------- GETTING STARTED -----------------------------
+* - Open the class with the ABAP development tools for Eclipse (ADT).
+* - Choose F9 to run the class.
+* - Check the console output.
+* - To understand the context and the ABAP syntax used, refer to the
+* notes included in the class as comments or refer to the respective
+* topic in the ABAP Keyword Documentation.
+* - Due to the amount of console output, the examples contain numbers
+* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
+* Also, the variable name is displayed in most cases. So to find
+* the relevant output in the console easier and faster, just search
+* for the number/variable name in the console (CTRL+F in the console)
+* or use the debugger.
+*
+* ----------------------------- NOTE -----------------------------------
+* The code presented in this class is intended only to support the ABAP
+* cheat sheets. It is not intended for direct use in a production system
+* environment. The code examples in the ABAP cheat sheets are primarily
+* intended to provide a better explanation and visualization of the
+* syntax and semantics of ABAP statements, not to solve concrete
+* programming tasks. For production application programs, you should
+* always work out your own solution for each individual case. There is
+* no guarantee for the correctness or completeness of the code.
+* Furthermore, there is no legal responsibility or liability for any
+* errors or their consequences that may occur when using the the example
+* code.
+*
+***********************************************************************
+"! ABAP cheat sheet: Constructor expressions
+"! Example to demonstrate the use of constructor expressions.
Choose F9 in ADT to run the class.
+CLASS zcl_demo_abap_constructor_expr DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ INTERFACES: if_oo_adt_classrun.
+
+protected section.
+ PRIVATE SECTION.
+ TYPES: BEGIN OF line1,
+ col1 TYPE i,
+ col2 TYPE i,
+ END OF line1,
+ BEGIN OF line2,
+ col2 TYPE i,
+ col3 TYPE i,
+ col4 TYPE i,
+ END OF line2,
+ BEGIN OF s1_type,
+ comp1 TYPE c LENGTH 1,
+ comp2 TYPE string,
+ comp3 TYPE i,
+ END OF s1_type,
+ BEGIN OF s2_type,
+ comp1 TYPE string,
+ comp2 TYPE c LENGTH 1,
+ comp3 TYPE i,
+ comp4 TYPE i,
+ END OF s2_type.
+
+ CLASS-DATA:
+ "Deep structures as examples to demonstrate the CORRESPONDING operator
+ BEGIN OF struc1,
+ comp1 TYPE c LENGTH 1 VALUE 'W',
+ BEGIN OF struc_nested,
+ comp1 TYPE c LENGTH 1 VALUE 'X',
+ BEGIN OF comp2,
+ col1 TYPE c LENGTH 1 VALUE 'Y',
+ col2 TYPE c LENGTH 1 VALUE 'Z',
+ END OF comp2,
+ END OF struc_nested,
+ itab TYPE TABLE OF line1 WITH EMPTY KEY,
+ END OF struc1,
+ BEGIN OF struc2,
+ BEGIN OF struc_nested,
+ comp1 TYPE string,
+ comp2 TYPE string,
+ comp3 TYPE string,
+ END OF struc_nested,
+ itab TYPE TABLE OF line2 WITH EMPTY KEY,
+ comp4 TYPE i,
+ END OF struc2,
+ s1 TYPE s1_type,
+ s2 TYPE s2_type,
+ tab1 TYPE TABLE OF s1_type WITH EMPTY KEY,
+ tab2 TYPE TABLE OF s2_type WITH EMPTY KEY,
+ tab3 TYPE TABLE OF s2_type WITH EMPTY KEY,
+ tab4 TYPE SORTED TABLE OF s2_type WITH NON-UNIQUE KEY comp3,
+ nl TYPE string..
+
+ CLASS-METHODS:
+ fill_deep_structures,
+ fill_struc_and_tab.
+
+ENDCLASS.
+
+
+
+CLASS zcl_demo_abap_constructor_expr IMPLEMENTATION.
+
+
+ METHOD fill_deep_structures.
+ "Clearing all contents of struc2
+ CLEAR struc2.
+ "Filling nested tables in deep structures
+ struc2-struc_nested = VALUE #( comp1 = `aaa`
+ comp2 = `bbb`
+ comp3 = `ccc` ).
+
+ struc1-itab = VALUE #(
+ ( col1 = 111 col2 = 222 )
+ ( col1 = 333 col2 = 444
+ ) ).
+
+ struc2-itab = VALUE #(
+ ( col2 = 1 col3 = 2 col4 = 3 )
+ ( col2 = 4 col3 = 5 col4 = 6 )
+ ( col2 = 7 col3 = 8 col4 = 9 )
+ ).
+
+ "Filling individual component that is not shared by both structures
+ struc2-comp4 = 999.
+ ENDMETHOD.
+
+
+ METHOD fill_struc_and_tab.
+ CLEAR: s1, s2, tab1, tab2, tab3.
+
+ s1 = VALUE #( comp1 = 'A' comp2 = `bbb` comp3 = 1 ).
+
+ s2 = VALUE #( comp1 = `ccc` comp2 = 'D' comp3 = 2 comp4 = 3 ).
+
+ tab1 = VALUE #(
+ ( comp1 = 'A' comp2 = `bbb` comp3 = 1 )
+ ( comp1 = 'B' comp2 = `ccc` comp3 = 2 )
+ ( comp1 = 'C' comp2 = `ddd` comp3 = 3 ) ).
+
+ tab2 = VALUE #(
+ ( comp1 = `eee` comp2 = 'F' comp3 = 4 comp4 = 5 )
+ ( comp1 = `ggg` comp2 = 'H' comp3 = 6 comp4 = 7 )
+ ( comp1 = `iii` comp2 = 'J' comp3 = 8 comp4 = 9 ) ).
+
+ tab3 = VALUE #(
+ ( comp1 = `aaa` comp2 = 'B' comp3 = 1 comp4 = 2 )
+ ( comp1 = `ccc` comp2 = 'D' comp3 = 3 comp4 = 4 )
+ ( comp1 = `eee` comp2 = 'F' comp3 = 5 comp4 = 6 )
+ ( comp1 = `ggg` comp2 = 'H' comp3 = 7 comp4 = 8 )
+ ( comp1 = `iii` comp2 = 'J' comp3 = 9 comp4 = 10 ) ).
+
+ tab4 = tab3.
+ ENDMETHOD.
+
+
+ METHOD if_oo_adt_classrun~main.
+
+ DATA(output) = NEW zcl_demo_abap_display( out ).
+
+ output->display( `ABAP Cheat Sheet Example: Constructor expressions` ).
+
+ output->display( `VALUE` ).
+ output->display( `1) Structures: Populating a flat structure` ).
+
+ "A flat structure is created based on a data type defined with a
+ "TYPES statement. The structure is then filled using a constructor
+ "expression with VALUE by specifying the components and assigning
+ "values. Here, the type can be inferred, hence, a # character can be used.
+
+ TYPES: BEGIN OF struc_type,
+ num TYPE i,
+ char1 TYPE c LENGTH 3,
+ char2 TYPE c LENGTH 3,
+ END OF struc_type.
+
+ DATA struc TYPE struc_type.
+
+ "Filling structure
+ struc = VALUE #( num = 1 char1 = 'aaa' char2 = 'abc' ).
+
+ output->display( input = struc name = `struc` ).
+
+**********************************************************************
+
+ output->next_section( `2) Structures: Omitting value assignment to components / BASE addition` ).
+
+ "The same structure is then filled purposely omitting components, i.
+ "e. these components remain initial.
+
+ struc = VALUE #( char1 = 'bbb' ).
+
+ output->display( input = struc name = `struc` ).
+
+ "You can use the BASE addition to retain existing content
+ "Compare with the BASE example further down regarding internal tables: There are
+ "no extra parentheses within the outer pair of parentheses.
+ struc = VALUE #( BASE struc char2 = 'xyz' ).
+
+ output->display( input = struc name = `struc` ).
+
+**********************************************************************
+
+ output->next_section( `3) Structures: Inline declaration, explicit type specification` ).
+
+ "The example demonstrates a variable that is declared inline. Here,
+ "the result is a structure which is filled using a constructor
+ "expression with VALUE and by specifying the components and assigning
+ "values in parentheses. The structure type is specified explicitly.
+ "The # symbol would not work since no type can be inferred from the
+ "specified parameters.
+
+ DATA(struc_inl) = VALUE struc_type( num = 3
+ char1 = 'ccc'
+ char2 = 'def' ).
+
+ output->display( input = struc_inl name = `struc_inl` ).
+
+**********************************************************************
+
+ output->next_section( `4) Internal tables: Declaration and population` ).
+
+ "The example demonstrates the declaration of an internal table. The
+ "internal table is then filled using a constructor expression with
+ "VALUE.
+ "The type can be inferred here and need not be specified explicitly.
+ "Note the extra pair of parentheses in which the components are
+ "specified and assigned values. In the example, 3 lines are added to
+ "the table. For one line, some components are purposely not assigned.
+
+ DATA itab TYPE TABLE OF struc_type WITH EMPTY KEY.
+
+ itab = VALUE #( ( num = 1 char1 = 'aaa' char2 = 'abc' )
+ ( num = 2 char1 = 'bbb' char2 = 'def' )
+ ( num = 3 char1 = 'ccc' ) ).
+
+ output->display( input = itab name = `itab` ).
+
+**********************************************************************
+
+ output->next_section( `5) Internal tables: Inline declaration, explicit type specification` ).
+
+ "The example demonstrates an internal table declared inline that is
+ "filled using a constructor expression with VALUE by specifying the
+ "internal table type explicitly. Note that the internal table type
+ "cannot be generic in this context.
+
+ TYPES: itab_type TYPE STANDARD TABLE OF struc_type
+ WITH NON-UNIQUE KEY num.
+
+ DATA(itab2) = VALUE itab_type(
+ ( num = 4 char1 = 'ddd' char2 = 'ghi' )
+ ( num = 5 char1 = 'eee' char2 = 'jkl' ) ).
+
+
+ DATA(str_table) = VALUE string_table( ( `this` )
+ ( `is a` )
+ ( `table` )
+ ( `of type string` ) ).
+
+ output->display( input = itab2 name = `itab2` ).
+ output->display( input = str_table name = `str_table` ).
+
+**********************************************************************
+
+ output->next_section( `6) LINES OF addition` ).
+
+ "Using the LINES OF addition, you can add lines of other tables.
+ "Note: The line type of the other internal table must match the one of
+ "the target internal table. Using FROM/TO, the table line selection can
+ "be further restricted. Without FROM/TO, all lines of the table are
+ "respected.
+
+ itab2 = VALUE #( ( num = 6 char1 = 'fff' char2 = 'mno' )
+ ( LINES OF itab )
+ ( LINES OF itab FROM 1 TO 2 ) ).
+
+ output->display( input = itab2 name = `itab2` ).
+
+**********************************************************************
+
+ output->next_section( `7) BASE addition for keeping existing data` ).
+
+ "Using the BASE addition, you can keep existing content of the source
+ "internal table.
+
+ itab2 = VALUE #( BASE itab2 ( num = 7 char1 = 'ggg' char2 = 'pqr' ) ).
+
+ output->display( input = itab2 name = `itab2` ).
+
+**********************************************************************
+
+ output->next_section( `8) Assignemnt with the VALUE operator without specifying content in parentheses` ).
+
+ "Using the VALUE operator without populating anything in the parentheses,
+ "data objects are initialized.
+
+ "elementary types
+ DATA(some_num) = 123.
+ some_num = VALUE #( ).
+
+ DATA(another_num) = VALUE i( ).
+
+ DATA(some_str) = `hallo`.
+ some_str = VALUE #( ).
+
+ "Initializing internal table/structure
+ str_table = VALUE #( ).
+ struc = VALUE #( ).
+
+ output->display( input = some_num name = `some_num` ).
+ output->display( input = another_num name = `another_num` ).
+ output->display( input = some_str name = `some_str` ).
+ output->display( input = str_table name = `str_table` ).
+ output->display( input = struc name = `struc` ).
+
+**********************************************************************
+
+ output->next_section( `Excursions: VALUE operator in use with ABAP statements and ABAP SQL statements` ).
+
+ "The following examples use ABAP and ABAP SQL statements in which table lines
+ "are constructed inline using the VALUE operator.
+
+ output->display( `9) Modifying internal table from a structure created inline` ).
+
+ MODIFY TABLE itab2 FROM VALUE #( num = 7 char1 = 'hhh' char2 = 'stu' ).
+
+ output->display( input = itab2 name = `itab2` ).
+
+**********************************************************************
+
+ output->next_section( `10) Inserting a table line that is created inline into an internal table` ).
+
+ INSERT VALUE #( num = 8 char1 = 'iii' char2 = 'vwx' ) INTO TABLE itab2.
+
+ output->display( input = itab2 name = `itab2` ).
+
+**********************************************************************
+
+ output->next_section( `11) Deleting a table entry based on a line created inline` ).
+
+ DELETE TABLE itab2 FROM VALUE #( num = 3 ).
+
+ output->display( input = itab2 name = `itab2` ).
+
+**********************************************************************
+
+ output->next_section( `12) Modifying a database table based on an internal table created inline` ).
+
+ "Deleting demo database table entries for the following example
+ DELETE FROM zdemo_abap_carr.
+
+ MODIFY zdemo_abap_carr FROM TABLE @( VALUE #(
+ ( carrid = 'CO'
+ carrname = 'Continental Airlines'
+ currcode = 'USD'
+ url = 'http://www.continental.com' )
+ ( carrid = 'SQ'
+ carrname = 'Singapore Airlines'
+ currcode = 'SGD'
+ url = 'http://www.singaporeair.com' )
+ ) ).
+
+ "Retrieving table entries for display purposes
+ SELECT FROM zdemo_abap_carr
+ FIELDS carrid, carrname, currcode, url
+ ORDER BY carrid
+ INTO TABLE @DATA(itab_carr).
+
+ output->display( input = itab_carr name = `itab_carr` ).
+
+**********************************************************************
+
+ output->next_section( `Excursion: Deep structures and tables` ).
+ output->display( `13) Deep structure` ).
+
+ "The example demonstrates the use of constructor expressions with
+ "VALUE in the context of a deep structure. Here, a structure is declared
+ "inline and filled. The structure type includes a nested structure. The
+ "nested structure is filled using a nested VALUE expression.
+
+ TYPES: BEGIN OF deep_struc_ty,
+ num TYPE i,
+ char1 TYPE c LENGTH 3,
+ BEGIN OF substruc,
+ int TYPE i,
+ str TYPE string,
+ END OF substruc,
+ END OF deep_struc_ty.
+
+ DATA(deep_struc) = VALUE deep_struc_ty( num = 1
+ char1 = 'aaa'
+ substruc = VALUE #( int = 123 str = `hallo` ) ).
+
+ output->display( input = deep_struc name = `deep_struc` ).
+
+**********************************************************************
+
+ output->next_section( `14) Deep internal table` ).
+
+ "A deep internal table is created. Also here, nested VALUE
+ "expressions are demonstrated.
+
+ TYPES: BEGIN OF deep_struc_ty2,
+ char TYPE c LENGTH 3,
+ tab TYPE TABLE OF i WITH EMPTY KEY,
+ END OF deep_struc_ty2.
+
+ TYPES: itab_deep_type TYPE STANDARD TABLE OF deep_struc_ty2
+ WITH NON-UNIQUE KEY char.
+
+ DATA(deep_itab) = VALUE itab_deep_type(
+ ( char = 'aaa' tab = VALUE #( ( 1 ) ( 2 ) ( 3 ) ) )
+ ( char = 'bbb' tab = VALUE #( ( 4 ) ( 5 ) ( 6 ) ) ) ).
+
+ output->display( input = deep_itab name = `deep_itab` ).
+
+**********************************************************************
+
+ output->next_section( `CORRESPONDING` ).
+ output->display( `Simple Examples with structures and internal tables` ).
+
+ "Method to fill demo structures and internal tables
+ "with values to work with
+ fill_struc_and_tab( ).
+
+ output->display( `15) Original structure and table content` ).
+
+ "Displaying the original structures and tables that are filled in the
+ "course of a method call. The structures and tables are filled anew
+ "throughout the examples so that all CORRESPONDING expressions are based
+ "on the same values.
+
+ output->display( input = s1 name = `s1` ).
+ output->display( input = s2 name = `s2` ).
+ output->display( input = tab1 name = `tab1` ).
+ output->display( input = tab2 name = `it_st` ).
+
+**********************************************************************
+
+ output->next_section( `16) CORRESPONDING without addition` ).
+
+ "The target structure and table have a different type but identically
+ "named components. The identically named components are filled. Note
+ "that the target variables are initialized here. Also note the effect
+ "of an automatic conversion of a variable-length string to a
+ "fixed-length string (one component is typed with c, the other,
+ "identically named component, is of type string).
+
+ s2 = CORRESPONDING #( s1 ).
+
+ tab2 = CORRESPONDING #( tab1 ).
+
+ output->display( input = s2 name = `s2` ).
+ output->display( input = tab2 name = `tab2` ).
+
+**********************************************************************
+
+ output->next_section( `17) BASE addition for keeping original content` ).
+
+ "The BASE addition keeps the original content. Structure: The non-
+ "identical component name retains its value. Internal table: Existing
+ "table lines are kept.
+
+ fill_struc_and_tab( ).
+
+ s2 = CORRESPONDING #( BASE ( s2 ) s1 ).
+
+ tab2 = CORRESPONDING #( BASE ( tab2 ) tab1 ).
+
+ output->display( input = s2 name = `s2` ).
+ output->display( input = tab2 name = `tab2` ).
+
+**********************************************************************
+
+ output->next_section( `18) MAPPING/EXCEPT additions` ).
+
+ "The example demonstrates the additions MAPPING and EXCEPT. MAPPING:
+ "One component of the target structure is assigned the value of a
+ "dedicated component of the source structure. EXCEPT: All corresponding
+ "components are assigned except a specific one.
+
+ fill_struc_and_tab( ).
+
+ s2 = CORRESPONDING #( s1 MAPPING comp4 = comp3 ).
+
+ tab2 = CORRESPONDING #( tab1 EXCEPT comp1 ).
+
+ output->display( input = s2 name = `s2` ).
+ output->display( input = tab2 name = `tab2` ).
+
+**********************************************************************
+
+ output->next_section( `CORRESPONDING: Demonstrating various` &&
+ ` additions using deep structures` ).
+
+ output->display( `19) Original content of deep structures` ).
+
+ "Displaying the original deep structures and tables that are filled in
+ "the course of a method call. The deep structures and tables are filled
+ "anew throughout the examples so that all CORRESPONDING expressions are
+ "based on the same values.
+
+ "Method to fill demo deep structures and internal tables
+ "with values to work with
+ fill_deep_structures( ).
+
+ output->display( input = struc1 name = `struc1` ).
+ output->display( input = struc2 name = `struc2` ).
+
+**********************************************************************
+
+ output->next_section( `20) CORRESPONDING without addition` ).
+
+ "CORRESPONDING operator without addition
+ "Existing contents of identically named components are replaced.
+ "Existing contents of components in the target structure that are not
+ "available in the source structure are initialized.
+ "Contents of the nested structure struc_nested is converted to
+ "string. Note that the two components of the nested structure in
+ "component struc_nested-comp2 of struc1 are drawn together when being
+ "converted to string.
+ "Contents of struc2-itab are replaced by table contents of struc1-
+ "itab. Note the value assignment, for example, for col2 in struc2-itab.
+ "Despite the fact that there is no identically named component comp1 in
+ "the target structure, values are assigned starting with the first
+ "column of the source structure. Check the conversion rules for
+ "internal tables.
+
+ struc2 = CORRESPONDING #( struc1 ).
+
+ output->display( input = struc2 name = `struc2` ).
+
+**********************************************************************
+
+ output->next_section( `21) DEEP addition` ).
+
+ "CORRESPONDING operator with the addition DEEP
+ "Existing contents of identically named components are replaced.
+ "Existing contents of components in the target structure that are not
+ "available in the source structure are initialized.
+ "Contents of the nested structure struc_nested is converted to
+ "string. Note that the two components of the nested structure in
+ "component struc_nested-comp2 of struc1 are drawn together when being
+ "converted to string.
+ "Contents of struc2-itab are replaced by table contents of struc1-
+ "itab. Due to the addition DEEP, the value assignment happens for
+ "identically named components in the nested table. Hence, only col2 as
+ "the only shared and identically named component is filled.
+
+ fill_deep_structures( ).
+
+ struc2 = CORRESPONDING #( DEEP struc1 ).
+
+ output->display( input = struc2 name = `struc2` ).
+
+**********************************************************************
+
+ output->next_section( `22) BASE addition` ).
+
+ "CORRESPONDING operator with the addition BASE
+ "Existing contents of identically named components are replaced.
+ "Existing contents of components in the target structure that are not
+ "available in the source structure are kept.
+ "Contents of the nested structure struc_nested is converted to
+ "string. Note that the two components of the nested structure in
+ "component struc_nested-comp2 of struc1 are drawn together when being
+ "converted to string.
+ "Contents of struc2-itab are replaced by table contents of struc1-
+ "itab. The value assignment in the nested table happens like using the
+ "CORRESPONDING operator without addition. Note the value assignment, for
+ "example, for col2 in struc2-itab. Despite the fact that there is no
+ "identically named component col1 in the target structure, values are
+ "assigned starting with the first column of the source structure. Check
+ "the conversion rules for internal tables.
+
+ fill_deep_structures( ).
+
+ struc2 = CORRESPONDING #( BASE ( struc2 ) struc1 ).
+
+ output->display( input = struc2 name = `struc2` ).
+
+**********************************************************************
+
+ output->next_section( `23) DEEP BASE addition` ).
+
+ "CORRESPONDING operator with the additions DEEP BASE
+ "Existing contents of identically named components are replaced.
+ "Existing contents of components in the target structure that are not
+ "available in the source structure are kept.
+ "Contents of the nested structure struc_nested is converted to
+ "string. Note that the two components of the nested structure in
+ "component struc_nested-comp2 of struc1 are drawn together when being
+ "converted to string.
+ "Contents of struc2-itab are replaced by table contents of struc1-
+ "itab. The value assignment in the nested table happens like using the
+ "CORRESPONDING operator with the addition DEEP. That is, the value
+ "assignment happens for identically named components in the nested table.
+ "Hence, only col2 as the only shared and identically named component is filled.
+
+ fill_deep_structures( ).
+
+ struc2 = CORRESPONDING #( DEEP BASE ( struc2 ) struc1 ).
+
+ output->display( input = struc2 name = `struc2` ).
+
+**********************************************************************
+
+ output->next_section( `NEW` ).
+ output->display( `26) Creating Anonymous Data Objects` ).
+
+ "The examples show the creation of anonymous data objects.
+ "First, data reference variables are declared using a DATA statement.
+ "Here, one variable is declared with a complete type, the other one with
+ "a generic type.
+ "Then, anonymous data objects are created using the NEW operator. For
+ "one example, the type can be inferred. In the other example, the type
+ "is specified explicitly.
+ "The next examples show the direct assigning of values.
+ "Furthermore, inline declarations can be used to avoid the prior
+ "declaration of a variable.
+
+ "Declaring data reference variables
+ DATA dref1 TYPE REF TO i. "Complete type
+ DATA dref2 TYPE REF TO data. "Generic type
+
+ "Creating anonymous data objects
+ "Here, no parameters are specified within the parentheses meaning the
+ "data objects retain their initial values.
+ dref1 = NEW #( ).
+ dref2 = NEW string( ).
+
+ "Directly assigning values within the parentheses.
+ dref1 = NEW #( 123 ).
+ dref2 = NEW string( `hallo` ).
+
+ "Inline declaration, explicit type specification
+ DATA(dref3) = NEW i( 456 ).
+
+ "Another constructor expression specified within the parentheses
+ DATA tx TYPE string VALUE `world`.
+ DATA(dref4) = NEW string( `Hello ` && tx && CONV string( '!' ) ).
+
+ DATA dref5 TYPE REF TO string_table.
+ dref5 = NEW #( VALUE string_table( ( `a` ) ( `b` ) ) ).
+
+ "Structured type; named arguments within the parentheses
+ DATA(dref6) = NEW zdemo_abap_carr( carrid = 'AA'
+ carrname = 'American Airlines' ).
+
+ output->display( input = dref1 name = `dref1` ).
+ output->display( input = dref2 name = `dref2` ).
+ output->display( input = dref3 name = `dref3` ).
+ output->display( input = dref4 name = `dref4` ).
+ output->display( input = dref5 name = `dref5` ).
+ output->display( input = dref6 name = `dref6` ).
+
+**********************************************************************
+
+ output->next_section( `27) Creating Instances of Classes` ).
+
+ "The example demonstrates the creation of instances of classes.
+ "First, an object reference variable is declared with a DATA statement.
+ "As a next step, an instance of a class is created. The type can be
+ "inferred here. The class has a constructor method defined. Hence, the
+ "parentheses contain the parameter binding for the constructor method.
+ "Here, it is only one parameter. That means the explicit specification
+ "of the parameter name is not needed and the value can be specified
+ "directly: oref1 = NEW #( `Hallo` ).
+ "The next examples show object reference variables that are declared
+ "inline. Here, the type (i. e. the class name) must be specified
+ "explicitly.
+ "The last example shows the method chaining that is possible with
+ "expressions using the NEW operator. The demo class has a method that
+ "has a returning parameter. In this case, the parameter of the method
+ "is of type REF TO i.
+
+ "Creating an object reference variable
+ DATA oref1 TYPE REF TO local_class.
+
+ "Creating an instance of a class, object reference variable
+ "is declared inline, explicit type specification
+ DATA(oref2) = NEW local_class( `Salut` ).
+
+ output->display( input = oref2 name = `oref2` ).
+
+**********************************************************************
+
+ output->next_section( `28) CONV` ).
+
+ "The examples show the effect of the CONV operator.
+ "A variable of type i is declared and assigned a value. Then,
+ "calculations are carried out. The result is stored in a variable
+ "declared inline. The first result is 0 because the derived type is i.
+ "The second calculation returns the precise value resulting from the
+ "division because the CONV
+ "expression triggers the conversion of the result (decfloat34).
+ "The next examples demonstrate logical expressions using character-like
+ "data types.
+ "A variable is of type abap_bool, i. e. a single character is expected.
+ "In this case, the variable is initial, i. e. the content is a blank.
+ "Another variable is of type string. A blank is assigned to this
+ "variable.
+ "A logical expression compares the two variables. Without the conversion
+ "using the CONV operator, the two are not equal due to the comparison
+ "rules for character-like data types (trailing blanks are not respected
+ "in variable-length strings). When the string is converted, the
+ "comparison results to true.
+
+ "Declaring data object and assign value
+ DATA num TYPE i VALUE 1.
+
+ "Effect of a calculation ...
+ "... without conversion
+ DATA(i) = num / 4.
+
+ "... with conversion using an appropriate type
+ DATA(dec_num) = CONV decfloat34( num / 4 ).
+
+ output->display( input = i name = `i` ).
+ output->display( input = dec_num name = `dec_num` ).
+
+ "Declaring data objects
+ DATA(txt) = VALUE abap_bool( ).
+
+ DATA(str) = ` `.
+
+ "Comparing the data objects with and without conversion
+ output->display( `Without conversion:` ).
+
+ IF txt = str.
+ output->display( `txt is equal to str.` ).
+ ELSE.
+ output->display( `txt is not equal to str.` ).
+ ENDIF.
+
+ output->display( `With conversion:` ).
+
+ IF txt = CONV abap_bool( str ).
+ output->display( `txt is equal to converted str.` ).
+ ELSE.
+ output->display( `txt is not equal to converted str.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `29) EXACT` ).
+
+ "The examples show the effect of the EXACT operator that enforces either
+ "a lossless assignment or a lossless calculation.
+ "1) Demonstrates data loss when converting to a data object that expects
+ "only a single character.
+ "2) Demonstrates an impossible lossless calculation. A rounding is
+ "necessary in this case.
+ "3) The example compares the effect of the EXACT and CONV operator.
+
+ "Example 1
+ TRY.
+ DATA(ex1) = EXACT abap_bool( 'XY' ).
+ CATCH cx_sy_conversion_data_loss INTO DATA(e1).
+ DATA(ex2) = e1->value.
+ DATA(t1) = e1->get_text( ).
+ ENDTRY.
+
+ "Example 2
+ TRY.
+ DATA(ex3) = EXACT decfloat34( 1 / 3 ).
+ CATCH cx_sy_conversion_rounding INTO DATA(e2).
+ DATA(ex4) = e2->value.
+ DATA(t2) = e2->get_text( ).
+ ENDTRY.
+
+ "Example 3
+ "Comparing the effect of CONV and EXACT
+ TYPES numtext TYPE n LENGTH 20.
+
+ TRY.
+ DATA(ex5) = EXACT numtext( '2 Apples + 5 Oranges' ).
+ CATCH cx_sy_conversion_error INTO DATA(e3).
+ DATA(t3) = e3->get_text( ).
+ ENDTRY.
+
+ DATA(conv_comp) = CONV numtext( '2 Apples + 5 Oranges' ).
+
+ IF ex1 IS INITIAL.
+ output->display( |ex2: { ex2 }; { t1 }| ).
+ ELSE.
+ output->display( ex1 ).
+ ENDIF.
+
+ IF ex3 IS INITIAL.
+ output->display( |ex4: { ex4 }; { t2 }| ).
+ ELSE.
+ output->display( input = ex3 name = `ex3` ).
+ ENDIF.
+
+ IF ex5 IS INITIAL.
+ output->display( input = t3 name = `t3` ).
+ ELSE.
+ output->display( input = ex5 name = `ex5` ).
+ ENDIF.
+
+ output->display( input = conv_comp name = `conv_comp` ).
+
+**********************************************************************
+
+ output->next_section( `30) REF` ).
+
+ "The example includes the declaration of a data object and some data
+ "reference variables. One data reference variable is typed with a
+ "complete type, the other one is typed with a generic type. Then, data
+ "references to the data object declared before are created. Using the #
+ "symbol means that the type can be automatically derived.
+ "You can also use inline declarations to omit the explicit declaration.
+ "Another example shows the explicit specification of the data type after
+ "REF.
+ "Furthermore, an object reference is created using inline declaration.
+
+ "Declaring data object
+ DATA number TYPE i VALUE 5.
+
+ "Declaring data reference variables
+ DATA dref_a TYPE REF TO i. "Complete type
+ DATA dref_b TYPE REF TO data. "Generic type
+
+ "Creating data references to data objects
+ dref_a = REF #( number ).
+ dref_b = REF #( number ).
+
+ "Data reference variable declared inline
+ DATA(dref_c) = REF #( number ).
+
+ "Type specified explicitly
+ DATA(dref_d) = REF string( `hallo` ).
+
+ "Object references
+ DATA(oref_a) = NEW local_class( `Ciao` ).
+ DATA(oref_b) = REF #( oref_a ).
+
+ output->display( input = dref_a name = `dref_a` ).
+ output->display( input = dref_b name = `dref_b` ).
+ output->display( input = dref_c name = `dref_c` ).
+ output->display( input = dref_d name = `dref_d` ).
+ output->display( input = oref_b name = `oref_b` ).
+
+**********************************************************************
+
+ output->next_section( `31) CAST` ).
+
+ "The example demonstrates the CAST operator in the context of Run Time
+ "Type Identification (RTTI).
+ "First, the components of a structure are retrieved. Secondly, the
+ "method information of a local class is retrieved. The syntax
+ "particularly shows the advantages of downcasts carried out with the
+ "CAST operator that also enables method chaining. An example is added
+ "that demonstrates the use of the older ?= operator with which extra
+ "variables are needed. Furthermore, simple downcasts are demonstrated
+ "using data references.
+
+ "RTTI examples
+ "Using CAST
+ "Retrieving structure components
+ DATA(components_s2) =
+ CAST cl_abap_structdescr(
+ cl_abap_typedescr=>describe_by_data( s2 ) )->components.
+
+ "Retrieving the methods of a local class
+ DATA(methods) =
+ CAST cl_abap_objectdescr(
+ cl_abap_objectdescr=>describe_by_name( 'LOCAL_CLASS' )
+ )->methods.
+
+ "Excursion: Using the older cast operator ?=
+ "Retrieving structure components
+ "Note: More lines of code, helper variables needed
+ DATA structdescr TYPE REF TO cl_abap_structdescr.
+
+ structdescr ?= cl_abap_typedescr=>describe_by_data( s1 ).
+
+ DATA(components_s1) = structdescr->components.
+
+ "Casting with data references
+ DATA dref_i TYPE REF TO i. "Complete type
+
+ DATA dref_data TYPE REF TO data. "Generic type
+
+ dref_data = NEW i( 123 ).
+
+ dref_i = CAST #( dref_data ).
+
+ output->display( input = components_s2 name = `components_s2` ).
+ output->display( input = methods name = `methods` ).
+ output->display( input = components_s1 name = `components_s1` ).
+ output->display( input = dref_i name = `dref_i` ).
+
+**********************************************************************
+
+ output->next_section( `32) COND` ).
+
+ "The example demonstrates the use of the COND operator. The syntax
+ "includes several WHEN and THEN expressions.
+ "The example returns a string based on the current time.
+
+ DATA(syst_time) = cl_abap_context_info=>get_system_time( ).
+
+ DATA(greets) =
+ COND #( WHEN syst_time BETWEEN '050001' AND '120000'
+ THEN |It's { syst_time TIME = ISO }. | &&
+ |Good morning, { sy-uname }.|
+ WHEN syst_time BETWEEN '120001' AND '170000'
+ THEN |It's { syst_time TIME = ISO }. | &&
+ |Good afternoon, { sy-uname }.|
+ WHEN syst_time BETWEEN '170001' AND '210000'
+ THEN |It's { syst_time TIME = ISO }. | &&
+ |Good evening, { sy-uname }.|
+ WHEN syst_time BETWEEN '210001' AND '050000'
+ THEN |It's { syst_time TIME = ISO }. | &&
+ |Good night, { sy-uname }.|
+ ELSE |Hallo, { sy-uname }.|
+ ).
+
+ output->display( input = greets name = `greets` ).
+
+**********************************************************************
+
+ output->next_section( `33) SWITCH` ).
+
+ "The example demonstrates the use of the SWITCH operator. Here,
+ "calculations are carried out. For this
+ "purpose, a string table is created that includes arithmetic operators
+ "and, purposely, one entry that does not fit. The internal table is looped
+ "across. Based on the current arithmetic operator, the calculation is
+ "carried out. A string is displayed accordingly. The code is embedded in
+ "a TRY ... CATCH ... ENDTRY block to take care of arithmetic errors. For
+ "example, you might insert the value 0 for the variable num2 to provoke 0
+ "division. The CONV operator is also used in the example to respect
+ "decimals.
+
+ DATA operator_tab TYPE TABLE OF string.
+
+ operator_tab = VALUE #( ( `+` ) ( `-` ) ( `*` ) ( `/` ) ( `#` ) ).
+
+ DATA(num1) = 2.
+ DATA(num2) = 4.
+
+ LOOP AT operator_tab ASSIGNING FIELD-SYMBOL().
+ TRY.
+ DATA(calc_result) =
+ SWITCH string(
+ WHEN '+' THEN CONV decfloat34( num1 + num2 )
+ WHEN '-' THEN CONV decfloat34( num1 - num2 )
+ WHEN '*' THEN CONV decfloat34( num1 * num2 )
+ WHEN '/' THEN CONV decfloat34( num1 / num2 )
+ ELSE `That doesn't work.` ).
+ output->display( |{ num1 } { } { num2 } = { calc_result }| ).
+ CATCH cx_sy_arithmetic_error INTO DATA(error).
+ output->display( |Arithmetic error. { error->get_text( ) }| ).
+ ENDTRY.
+ ENDLOOP.
+
+**********************************************************************
+
+ output->next_section( `34) FILTER` ).
+
+ "This section covers multiple examples demonstrating the syntactical variety
+ "of the FILTER operator.
+
+ TYPES: BEGIN OF fi_str,
+ a TYPE i,
+ b TYPE c LENGTH 3,
+ c TYPE c LENGTH 3,
+ END OF fi_str.
+
+ "basic form, condition created with single values
+ "itab must have at least one sorted key or one hash key used for access.
+ "This variant of the filter operator is not possible for an internal table itab without a sorted key or hash key.
+ DATA fi_tab1 TYPE SORTED TABLE OF fi_str WITH NON-UNIQUE KEY a.
+ DATA fi_tab2 TYPE STANDARD TABLE OF fi_str WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS a.
+ DATA fi_tab3 TYPE HASHED TABLE OF fi_str WITH UNIQUE KEY a.
+
+ "Filling internal tables
+ fi_tab1 = VALUE #( ( a = 1 b = 'aaa' c = 'abc' )
+ ( a = 2 b = 'bbb' c = 'def' )
+ ( a = 3 b = 'ccc' c = 'hij' )
+ ( a = 4 b = 'ddd' c = 'klm' )
+ ( a = 5 b = 'eee' c = 'nop' ) ).
+
+ fi_tab2 = fi_tab1.
+ fi_tab3 = fi_tab1.
+
+ "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 #( fi_tab1 WHERE a >= 3 ).
+
+ output->display( input = f1 name = `f1` ).
+
+ "USING KEY primary_key explicitly specified; same as above
+ DATA(f2) = FILTER #( fi_tab1 USING KEY primary_key WHERE a >= 3 ).
+
+ output->display( input = f2 name = `f2` ).
+
+ "EXCEPT addition
+ DATA(f3) = FILTER #( fi_tab1 EXCEPT WHERE a >= 3 ).
+
+ output->display( input = f3 name = `f3` ).
+
+ DATA(f4) = FILTER #( fi_tab1 EXCEPT USING KEY primary_key WHERE a >= 3 ).
+
+ output->display( input = f4 name = `f4` ).
+
+ "Secondary table key specified after USING KEY
+ DATA(f5) = FILTER #( fi_tab2 USING KEY sec_key WHERE a >= 4 ).
+
+ output->display( input = f5 name = `f5` ).
+
+ DATA(f6) = FILTER #( fi_tab2 EXCEPT USING KEY sec_key WHERE a >= 3 ).
+
+ output->display( input = f6 name = `f6` ).
+
+ "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 #( fi_tab3 WHERE a = 3 ).
+
+ output->display( input = f7 name = `f7` ).
+
+ "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.
+
+ "Declaring and filling filter tables
+ 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.
+
+ filter_tab1 = VALUE #( ( 3 ) ( 5 ) ).
+ filter_tab2 = filter_tab1.
+
+ DATA(f8) = FILTER #( fi_tab1 IN filter_tab1 WHERE a = table_line ).
+
+ output->display( input = f8 name = `f8` ).
+
+ "EXCEPT addition
+ DATA(f9) = FILTER #( fi_tab1 EXCEPT IN filter_tab1 WHERE a = table_line ).
+
+ output->display( input = f9 name = `f9` ).
+
+ "USING KEY is specified for the filter table
+ DATA(f10) = FILTER #( fi_tab2 IN filter_tab2 USING KEY line WHERE a = table_line ).
+
+ output->display( input = f10 name = `f10` ).
+
+ "USING KEY is specified for the source table, including EXCEPT
+ DATA(f11) = FILTER #( fi_tab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE a = table_line ).
+
+ output->display( input = f11 name = `f11` ).
+
+**********************************************************************
+
+ output->next_section( `Iteration Expressions with FOR` ).
+
+ "The examples demonstrate iteration expressions with FOR. The examples
+ "are based on demo internal tables that are filled using a method. The
+ "tables are displayed to show the original content of the internal
+ "tables that are to be processed.
+
+ output->display( `35) Original table content` ).
+
+ "Method to fill demo internal tables with values to work with.
+ "Tables are displayed showing the values.
+ fill_struc_and_tab( ).
+
+ output->display( input = tab1 name = `tab1` ).
+ output->display( input = tab2 name = `tab2` ).
+ output->display( input = tab3 name = `tab3` ).
+
+**********************************************************************
+
+ output->next_section( `36) FOR ... IN ... (LOOP Semantics)` ).
+
+ "Examples demonstrating FOR ... IN ... that has the semantics of LOOP.
+ "1) An internal table is looped across. The whole line is stored in a
+ "new table which is declared inline. The target table must have the
+ "same table type as the internal table that is looped across. The
+ "example is without a WHERE condition, i. e. all lines of the source
+ "table are considered.
+ "2) A new table is created that has a different table type. However,
+ "both table types have identically named components. The example shows
+ "how you can fill all identically named components of the target table.
+ "The example includes a WHERE condition to restrict the lines to be
+ "considered. Pay attention to potential type conversions.
+ "3) A new table is created that has a different table type. Here, it is
+ "shown that the components and their assignment might be specified
+ "individually. A WHERE clause is included. Pay attention to potential
+ "type conversions.
+
+ "1) Storing the whole line in a new table.
+ "The target table must have the same table type as the source table.
+ "Without the WHERE condition, all lines are considered.
+
+ TYPES t_type1 LIKE tab3.
+
+ DATA(for1) = VALUE t_type1( FOR wa IN tab3 ( wa ) ).
+
+ "2) Storing specific components having the same names.
+ "The target type is not compatible to the type of the source table.
+ "Identically named components exist.
+
+ TYPES t_type2 LIKE tab1.
+
+ DATA(for2) = VALUE t_type2( FOR wa IN tab3
+ WHERE ( comp4 > 7 )
+ ( CORRESPONDING #( wa ) ) ).
+
+ "3) Specify components individually and providing a mapping
+
+ DATA(for3) = VALUE t_type2( FOR wa IN tab3
+ WHERE ( comp4 > 7 )
+ ( comp1 = wa-comp1
+ comp2 = `hallo`
+ comp3 = wa-comp4 ) ).
+
+ output->display( input = for1 name = `for1` ).
+ output->display( input = for2 name = `for2` ).
+ output->display( input = for3 name = `for3` ).
+
+ "The example demonstrates multiple iteration expressions with FOR. Here,
+ "a new table is created that is declared inline. Three tables are
+ "respected. The lines to be considered are restricted by a WHERE
+ "clause.
+ "A component name mapping takes care of assigning specific values to
+ "non-identically named components.
+
+ "Declaring an internal table type
+ TYPES: BEGIN OF line_type2,
+ compX TYPE c LENGTH 1,
+ compY TYPE string,
+ compZ TYPE i,
+ END OF line_type2,
+ t_type3 TYPE STANDARD TABLE OF line_type2 WITH EMPTY KEY.
+
+ "Nested iteration expressions with FOR
+ DATA(for4) = VALUE t_type3(
+ FOR wa1 IN tab1 WHERE ( comp1 = 'A' )
+ FOR wa2 IN tab2 WHERE ( comp4 > 6 )
+ FOR wa3 IN tab3 WHERE ( comp3 < 4 )
+ ( compX = wa1-comp1
+ compY = wa2-comp1
+ compZ = wa3-comp3 ) ).
+
+ output->display( input = for4 name = `for4` ).
+
+**********************************************************************
+
+ output->next_section( `37) FOR ... WHILE/UNTIL ... ` &&
+ `(DO/WHILE Semantics)` ).
+
+ "Examples demonstrating FOR ... WHILE/UNTIL ... that has the semantics
+ "of DO/WHILE.
+ "The example demonstrates the construction of internal tables using
+ "condition iterations with a constructor expression
+ "and the corresponding variant of the value operator VALUE. Two internal
+ "tables with different iterations, one using FOR ... WHILE ..., the
+ "other FOR ... UNTIL ..., are created.
+
+ "Declaring and internal table type
+ TYPES:
+ BEGIN OF line_type3,
+ col1 TYPE i,
+ col2 TYPE i,
+ col3 TYPE i,
+ END OF line_type3,
+ t_type4 TYPE STANDARD TABLE OF line_type3 WITH EMPTY KEY.
+
+ "FOR ... WHILE ...
+ DATA(for5) = VALUE t_type4(
+ FOR x = 11 THEN x + 10 WHILE x < 40
+ ( col1 = x col2 = x + 1 col3 = x + 2 ) ).
+
+ "FOR ... UNTIL ...
+ DATA(for6) = VALUE t_type4(
+ FOR y = 31 THEN y - 10 UNTIL y < 10
+ ( col1 = y col2 = y + 1 col3 = y + 2 ) ).
+
+ output->display( input = for5 name = `for5` ).
+ output->display( input = for6 name = `for6` ).
+
+**********************************************************************
+
+ output->next_section( `38) REDUCE (1)` ).
+
+ "The examples demonstrate the REDUCE operator using values contained in
+ "an internal table column. Here, the table is of type string.
+ "1) The values of the columns are sequentially concatenated into a
+ "string.
+ "INIT ...: A temporary variable is specified that sets an initial
+ "value for the result variable
+ "FOR ...: Represents a loop, the loop is carried out for all table
+ "entries.
+ "NEXT ...: Represents the assignment to the temporary variable after
+ "every iteration.
+ "Once the loop has finished, the target variable is assigned the
+ "resulting value.
+ "2) Also here, the table rows are reduced to a text string using a
+ "chaining after NEXT. The auxiliary variable sep declared after
+ "INIT is initial for the first read row and is filled with a blank here
+ "for the evaluation of further rows.
+
+ "Creating and filling a string table
+ DATA tab TYPE STANDARD TABLE OF string WITH EMPTY KEY.
+
+ tab = VALUE #( ( `h` ) ( `a` ) ( `l` ) ( `l` ) ( `o` ) ).
+
+ "Example 1
+ DATA(a_word) =
+ REDUCE string( INIT text = ``
+ FOR word IN tab
+ NEXT text = |{ text }{ word }| ).
+
+ "Example 2
+ tab = VALUE #( ( `Some` ) ( `cool` ) ( `stuff` )
+ ( `using` ) ( `REDUCE` ) ).
+
+ DATA(sentence) =
+ REDUCE string( INIT text = `` sep = ``
+ FOR word IN tab
+ NEXT text = |{ text }{ sep }{ word }| sep = ` ` ) && '.'.
+
+ output->display( input = a_word name = `a_word` ).
+ output->display( input = sentence name = `sentence` ).
+
+**********************************************************************
+
+ output->next_section( `39) REDUCE (2)` ).
+
+ "The examples demonstrate summations using the REDUCE operator.
+ "1) Example using FOR ... UNTIL .... It calculates the total of the
+ "numbers from 1 to 10. The resulting number is stored in a variable that
+ "is declared inline.
+ "2) The example has the same output as the first example. Here, a table
+ "column is reduced. The table that is of type i is filled with numbers
+ "from 1 to 10 (using a constructor expression with FOR ... WHILE ...).
+ "The reduction is then carried out based on the numbers contained in
+ "this table.
+
+ "Example 1
+ DATA(sum1) = REDUCE i( INIT b = 0
+ FOR n = 1 UNTIL n > 10
+ NEXT b += n ).
+
+ "Example 2
+ DATA itab_i TYPE STANDARD TABLE OF i WITH EMPTY KEY.
+
+ itab_i = VALUE #( FOR j = 1 WHILE j <= 10 ( j ) ).
+
+ DATA(sum2) = REDUCE i( INIT x = 0
+ FOR z IN itab_i
+ NEXT x = x + z ).
+
+ output->display( input = sum1 name = `sum1` ).
+ output->display( input = sum2 name = `sum2` ).
+
+**********************************************************************
+
+ output->next_section( `40) REDUCE (3)` ).
+
+ "The examples demonstrate the concatenation of strings
+ "1) without the addition THEN
+ "2) with the addition THEN
+ "3) in the context of a non-arithmetic expression.
+
+ "1) Concatenation without THEN
+ DATA(conc1) = REDUCE string( INIT text = `Count up:`
+ FOR n = 1 UNTIL n > 10
+ NEXT text &&= | { n }| ).
+
+ "2) Concatenation with THEN
+ DATA(conc2) = REDUCE string( INIT text = `Count down:`
+ FOR n = 10 THEN n - 1 WHILE n > 0
+ NEXT text &&= | { n }| ).
+
+ "3) Non-arithmetic expression
+ DATA(conc3) = REDUCE string( INIT text = ``
+ FOR t = `x` THEN t && `y`
+ UNTIL strlen( t ) > 10
+ NEXT text &&= |{ t } | ).
+
+ output->display( input = conc1 name = `conc1` ).
+ output->display( input = conc2 name = `conc2` ).
+ output->display( input = conc3 name = `conc3` ).
+
+**********************************************************************
+
+ output->next_section( `41) LET Expressions (1)` ).
+
+ "The examples demonstrate LET expressions in different contexts.
+
+ "1) LET within a constructor expression with VALUE: The temporary
+ "variable is assigned a value of type string and all lines of the
+ "resulting table (a table of type string) receive the content of this
+ "variable in the specified position.
+
+ DATA(str_tab) = VALUE string_table( LET it = `be` IN
+ ( |To { it } is to do| )
+ ( |To { it } or not to { it }| )
+ ( |To do is to { it }| )
+ ( |Do { it } do { it } do| ) ).
+
+ output->display( input = str_tab name = `str_tab` ).
+
+**********************************************************************
+
+ output->next_section( `42) LET Expressions (2)` ).
+
+ "2) LET within a constructor expression with COND: 12 o'clock is
+ "specified as value for the LET expression. Based on this value, checks
+ "are carried out and an appropriate result is returned.
+
+ DATA(system_time) = cl_abap_context_info=>get_system_time( ).
+
+ DATA(time) =
+ COND #( LET tm = '120000' IN
+ WHEN system_time < tm THEN
+ |{ system_time TIME = ISO } AM|
+ WHEN system_time > tm AND system_time < '240000' THEN
+ |{ CONV t( system_time - 12 * 3600 ) TIME = ISO } PM|
+ WHEN system_time = tm THEN |High Noon|
+ ELSE |?| ).
+
+ output->display( input = time name = `time` ).
+
+**********************************************************************
+
+ output->next_section( `43) LET Expressions (3)` ).
+
+ "3) An internal table that includes three components is created and
+ "filled. A loop across this table is carried out. The purpose of the
+ "constructor expression is to construct a string by concatenating the
+ "values in the table columns. Here, the LET expression includes a field
+ "symbol representing the table line. The field symbol receives the
+ "concatenation result which is then stored in the variable that is
+ "declared inline. The content is then added to an internal table of type
+ "string which is then output to show the result of the loop.
+
+ TYPES:
+ BEGIN OF date,
+ year TYPE c LENGTH 4,
+ month TYPE c LENGTH 2,
+ day TYPE c LENGTH 2,
+ END OF date,
+ dates TYPE TABLE OF date WITH EMPTY KEY.
+
+ DATA stringtab TYPE TABLE OF string WITH EMPTY KEY.
+
+ DATA(dates) = VALUE dates(
+ ( year = '2020' month = '07' day = '16' )
+ ( year = '2021' month = '08' day = '31' )
+ ( year = '2022' month = '09' day = '07' ) ).
+
+ DO lines( dates ) TIMES.
+ DATA(isodate) = CONV string(
+ LET = dates[ sy-index ]
+ separator = '-'
+ IN -year && separator && -month &&
+ separator && -day ).
+
+ "Adding line to table
+ stringtab = VALUE #( BASE stringtab ( isodate ) ).
+ ENDDO.
+
+ output->display( input = stringtab name = `stringtab` ).
+
+ ENDMETHOD.
+ENDCLASS.
+
diff --git a/src/zcl_demo_abap_constructor_expr.clas.locals_imp.abap b/src/zcl_demo_abap_constructor_expr.clas.locals_imp.abap
new file mode 100644
index 0000000..280d1a9
--- /dev/null
+++ b/src/zcl_demo_abap_constructor_expr.clas.locals_imp.abap
@@ -0,0 +1,27 @@
+CLASS local_class DEFINITION.
+ PUBLIC SECTION.
+ METHODS: constructor IMPORTING txt TYPE string,
+ double IMPORTING int TYPE
+ REF TO i RETURNING VALUE(res) TYPE i.
+
+ DATA: timestamp TYPE string,
+ text TYPE string.
+
+ CLASS-DATA: no_of_instances TYPE i READ-ONLY.
+ENDCLASS.
+
+CLASS local_class IMPLEMENTATION.
+ METHOD constructor.
+ "Number of instances of the class are counted.
+ no_of_instances = no_of_instances + 1.
+ "Set a time stamp.
+ DATA: ts TYPE timestampl.
+ GET TIME STAMP FIELD ts.
+ timestamp = |{ ts TIMESTAMP = SPACE }|.
+
+ text = |{ txt }, { sy-uname }.|.
+ ENDMETHOD.
+ METHOD double.
+ res = int->* * 2.
+ ENDMETHOD.
+ENDCLASS.
diff --git a/src/zcl_demo_abap_constructor_expr.clas.xml b/src/zcl_demo_abap_constructor_expr.clas.xml
new file mode 100644
index 0000000..45764df
--- /dev/null
+++ b/src/zcl_demo_abap_constructor_expr.clas.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ZCL_DEMO_ABAP_CONSTRUCTOR_EXPR
+ E
+ ABAP cheat sheet: Constructor expressions
+ 1
+ X
+ X
+ X
+
+
+
+
diff --git a/src/zcl_demo_abap_display.clas.abap b/src/zcl_demo_abap_display.clas.abap
new file mode 100644
index 0000000..c1206e6
--- /dev/null
+++ b/src/zcl_demo_abap_display.clas.abap
@@ -0,0 +1,162 @@
+***********************************************************************
+*
+* Class for ABAP cheat sheet examples designed to support displaying
+* output in the ADT console
+*
+* -------------------------- NOTE -------------------------------------
+* This helper class is only used to display complex types contained in
+* the example classes of the ABAP cheat sheets in older ABAP releases.
+* In newer ABAP releases, this helper class is, in principle, not needed.
+* You can use the write method of the classrun interface directly and
+* display all types.
+*
+* The code presented in this class is intended only to support the ABAP
+* cheat sheets. It is not intended for direct use in a production system
+* environment. The code examples in the ABAP cheat sheets are primarily
+* intended to provide a better explanation and visualization of the
+* syntax and semantics of ABAP statements, not to solve concrete
+* programming tasks. For production application programs, you should
+* always work out your own solution for each individual case. There is
+* no guarantee for the correctness or completeness of the code.
+* Furthermore, there is no legal responsibility or liability for any
+* errors or their consequences that may occur when using the the example
+* code.
+*
+***********************************************************************
+"! Class supporting ABAP cheat sheet examples
+"! The class supports displaying output of the ABAP cheat sheet examples in the ADT console.
+CLASS zcl_demo_abap_display DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ METHODS:
+ constructor
+ IMPORTING
+ io_out TYPE REF TO if_oo_adt_classrun_out,
+ display
+ IMPORTING
+ input TYPE data
+ name TYPE string DEFAULT ``
+ RETURNING
+ VALUE(output) TYPE string,
+ next_section
+ IMPORTING
+ heading TYPE string.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ DATA:
+ mo_out TYPE REF TO if_oo_adt_classrun_out,
+ offset TYPE i.
+
+ CONSTANTS nl TYPE string VALUE cl_abap_char_utilities=>newline.
+ENDCLASS.
+
+
+
+CLASS zcl_demo_abap_display IMPLEMENTATION.
+
+
+ METHOD constructor.
+ mo_out = io_out.
+ ENDMETHOD.
+
+
+ METHOD display.
+ "Checking data type
+ DATA(type_descr) = cl_abap_typedescr=>describe_by_data( input ).
+ CASE type_descr->kind.
+ WHEN cl_abap_typedescr=>kind_struct.
+ DATA(struct_descr) = CAST cl_abap_structdescr( type_descr ).
+ "Checking for complex output
+ IF struct_descr->struct_kind = cl_abap_structdescr=>structkind_nested
+ OR line_exists( struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_table ] )
+ OR line_exists( struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_dref ] )
+ OR line_exists( struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_oref ] ).
+ DATA(to_be_serialized) = abap_true.
+ ELSE.
+ DATA(display) = mo_out->get( data = input name = name ).
+ ENDIF.
+ WHEN cl_abap_typedescr=>kind_table.
+ DATA(table_descr) = CAST cl_abap_tabledescr( type_descr ).
+ TRY.
+ DATA(line_type_struct_descr) = CAST cl_abap_structdescr( table_descr->get_table_line_type( ) ).
+ "Checking for complex output
+ IF line_type_struct_descr->struct_kind = cl_abap_structdescr=>structkind_nested
+ OR line_exists( line_type_struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_table ] )
+ OR line_exists( line_type_struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_dref ] )
+ OR line_exists( line_type_struct_descr->components[ type_kind = cl_abap_typedescr=>typekind_oref ] ).
+ to_be_serialized = abap_true.
+ ELSE.
+ display = mo_out->get( data = input name = name ).
+ ENDIF.
+ CATCH cx_sy_move_cast_error.
+ to_be_serialized = abap_true.
+ ENDTRY.
+ WHEN cl_abap_typedescr=>kind_class.
+ to_be_serialized = abap_true.
+ WHEN cl_abap_typedescr=>kind_intf.
+ to_be_serialized = abap_true.
+ WHEN cl_abap_typedescr=>kind_elem.
+ display = mo_out->get( data = COND string( WHEN name IS INITIAL THEN input ELSE `"` && name && `":` && nl && input ) ).
+ WHEN cl_abap_typedescr=>kind_ref.
+ "Checking for data references
+ IF type_descr->type_kind = cl_abap_typedescr=>typekind_dref.
+ "Checking type of dereferenced data object
+ ASSIGN input->* TO FIELD-SYMBOL().
+ DATA(type_check_dref) = cl_abap_typedescr=>describe_by_data( ).
+ "Processing (non-)elementary types
+ IF type_check_dref->kind = type_descr->kind_elem.
+ display = mo_out->get( data = COND string( WHEN name IS INITIAL THEN ELSE `"` && name && `":` && nl && ) ).
+ ELSE.
+ to_be_serialized = abap_true.
+ ENDIF.
+ ELSE.
+ to_be_serialized = abap_true.
+ ENDIF.
+ ENDCASE.
+
+ "Processing complex output by serializiation
+ FIND SUBSTRING `Data type not yet supported ...` IN display MATCH OFFSET DATA(off) MATCH LENGTH DATA(len).
+ IF sy-subrc = 0 OR to_be_serialized = abap_true.
+ "ABAP JSON serializing
+ DATA(json) = /ui2/cl_json=>serialize( data = input
+ pretty_name = /ui2/cl_json=>pretty_mode-low_case
+ compress = abap_false
+ hex_as_base64 = abap_false
+ format_output = abap_true
+ assoc_arrays = abap_true
+ assoc_arrays_opt = abap_true ).
+ IF to_be_serialized = abap_true.
+ IF name IS INITIAL.
+ REPLACE PCRE `^` IN display WITH json && nl.
+ ELSE.
+ REPLACE PCRE `^` IN display WITH `"` && name && `":` && nl && json && nl.
+ ENDIF.
+ "substring found
+ ELSE.
+ IF name IS INITIAL.
+ REPLACE SECTION OFFSET off LENGTH len OF display WITH json && nl.
+ ELSE.
+ REPLACE SECTION OFFSET off LENGTH len OF display WITH `"` && name && `":` && nl && json && nl.
+ ENDIF.
+ ENDIF.
+ mo_out->write( display && nl ).
+ ELSE.
+ mo_out->write( display && nl ).
+ ENDIF.
+ ENDMETHOD.
+
+
+ METHOD next_section.
+ mo_out->write( `_________________________________________________________________________________`
+ && nl
+ && nl
+ && heading
+ && nl
+ && nl ).
+ ENDMETHOD.
+ENDCLASS.
+
diff --git a/src/zcl_demo_abap_display.clas.xml b/src/zcl_demo_abap_display.clas.xml
new file mode 100644
index 0000000..e171bfc
--- /dev/null
+++ b/src/zcl_demo_abap_display.clas.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ZCL_DEMO_ABAP_DISPLAY
+ E
+ Class supporting ABAP cheat sheet examples
+ 1
+ X
+ X
+ X
+
+
+
+
diff --git a/src/zcl_demo_abap_dtype_dobj.clas.abap b/src/zcl_demo_abap_dtype_dobj.clas.abap
new file mode 100644
index 0000000..60b1dd6
--- /dev/null
+++ b/src/zcl_demo_abap_dtype_dobj.clas.abap
@@ -0,0 +1,1921 @@
+***********************************************************************
+*
+* ABAP cheat sheet: Data Types and Data Objects
+*
+* -------------------------- PURPOSE ----------------------------------
+* - Example to demonstrate data types and data objects.
+* - Note that in many cases there is no output displayed because 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.
+*
+* ----------------------- GETTING STARTED -----------------------------
+* - Open the class with the ABAP development tools for Eclipse (ADT).
+* - Choose F9 to run the class.
+* - Check the console output.
+* - To understand the context and the ABAP syntax used, refer to the
+* notes included in the class as comments or refer to the respective
+* topic in the ABAP Keyword Documentation.
+* - Due to the amount of console output, the examples contain numbers
+* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
+* Also, the variable name is displayed in most cases. So to find
+* the relevant output in the console easier and faster, just search
+* for the number/variable name in the console (CTRL+F in the console)
+* or use the debugger.
+*
+* ----------------------------- NOTE -----------------------------------
+* The code presented in this class is intended only to support the ABAP
+* cheat sheets. It is not intended for direct use in a production system
+* environment. The code examples in the ABAP cheat sheets are primarily
+* intended to provide a better explanation and visualization of the
+* syntax and semantics of ABAP statements, not to solve concrete
+* programming tasks. For production application programs, you should
+* always work out your own solution for each individual case. There is
+* no guarantee for the correctness or completeness of the code.
+* Furthermore, there is no legal responsibility or liability for any
+* errors or their consequences that may occur when using the the example
+* code.
+*
+***********************************************************************
+"! ABAP Cheat Sheet: Data Types and Data Objects
+"! Example to demonstrate data types and data objects in ABAP.
Choose F9 in ADT to run the class.
+CLASS zcl_demo_abap_dtype_dobj DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ INTERFACES: if_oo_adt_classrun.
+ CLASS-METHODS:
+ class_constructor.
+
+ TYPES t_pub_text_c30 TYPE c LENGTH 30.
+ CONSTANTS: comma TYPE string VALUE `, `.
+ CLASS-DATA: read_only_attribute TYPE string VALUE `Hallo` READ-ONLY.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+
+ TYPES t_prv_text_c30 TYPE c LENGTH 30.
+ CLASS-DATA cl_text TYPE t_prv_text_c30.
+ DATA text TYPE t_pub_text_c30 VALUE '!!!'.
+
+ METHODS adapt_text RETURNING VALUE(str) TYPE string.
+
+ METHODS addition_with_generic_num IMPORTING num1 TYPE numeric
+ num2 TYPE numeric
+ RETURNING VALUE(result) TYPE decfloat34.
+
+**********************************************************************
+
+ "Types and methods for demonstrating enumerated types and objects
+
+ "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) For the following enumerated type, an 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,
+ "If VALUE is specified explicitly, VALUE IS INITIAL must be used exactly once.
+ 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.
+ "Use case: If you have more than one enumerated type within one context. In doing so, you declare a constant enumeration structure.
+ "The components of the structure are the enumeration constants of the enumerated type.
+ 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.
+
+
+ METHODS enum_meth_params IMPORTING char TYPE t_enum
+ RETURNING VALUE(output) TYPE string.
+ METHODS enum_processing RETURNING VALUE(output) TYPE string_table.
+ METHODS rtti_enum RETURNING VALUE(output) TYPE string_table.
+
+ENDCLASS.
+
+
+
+CLASS ZCL_DEMO_ABAP_DTYPE_DOBJ IMPLEMENTATION.
+
+
+ METHOD adapt_text.
+ DATA text TYPE t_pub_text_c30.
+
+ text = cl_text && comma && sy-uname && me->text.
+
+ str = text && |\n(Note: The value of me->text is "{ me->text }")|.
+ ENDMETHOD.
+
+
+ METHOD addition_with_generic_num.
+ result = num1 + num2.
+ ENDMETHOD.
+
+
+ METHOD class_constructor.
+ "Filling demo database tables.
+ zcl_demo_abap_flight_tables=>fill_dbtabs( ).
+ ENDMETHOD.
+
+
+ METHOD enum_meth_params.
+
+ CASE char.
+ WHEN a.
+ output = a.
+ WHEN b.
+ output = b.
+ WHEN OTHERS.
+ output = `Either c or d: ` && char.
+ ENDCASE.
+
+ ENDMETHOD.
+
+
+ METHOD enum_processing.
+
+ "Read and write positions of enumerated objects
+ "Enumerated objects can be used in all read positions in which the operand
+ "type is their enumerated type.
+ "Likewise, enumerated variables can only be used in write positions in which
+ "the operand type is the enumerated type and only the associated enumerated
+ "values can be written.
+ "So, assignments are possible only from one enumerated type to the same (with one
+ "exception -> assignment to character-like variables of the types c and string)
+ DATA do_enum TYPE t_enum.
+ do_enum = a.
+ APPEND |do_enum: { do_enum }| TO output.
+
+ DATA do_enum_2 LIKE do_enum.
+ do_enum_2 = do_enum.
+ APPEND |do_enum_2: { do_enum_2 }| TO output.
+
+ "Assignment to character-like variables of the types c and string.
+ "In this case, the target field is assigned the name of the enumerated constant or
+ "the component of the enumerated structure under which the enumerated value of the
+ "source field is defined in the enumerated type.
+ DATA do_a_string TYPE string.
+ do_a_string = do_enum.
+ APPEND |do_a_string: { do_a_string }| TO output.
+
+ "Or using the CONV operator as follows
+ DATA(do_next_string) = CONV string( do_enum ).
+ APPEND |do_next_string: { do_next_string }| TO output.
+
+ "Enumerated constants are converted implicitly to the type string
+ "before the concatenation in the string template.
+ DATA(str_from_enum) = |{ a }{ b }{ c }{ d }|.
+ APPEND |str_from_enum: { str_from_enum }| TO output.
+
+ "Note that only the enumerated type itself is relevant. Usually, the content
+ "of an enumerated object is not of interest.
+ "The enumerated value in the base type can be accessed using the constructor
+ "operators CONV and EXACT only. The base type is i in this case.
+ DATA(conv_value) = CONV i( do_enum ).
+ APPEND |conv_value: { conv_value }| TO output.
+
+ "Converting the other way round.
+ DATA(another_conv) = CONV t_enum( 3 ).
+ APPEND |another_conv: { another_conv }| TO output.
+
+ "If known statically, an attempt to assign a value other than a valid enumerated value
+ "to an enumerated variable produces a syntax error.
+ "If not known statically, an exception is raised.
+ "The following produces a syntax error
+ "do_enum = f.
+
+ "The following example shows raising an exception.
+ DATA dobj TYPE t_enum.
+
+ TYPES t_int_tab TYPE TABLE OF i WITH EMPTY KEY.
+ DATA(int_tab) = VALUE t_int_tab( ( 0 ) ( 1 ) ( 2 ) ( 3 ) ( 4 ) ).
+
+ DATA str_tab TYPE TABLE OF string.
+ LOOP AT int_tab INTO DATA(wa_en).
+ TRY.
+ dobj = CONV t_enum( wa_en ).
+ APPEND dobj TO str_tab.
+ CATCH cx_sy_conversion_no_enum_value INTO DATA(error_enum).
+ APPEND error_enum->get_text( ) TO str_tab.
+ ENDTRY.
+ ENDLOOP.
+
+ APPEND `------------- START: Output for str_tab -------------` TO output.
+ APPEND LINES OF str_tab TO output.
+ APPEND `^^^^^^^^^^^^^ END: Output for str_tab ^^^^^^^^^^^^^` TO output.
+
+ "An enumerated variable can be set to the initial value of its base type
+ "using CLEAR.
+ CLEAR do_enum.
+ APPEND |do_enum: { do_enum }| TO output.
+
+ "Enumerated structures
+ DATA do_enum_s TYPE t_enum_struc.
+
+ "The enumerated structure en_struc was decalred in the public section.
+ "Using the addition LIKE, a second structure is created referring to the enumerated structure.
+ "Note that the second structure is not a constant structure.
+ "The components of the constant structure contain the enumerated values of the enumerated type.
+ "All the components of the variable structure declared by LIKE contain the initial values.
+ DATA do_s LIKE en_struc.
+ APPEND |do_s: { do_s-j } / { do_s-k } / { do_s-l } / { do_s-m }| TO output.
+
+ DATA(do_en) = en_struc.
+ APPEND |do_en: { do_en-j } / { do_en-k } / { do_en-l } / { do_en-m }| TO output.
+
+ "Accessing structure components using the component selector
+ DATA(do_en_k) = en_struc-k.
+ APPEND |do_en_k: { do_en_k }| TO output.
+
+ DATA(do_s_m) = do_s-m.
+ APPEND |do_s_m: { do_s_m }| TO output.
+ "Assigning enumerated constants to the variable structure
+ do_s = en_struc.
+ APPEND |do_s: { do_s-j } / { do_s-k } / { do_s-l } / { do_s-m }| TO output.
+
+ ENDMETHOD.
+
+
+ METHOD if_oo_adt_classrun~main.
+
+ DATA(output) = NEW zcl_demo_abap_display( out ).
+
+ output->display( `ABAP Cheat Sheet Example: Data Types and Data Objects` ).
+
+**********************************************************************
+
+ output->display( `Declaring data types` ).
+
+ "The following examples deal with the declaration of data types.
+ "They show how data types can be declared locally in an ABAP program.
+ "Note:
+ "- Data types can also be declared in the ABAP Dictionary (DDIC) or as a
+ " CDS entity, which is not covered in this demo example.
+ "- In ADT and because of the many type declarations, you may want to press
+ " F2 on the types to get more information.
+ "- The examples show a selection.
+ "- Only non-generic types can be used.
+
+ output->display( `1) Declaring data types based on elementary types` ).
+
+ "See the ABAP Keyword Documentation for the value ranges that are
+ "accepted by these types.
+
+ "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 as it is the case here in the example class.
+
+ "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_do_string 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.
+ "In ADT, you can check out the data elements by forward navigation (hold CTRL
+ "and click on the type). You can also use F2 Information (click F2 when on
+ "the type) to get information.
+ TYPES te_int1 TYPE int1.
+ TYPES te_int2 TYPE int2.
+
+ "Referring to types in global classes
+ "Also here, check out the forward navigation or F2 information for the types.
+ "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.
+ "The type pool contains the definitions of globally visible data types and
+ "constants. Check it out using the forward navigation and the F2 information.
+ TYPES te_tp TYPE abap_bool.
+ TYPES te_const_in_tp LIKE abap_true.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `2) Declaring data types based on complex types` ).
+
+ "Structure and internal table types as examples for complex types
+
+ "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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `3) Declaring reference types` ).
+
+ "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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `Declaring data objects` ).
+
+ "The following examples deal with the declaration of data ojects.
+ "They show how data objects can be declared locally in an ABAP program.
+ "Note:
+ "- With the exception of two additions (VALUE and READ-ONLY), the syntax
+ " follows the pattern as for TYPES statements.
+ "- A data type defined using DATA, which is not derived from an existing type,
+ " is available only as a property of the
+ " declared data object and not on its own. This kind of data type is bound to
+ " its data object.
+ "- The examples show the creation of named data objects. Anonymous data objects
+ " are covered below.
+ "- In ADT and because of the many type declarations, you may want to press F2 on
+ " the types to get more information.
+ "- The examples show a selection. For more information, check out the ABAP
+ " Keyword Documentation.
+
+ output->display( `4) Declaring data objects based on elementary data types` ).
+
+ "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 this 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, 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_demo_abap_dtype_dobj=>read_only_attribute = `adapt read only attribute`.
+ ...
+ "Since we are here in the very class of this example attribute, a changing
+ "of the value would be possible. And the class name can, in that case, be
+ "ommitted.
+ read_only_attribute = `changed`.
+ ELSE.
+ ...
+ ENDIF.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `5) Declaring structures and internal tables as examples for complex types` ).
+
+ "Note: See more details and examples in the ABAP Keyword Documentations and in the
+ "respective ABAP cheat sheets.
+
+ "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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `6) Declaring data reference variables` ).
+
+ "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 the generic type data as static type
+ DATA dref_8_dataa 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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `7) Assigning values to data objects` ).
+
+ "An assignment passes the content 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. See further down.
+ "- In old ABAP code, you may see MOVE ... TO ... statements for value
+ " assignments. These statements are obsolete. This is not to be confused
+ " with MOVE-CORRESPONDING statements for complex types. They are not obsolete.
+
+ "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.
+
+ "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 cheat sheet. 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 ininial value.
+ DATA some_itab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
+ some_itab = VALUE #( ( carrid = 'XY' carrname = 'XY Airways' )
+ ( carrid = 'ZZ' carrname = 'ZZ 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 expressions
+ num = 1 + 2.
+ "A calculation assignment as follows
+ num += 1.
+ "is the short form of
+ num = num + 1.
+ "Syntax options: +=, -=, *= and /=
+
+ "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.
+ " 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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `8) Creating data objects by inline declaration` ).
+
+ "The declaration operator DATA can be specified in any designated declaration position.
+ "The data type of the variable is determined by the operand type. It must be possible
+ "to derive this type completely statically.
+ "Note: As shown in the previous section, there are many options for what can be placed
+ " on the right side.
+
+ "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 below.
+ 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).
+ "NEW addition
+ SELECT * FROM zdemo_abap_carr INTO TABLE NEW @DATA(itab_ref).
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `9) Assigning references to data reference variables` ).
+
+ "Note:
+ "- As is true for other data object and types, there are special assignment rules
+ " for data reference variables. Check out the ABAP Keyword Documentation.
+ "- An initial reference variable contains the null reference, which does not point
+ " to any objects. This means that it does not have a data type or a class as
+ " a dynamic type.
+
+ "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. Check the F2 information.
+ 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 type 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 of 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).
+ output->display( input = e->get_text( ) name = `e->get_text( )` ).
+ 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 ).
+
+**********************************************************************
+
+ output->next_section( `10) Creating anonymous data objects` ).
+
+ "Anonymous data objects are a topic related to data reference variables.
+ "These data objects are unnamed data objects.
+ "Most of the data objects above are named data objects, i.e. they can be addressed
+ "by a dedicated name.
+ "Unnamed data objects are literals and anonymous data objects. Anonymous data objects
+ "can be addressed using data reference variables.
+ "Note: Unlike data objects created with the statement DATA, anonymous data objects
+ "are created at runtime. Data objects declared using DATA are created when the
+ "program is loaded.
+
+ "Options to create anonymous data objects
+ "- CREATE DATA statements
+ "- Using the instance operator NEW
+ "- Addition NEW of the INTO clause in ABAP SQL SELECT statements
+
+ "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.
+
+ "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.
+
+ "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.
+
+ "Creating an anonymous structure
+ CREATE DATA dref_8_data TYPE zdemo_abap_fli.
+
+ "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
+ "As shown above, using the NEW addition in the INTO clause, an anonymous data
+ "object with suitable type can be created in place.
+ SELECT *
+ FROM zdemo_abap_carr
+ INTO TABLE NEW @DATA(dref_14_inline).
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `Excursions: Elementary types and type conversions` ).
+
+ output->display( `11) Implicit and explicit conversion` ).
+
+ "Implicit conversions are performed in assignments using the assignment operator =
+ "The content of a data object is converted according to the associated conversion rules.
+ "The following examples demonstrate implicit type conversions and their consequences
+ "that might be undesired.
+
+ "Conversions with 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.
+
+ output->display( input = do_2_c3 name = `do_2_c3` ).
+
+ "Conversions with 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.
+
+ output->display( input = do_4_i name = `do_4_i` ).
+
+ "Conversions with the types i and string
+ do_4_i = -5.
+ do_1_str = do_4_i.
+
+ output->display( input = do_1_str name = `do_1_str` ).
+
+ "Explicit type conversions can be performed with the CONV operator
+ "It converts the value specified within the parentheses to the data type specified
+ "before the parentheses and and creates an appropriate result.
+ "Note:
+ "- CONV closes the gap where the value operator VALUE cannot be used to construct
+ " values for elementary data objects except for the initial value.
+ "- The conversion is performed in accordance with the associated conversion rule.
+
+ "Explicitly converting decfloat34 to i
+ DATA do_6_dcfl34 TYPE decfloat34 VALUE '2.78'.
+ DATA(do_7_i) = CONV i( do_6_dcfl34 ).
+
+ output->display( input = do_7_i name = `do_7_i` ).
+
+ "# character when the type can be derived
+ DATA do_8_i TYPE i.
+ do_8_i = CONV #( do_6_dcfl34 ).
+
+ output->display( input = do_8_i name = `do_8_i` ).
+
+ "The following two calculations yield different results
+ do_8_i = sqrt( 5 ) + sqrt( 6 ).
+
+ output->display( input = do_8_i name = `do_8_i` ).
+
+ do_8_i = CONV i( sqrt( 5 ) ) + CONV i( sqrt( 6 ) ).
+
+ output->display( input = do_8_i name = `do_8_i` ).
+
+ "CONV operator for creating data objects inline with elementary data types
+ "Assume, you want a data object typed with decfloat34.
+ "The following example assigns a text field literal to the left side.
+ DATA(do_9_c4) = '4.56'. "It is type c
+
+ "Using the CONV operator and explicitly specifing the type, you can contruct a
+ "data object with an appropriate elementary data type.
+ DATA(do_10_dcfl34) = CONV decfloat34( '4.56' ).
+ "It corresponds to the following
+ DATA do_11_dcfl34 TYPE decfloat34 VALUE '4.56'.
+
+ "Note that the EXACT operator is available for lossless assignments.
+
+**********************************************************************
+
+ output->next_section( `12) Character strings and text field strings` ).
+
+ "The following example shows the difference between text field strings
+ "of type c and character strings of type string when it comes to trailing
+ "blanks.
+
+ DATA: text_space TYPE c LENGTH 1 VALUE ' ',
+ string_space TYPE string VALUE ` `,
+ result3 TYPE string,
+ result4 TYPE string.
+ result3 = '-->' && text_space && '<--'.
+ result4 = '-->' && string_space && '<--'.
+
+ output->display( |{ result3 }\n{ result4 }| ).
+
+**********************************************************************
+
+ output->next_section( `13) Floating point numbers` ).
+
+ "The following example shows the difference between binary and decimal
+ "floating point numbers.
+
+ DATA: result1 TYPE f,
+ result2 TYPE decfloat34.
+ result1 = 815 / 1000.
+ result2 = 815 / 1000.
+
+ output->display( |Binary floating point: { result1 }\n| &&
+ |Decimal floating point: { result2 }\n| ).
+
+**********************************************************************
+
+ output->next_section( `14) Byte-like types` ).
+
+ "The following example shows byte-like types x and xstring.
+
+ "A byte string is filled with binary data created from a string
+ "using the convert_out method of the cl_abap_codepage class.
+ "The result is the UTF-8 representation of the string (type xstring)
+ "which is displayed at first.
+ "Using the create_in method, the data object of type xstring is converted
+ "back to string.
+ "Without knowing how it was created or what it is supposed to mean, you can
+ "hardly do anything with a byte string.
+ "The second part of the example deals with type x.
+ "The binary representation of a new line feed (0A) is converted to string.
+ "The result is compared to the actual means of previding a new line feed
+ "(string template with \n and the older cl_abap_char_utilities=>newline).
+ "The same is done using the binary representation of a blank (20).
+
+ DATA(some_string) = `Hi there!`.
+
+ DATA(xstr) =
+ cl_abap_conv_codepage=>create_out(
+ codepage = `UTF-8`
+ )->convert( source = some_string ).
+
+ output->display( input = xstr name = `xstr` ).
+
+ DATA(xstring2string) = cl_abap_conv_codepage=>create_in( codepage = `UTF-8`
+ )->convert( source = xstr ).
+
+ output->display( input = xstring2string name = `xstring2string` ).
+
+ DATA line_feed_hex TYPE x LENGTH 1 VALUE '0A'.
+
+ DATA(line_feed_str) = cl_abap_conv_codepage=>create_in( codepage = `UTF-8`
+ )->convert( source = CONV xstring( line_feed_hex ) ).
+
+ ASSERT line_feed_str = |\n|.
+ ASSERT line_feed_str = cl_abap_char_utilities=>newline.
+
+ output->display( `Y-->` && line_feed_str && `<--` ).
+ output->display( `Y-->` && |\n| && `<--` ).
+
+ DATA a_blank_x TYPE x LENGTH 1 VALUE '20'.
+
+ DATA(blank) = cl_abap_conv_codepage=>create_in( codepage = `UTF-8`
+ )->convert( source = CONV xstring( a_blank_x ) ).
+
+ ASSERT blank = ` `.
+
+ output->display( `-->` && blank && `<--` ).
+
+**********************************************************************
+
+ output->next_section( `15) Date and time` ).
+
+ "In the example, a date field is assigned the current values
+ "using the cl_abap_context_info class. A calculation follow. The date of next
+ "day is calculated.
+ "Note: The data types behave like numeric values in the context of calculations.
+ "In assignments and in the output, they behave like character-like types.
+ "The second example shows an undesired result for a conversion of type i to d.
+ "The number is interpreted as number of days since 0001-01-01 of the Gregorian
+ "calendar. In this case, the date would exceeed the maximum value '99991231'.
+ "In such a case, the date field is assigned the invalid value '00000000'.
+
+ DATA: today TYPE d,
+ tomorrow TYPE d.
+ today = cl_abap_context_info=>get_system_date( ).
+ tomorrow = today + 1.
+ output->display(
+ |Today: { today }\n| &&
+ |Tommorow: { tomorrow }\n| ).
+
+ DATA date TYPE d.
+ date = '20240101'.
+ output->display( input = date name = `date` ).
+
+ date = 20240101.
+ output->display( input = date name = `date` ).
+
+**********************************************************************
+
+ output->next_section( `16) Type conversion rules` ).
+
+ "The purpose of this example is to emphasize the conversion rules
+ "that should be noted when performing conversions. The example
+ "uses only a selection of elementary data types.
+ "The result of the conversion may be unexpected or surprising.
+ "For all the details, check the ABAP Keyword Documentation.
+ "In the following example, a structured type is created.
+ "The components are as follows:
+ "- A data object having a specific data type is to be converted.
+ "- The conversion results are reflected in the other components.
+ "- If there is a conversion error, the conv_err* components hold
+ " the error message.
+ "An internal table is created based on this structured type.
+ "Several data objects are inserted into the internal table, on the
+ "basis of which a conversion is performed. The table is looped over.
+ "Implicit conversions are performed using the assignment operator.
+
+ "Some noteworthy type conversions:
+ "Conversion of d to decfloat34 and i:
+ " If the source field contains a valid date in the format yyyymmdd,
+ " it is used to calculate the number of days since 01.01.0001, and
+ " this value is then converted to the internal representation of the
+ " corresponding integer. If the source field contains an invalid date,
+ " the target field is assigned the value 0.
+ "Conversion of t to decfloat34 and i:
+ " If the source field contains only digits, the content is interpreted
+ " as a time specification in the format hhmmss from which the value
+ " hh*3600+mm*60+ss is calculated and then converted to the internal
+ " representation of the corresponding integer.
+ "Conversion of type i to c:
+ " The value is passed right-aligned. If the target field is too short,
+ " it is truncated on the left and the carachter * is set in the first
+ " position.
+ "Conversion of type i to t:
+ " The value of the integer is divided by the number of seconds in a day
+ " (86,400) and the integer remainder of the division is interpreted as
+ " the number of seconds since midnight. The resulting time is placed in
+ " the target field in the format hhmmss.
+ "Conversion of type i to string:
+ " The character - is set in the last position for a negative value and
+ " a blank is set in the last position for a positive value.
+ "Conversion of type decfloat34 to t:
+ " The content of the source field is first converted to data type i
+ " and then to type t.
+
+ TYPES: BEGIN OF ts_conv_struc,
+ to_be_converted TYPE REF TO data,
+ type TYPE string,
+ conv_c_len2 TYPE c LENGTH 2,
+ conv_err_c_len2 TYPE string,
+ conv_d TYPE d,
+ conv_err_d TYPE string,
+ conv_n_len3 TYPE n LENGTH 3,
+ conv_err_n_len3 TYPE string,
+ conv_t TYPE t,
+ conv_err_t TYPE string,
+ conv_decfl34 TYPE decfloat34,
+ conv_err_decfl34 TYPE string,
+ conv_i TYPE i,
+ conv_err_i TYPE string,
+ conv_str TYPE string,
+ conv_err_str TYPE string,
+ END OF ts_conv_struc.
+
+ DATA tt_conv_tab TYPE TABLE OF ts_conv_struc WITH EMPTY KEY.
+ DATA err TYPE REF TO cx_root.
+
+ DATA d_to_conv TYPE d VALUE '20230101'.
+ DATA t_to_conv TYPE t VALUE '120000'.
+ DATA dec34_to_conv TYPE decfloat34 VALUE '36000.999'.
+
+ "Filling internal table
+ tt_conv_tab = VALUE #(
+ "c
+ ( to_be_converted = REF #( 'abc' ) type = `C LENGTH 3` )
+ ( to_be_converted = REF #( '11111111' ) type = `C LENGTH 8` )
+ "d
+ ( to_be_converted = REF #( d_to_conv ) type = `D` )
+ "t
+ ( to_be_converted = REF #( t_to_conv ) type = `T` )
+ "decfloat34
+ ( to_be_converted = REF #( dec34_to_conv ) type = `DECFLOAT34` )
+ "i
+ ( to_be_converted = REF #( 12345678 ) type = `I` )
+ ( to_be_converted = REF #( -321 ) type = `I` )
+ "string
+ ( to_be_converted = REF #( `hello abap` ) type = `STRING` )
+ ( to_be_converted = REF #( `12345` ) type = `STRING` )
+ ).
+
+ LOOP AT tt_conv_tab REFERENCE INTO DATA(wa_ref_con).
+ ASSIGN wa_ref_con->to_be_converted->* TO FIELD-SYMBOL().
+
+ TRY.
+ wa_ref_con->conv_c_len2 = .
+ wa_ref_con->conv_err_c_len2 = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_c_len2 = err->get_text( ).
+ ENDTRY.
+
+ IF wa_ref_con->type = `T`.
+ wa_ref_con->conv_err_d = `Move error: T to D. Otherwise, a runtime error is caused.`.
+ ELSE.
+ TRY.
+ wa_ref_con->conv_d = .
+ wa_ref_con->conv_err_d = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_d = err->get_text( ).
+ ENDTRY.
+ ENDIF.
+
+ TRY.
+ wa_ref_con->conv_n_len3 = .
+ wa_ref_con->conv_err_n_len3 = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_n_len3 = err->get_text( ).
+ ENDTRY.
+
+ IF wa_ref_con->type = `D`.
+ wa_ref_con->conv_err_t = `Move error: D to T. Otherwise, a runtime error is caused.`.
+ ELSE.
+ TRY.
+ wa_ref_con->conv_t = .
+ wa_ref_con->conv_err_t = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_t = err->get_text( ).
+ ENDTRY.
+ ENDIF.
+
+ TRY.
+ wa_ref_con->conv_decfl34 = .
+ wa_ref_con->conv_err_decfl34 = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_decfl34 = err->get_text( ).
+ ENDTRY.
+
+ TRY.
+ wa_ref_con->conv_i = .
+ wa_ref_con->conv_err_i = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_i = err->get_text( ).
+ ENDTRY.
+
+ TRY.
+ wa_ref_con->conv_str = .
+ wa_ref_con->conv_err_str = `-`.
+ CATCH cx_root INTO err.
+ wa_ref_con->conv_err_str = err->get_text( ).
+ ENDTRY.
+
+ ENDLOOP.
+
+ output->display( input = tt_conv_tab name = `tt_conv_tab` ).
+
+**********************************************************************
+
+ output->next_section( `18) Constants and immutable variables` ).
+
+ "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.
+
+ output->display( `No output for this section. Check out the code, `
+ && `for example, when running the class in the debugger after setting `
+ && `a breakpoint, or the F2 information in ADT when selecting a type.` ).
+
+**********************************************************************
+
+ output->next_section( `19) Various ABAP glossary terms on data types and objects in a nutshell` ).
+
+ "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.
+
+ "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 with which data reference
+ "variables can be typed.
+ "As the name implies, clike expects character-like data types. data can
+ "expect any data type. This is shown in the example. Apart from the
+ "character-like types, internal table types are also accepted.
+ FIELD-SYMBOLS TYPE clike.
+ FIELD-SYMBOLS TYPE data.
+
+ "Data object declarations
+ DATA do_e_c5 TYPE c LENGTH 5 VALUE 'abcde'.
+ DATA do_f_str TYPE string VALUE `Hallo, how are you?`.
+ DATA(itab_a) = VALUE string_table( ( `a` ) ( `b` ) ( `c` ) ).
+
+ "Generic type clike
+ "Field symbols with generic data types can be assigned appropriate values
+ ASSIGN do_e_c5 TO .
+
+ output->display( input = name = `` ).
+
+ ASSIGN do_f_str TO .
+
+ output->display( input = name = `` ).
+
+ "Generic type data
+ ASSIGN do_e_c5 TO .
+
+ output->display( input = name = `` ).
+
+ ASSIGN do_f_str TO .
+
+ output->display( input = name = `` ).
+
+ ASSIGN itab_a TO .
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ "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.
+ "An assignment as follows is not possible. The data object cannot be
+ "modified.
+ "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
+ "Set a breakpoint here and check the Variables tab in ADT how the value and
+ "the information changes.
+ 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 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 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.
+ output->display( `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` ).
+
+ output->display( input = dref_c_str->* name = `dref_c_str->*` ).
+
+ "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.
+
+ output->display( input = dref_d_tab->* name = `dref_d_tab->*` ).
+
+**********************************************************************
+
+ output->next_section( `20) Generic ABAP types for formal parameters of methods` ).
+
+ "Generic data types have already been covered above.
+ "A generic data type is an incomplete type specification that covers multiple
+ "complete type specifications.
+ "This example demonstrates generic ABAP types in the context of formal parameters
+ "of methods.
+ "Unlike data objects, where the data type has a specific property and is always
+ "completely known, formal parameters and field symbols that are generically typed
+ "receive their complete data type only when an actual parameter is passed in a method
+ "call, or, regarding field symbols, when a memory area is assigned.
+ "In the following example, a method is called that has two importing parameters typed
+ "with the generic type numeric. An internal table is filled with values on whose basis
+ "the method is provided with actual parameters. Intentionally, various numeric values
+ "are included as well as values that will not work.
+
+ TYPES: BEGIN OF str_num,
+ num1 TYPE REF TO data,
+ num2 TYPE REF TO data,
+ result TYPE decfloat34,
+ END OF str_num.
+
+ DATA tab_num TYPE TABLE OF str_num WITH EMPTY KEY.
+
+ tab_num = VALUE #( ( num1 = NEW i( 1 ) num2 = NEW i( 2 ) )
+ ( num1 = NEW decfloat34( '1.74' ) num2 = NEW decfloat34( '4.04' ) )
+ ( num1 = NEW i( 11 ) num2 = NEW decfloat34( '10.621' ) )
+ ( num1 = NEW string( `Some string` ) num2 = NEW i( 2 ) ) ).
+
+ LOOP AT tab_num REFERENCE INTO DATA(fp_ref).
+ TRY.
+ ASSIGN fp_ref->num1->* TO FIELD-SYMBOL().
+ ASSIGN fp_ref->num2->* TO FIELD-SYMBOL().
+ fp_ref->result = addition_with_generic_num( num1 = num2 = ).
+ CATCH cx_sy_dyn_call_illegal_type INTO DATA(error).
+ ENDTRY.
+ ENDLOOP.
+
+ output->display( input = tab_num name = `tab_num` ).
+
+ output->display( input = error->get_text( ) name = `error->get_text( )` ).
+
+**********************************************************************
+
+ output->next_section( `21) Built-in data objects` ).
+
+ "This example demonstrates the availability of built-in data objects in ABAP.
+
+ "System fields are filled by the ABAP runtime framework and can be used in an ABAP
+ "program to query various things.
+ "The following example covers the values provided with sy-index and sy-tabix.
+ "Check both loops in the debugger and insert sy-index/sy-tabix in the
+ "Variables tab to see the value change.
+
+ DATA syidx LIKE TABLE OF sy-index.
+
+ "In DO and WHILE loops, sy-index contains the number of previous loop passes,
+ "including the current pass.
+ DO 5 TIMES.
+ APPEND sy-index TO syidx.
+ ENDDO.
+
+ output->display( input = syidx name = `syidx` ).
+
+ DATA str_tab TYPE TABLE OF string.
+
+ "In loops with LOOP AT, sy-tabix contains the line number in the table
+ "index of an index table.
+ LOOP AT syidx INTO DATA(wa_sy1).
+ APPEND |Value of processed table line: { wa_sy1 } / Table index { sy-tabix }| TO str_tab.
+ ENDLOOP.
+
+ output->display( input = str_tab name = `str_tab` ).
+
+ "sy-subrc contains a return code that is set by many ABAP statements.
+ "In general, the value 0 means that the statement was executed without problems.
+
+ READ TABLE syidx INDEX 6 INTO DATA(wa_sy2).
+
+ IF sy-subrc = 0.
+ output->display( |Yes, the table line was found. sy-subrc value that was returned is { sy-subrc }.| ).
+ ELSE.
+ output->display( |No, the table line was not found. sy-subrc value that was returned is { sy-subrc }.| ).
+ ENDIF.
+
+ "The program-global constant space has the data type c, length 1, and contains a blank character.
+ "In the following example, the table lines are concatenated into a string, separated by a blank.
+
+ DATA ctab TYPE TABLE OF c.
+
+ ctab = VALUE #( ( 'a' ) ( 'b' ) ( 'c' ) ).
+
+ DATA c_f TYPE c LENGTH 10.
+
+ CONCATENATE LINES OF ctab INTO c_f SEPARATED BY space.
+
+ output->display( input = c_f name = `c_f` ).
+
+ "Self-reference me
+ "Within the implementation of each instance method, an implicitly created local
+ "reference variable called me is available at runtime, which points to the instance
+ "in which the method is currently being executed.
+ "me is handled like a local constant, which means that the value of me cannot be
+ "changed in an instance method. The static type of me is the class in which the
+ "instance method is implemented.
+ "In the following example, an instance of this class is created. Then a method is
+ "called, and a string is returned. The method implementation includes a data object
+ "that is (intentionally) declared with the same name of the instance attribute
+ "available in the private section of the class (text). Using the self-reference me
+ "(me->text), you can explicitly refer to the instance attribute. Just 'text' means
+ "referring to the data object locally declared in the method.
+
+ DATA(oref) = NEW zcl_demo_abap_dtype_dobj( ).
+
+ cl_text = 'Hallo'.
+
+ DATA(res_str) = oref->adapt_text( ).
+
+ output->display( input = res_str name = `res_str` ).
+
+
+**********************************************************************
+
+ output->next_section( `22) Declaration context` ).
+
+ "The purpose of this example is to emphasize the importance of where
+ "data objects are decalred. The example deals with local declarations
+ "and control structures. A data object of type i is declared within
+ "the control structure. However, it is valid globally in this ABAP
+ "program, i.e. in the whole method here.
+ "The value of the data object is not set to 10 in each loop pass.
+ "Furthermore, the data object can also be used in the second DO loop.
+
+ DO 10 TIMES.
+ DATA number TYPE i VALUE 10.
+ number = number + 1.
+ ENDDO.
+
+ output->display( input = number name = `number` ).
+
+ DO 10 TIMES.
+ number = number + 1.
+ ENDDO.
+
+ output->display( input = number name = `number` ).
+
+ "Comparing the behavior with a data object declared inline.
+ "In each loop pass, the value object is set to 10. Therefore,
+ "the value is 11 after exiting the DO loop.
+ "The data object declared inline can also be used in the second DO loop.
+ "The value of the data object is 21 when exiting the loop.
+ "That means you should be careful when using variables declared inline
+ "in control structures. It should only be used within the control structure
+ "in which it is declared and not beyond.
+
+ DO 10 TIMES.
+ DATA(number_B) = 10.
+ number_B = number_B + 1.
+ ENDDO.
+
+ output->display( input = number_b name = `number_b` ).
+
+ DO 10 TIMES.
+ number_b = number_b + 1.
+ ENDDO.
+ output->display( input = number_b name = `number_b` ).
+
+**********************************************************************
+
+ output->next_section( `23) Enumerated Types and Objects` ).
+
+ "Examples for enumerated types and objects are contained in
+ "separate methods. Check the comments there.
+ "Note that the output that is created in the methods is combined
+ "in a string (table).
+
+ "The enum_meth_params method demonstrates the use of enumerated objects
+ "when comparing them with the respective enumeration constants to branch
+ "to some functionality (CASE statement in the method implementation).
+ "In typing the formal parameter this way, it is guaranteed that only
+ "enumerated values of the enumerated type can be passed to the parameter.
+ DATA enum_var1 TYPE t_enum VALUE a.
+ DATA(output_for_enum_var1) = enum_meth_params( enum_var1 ).
+ output->display( input = output_for_enum_var1 name = `output_for_enum_var1` ).
+
+ DATA enum_var2 TYPE t_enum VALUE b.
+ DATA(output_for_enum_var2) = enum_meth_params( enum_var2 ).
+ output->display( input = output_for_enum_var2 name = `output_for_enum_var2` ).
+
+ DATA enum_var3 TYPE t_enum VALUE d.
+ DATA(output_for_enum_var3) = enum_meth_params( enum_var3 ).
+ output->display( input = output_for_enum_var3 name = `output_for_enum_var3` ).
+
+ "The enum_processing method demonstrates various ways of processing enumerated
+ "objects.
+ DATA(output_for_enum_processing) = enum_processing( ).
+ output->display( input = output_for_enum_processing name = `output_for_enum_processing` ).
+
+ "The rtti_enum method demonstrates the RTTI class cl_abap_enumdescr.
+ DATA(output_for_rtti_enum) = rtti_enum( ).
+ output->display( input = output_for_rtti_enum name = `output_for_rtti_enum` ).
+
+ ENDMETHOD.
+
+
+ METHOD rtti_enum.
+
+ DATA enum1 TYPE t_enum.
+ enum1 = d.
+
+ DATA enum2 TYPE t_enum_base.
+ enum2 = f.
+
+ "Return type information
+ DATA(enum_descr) = CAST cl_abap_enumdescr(
+ cl_abap_typedescr=>describe_by_data( enum1 ) ).
+
+ APPEND `------ Properties for enum1 ------` TO output.
+
+ APPEND ` kind: ` && enum_descr->kind TO output.
+ APPEND ` type_kind: ` && enum_descr->type_kind TO output.
+ APPEND ` base_type_kind: ` && enum_descr->base_type_kind TO output.
+
+ DATA mem_string TYPE string.
+
+ "For output purposes, the table content is put in a string.
+ "Note the object component selector -> when reading into data reference variables
+ "and accessing componts. You can also use the dereferencing operator followed by the
+ "structure component selector ref->*-comp.
+ LOOP AT enum_descr->members REFERENCE INTO DATA(ref_en1).
+ mem_string = mem_string && ` / Name: ` && ref_en1->name && `; Value: ` && ref_en1->*-value.
+ ENDLOOP.
+
+ REPLACE FIRST OCCURRENCE OF PCRE `/\s` IN mem_string WITH ``.
+ APPEND ` members:` && mem_string TO output.
+ CLEAR mem_string.
+
+ enum_descr = CAST cl_abap_enumdescr(
+ cl_abap_typedescr=>describe_by_data( enum2 ) ).
+
+ APPEND `------ Properties for enum2 ------` TO output.
+ APPEND ` kind: ` && enum_descr->kind TO output.
+ APPEND ` type_kind: ` && enum_descr->type_kind TO output.
+ APPEND ` base_type_kind: ` && enum_descr->base_type_kind TO output.
+
+ "For output purposes, the table content is put in a string.
+ LOOP AT enum_descr->members REFERENCE INTO DATA(ref_en2).
+ mem_string = mem_string && ` / Name: ` && ref_en2->name && `; Value: ` && ref_en2->value.
+ ENDLOOP.
+
+ REPLACE FIRST OCCURRENCE OF PCRE `/\s` IN mem_string WITH ``.
+ APPEND ` members:` && mem_string TO output.
+ ENDMETHOD.
+ENDCLASS.
+
diff --git a/src/zcl_demo_abap_dtype_dobj.clas.xml b/src/zcl_demo_abap_dtype_dobj.clas.xml
new file mode 100644
index 0000000..967117a
--- /dev/null
+++ b/src/zcl_demo_abap_dtype_dobj.clas.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+ ZCL_DEMO_ABAP_DTYPE_DOBJ
+ E
+ ABAP Cheat Sheet: Data Types and Data Objects
+ 1
+ X
+ X
+ X
+
+
+
+
diff --git a/src/zcl_demo_abap_dynamic_prog.clas.abap b/src/zcl_demo_abap_dynamic_prog.clas.abap
new file mode 100644
index 0000000..1239e46
--- /dev/null
+++ b/src/zcl_demo_abap_dynamic_prog.clas.abap
@@ -0,0 +1,1948 @@
+***********************************************************************
+*
+* ABAP cheat sheet: Dynamic programming
+*
+* -------------------------- PURPOSE ----------------------------------
+* - Example to demonstrate various syntax options and concepts related
+* to dynamic programming.
+* - Topics covered: Field symbols and data references (both as supporting
+* elements for dynamic programming), dynamic ABAP syntax components,
+* runtime type services (RTTS), i. e. runtime type identification (RTTI)
+* and runtime type creation (RTTC)
+* - To provide a "real" dynamic determination at runtime for several code
+* examples in this class, the example class includes local classes
+* in the CCIMP include (local types tab in ADT) whose methods return
+* character-like content to be used in the ABAP statements. The content
+* is predefined in these classes but the content that is actually used
+* in the end is random.
+*
+* ----------------------- GETTING STARTED -----------------------------
+* - Open the class with the ABAP development tools for Eclipse (ADT).
+* - Choose F9 to run the class.
+* - Check the console output.
+* - To understand the context and the ABAP syntax used, refer to the
+* notes included in the class as comments or refer to the respective
+* topic in the ABAP Keyword Documentation.
+* - Due to the amount of console output, the examples contain numbers
+* (e.g. 1) ..., 2) ..., 3) ...) for the individual example sections.
+* Also, the variable name is displayed in most cases. So to find
+* the relevant output in the console easier and faster, just search
+* for the number/variable name in the console (CTRL+F in the console)
+* or use the debugger.
+*
+* ----------------------------- NOTE -----------------------------------
+* The code presented in this class is intended only to support the ABAP
+* cheat sheets. It is not intended for direct use in a production system
+* environment. The code examples in the ABAP cheat sheets are primarily
+* intended to provide a better explanation and visualization of the
+* syntax and semantics of ABAP statements, not to solve concrete
+* programming tasks. For production application programs, you should
+* always work out your own solution for each individual case. There is
+* no guarantee for the correctness or completeness of the code.
+* Furthermore, there is no legal responsibility or liability for any
+* errors or their consequences that may occur when using the the example
+* code.
+*
+***********************************************************************
+"! ABAP cheat sheet: Dynamic programming
+"! Example to demonstrate syntax related to dynamic programming.
Choose F9 in ADT to run the class.
+CLASS zcl_demo_abap_dynamic_prog DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+ INTERFACES: if_oo_adt_classrun.
+
+ CLASS-METHODS:
+ class_constructor.
+ENDCLASS.
+
+
+
+CLASS zcl_demo_abap_dynamic_prog IMPLEMENTATION.
+
+
+ METHOD class_constructor.
+ "Filling demo database tables.
+ zcl_demo_abap_flight_tables=>fill_dbtabs( ).
+ ENDMETHOD.
+
+
+ METHOD if_oo_adt_classrun~main.
+
+ DATA(output) = NEW zcl_demo_abap_display( out ).
+
+ output->display( `ABAP Cheat Sheet Example: Dynamic Programming` ).
+
+**********************************************************************
+
+ output->display( `Excursion: Field Symbols` ).
+ output->display( `1) Declaring Field Symbols` ).
+
+ "Some data declarations and type definitions used further down
+ DATA: str TYPE string.
+
+ TYPES: BEGIN OF struc, "Structured data type
+ num1 TYPE i,
+ num2 TYPE i,
+ END OF struc,
+ tab_type TYPE TABLE OF struc. "Internal table type
+
+ "Field symbol declarations
+ "- Name of the field symbol goes between angle brackets
+ "- Type: either a complete data type or a generic type.
+
+ "Complete types
+ "Here, a chained statement with a colon is used.
+ FIELD-SYMBOLS: TYPE i,
+ TYPE zdemo_abap_flsch,
+ TYPE LINE OF tab_type,
+ LIKE str.
+
+ "Generic types
+ "There are plenty of options for generic ABAP types. Check the
+ "keyword docu.
+ FIELD-SYMBOLS TYPE c. "Text field with a generic length
+ FIELD-SYMBOLS TYPE csequence. "Text-like (c, string)
+ FIELD-SYMBOLS TYPE data. "Any data type
+ FIELD-SYMBOLS TYPE ANY TABLE. "Internal table with any table type
+
+ "Declaring field symbols inline
+ "Prominent use case: Inline declaration of a field symbol for an internal table
+ "following ASSIGNING.
+ DATA demo_itab TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
+
+ LOOP AT demo_itab ASSIGNING FIELD-SYMBOL().
+ ...
+ ENDLOOP.
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `2) Assigning Data Objects to Field Symbols` ).
+
+ "ASSIGN statements assigns the memory area of a data object to a field symbol.
+ "Once the memory area is assigned, you can work with the content.
+ "You can also assign a particular component of a structure. Either you
+ "specify the position of the component or the name of the component.
+
+ "Data objects.
+ DATA: num_a TYPE i,
+ struc_a TYPE zdemo_abap_fli,
+ tab_a TYPE string_table.
+
+ "Field symbols with complete types
+ FIELD-SYMBOLS: TYPE i,
+ TYPE zdemo_abap_fli,
+ TYPE string_table.
+
+ "Field symbols with complete types
+ FIELD-SYMBOLS TYPE data.
+ FIELD-SYMBOLS TYPE ANY TABLE.
+
+ "Assigning data objects to field symbols
+ ASSIGN num_a TO .
+ ASSIGN struc_a TO .
+ ASSIGN tab_a TO .
+ ASSIGN: num_a TO ,
+ struc_a TO ,
+ tab_a TO ,
+ tab_a TO .
+
+ "Inline declaration is possible, too. The type is derived automatically.
+ ASSIGN num_a TO FIELD-SYMBOL().
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `3) Checking Field Symbol Assignment` ).
+
+ "When working with field symbols, you should make sure that they are
+ "assigned. Otherwise, a runtime error occurs.
+ "You can make use of a logical expression with IS [NOT] ASSIGNED.
+ "The example includes data object declarations. One data object is
+ "assigned, the other is not. Consequently, the expression is
+ "true for the one and false for the other.
+
+ DATA num_b TYPE i VALUE 123.
+
+ FIELD-SYMBOLS: TYPE i,
+ TYPE string.
+
+ ASSIGN num_b TO .
+
+ IF IS ASSIGNED.
+ output->display( `Field symbol is assigned.` ).
+ ELSE.
+ output->display( `Field symbol not assigned.` ).
+ ENDIF.
+
+ IF IS ASSIGNED.
+ output->display( `Field symbol is assigned.` ).
+ ELSE.
+ output->display( `Field symbol is not assigned.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `4) Unassigning Data Objects from Field Symbols` ).
+
+ "If you use an unassigned field symbol, an exception is raised. Before
+ "using it, you can check the assignment with the following logical
+ "expression. The statement is true if the field symbol is assigned.
+ "Using the statement UNASSIGN, you can explicitly remove the assignment
+ "of the field symbol.
+
+ DATA num_c TYPE i VALUE 123.
+
+ FIELD-SYMBOLS: TYPE i.
+
+ ASSIGN num_c TO .
+
+ IF IS ASSIGNED.
+ output->display( `1. Field symbol is assigned.` ).
+ ELSE.
+ output->display( `1. Field symbol is not assigned.` ).
+ ENDIF.
+
+ UNASSIGN .
+
+ IF IS ASSIGNED.
+ output->display( `2. Field symbol is assigned.` ).
+ ELSE.
+ output->display( `2. Field symbol is not assigned.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `5) Type Casting with Field Symbols` ).
+
+ "The example demonstrates the CASTING addition. Various additions after
+ "CASTING are possible.
+
+ TYPES type_d_l9 TYPE c LENGTH 9.
+
+ DATA: dobj_d_l5 TYPE c LENGTH 5,
+ dobj_d_l10 TYPE c LENGTH 10 VALUE '1234567890',
+ type_name_d TYPE string VALUE 'TYPE_D_L9'.
+
+ FIELD-SYMBOLS: TYPE data,
+ TYPE type_d_l9.
+
+ "Casting to a statically, completely specified type
+ "CASTING addition without any more additions: Field symbol inherits
+ "the data type of the data object. The field symbol must be either
+ "completely typed or with one of the generic built-in ABAP types
+ "c, n, p, or x. The other field symbol declared in the example
+ "cannot be used.
+ ASSIGN dobj_d_l10 TO CASTING.
+
+ output->display( input = name = `` ).
+
+ ASSIGN dobj_d_l10 TO CASTING TYPE type_d_l9.
+
+ output->display( input = name = `` ).
+
+ "Casting to a generic type
+ ASSIGN dobj_d_l10 TO CASTING TYPE c.
+
+ output->display( input = name = `` ).
+
+ "Casting to a static field type
+ ASSIGN dobj_d_l10 TO CASTING LIKE dobj_d_l5.
+
+ output->display( input = name = `` ).
+
+ "Casting to a dynamic field type
+ ASSIGN dobj_d_l10 TO CASTING LIKE .
+
+ output->display( input = name = `` ).
+
+ "Anticipating dynamic specification of data types
+ "for the CASTING addition.
+ "The type name is specified as a character-like data
+ "object within parentheses.
+ ASSIGN dobj_d_l10 TO CASTING TYPE (type_name_d).
+
+ output->display( input = name = `` ).
+
+ "Anticipating RTTS
+ "A type description object is created which can be
+ "specified after the TYPE HANDLE additions.
+ DATA(sometype) = CAST cl_abap_datadescr(
+ cl_abap_typedescr=>describe_by_name( 'TYPE_D_L9' ) ).
+ ASSIGN dobj_d_l10 TO CASTING TYPE HANDLE sometype.
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `6) Addressing Field Symbols` ).
+
+ "The example includes multiple data objects that are assigned to field
+ "symbols. It is demonstrated that field symbols are addressed in various
+ "occasions. Among them: Changing the value of data objects assigned to
+ "field symbols, the use of field symbols in expressions, structures, and
+ "internal tables.
+
+ DATA: num_e TYPE i VALUE 456,
+ struc_e TYPE zdemo_abap_carr,
+ tab_e TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
+
+ SELECT SINGLE *
+ FROM zdemo_abap_carr
+ WHERE carrid = 'LH'
+ INTO @struc_e.
+
+ FIELD-SYMBOLS: TYPE i,
+ TYPE zdemo_abap_carr,
+ LIKE tab_e,
+ TYPE ANY TABLE.
+
+ "Without an assignment, this would result in a runtime error:
+ " = 1.
+
+ ASSIGN num_e TO .
+ ASSIGN struc_e TO .
+ ASSIGN tab_e TO .
+ ASSIGN tab_e TO .
+
+ "Changing values
+ = 789.
+
+ output->display( input = name = `` ).
+ output->display( input = num_e name = `num_e` ).
+
+ "Use in expressions
+ DATA(calc_e) = + 211.
+
+ output->display( input = calc_e name = `calc_e` ).
+
+ IF < 1000.
+ output->display( `The value of is less than 1000` ).
+ ELSE.
+ output->display( `The value of is greater than 1000` ).
+ ENDIF.
+
+ "Structure
+ output->display( input = name = `` ).
+
+ DATA(comp_e1) = -carrid.
+
+ output->display( input = comp_e1 name = `comp_e1` ).
+
+ -url = 'www.lh.com'.
+
+ output->display( input = -url name = `-url` ).
+
+ "Internal table
+ SELECT *
+ FROM zdemo_abap_carr
+ ORDER BY carrid
+ INTO TABLE @
+ UP TO 3 ROWS.
+
+ output->display( input = name = `` ).
+
+ TRY.
+ DATA(comp_e2) = [ 2 ]-carrname.
+ output->display( input = comp_e2 name = `comp_e2` ).
+ CATCH cx_sy_itab_line_not_found INTO DATA(error_e).
+ ENDTRY.
+
+ SELECT *
+ FROM zdemo_abap_carr
+ ORDER BY carrid
+ INTO TABLE @
+ UP TO 3 ROWS.
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `7) Using Field Symbols when Processing ` &&
+ `Internal Tables` ).
+
+ "By using field symbols in the context of loops across internal tables,
+ "you can avoid an actual copying of content to a work area during
+ "the loop.
+ "The example includes multiple loops. First, internal tables are
+ "declared. One of them is filled. Then, field symbols are declared to
+ "which data objects are assigned. In the first loop, a previously
+ "declared field symbol is used as target area to hold the table line
+ "that is processed. In the course of the loop, some values are changed. The
+ "components are accessed using the component selector '-'. At the end of
+ "the loop, another internal table is filled using the currently
+ "processed line for the second loop. The second loop (the loop is
+ "carried out based on
+ "an internal table a field symbol points to) uses a directly declared
+ "field symbol using ASSIGNING FIELD-SYMBOL(<...>). Also here, some
+ "values are changed and another internal table is filled. This table
+ "is of a generic type. At the end, this internal table is output, too.
+
+ DATA: tab_f1 TYPE TABLE OF zdemo_abap_fli WITH EMPTY KEY,
+ tab_f2 LIKE tab_f1,
+ tab_f3 LIKE tab_f1.
+
+ SELECT *
+ FROM zdemo_abap_fli
+ ORDER BY carrid
+ INTO TABLE @tab_f1
+ UP TO 3 ROWS.
+
+ FIELD-SYMBOLS: LIKE LINE OF tab_f1,
+ LIKE tab_f1,
+ TYPE ANY TABLE.
+
+ ASSIGN tab_f2 TO .
+ ASSIGN tab_f3 TO .
+
+ LOOP AT tab_f1 ASSIGNING .
+ -connid = '99'.
+ -fldate = cl_abap_context_info=>get_system_date( ).
+ -price = -price + 100.
+ -currency = 'EUR'.
+ CLEAR: -paymentsum,
+ -seatsocc,
+ -seatsocc_b,
+ -seatsocc_f.
+
+ "Filling another itab
+ = VALUE #( BASE ( ) ).
+ ENDLOOP.
+
+ output->display( input = tab_f1 name = `tab_f1` ).
+
+ "The following example shows a field symbol declared inline.
+ LOOP AT ASSIGNING FIELD-SYMBOL().
+ -connid = '100'.
+ -fldate = cl_abap_context_info=>get_system_date( ) + 1.
+ -price = -price - 50.
+ -currency = 'USD'.
+
+ "Filling another itab
+ = VALUE #( BASE ( ) ).
+ ENDLOOP.
+
+ output->display( input = name = `` ).
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `8) Field Symbols in the Context of Processing a Structure` ).
+
+ "In this example, all components of a structure are processed using
+ "field symbols and an ASSIGN COMPONENT ... OF STRUCTURE ... statement.
+ "First, a field symbol is declared with a generic type. A structure is
+ "filled with values from a demo table. The structure is assigned to the
+ "field symbol. Using a DO loop, all components are processed. The
+ "sy-index value represents the position of the component in the
+ "structure. Once all components have been processed (i. e. if sy-subrc
+ "does not return '0' for a sy-index value), the loop is exited. The output
+ "shows all components and their values.
+
+ FIELD-SYMBOLS: TYPE data.
+
+ DATA: comp_tab TYPE string_table.
+
+ SELECT SINGLE carrid, carrname, currcode, url
+ FROM zdemo_abap_carr
+ WHERE carrid = 'LH'
+ INTO @DATA(struct).
+
+ FIELD-SYMBOLS: TYPE data.
+
+ ASSIGN struct TO .
+
+ DO.
+ "sy-index represents the position of a structure component
+
+ ASSIGN COMPONENT sy-index OF STRUCTURE TO .
+
+ IF sy-subrc <> 0.
+ "If all components are processed, the loop is exited.
+ EXIT.
+ ELSE.
+ output->display( |sy-index: { sy-index }, component content:| ).
+ output->display( ).
+ ENDIF.
+
+ ENDDO.
+
+**********************************************************************
+
+ output->next_section( `Data references` ).
+ output->display( `9) Declaring Data References` ).
+
+ "Like field symbols, data reference variables can be declared with both
+ "a complete and a generic data type using DATA statements and the
+ "addition REF TO. The type after REF TO represents the static data type.
+ "The example shows multiple ways of declaring a data reference variable
+ "using both complete and generic data types.
+
+ DATA: some_string TYPE string.
+
+ TYPES: ref_type TYPE REF TO zdemo_abap_flsch.
+
+ DATA: ref_a1 TYPE REF TO i, "Complete data type
+ ref_a2 TYPE REF TO zdemo_abap_carr, "Complete data type
+ ref_a3 LIKE REF TO some_string,
+ ref_a4 LIKE ref_a1,
+ ref_a5 TYPE ref_type,
+ ref_a6 TYPE REF TO data. "Generic data type
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `10) Creating Data References ` &&
+ `to Existing Data Objects` ).
+
+ "The example includes data reference variables with both complete and
+ "generic type. When using the REF operator, the '#' sign means that the
+ "type is derived from the data object. You can also explicitly specify
+ "the data type after REF before the parenthesis. Within the parentheses,
+ "you can provide a value.
+
+ "Declaring data object
+ DATA number_b TYPE i VALUE 5.
+
+ "Declaring data reference variables
+ DATA ref_b1 TYPE REF TO i.
+ DATA ref_data_b TYPE REF TO data.
+
+ "Creating data references to data objects.
+ "The '#' sign means that the type is derived from the data object.
+ ref_b1 = REF #( number_b ).
+ ref_data_b = REF #( number_b ).
+
+ "You can also use inline declarations to omit the explicit declaration.
+ DATA(ref_b2) = REF #( number_b ).
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `11) Dynamically Creating Data Objects at Runtime Using Static Type Definitions` ).
+
+ "The example code shows the creation of anonymous data objects. They
+ "can be created using the statement CREATE DATA, the instance operator
+ "NEW, or the addition NEW of the INTO clause in a SELECT statement.
+ "A data reference variable is expected when anonymous objects are
+ "declared. They cannot be addressed by a name (hence anonymous).
+ "Note:
+ "- The examples cover static type definitions. As shown further down,
+ " there are options to dynamically specify the type definitions.
+ "- To output the content of the data reference variables, they
+ " must be dereferenced first. The details are shown further down.
+
+ "CREATE DATA statements
+ "Note that there are many additions available. The examples show a selection.
+ "Behind TYPE and LIKE, the syntax offers the same possibilities as the DATA statement.
+
+ "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_c1 TYPE REF TO string.
+ CREATE DATA dref_c1.
+
+ "Creating anonymous data objects with explicit data type specification.
+ "Data reference variable with a generic type to be used in the following examples
+ "for the anonymous data object.
+ DATA dref_c2 TYPE REF TO data.
+
+ "Elementary, built-in ABAP type
+ CREATE DATA dref_c2 TYPE p LENGTH 8 DECIMALS 3.
+
+ "Anomyous internal table ...
+ "using the LIKE addition to refer to an existing internal table
+ DATA itab_c TYPE TABLE OF zdemo_abap_carr.
+ CREATE DATA dref_c2 LIKE itab_c.
+
+ "by specifying the entire table type
+ CREATE DATA dref_c2 TYPE HASHED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid.
+
+ "Anonymous structures
+ CREATE DATA dref_c2 LIKE LINE OF itab_c.
+ CREATE DATA dref_c2 TYPE zdemo_abap_carr.
+
+ "Creating reference variable
+ TYPES elem_type_c TYPE c LENGTH 3.
+ CREATE DATA dref_c2 TYPE REF TO elem_type_c.
+
+ "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_c3 TYPE REF TO i,
+ dref_c4 TYPE REF TO data.
+
+ "# character after NEW if the data type can be identified completely
+ "instead of the explicit type specification (only non-generic types)
+ dref_c3 = NEW #( 123 ).
+ dref_c3 = NEW i( 456 ).
+ dref_c4 = NEW zdemo_abap_carr( ). "not assigning any values
+ dref_c4 = NEW string( `hi` ).
+
+ "Creating anonymous data objects inline
+ "In doing so, you can omit a prior declaration of a variable.
+ DATA(dref_c5) = NEW i( 789 ).
+ DATA(dref_c6) = NEW zdemo_abap_carr( carrid = 'AB' carrname = 'AB Airlines' ).
+
+ "ABAP SQL SELECT statements
+ "Using the NEW addition in the INTO clause, an anonymous data object with
+ "suitable type can be created in place.
+ SELECT *
+ FROM zdemo_abap_carr
+ INTO TABLE NEW @DATA(dref_c7) "Internal table
+ UP TO 3 ROWS.
+
+ SELECT SINGLE *
+ FROM zdemo_abap_carr
+ WHERE carrid = 'LH'
+ INTO NEW @DATA(dref_c8). "Structure
+
+ output->display( input = dref_c6->* name = `dref_c6->*` ).
+ output->display( input = dref_c7->* name = `dref_c7->*` ).
+ output->display( input = dref_c8->* name = `dref_c8->*` ).
+
+**********************************************************************
+
+ output->next_section( `12) Data References and Assignments` ).
+
+ "Regarding the assignment, note that static types of both data
+ "reference variables must be compatible. As a result of an assignment,
+ "both the target reference variable and the source reference variable
+ "point to the same data object.
+ "Upcast/downcasts: For an assignment to work, the basic rule applies:
+ "The static type of the target reference variable must be more general
+ "than or the same as the dynamic type of the source reference variable.
+ "In the example below:
+ "Upcast: The target data reference variable is of generic type, the
+ "source variable is of complete type. The assignment is done with the
+ "assignment operator '='.
+ "Downcast: The target data reference variable is of complete type, the
+ "source variable is of generic type. The assignment is done with casting
+ "operators, either with the constructor operator CAST or the older ?=.
+
+ "Declaring data reference variables
+ DATA ref_d1 TYPE REF TO i.
+ DATA ref_d2 TYPE REF TO i.
+
+ ref_d1 = NEW #( 789 ).
+
+ "Assigning data reference
+ ref_d2 = ref_d1.
+
+ "Casting
+ "Complete type
+ DATA(ref_d3) = NEW i( 321 ).
+
+ "Generic type
+ DATA ref_data_d1 TYPE REF TO data.
+
+ "Upcast
+ ref_data_d1 = ref_d3.
+ ASSIGN ref_data_d1->* TO FIELD-SYMBOL().
+
+ "Downcasts
+ DATA ref_d5 TYPE REF TO i.
+
+ "Generic type
+ DATA ref_data_d2 TYPE REF TO data.
+
+ ref_data_d2 = NEW i( 654 ).
+
+ ref_d5 = CAST #( ref_data_d2 ).
+
+ ref_d5 ?= ref_data_d2.
+
+ output->display( input = ref_d2->* name = `ref_d2->*` ).
+ output->display( input = name = `` ).
+ output->display( input = ref_d5->* name = `ref_d5->*` ).
+
+**********************************************************************
+
+ output->next_section( `13) Addressing Data References ` ).
+
+ "Before addressing the content of data objects a data reference points
+ "to, you must dereference data reference variables. Use the
+ "dereferencing operator ->*.
+ "The example includes multiple occasions in which data reference are
+ "addressed: Changing the content of a referenced data object, the use in
+ "logical expressions, structures, and internal tables.
+
+ "Creating data reference variables and assigning values
+ DATA(ref_e1) = NEW i( 1 ).
+ DATA(ref_e2) = NEW zdemo_abap_carr( carrid = 'LH'
+ carrname = 'Lufthansa' ).
+
+ "Generic type
+ DATA ref_data_e TYPE REF TO data.
+
+ "Copying reference
+ ref_data_e = ref_e1.
+
+ "Addressing
+ "Variable receives the content.
+ DATA(some_num) = ref_e1->*.
+
+ output->display( input = ref_e1->* name = `ref_e1->*` ).
+
+ "Content of referenced data object is changed
+ ref_e1->* = 10.
+
+ output->display( input = ref_e1->* name = `ref_e1->*` ).
+
+ "Data reference used in a logical expression
+ IF ref_e1->* > 5.
+ output->display( `The value of ref_e1 is greater than 5.` ).
+ ELSE.
+ output->display( `The value of ref_e1 is lower than 5.` ).
+ ENDIF.
+
+ "Complete structure
+ DATA(struc) = ref_e2->*.
+
+ output->display( input = ref_e2->* name = `ref_e2->*` ).
+
+ "Individual structure component
+ "When dereferencing a data reference variable that has a structured
+ "data type, you can use the component selector -> to address individual components.
+ DATA(carrid) = ref_e2->carrid.
+
+ ref_e2->carrid = 'UA'.
+
+ output->display( input = ref_e2->carrid name = `ref_e2->carrid` ).
+
+ "The following syntax also works (dereferencing operator and the component selector).
+ ref_e2->*-carrname = 'United Airlines'.
+
+ output->display( input = ref_e2->*-carrname name = `ref_e2->*-carrname` ).
+
+**********************************************************************
+
+ output->next_section( `14) Checking if Data Reference ` &&
+ `Can Be Dereferenced` ).
+
+ "You can check if a data reference can be dereferenced by using
+ "a logical expression with IS [NOT] BOUND.
+ "The example shows both a data reference that is bound and not bound.
+
+ DATA(ref_f1) = NEW string( `hello` ).
+ DATA ref_f2 TYPE REF TO i.
+
+ IF ref_f1 IS BOUND.
+ output->display( `ref_f1 is bound.` ).
+ ELSE.
+ output->display( `ref_f1 is not bound.` ).
+ ENDIF.
+
+ IF ref_f2 IS BOUND.
+ output->display( `ref_f2 is bound.` ).
+ ELSE.
+ output->display( `ref_f2 is not bound.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `15) Explicitly Removing a Reference` ).
+
+ "Note that the garbage collector takes care of removing the references
+ "automatically once the data is not used any more by a reference.
+
+ DATA(ref_g1) = NEW string( `hello` ).
+
+ IF ref_g1 IS INITIAL.
+ output->display( `Before CLEAR: ref_g1 is initial.` ).
+ ELSE.
+ output->display( `Before CLEAR: ref_g1 is not intial.` ).
+ ENDIF.
+
+ IF ref_g1 IS BOUND.
+ output->display( `Before CLEAR: ref_g1 is bound.` ).
+ ELSE.
+ output->display( `Before CLEAR: ref_g1 is not bound.` ).
+ ENDIF.
+
+ CLEAR ref_g1.
+
+ IF ref_g1 IS INITIAL.
+ output->display( `After CLEAR: ref_g1 is initial.` ).
+ ELSE.
+ output->display( `After CLEAR: ref_g1 is not initial.` ).
+ ENDIF.
+
+ IF ref_g1 IS BOUND.
+ output->display( `After CLEAR: ref_g1 is bound.` ).
+ ELSE.
+ output->display( `After CLEAR: ref_g1 is not bound.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `16) Overwriting Data Reference Variables` ).
+
+ "A data reference variable is overwritten if a new object is created
+ "with a data reference variable already pointing to a data object
+
+ DATA ref_h1 TYPE REF TO data.
+
+ ref_h1 = NEW i( 111 ).
+
+ ASSIGN ref_h1->* TO FIELD-SYMBOL().
+ output->display( input = name = `` ).
+
+ ref_h1 = NEW string( `ref_h1 overwritten.` ).
+
+ ASSIGN ref_h1->* TO .
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `17) Retaining Data References` ).
+
+ "Storing data reference variables in an internal table using
+ "TYPE TABLE OF REF TO prevents the overwriting.
+ "The example demonstrates that three data references are created with
+ "the same reference variable in the course of a DO loop. There, the data
+ "reference is overwritten. However, due to saving the data reference
+ "variable in an internal table, the content is preserved.
+
+ DATA: ref_data_i TYPE REF TO data,
+ itab_i TYPE TABLE OF REF TO data,
+ number_i TYPE i VALUE 0.
+
+ DO 3 TIMES.
+ "Adding up 1 to demonstrate a changed data object
+ number_i += 1.
+
+ "Creating a data reference and assigning value
+ "In the course of the loop, the variable is overwritten.
+ ref_data_i = NEW i( number_i ).
+
+ "Adding the reference to an internal table
+ itab_i = VALUE #( BASE itab_i ( ref_data_i ) ).
+ ENDDO.
+
+ output->display( input = itab_i name = `itab_i` ).
+
+**********************************************************************
+
+ output->next_section( `18) Processing Internal Tables Using ` &&
+ `Data References ` ).
+
+ "Similar use case to using field symbols: In a loop across an internal table,
+ "you can store the content of the line in a data reference variable
+ "instead of actually copying the content to boost performance.
+ "In the example, an internal table is created including values of
+ "database table. A data reference variable is declared as target area of
+ "the loop. In the course of the loop, some values are changed.
+
+ SELECT *
+ FROM zdemo_abap_flsch
+ WHERE distid = 'MI'
+ ORDER BY carrid
+ INTO TABLE @DATA(flsch_tab)
+ UP TO 3 ROWS.
+
+ "The table line is written into a data reference variable
+ "that is declared inline.
+ LOOP AT flsch_tab REFERENCE INTO DATA(ref_k).
+ ref_k->connid = '123'.
+ ref_k->distance = ref_k->distance * '1.609344'.
+ ref_k->distid = 'KM' .
+ ENDLOOP.
+
+ output->display( input = flsch_tab name = `flsch_tab` ).
+
+**********************************************************************
+
+ output->next_section( `19) Data References as Part of ` &&
+ `Structures and Internal Tables` ).
+
+ "In contrast to field symbols, data reference variables can be used as
+ "components of structures or columns in internal tables.
+ "The example includes the declaration of a structure that contains a
+ "data reference variable.
+ "The structure is filled. Based on this structure, an
+ "internal table is created. In a DO loop, the internal table is filled.
+
+ "Declaring a structure
+ DATA: BEGIN OF struc_l,
+ number_l TYPE i,
+ ref_l TYPE REF TO i,
+ END OF struc_l,
+ some_int TYPE i VALUE 0.
+
+ "Filling structure
+ struc_l = VALUE #( number_l = 1 ref_l = NEW #( 2 ) ).
+
+ output->display( input = struc_l name = `struc_l` ).
+
+ "Declaring an internal table
+ DATA itab_l LIKE TABLE OF struc_l WITH EMPTY KEY.
+
+ "Filling internal table.
+ DO 3 TIMES.
+ some_int += 1.
+
+ "Filling structure
+ struc_l = VALUE #( number_l = some_int
+ ref_l = NEW #( some_int ) ).
+
+ "Filling internal table
+ itab_l = VALUE #( BASE itab_l ( struc_l ) ).
+ ENDDO.
+
+ output->display( input = itab_l name = `itab_l` ).
+
+**********************************************************************
+
+ output->next_section( `Dynamic ABAP Statements` ).
+ output->display( `20) Dynamic Specifications in ASSIGN Statements (1) - Attributes of Classes/Interfaces` ).
+
+ "The following examples demonstrate a selection of various dynamic specifications
+ "that are possible with ASSIGN statements.
+
+ "Dynamic specification of attributes of classes/interfaces that are assigned to a field symbol.
+
+ DATA(dobj_name) = lcl_det_at_runtime=>get_dyn_dobj( ).
+
+ ASSIGN lcl_det_at_runtime=>(dobj_name) TO FIELD-SYMBOL().
+
+ output->display( |Data object name determined at runtime: { dobj_name } | ).
+ output->display( |The content of the data object is: { } | ).
+
+ dobj_name = lcl_det_at_runtime=>get_dyn_dobj( ).
+
+ "Completely dynamic assign
+ ASSIGN ('LCL_DET_AT_RUNTIME')=>(dobj_name) TO FIELD-SYMBOL().
+ output->display( input = name = `` ).
+
+ ASSIGN ('ZDEMO_ABAP_OBJECTS_INTERFACE')=>('CONST_INTF') TO FIELD-SYMBOL().
+ output->display( input = name = `` ).
+
+ "Class/interface reference variables pointing to an object that contains attributes
+ "and that are specified dynamically.
+ DATA iref TYPE REF TO zdemo_abap_objects_interface.
+ DATA(cl_ref) = NEW zcl_demo_abap_objects( ).
+ iref = cl_ref.
+
+ ASSIGN iref->('CONST_INTF') TO FIELD-SYMBOL().
+
+ output->display( input = name = `` ).
+
+ ASSIGN cl_ref->('ANOTHER_STRING') TO FIELD-SYMBOL().
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `22) Dynamic Specifications in ASSIGN Statements (3) - Structure Components` ).
+
+ "Dynamic specification of structure components that are assigned to a field symbol.
+
+ SELECT SINGLE * FROM zdemo_abap_carr INTO @DATA(wa).
+ "Reading into data reference variable
+ SELECT SINGLE * FROM zdemo_abap_carr INTO NEW @DATA(ref_m).
+
+ DATA(comp_name) = lcl_det_at_runtime=>get_dyn_field( ).
+
+ ASSIGN COMPONENT comp_name OF STRUCTURE wa TO FIELD-SYMBOL().
+
+ ASSIGN COMPONENT 'CARRNAME' OF STRUCTURE wa TO FIELD-SYMBOL().
+
+ IF sy-subrc = 0.
+ DATA(subrc1) = sy-subrc.
+ ENDIF.
+
+ "No exception occurs in case of an unsuccessful assignment.
+ ASSIGN COMPONENT 'CRRNM' OF STRUCTURE wa TO FIELD-SYMBOL().
+
+ IF sy-subrc <> 0.
+ DATA(subrc2) = sy-subrc.
+ ENDIF.
+
+ "Numeric expressions are possible. Its value is interpreted as the position
+ "of the component in the structure.
+ ASSIGN COMPONENT 4 OF STRUCTURE wa TO FIELD-SYMBOL().
+
+ "If the value is 0, the memory area of the entire structure is assigned to the field symbol.
+ ASSIGN COMPONENT 0 OF STRUCTURE wa TO FIELD-SYMBOL().
+
+ output->display( input = name = `` ).
+ output->display( input = name = `` ).
+ output->display( input = subrc1 name = `subrc1` ).
+ output->display( input = subrc2 name = `subrc2` ).
+ output->display( input = name = `` ).
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `23) Dynamic Specifications in ASSIGN Statements (4) - Type Casting` ).
+
+ "As covered above, the CASTING addition of the ASSIGN statement
+ "has dynamic syntax elements.
+ DATA dobj_c_l5 TYPE c LENGTH 5 VALUE 'abcde'.
+ TYPES dtype_c_l2 TYPE c LENGTH 2.
+ FIELD-SYMBOLS TYPE data.
+
+ "A text literal with the name of a type is specified within the parentheses.
+ ASSIGN dobj_c_l5 TO CASTING TYPE ('DTYPE_C_L2').
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `Dynamically Creating Data Objects at Runtime Using Dynamic Type Definitions` ).
+ output->next_section( `25) Elementary Data Object (2)` ).
+
+ "The example demonstrates the following:
+ "- The method call takes care of providing the name of a built-in data type and more
+ "- An elementary data object is created based on the data type
+ "- For demonstration purposes, RTTI (as shown further down in more detail) is used
+ " to check on the created data object by retrieving the type description.
+
+ DATA(b_type) = lcl_det_at_runtime=>get_builtin_type( ).
+
+ DATA ref_bt TYPE REF TO data.
+
+ TRY.
+ CASE b_type-builtin_type.
+ WHEN 'd' OR 'decfloat16' OR 'decfloat34' OR 'f' OR 'i'
+ OR 'string' OR 't' OR 'xstring'.
+
+ CREATE DATA ref_bt TYPE (b_type-builtin_type).
+ WHEN 'c' OR 'n' OR 'x'.
+ CREATE DATA ref_bt TYPE (b_type-builtin_type) LENGTH b_type-len.
+ WHEN 'p'.
+ CREATE DATA ref_bt TYPE p LENGTH b_type-len DECIMALS b_type-dec.
+ WHEN OTHERS.
+ output->display( `That didn't work.` ).
+ ENDCASE.
+
+ "Getting type information using RTTI
+ ASSIGN ref_bt->* TO FIELD-SYMBOL().
+ DATA(descr_builtin_type) = CAST cl_abap_elemdescr(
+ cl_abap_typedescr=>describe_by_data( ) ).
+
+ output->display( |Built-in type determined at runtime: { b_type-builtin_type } | ).
+ output->display( `Created data object at runtime:` ).
+ output->display( input = descr_builtin_type name = `descr_builtin_type` ).
+
+ CATCH cx_root.
+ output->display( `Something went wrong.` ).
+ ENDTRY.
+
+**********************************************************************
+
+ output->next_section( `26) Structure (3)` ).
+
+ "The example demonstrates the following:
+ "- The method call takes care of providing the name of a database table name.
+ "- A structured data object is created based on the dynamically determined type.
+ " It is used as target data object for a SELECT statement. As shown further
+ " down in more detail, clauses of SELECT statements can be specified
+ " dynamically.
+
+ "Retrieving table name
+ DATA(type4struc) = lcl_det_at_runtime=>get_dyn_table_name( ).
+
+ DATA ref_dynstruc TYPE REF TO data.
+
+ "Creating structured data object
+ CREATE DATA ref_dynstruc TYPE (type4struc).
+ ASSIGN ref_dynstruc->* TO FIELD-SYMBOL().
+
+ "Dynamic specification of the FROM clause
+ SELECT SINGLE *
+ FROM (type4struc)
+ INTO @.
+
+ output->display( |Structured data type/database table name determined at runtime: { type4struc } | ).
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `27) Internal Table (4)` ).
+
+ "The example demonstrates the following:
+ "- The method call takes care of providing the name of a database table name.
+ "- An internal table is created based on the dynamically determined type.
+ " It is used as target data object for a SELECT statement.
+ "- The UP TO ... ROWS addition is provided with a random number in the example.
+ "- AS in the example above, the SELECT statement includes the dynamic
+ " specification of the FROM clause.
+
+ "Retrieving table name
+ DATA(type_name) = lcl_det_at_runtime=>get_dyn_table_name( ).
+
+ DATA ref_n TYPE REF TO data.
+
+ "Creating internal table based on the type determined at runtime
+ CREATE DATA ref_n TYPE TABLE OF (type_name).
+
+ "Specifying random number for up to clause
+ DATA(random_upto) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 2
+ max = 6 )->get_next( ).
+
+ "Dynamic specification of the FROM clause
+ SELECT *
+ FROM (type_name)
+ INTO TABLE NEW @DATA(ta)
+ UP TO @random_upto ROWS.
+
+ ASSIGN ta->* TO FIELD-SYMBOL().
+
+ output->display( |Table/type name determined at runtime: { type_name } | ).
+ output->display( |At most, { random_upto } lines should have been read from the database table.| ).
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `28) Excursion: Absolute Type Names for Dynamically Specifying Types` ).
+
+ "In addition to character-like data objects for the type name specified within the
+ "parentheses, you can also use absolute type names for statements such as CREATE DATA.
+ "The absolute type name is retrieved using RTTI. See more on RTTI further down.
+
+ "Type to refer to
+ TYPES type4abs TYPE p LENGTH 4 DECIMALS 3.
+ "Data and object reference variables
+ DATA dref4abs TYPE REF TO data.
+ DATA oref4abs TYPE REF TO object.
+ "Getting absolute names using RTTI
+ DATA(abs_name_type) = cl_abap_typedescr=>describe_by_name( 'TYPE4ABS' )->absolute_name.
+ DATA(abs_name_cl) = cl_abap_typedescr=>describe_by_name( 'ZCL_DEMO_ABAP_DYNAMIC_PROG' )->absolute_name.
+
+ "Data references
+ ""Named data object holding the absolute name
+ CREATE DATA dref4abs TYPE (abs_name_type).
+ "Unnamed data object
+ CREATE DATA dref4abs TYPE ('\TYPE=STRING').
+
+ "Object references
+ "Named data object
+ CREATE OBJECT oref4abs TYPE (abs_name_cl).
+ "Unnamed data object
+ CREATE OBJECT oref4abs TYPE ('\CLASS=ZCL_DEMO_ABAP_DYNAMIC_PROG').
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `Dynamically Specifying Components/Clauses in Statements for Processing Internal Tables with ...` ).
+ output->display( `29) SORT` ).
+
+ "A field is determined at runtime on whose basis a sorting is done on an
+ "internal table.
+
+ DATA(field_name) = lcl_det_at_runtime=>get_dyn_field( ).
+
+ SELECT *
+ FROM zdemo_abap_carr
+ ORDER BY carrid
+ INTO TABLE @DATA(carr_itab)
+ UP TO 3 ROWS.
+
+ SORT carr_itab BY (field_name).
+
+ output->display( |Field name determined at runtime | &&
+ |by which the sorting was done: { field_name } | ).
+ output->display( input = carr_itab name = `carr_itab` ).
+
+**********************************************************************
+
+ output->next_section( `30) READ TABLE` ).
+
+ "Dynamic key specification in READ TABLE statements
+
+ TYPES: BEGIN OF s,
+ comp TYPE string,
+ value TYPE string,
+ END OF s.
+
+ TYPES comps_type TYPE TABLE OF s WITH EMPTY KEY.
+
+ "Providing components and values for READ TABLE statement
+ DATA(comps) = VALUE comps_type( ( comp = `CARRID` value = `LH` )
+ ( comp = `CONNID` value = `0555` )
+ ( comp = `SEATSOCC` value = `115` )
+ ( comp = `CARRID` value = `XY` ) ). "not found
+
+ SELECT *
+ FROM zdemo_abap_fli
+ INTO TABLE @DATA(itab_read_tab_dyn).
+
+ LOOP AT comps INTO DATA(wa_comps).
+ READ TABLE itab_read_tab_dyn
+ INTO DATA(read_line)
+ WITH KEY (wa_comps-comp) = wa_comps-value.
+
+ IF sy-subrc = 0.
+ output->display( input = wa_comps-comp name = `wa_comps-comp` ).
+ output->display( input = wa_comps-value name = `wa_comps-value` ).
+ output->display( input = read_line name = `read_line` ).
+ CLEAR read_line.
+ ELSE.
+ output->display( input = wa_comps-comp name = `wa_comps-comp` ).
+ output->display( input = wa_comps-value name = `wa_comps-value` ).
+ output->display( `Line not found.` ).
+ ENDIF.
+
+ ENDLOOP.
+
+**********************************************************************
+
+ output->next_section( `31) MODIFY` ).
+
+ "Dynamic WHERE condition in MODIFY statements
+ "Note:
+ "- The addition WHERE can only be specified together with the addition TRANSPORTING.
+ "- Invalid logical expressions raise an exception from the class CX_SY_ITAB_DYN_LOOP.
+
+ TYPES:
+ BEGIN OF line,
+ col1 TYPE c LENGTH 1,
+ col2 TYPE i,
+ END OF line.
+
+ DATA itab_mod_tab_dyn TYPE SORTED TABLE OF line
+ WITH UNIQUE KEY col1.
+
+ itab_mod_tab_dyn = VALUE #( ( col1 = 'A' col2 = 1 )
+ ( col1 = 'B' col2 = 10 )
+ ( col1 = 'C' col2 = 100 ) ).
+
+ output->display( `Internal table content before modifications:` ).
+ output->display( input = itab_mod_tab_dyn name = `itab_mod_tab_dyn` ).
+
+ "Providing conditions for MODIFY statement
+ DATA(conditions) = VALUE string_table( ( `col2 < 5` )
+ ( `col2 = 10` )
+ ( `colxyz > 50` ) ). "to fail
+
+ LOOP AT itab_mod_tab_dyn INTO DATA(wa_mod_dyn).
+ TRY.
+
+ DATA(condition) = conditions[ sy-tabix ].
+
+ MODIFY itab_mod_tab_dyn
+ FROM VALUE line( col2 = wa_mod_dyn-col2 * 2 )
+ TRANSPORTING col2
+ WHERE (condition).
+
+ CATCH cx_sy_itab_dyn_loop.
+ output->display( |Invalid WHERE condition "{ condition }".| ).
+ ENDTRY.
+ ENDLOOP.
+
+ output->display( `Internal table content after modifications:` ).
+ output->display( input = itab_mod_tab_dyn name = `itab_mod_tab_dyn` ).
+
+**********************************************************************
+
+ output->next_section( `32) DELETE` ).
+
+ "Dynamic WHERE condition in DELETE statements
+
+ DATA itab_del_tab_dyn TYPE TABLE OF i WITH EMPTY KEY
+ WITH NON-UNIQUE SORTED KEY skey COMPONENTS table_line.
+
+ itab_del_tab_dyn = VALUE #( ( 100 )
+ ( 200 )
+ ( 300 )
+ ( 400 )
+ ( 500 )
+ ( 600 ) ).
+
+ output->display( `Internal table content before modifications:` ).
+ output->display( input = itab_del_tab_dyn name = `itab_del_tab_dyn` ).
+
+ DO 3 TIMES.
+ TRY.
+
+ CASE sy-index.
+ WHEN 1.
+ condition = `table_line <= 200`.
+ WHEN 2.
+ condition = `table_line >= 500`.
+ WHEN 3.
+ condition = `col1 = 600`.
+ ENDCASE.
+
+ DELETE itab_del_tab_dyn
+ USING KEY skey
+ WHERE (condition).
+
+ output->display( |Condition: { condition }| ).
+ output->display( input = itab_del_tab_dyn name = `itab_del_tab_dyn` ).
+
+ CATCH cx_sy_itab_dyn_loop.
+ output->display( |Invalid WHERE condition "{ condition }".| ).
+ ENDTRY.
+ ENDDO.
+
+**********************************************************************
+
+ output->next_section( `33) LOOP` ).
+
+ "Dynamic specification of the key in LOOP statements
+ "In the example, the loop can be executed with the entries 'skey' and 'primary_key'.
+ "This is not case sensitive. Any other entries produce a runtime error.
+
+ DATA(keys) = VALUE string_table( ( `PRIMARY_KEY` ) ( `SKEY` ) ).
+
+ DATA itab_loop TYPE TABLE OF i
+ WITH NON-UNIQUE KEY primary_key COMPONENTS table_line
+ WITH NON-UNIQUE SORTED KEY skey COMPONENTS table_line.
+
+ itab_loop = VALUE #( ( 3 ) ( 2 ) ( 1 ) ).
+
+ DATA itab_dyn_key LIKE itab_loop.
+
+ LOOP AT keys INTO DATA(k).
+
+ LOOP AT itab_loop INTO DATA(wa_lo) USING KEY (k).
+ APPEND wa_lo TO itab_dyn_key.
+ ENDLOOP.
+
+ output->display( |Loop over internal table using key "{ k }".| ).
+ output->display( input = itab_dyn_key name = `itab_dyn_key` ).
+ CLEAR itab_dyn_key.
+
+ ENDLOOP.
+
+**********************************************************************
+
+ output->next_section( `Dynamically Specifying Clauses in ABAP SQL SELECT Statements` ).
+ output->display( `34) SELECT List` ).
+
+ "In the example, the SELECT list that is used in a SELECT statement is
+ "determined at runtime.
+
+ DATA(select_list) = lcl_det_at_runtime=>get_dyn_select_list( ).
+
+ DATA sel_table TYPE TABLE OF zdemo_abap_flsch WITH EMPTY KEY.
+
+ SELECT (select_list)
+ FROM zdemo_abap_flsch
+ ORDER BY carrid
+ INTO CORRESPONDING FIELDS OF TABLE @sel_table
+ UP TO 3 ROWS.
+
+ output->display( |SELECT list determined at runtime: { select_list } | ).
+ output->display( input = sel_table name = `sel_table` ).
+
+**********************************************************************
+
+ output->next_section( `35) FROM Clause` ).
+
+ "In the example, the FROM clause that is used in a SELECT statement is
+ "determined at runtime. Here, the number of entries of a database table
+ "is counted.
+
+ DATA(tab_name) = lcl_det_at_runtime=>get_dyn_table_name( ).
+
+ SELECT COUNT(*)
+ FROM (tab_name)
+ INTO @DATA(count).
+
+ output->display( |Table name determined at runtime: { tab_name } | ).
+ output->display( |The table { tab_name } has { count } entries.| ).
+
+**********************************************************************
+
+ output->next_section( `36) WHERE Clause` ).
+
+ "In the example, the WHERE clause that is used in a SELECT statement is
+ "determined at runtime. Here, the WHERE clause is based on a string
+ "table.
+
+ DATA(where_clause) = lcl_det_at_runtime=>get_dyn_where_clause( ).
+
+ SELECT *
+ FROM zdemo_abap_flsch
+ WHERE (where_clause)
+ ORDER BY carrid
+ INTO TABLE @DATA(where_tab)
+ UP TO 5 ROWS.
+
+ output->display( |WHERE clause determined at runtime:| ).
+ output->display( input = where_clause name = `where_clause` ).
+ output->display( input = where_tab name = `where_tab` ).
+
+**********************************************************************
+
+ output->next_section( `37) Excursion: Multiple Dynamically Specified ` &&
+ `Clauses in an ABAP SQL SELECT Statement` ).
+
+ "In this example, multiple clauses in a SELECT statement are
+ "determined at runtime to demonstrate the rich variety of possibilities.
+ "Note: The rows and target table specifications are not real dynamic
+ "specifications in the SELECT statement in the sense of syntax elements
+ "enclosed by parentheses. Here, they are just included to provide some
+ "more 'dynamic' touch of the statement :)
+
+ "Getting all clauses of the SELECT statement
+ DATA(dyn_syntax_elem) = lcl_det_at_runtime=>get_dyn_syntax_elements( ).
+
+ IF dyn_syntax_elem-table IS NOT INITIAL
+ AND dyn_syntax_elem-select_list IS NOT INITIAL
+ AND dyn_syntax_elem-where_clause IS NOT INITIAL
+ AND dyn_syntax_elem-order_by IS NOT INITIAL
+ AND dyn_syntax_elem-target IS BOUND
+ AND dyn_syntax_elem-rows IS NOT INITIAL.
+
+ output->display( `Dynamically determined syntax elements:` ).
+ output->display( input = dyn_syntax_elem name = `dyn_syntax_elem` ).
+
+ FIELD-SYMBOLS TYPE ANY TABLE.
+ ASSIGN dyn_syntax_elem-target->* TO .
+
+ SELECT (dyn_syntax_elem-select_list)
+ FROM (dyn_syntax_elem-table)
+ WHERE (dyn_syntax_elem-where_clause)
+ ORDER BY (dyn_syntax_elem-order_by)
+ INTO CORRESPONDING FIELDS OF TABLE @
+ UP TO @dyn_syntax_elem-rows ROWS.
+
+
+ output->display( input = name = `` ).
+
+ ELSE.
+ output->display( `There's an issue with syntax elements.` ).
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `38) Dynamic Invoke` ).
+
+ "In the example, both class and method are determined at runtime for
+ "the method call. The suitable parameter table is filled in the
+ "method get_dyn_class_meth. The example is implemented in a way that
+ "all the methods that are called store some text in a string. This
+ "string is displayed to see the effect of the dynamic method call.
+
+ lcl_det_at_runtime=>get_dyn_class_meth( IMPORTING cl = DATA(cl_name)
+ meth = DATA(meth_name)
+ ptab = DATA(p_tab) ).
+
+ CALL METHOD (cl_name)=>(meth_name) PARAMETER-TABLE p_tab.
+
+ output->display( |Class name determined at runtime: { cl_name } | ).
+ output->display( |Method name determined at runtime: { meth_name } | ).
+
+ output->display( `Result of method call (text stored in a variable):` ).
+ output->display( input = lcl_det_at_runtime=>dyn_meth_call_result name = `lcl_det_at_runtime=>dyn_meth_call_result` ).
+
+ "Further method calls
+ "The class and method to be used is determined here by just providing
+ "the character-like content (the name) via a data object in a predefined way.
+
+ DATA method TYPE string VALUE `FILL_STRING`.
+
+ "Note that the method has no parameters in this example.
+ "Similar to above. The method stores some text in a string which is
+ "displayed to see the effect of the dynamic method call.
+ CALL METHOD lcl_det_at_runtime=>(method).
+
+ output->display( input = lcl_det_at_runtime=>dyn_meth_call_result name = `lcl_det_at_runtime=>dyn_meth_call_result` ).
+
+ DATA class TYPE string VALUE `LCL_DET_AT_RUNTIME`.
+
+ CALL METHOD (class)=>fill_string.
+
+ output->display( input = lcl_det_at_runtime=>dyn_meth_call_result name = `lcl_det_at_runtime=>dyn_meth_call_result` ).
+
+**********************************************************************
+
+ output->next_section( `39) RTTI: Getting Type Information at Runtime/Getting a Reference to a Type Description Object` ).
+
+ "Getting a reference to a type description object of a type.
+ "i.e. getting an instance of a type description class
+ "As shown below, the type decription object can be used
+ "to create data objects dynamically.
+
+ "Type for which information should be retrieved
+ TYPES: elem_type TYPE c LENGTH 5.
+
+ "Creating a data reference variable to hold the reference to
+ "the type description object
+ DATA type_descr_obj_elem TYPE REF TO cl_abap_elemdescr.
+
+ "Retrieving type information by creating an instance of a type description class
+ "As the name implies, the describe_by_name method expects the name of the type
+ "The following example uses the CAST operator for the necessary downcast.
+ type_descr_obj_elem = CAST #( cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ).
+
+ "Using the older ?= operator
+ type_descr_obj_elem ?= cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ).
+
+ "Inline declaration is handy to avoid helper variables.
+ DATA(type_descr_obj_elem_inl) = CAST cl_abap_elemdescr(
+ cl_abap_typedescr=>describe_by_name( 'ELEM_TYPE' ) ).
+
+ "You may also want to check the type description object in the debugger.
+ output->display( input = type_descr_obj_elem_inl name = `type_descr_obj_elem_inl` ).
+
+ "Various methods/attributes (note that they vary depending on the type) provide
+ "you with detailed information.
+ "The following examples show a selection.
+ "Kind/Type kind/Output length
+ DATA(kind_elem) = type_descr_obj_elem_inl->kind.
+ DATA(type_kind_elem) = type_descr_obj_elem_inl->type_kind.
+ DATA(output_length_elem) = type_descr_obj_elem_inl->output_length.
+
+ output->display( input = kind_elem name = `kind_elem` ).
+ output->display( input = type_kind_elem name = `type_kind_elem` ).
+ output->display( input = output_length_elem name = `output_length_elem` ).
+
+ "In the following example, the type properties are retrieved
+ "without casting. The data object has the type ref to
+ "cl_abap_typedescr. See the hierarchy tree of type description classes.
+ "The reference in the type description object references an
+ "object from one of the classes CL_ABAP_ELEMDESCR, CL_ABAP_ENUMDESCR,
+ "CL_ABAP_REFDESCR, CL_ABAP_STRUCTDESCR, CL_ABAP_TABLEDSECR,
+ "CL_ABAP_CLASSDESCR, or CL_ABAP_INTFDESCR.
+ "In the following case, it is CL_ABAP_ELEMDESCR.
+ "Note that in most of the RTTI examples in this class, the explicit
+ "casting is included when retrieving a reference to the type
+ "description object.
+ TYPES another_elem_type TYPE n LENGTH 3.
+ DATA(type_descr_obj_elem_inl_2) = cl_abap_typedescr=>describe_by_name( 'ANOTHER_ELEM_TYPE' ).
+
+ output->display( input = type_descr_obj_elem_inl_2->kind name = `type_descr_obj_elem_inl_2->kind` ).
+ output->display( input = type_descr_obj_elem_inl_2->type_kind name = `type_descr_obj_elem_inl_2->type_kind` ).
+
+ "More types
+ "Structured data type (here, using the name of a database table)
+ DATA(type_descr_obj_struc) = CAST cl_abap_structdescr(
+ cl_abap_typedescr=>describe_by_name( 'ZDEMO_ABAP_CARR' ) ).
+
+ "Various attributes/methods available for detailed information
+ "Kind
+ DATA(struc_kind) = type_descr_obj_struc->kind.
+ "Components of the structure (e.g. the component names and type description
+ "objects for the individual components)
+ DATA(comps_struc) = type_descr_obj_struc->get_components( ).
+ "The attribute also lists the component names and types (but not the type
+ "desription objects)
+ DATA(comps_struc2) = type_descr_obj_struc->components.
+ "Kind of structure
+ DATA(struct_kind) = type_descr_obj_struc->struct_kind.
+
+ output->display( input = struc_kind name = `struc_kind` ).
+ output->display( input = comps_struc name = `comps_struc` ).
+ output->display( input = comps_struc2 name = `comps_struc2` ).
+ output->display( input = struct_kind name = `struct_kind` ).
+
+ "Internal table type
+ TYPES table_type TYPE SORTED TABLE OF zdemo_abap_carr WITH UNIQUE KEY carrid.
+
+ DATA(type_descr_obj_tab) = CAST cl_abap_tabledescr(
+ cl_abap_typedescr=>describe_by_name( 'TABLE_TYPE' ) ).
+
+ "Kind
+ DATA(tab_kind) = type_descr_obj_tab->kind.
+ "The following method returns more information than the attribute below
+ "(e.g. key kind (unique) etc.)
+ DATA(tab_keys) = type_descr_obj_tab->get_keys( ).
+ DATA(tab_keys2) = type_descr_obj_tab->key. "Attribute; lists the keys
+ "Getting internal table components
+ "The method get_table_line_type returns a variable of type ref to cl_abap_datadescr.
+ "This way you can retrieve the table components. Method chaining comes in handy.
+ DATA(tab_comps) = CAST cl_abap_structdescr(
+ type_descr_obj_tab->get_table_line_type( ) )->get_components( ).
+
+ output->display( input = tab_kind name = `tab_kind` ).
+ output->display( input = tab_keys name = `tab_keys` ).
+ output->display( input = tab_keys2 name = `tab_keys2` ).
+ output->display( input = tab_comps name = `tab_comps` ).
+
+ "Reference type
+ TYPES ref_str TYPE REF TO string.
+ DATA(type_descr_obj_ref) = CAST cl_abap_refdescr(
+ cl_abap_typedescr=>describe_by_name( 'REF_STR' ) ).
+
+ "Kind
+ DATA(ref_kind) = type_descr_obj_ref->kind.
+ "Returns type description object of the referenced type
+ DATA(ref_type) = type_descr_obj_ref->get_referenced_type( ).
+ "Absolute type name
+ DATA(ref_type_abs_name) =
+ type_descr_obj_ref->get_referenced_type( )->absolute_name.
+ "Type kind
+ DATA(ref_type_type_kind) =
+ type_descr_obj_ref->get_referenced_type( )->type_kind.
+
+ output->display( input = ref_kind name = `ref_kind` ).
+ output->display( input = ref_type name = `ref_type` ).
+ output->display( input = ref_type_abs_name name = `ref_type_abs_name` ).
+ output->display( input = ref_type_type_kind name = `ref_type_type_kind` ).
+
+ "Getting a reference to a type description object of an existing data object.
+ "Instead of referring to the name of a type, referring to a data object here.
+ "The relevant method is describe_by_data
+
+ "Elementary data object
+ DATA dobj_elem TYPE i.
+ DATA(ty_des_obj_el) = CAST cl_abap_elemdescr(
+ cl_abap_typedescr=>describe_by_data( dobj_elem ) ).
+
+ "Structure
+ DATA dobj_struc TYPE zdemo_abap_carr.
+ DATA(ty_des_obj_struc) = CAST cl_abap_structdescr(
+ cl_abap_typedescr=>describe_by_data( dobj_struc ) ).
+
+ "Internal table
+ DATA dobj_itab TYPE TABLE OF zdemo_abap_carr WITH EMPTY KEY.
+ DATA(ty_des_obj_itab) = CAST cl_abap_tabledescr(
+ cl_abap_typedescr=>describe_by_data( dobj_itab ) ).
+
+ "Reference variable
+ DATA dref_var TYPE REF TO string.
+ DATA(ty_des_obj_dref) = CAST cl_abap_refdescr(
+ cl_abap_typedescr=>describe_by_data( dref_var ) ).
+
+**********************************************************************
+
+ output->next_section( `40) RTTI: Getting Type Information at Runtime for Miscellaneous Types` ).
+
+ "The example demonstrates RTTI as follows:
+ "- The method call takes care of providing the name of a type. It is implemented
+ " in a way that various types can be returned, i. e. elementary, structure,
+ " internal table, reference, class, interface.
+ "- If the retrieved type is not a class or interface, a data object is created
+ " based on the type determined at runtime.
+ "- The type description is retrieved using the method cl_abap_typedescr=>describe_by_data.
+ " Note the casts for the information retrieval statements.
+ "- Depending on the type kind, various pieces of information are retrieved. There
+ " are plenty of options. In ADT, you can use the input help. Just position the
+ " cursor after the reference variable and ->, e.g. el->, and hit CTRL-Space.
+ " A dropdown appears showing you the variety you can explore. Check the class
+ " documentation for more information.
+ "- If the retrieved type is a class or interface, the type description is
+ " retrieved using cl_abap_typedescr=>describe_by_name.
+ "- The example for a class type includes the creation of an object based
+ " on a type determined at runtime using a CREATE OBJECT statement.
+
+ "Retrieving type
+ DATA(get_type) = lcl_det_at_runtime=>get_random_type( ).
+
+ output->display( |Type name determined at runtime: { get_type }| ).
+
+ DATA dref TYPE REF TO data.
+
+ IF get_type <> `LCL_DET_AT_RUNTIME`
+ AND get_type <> `IF_OO_ADT_CLASSRUN`.
+ TRY.
+ CREATE DATA dref TYPE (get_type).
+ CATCH cx_sy_create_data_error.
+ output->display( `Create data error!` ).
+ ENDTRY.
+
+ "Retrieving type information
+ "When referring to a concrete data object name, you can use this method:
+ ASSIGN dref->* TO FIELD-SYMBOL().
+ DATA(some_type) = cl_abap_typedescr=>describe_by_data( ).
+
+ "Elementary type
+ IF some_type->kind = cl_abap_typedescr=>kind_elem.
+ DATA(el) = CAST cl_abap_elemdescr( some_type ).
+ output->display( input = el name = `el` ).
+ "Various attributes and methods possible
+ output->display( input = el->type_kind name = `el->type_kind` ).
+ output->display( input = el->absolute_name name = `el->absolute_name` ).
+ output->display( input = el->get_relative_name( ) name = `el->get_relative_name( )` ).
+
+ "Structure
+ ELSEIF some_type->kind = cl_abap_typedescr=>kind_struct.
+ DATA(stru) = CAST cl_abap_structdescr( some_type ).
+ output->display( input = stru->absolute_name name = `stru->absolute_name` ).
+ output->display( input = stru->components name = `stru->components` ).
+ output->display( input = stru->struct_kind name = `stru->struct_kind` ).
+ output->display( input = stru->get_components( ) name = `stru->get_components( )` ).
+
+ "Internal table
+ ELSEIF some_type->kind = cl_abap_typedescr=>kind_table.
+ DATA(tab) = CAST cl_abap_tabledescr( some_type ).
+ output->display( input = tab->absolute_name name = `tab->absolute_name` ).
+ output->display( input = tab->table_kind name = `tab->table_kind` ).
+ output->display( input = tab->get_keys( ) name = `tab->get_keys` ).
+ output->display( input = tab->get_table_line_type( ) name = `tab->get_table_line_type( )` ).
+
+ "Reference
+ ELSEIF some_type->kind = cl_abap_typedescr=>kind_ref.
+ DATA(ref_descr) = CAST cl_abap_refdescr( some_type ).
+ output->display( input = ref_descr->absolute_name name = `ref_descr->absolute_name` ).
+ output->display( input = ref_descr->get_referenced_type( ) name = `ref_descr->get_referenced_type( )` ).
+ ELSE.
+ output->display( `Others ...` ).
+ ENDIF.
+
+ ELSE.
+
+ "Retrieving type information
+ "Here, using the type name and not a concrete data object as above.
+ some_type = cl_abap_typedescr=>describe_by_name( get_type ).
+
+ "Class
+ IF some_type->kind = cl_abap_typedescr=>kind_class.
+ DATA(class_desc) = CAST cl_abap_classdescr( some_type ).
+ output->display( input = class_desc->absolute_name name = `class_desc->absolute_name` ).
+ output->display( input = class_desc->attributes name = `class_desc->attributes` ).
+ output->display( input = class_desc->methods name = `class_desc->methods` ).
+
+ "Creating an object based on a type determined at runtime
+ DATA oref TYPE REF TO object.
+
+ TRY.
+ CREATE OBJECT oref TYPE (get_type).
+ "Retrieving type information
+ DATA(descr_ref) = cl_abap_typedescr=>describe_by_object_ref( oref ).
+ output->display( input = descr_ref->absolute_name name = `descr_ref->absolute_name` ).
+ output->display( input = descr_ref->kind name = `descr_ref->kind` ).
+ CATCH cx_root.
+ output->display( `Error` ).
+ ENDTRY.
+
+ "Interface
+ ELSEIF some_type->kind = cl_abap_typedescr=>kind_intf.
+ DATA(if_descr) = CAST cl_abap_intfdescr( some_type ).
+ output->display( input = if_descr->absolute_name name = `if_descr->absolute_name` ).
+ output->display( input = if_descr->methods name = `class_desc->methods` ).
+ ELSE.
+ output->display( `Others ...` ).
+ ENDIF.
+ ENDIF.
+
+**********************************************************************
+
+ output->next_section( `41) RTTC: Dynamically Creating Data Types at Runtime` ).
+
+ "You can create data types at program runtime using methods of the type
+ "description classes of RTTS. These types are only valid locally in the
+ "program. They are also anonymous, i.e. they are only accessible through
+ "type description objects. As shown above, you can get a reference to a
+ "type description object of a type using the static methods of the class
+ "CL_ABAP_TYPEDESCR. The focus here is on using RTTC methods such as get*.
+
+ "Creating type description objects using ...
+ "... elementary data types
+ "Conceptually, all elementary, built-in ABAP types already exist and can
+ "be accessed by the corresponding get_* methods.
+ "In ADT, click CTRL + space after cl_abap_elemdescr=>... to check out the options.
+ "The following examples show a selection.
+ DATA(tdo_elem_i) = cl_abap_elemdescr=>get_i( ).
+ DATA(tdo_elem_string) = cl_abap_elemdescr=>get_string( ).
+ "For the length specification of type c, there is an importing parameter available.
+ DATA(tdo_elem_c_l20) = cl_abap_elemdescr=>get_c( 10 ).
+ "Type p with two parameters to be specified.
+ DATA(tdo_elem_p) = cl_abap_elemdescr=>get_p( p_length = 3 p_decimals = 2 ).
+
+ "Instead of calling get_i() and others having no importing parameters, you could also call
+ "the describe_by_name( ) method and pass the type names (I‚ STRING etc.) as arguments.
+ "DATA(tdo_elem_i_2) = CAST cl_abap_elemdescr(
+ " cl_abap_typedescr=>describe_by_name( 'I' ) ).
+ "DATA(tdo_elem_string_2) = CAST cl_abap_elemdescr(
+ " cl_abap_typedescr=>describe_by_name( 'STRING' ) ).
+
+ "... structured data types
+ "They are created based on a component description table.
+
+ "A structured type such as the following shall be created using a
+ "type description object.
+ TYPES:
+ BEGIN OF struc_type,
+ a TYPE string,
+ b TYPE i,
+ c TYPE c LENGTH 5,
+ d TYPE p LENGTH 4 DECIMALS 3,
+ END OF struc_type.
+
+ "Creating a type description object using RTTC method
+ "Using the get method, you can create the type description object
+ "dynamically based on a component table. The component table is of type
+ "abap_component_tab. In this example, the component table is created inline.
+ DATA(tdo_struc) = cl_abap_structdescr=>get(
+ VALUE #(
+ ( name = 'A' type = cl_abap_elemdescr=>get_string( ) )
+ ( name = 'B' type = cl_abap_elemdescr=>get_i( ) )
+ ( name = 'C' type = cl_abap_elemdescr=>get_c( 5 ) )
+ ( name = 'D' type = cl_abap_elemdescr=>get_p( p_length = 4 p_decimals = 3 ) ) ) ).
+
+ "... internal table types
+ "Note: Specifying the line type is mandatory, the rest is optional.
+
+ "An internal table type such as the following shall be created using a
+ "type description object.
+ TYPES std_tab_type_std_key TYPE STANDARD TABLE OF string WITH DEFAULT KEY.
+
+ "Creating a type description object using RTTC method
+ "Not specifying the other optional parameters means that the
+ "default values are used, for example, standard table is the
+ "default value for p_table_kind.
+ DATA(tdo_tab_1) = cl_abap_tabledescr=>get(
+ p_line_type = cl_abap_elemdescr=>get_string( ) ).
+
+ "Another internal table type for which more parameter specifications are needed
+ "The following internal table type shall be created using a type description object.
+ TYPES so_table_type TYPE SORTED TABLE OF zdemo_abap_flsch WITH UNIQUE KEY carrid connid.
+
+ "Creating a type description object using RTTC method
+ "The following example also demonstrates how comfortably constructor
+ "operators can be used at these positions.
+ DATA(tdo_tab_2) = cl_abap_tabledescr=>get(
+ p_line_type = CAST cl_abap_structdescr( cl_abap_tabledescr=>describe_by_name( 'ZDEMO_ABAP_FLSCH' ) )
+ p_table_kind = cl_abap_tabledescr=>tablekind_sorted
+ p_key = VALUE #( ( name = 'CARRID' ) ( name = 'CONNID' ) )
+ p_unique = cl_abap_typedescr=>true ).
+
+ " ... reference types
+ "Reference types such as the following shall be created using a
+ "type description object.
+ TYPES some_ref_type2t TYPE REF TO t.
+ TYPES some_ref_type2cl TYPE REF TO zcl_demo_abap_dynamic_prog.
+
+ "Using RTTC methods
+ "You can create a reference type from a base type. This base type
+ "may be class, interface or data type.
+ DATA(tdo_ref_1) = cl_abap_refdescr=>get( cl_abap_elemdescr=>get_t( ) ).
+ DATA(tdo_ref_2) = cl_abap_refdescr=>get( cl_abap_typedescr=>describe_by_name( 'ZCL_DEMO_ABAP_DYNAMIC_PROG' ) ).
+ "Alternative: get_by_name method
+ DATA(tdo_ref_3) = cl_abap_refdescr=>get_by_name( 'T' ).
+ DATA(tdo_ref_4) = cl_abap_refdescr=>get_by_name( 'ZCL_DEMO_ABAP_DYNAMIC_PROG' ).
+
+ output->display( `No output for this section. See the code.` ).
+
+**********************************************************************
+
+ output->next_section( `43) Dynamically Creating Data Objects at Runtime Using Type Description Objects (2) - Structure` ).
+
+ "This example includes the dynamic definition of a structure with three components
+ "using the GET method of the CL_ABAP_STRUCTDESCR class.
+
+ DATA: struct_type TYPE REF TO cl_abap_structdescr,
+ dref_struc TYPE REF TO data.
+
+ DATA column1 TYPE c LENGTH 5.
+ DATA column2 TYPE c LENGTH 5.
+ DATA column3 TYPE c LENGTH 5.
+
+ "Potential component names
+ DATA(comp_names) = VALUE string_table( ( `A` ) ( `B` ) ( `C` ) ( `D` ) ( `E` ) ( `F` ) ).
+
+ "The structure should contain 3 components.
+ DO 3 TIMES.
+
+ "Getting a random integer that represents the table index
+ "The line (the component name) is deleted from the table so as to
+ "guarantee unique component names.
+ DATA(num) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( comp_names ) )->get_next( ).
+ CASE sy-index.
+ WHEN 1.
+ column1 = comp_names[ num ].
+ WHEN 2.
+ column2 = comp_names[ num ].
+ WHEN 3.
+ column3 = comp_names[ num ].
+ ENDCASE.
+
+ DELETE comp_names INDEX num.
+
+ ENDDO.
+
+ "All components should be typed with c length 3
+ struct_type = cl_abap_structdescr=>get(
+ VALUE #(
+ ( name = column1 type = cl_abap_elemdescr=>get_c( 3 ) )
+ ( name = column2 type = cl_abap_elemdescr=>get_c( 3 ) )
+ ( name = column3 type = cl_abap_elemdescr=>get_c( 3 ) ) ) ).
+
+ "Creating structured data object
+ CREATE DATA dref_struc TYPE HANDLE struct_type.
+
+ "Assigning values to the structure components
+ ASSIGN dref_struc->* TO FIELD-SYMBOL().
+ ASSIGN COMPONENT column1 OF STRUCTURE TO FIELD-SYMBOL().
+ ASSIGN COMPONENT column2 OF STRUCTURE TO FIELD-SYMBOL().
+ ASSIGN COMPONENT column3 OF STRUCTURE TO FIELD-SYMBOL().
+ = 'abc'.
+ = 'def'.
+ = 'ghi'.
+
+ output->display( input = name = `` ).
+
+**********************************************************************
+
+ output->next_section( `44) Dynamically Creating Data Objects at Runtime Using Type Description Objects (3) - Internal Table` ).
+
+ "In the example an internal table type is created based on a DDIC type.
+ "See the comments in the code.
+
+ "Retrieving table name
+ DATA(table_name) = lcl_det_at_runtime=>get_dyn_table_name( ).
+
+ "Retrieving type information using RTTI
+ DATA(st) = CAST cl_abap_structdescr(
+ cl_abap_tabledescr=>describe_by_name( table_name ) ).
+
+ "Declaring an internal table to hold the components;
+ "it will include the component name and the component type
+ DATA comp_table TYPE cl_abap_structdescr=>component_table.
+
+ "Looping across the retrieved field list to extract information
+ "In principle, you could also just use method get_components( ) :)
+ LOOP AT st->components ASSIGNING FIELD-SYMBOL().
+
+ "Adding name of the component and its type, which is retrieved using the
+ "get_component_type method, are added to the internal table that holds the components
+ APPEND VALUE #( name = -name
+ type = st->get_component_type( -name ) ) TO comp_table.
+
+ "The SELECT statement further down includes a dynamic specification
+ "of the ORDER BY clause.
+ "In this case, just using the second field since MANDT is the first.
+ IF sy-tabix = 2.
+ DATA(dyn_order_by) = -name.
+ ENDIF.
+
+ ENDLOOP.
+
+ "Creating an internal table type
+ "Note: The parameter p_key is not filled here, i. e. the default key is used.
+ DATA(itab_type) = cl_abap_tabledescr=>create(
+ p_line_type = st
+ p_table_kind = cl_abap_tabledescr=>tablekind_sorted
+ p_unique = cl_abap_typedescr=>true ).
+
+ "Creating an internal table based on the created table type
+ DATA ref_tab TYPE REF TO data.
+ CREATE DATA ref_tab TYPE HANDLE itab_type.
+ FIELD-SYMBOLS TYPE ANY TABLE.
+ ASSIGN ref_tab->* TO .
+
+ "Filling an internal table
+ SELECT *
+ FROM (table_name)
+ ORDER BY (dyn_order_by)
+ INTO CORRESPONDING FIELDS OF TABLE @
+ UP TO 3 ROWS.
+
+ output->display( |Type/Database table name determined at runtime: { table_name }| ).
+ output->display( |Internal table entries (ordered by { dyn_order_by }):| ).
+ output->display( input = name = `` ).
+
+ ENDMETHOD.
+ENDCLASS.
+
diff --git a/src/zcl_demo_abap_dynamic_prog.clas.locals_imp.abap b/src/zcl_demo_abap_dynamic_prog.clas.locals_imp.abap
new file mode 100644
index 0000000..0dc37f4
--- /dev/null
+++ b/src/zcl_demo_abap_dynamic_prog.clas.locals_imp.abap
@@ -0,0 +1,437 @@
+CLASS lcl_det_at_runtime DEFINITION.
+
+ PUBLIC SECTION.
+
+ CLASS-DATA: string1 TYPE string,
+ string2 TYPE string,
+ string3 TYPE string,
+ dyn_meth_call_result TYPE string.
+
+ TYPES: type_p TYPE p LENGTH 8 DECIMALS 2, "elementary type
+ type_struc TYPE zdemo_abap_carr, "structure type
+ "internal table type
+ type_itab TYPE SORTED TABLE OF zdemo_abap_flsch WITH NON-UNIQUE KEY carrid connid "primary key
+ WITH UNIQUE SORTED KEY cities COMPONENTS cityfrom cityto, "secondary key
+ type_ref TYPE REF TO lcl_det_at_runtime. "reference type
+
+ TYPES: BEGIN OF struc_builtin,
+ builtin_type TYPE c LENGTH 10,
+ len TYPE i,
+ dec TYPE i,
+ END OF struc_builtin.
+
+ TYPES: BEGIN OF struc_dyn,
+ table TYPE string,
+ select_list TYPE string,
+ where_clause TYPE string_table,
+ order_by TYPE string,
+ target TYPE REF TO data,
+ rows TYPE i,
+ END OF struc_dyn.
+
+ CLASS-METHODS:
+ get_dyn_table_name RETURNING VALUE(tab) TYPE string,
+ get_dyn_dobj RETURNING VALUE(dobj) TYPE string,
+ get_dyn_field RETURNING VALUE(field) TYPE string,
+ get_dyn_select_list RETURNING VALUE(list) TYPE string,
+ get_dyn_where_clause RETURNING VALUE(clause_tab) TYPE string_table,
+ get_random_type RETURNING VALUE(random_type) TYPE string,
+ get_builtin_type RETURNING VALUE(builtin_type) TYPE struc_builtin,
+ get_dyn_class_meth EXPORTING cl TYPE string
+ meth TYPE string
+ ptab TYPE abap_parmbind_tab,
+ get_dyn_syntax_elements RETURNING VALUE(syntax_elements) TYPE struc_dyn,
+ fill_string.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ENDCLASS.
+
+CLASS lcl_det_at_runtime IMPLEMENTATION.
+ METHOD get_dyn_table_name.
+
+ "Providing DDIC table names in a string table to be selected from.
+ DATA(flight_tables) = VALUE string_table(
+ ( `ZDEMO_ABAP_CARR` ) ( `ZDEMO_ABAP_FLSCH` ) ( `ZDEMO_ABAP_FLI` ) ).
+
+ "Getting random number to determine the table index at runtime.
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( flight_tables ) )->get_next( ).
+
+ "Returning parameter to receive the random table name.
+ tab = VALUE #( flight_tables[ idx ] DEFAULT `ZDEMO_ABAP_CARR` ).
+
+ ENDMETHOD.
+
+ METHOD get_builtin_type.
+
+ "Providing the names of built-in types in a string table to be selected from.
+ TYPES tabtyp TYPE TABLE OF struc_builtin-builtin_type WITH EMPTY KEY.
+
+ DATA(built) = VALUE tabtyp(
+ ( 'd' )
+ ( 'decfloat16' )
+ ( 'decfloat34' )
+ ( 'f' )
+ ( 'i' )
+ ( 'string' )
+ ( 't' )
+ ( 'xstring' )
+ ( 'c' )
+ ( 'n' )
+ ( 'x' )
+ ( 'p' )
+ ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( built ) )->get_next( ).
+
+ "Providing the returning parameter with a random type name
+ TRY.
+ builtin_type = VALUE #( builtin_type = built[ idx ] dec = idx len = idx ).
+ CATCH cx_sy_itab_line_not_found.
+ builtin_type = VALUE #( builtin_type = `p` dec = 5 len = 5 ).
+ ENDTRY.
+
+ ENDMETHOD.
+
+ METHOD get_dyn_dobj.
+
+ "Providing strings with demo content
+ string1 = |Hallo, { sy-uname }. | &&
+ |This is string1.|.
+ string2 = |Hallo, { sy-uname }. | &&
+ |This is string2.|.
+ string3 = |Hallo, { sy-uname }. | &&
+ |This is string3.|.
+
+ "Filling table with data object names
+ DATA(str_tab) = VALUE string_table(
+ ( `STRING1` ) ( `STRING2` ) ( `STRING3` ) ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( str_tab ) )->get_next( ).
+
+ "Providing the returning parameter with a random data object name
+ dobj = VALUE #( str_tab[ idx ] DEFAULT |Hallo, { sy-uname }. This is a string.| ).
+
+ ENDMETHOD.
+
+ METHOD get_dyn_field.
+
+ "Getting list of components of DDIC type zdemo_abap_carr
+ DATA(comp) = CAST cl_abap_structdescr(
+ cl_abap_typedescr=>describe_by_name(
+ 'ZDEMO_ABAP_CARR' )
+ )->components.
+
+ "Getting random number to determine the table index at runtime;
+ "starting from 2 to exclude MANDT field
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 2
+ max = lines( comp ) )->get_next( ).
+
+ "Providing the returning parameter with a random component name
+ field = VALUE #( comp[ idx ]-name DEFAULT `CARRID` ).
+
+ ENDMETHOD.
+
+ METHOD get_dyn_select_list.
+
+ "Providing SELECT lists in a string table to be selected from
+ DATA sel_list_tab TYPE string_table.
+ sel_list_tab = VALUE #(
+ ( `CARRID, CONNID, COUNTRYFR, COUNTRYTO` )
+ ( `CARRID, CONNID, CITYFROM, CITYTO` )
+ ( `CARRID, CONNID, AIRPFROM, AIRPTO` )
+ ( `CARRID, CONNID, AIRPFROM, AIRPTO, ` &&
+ `FLTIME, DEPTIME, ARRTIME, DISTANCE` )
+ ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( sel_list_tab ) )->get_next( ).
+
+ "Providing the returning parameter with a random SELECT list
+ list = VALUE #( sel_list_tab[ idx ] DEFAULT `CARRID, CONNID, COUNTRYFR, COUNTRYTO` ).
+
+ ENDMETHOD.
+
+ METHOD get_dyn_where_clause.
+
+ "Providing WHERE clauses in a table to be selected from
+ DATA: BEGIN OF where_struc,
+ where_clause_tab TYPE string_table,
+ END OF where_struc.
+
+ DATA where_itab LIKE TABLE OF where_struc WITH EMPTY KEY.
+
+ where_itab = VALUE #(
+ ( where_clause_tab = VALUE #( ( `CARRID = 'LH'` )
+ ( `OR CARRID = 'AA'` ) ) )
+ ( where_clause_tab = VALUE #( ( `CONNID BETWEEN 0 AND 300` ) ) )
+ ( where_clause_tab = VALUE #( ( `CITYFROM LIKE '%FRA%'` ) ) )
+ ( where_clause_tab =
+ VALUE #( ( `DISTANCE > 500 AND DISTID = 'KM'` ) ) ) ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( where_itab ) )->get_next( ).
+
+ "Providing the returning parameter with a random WHERE clause
+ clause_tab = VALUE #( where_itab[ idx ]-where_clause_tab DEFAULT VALUE #( ( `CARRID = 'LH'` ) ( `OR CARRID = 'AA'` ) ) ).
+
+ ENDMETHOD.
+
+ METHOD get_random_type.
+
+ "Providing names of classes in a string table to be selected from
+ "In this example, some types are defined in the public section
+ "of a local class. The class name is added here since the names
+ "are used in the global class.
+ DATA(str_tab) = VALUE string_table(
+ ( `LCL_DET_AT_RUNTIME=>TYPE_P` )
+ ( `LCL_DET_AT_RUNTIME=>TYPE_STRUC` )
+ ( `LCL_DET_AT_RUNTIME=>TYPE_ITAB` )
+ ( `LCL_DET_AT_RUNTIME=>TYPE_REF` )
+ ( `LCL_DET_AT_RUNTIME` )
+ ( `IF_OO_ADT_CLASSRUN` )
+ ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( str_tab ) )->get_next( ).
+
+ "Providing the returning parameter with a random type name
+ random_type = VALUE #( str_tab[ idx ] DEFAULT `LCL_DET_AT_RUNTIME=>TYPE_STRUC` ).
+
+ ENDMETHOD.
+
+ METHOD get_dyn_class_meth.
+
+ "Providing class names in a string table to be selected from
+ DATA(class_tab) = VALUE string_table(
+ ( `LCL_DEMO1` )
+ ( `LCL_DEMO2` ) ).
+
+ "Getting random number to determine the table index at runtime
+ DATA(idx) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( class_tab ) )->get_next( ).
+
+ "Provide the exporting parameter with the random class name
+ cl = VALUE #( class_tab[ idx ] DEFAULT `LCL_DEMO1` ).
+
+ "Getting method names using RTTI
+ DATA(methods) = CAST cl_abap_classdescr( cl_abap_typedescr=>describe_by_name( cl ) )->methods.
+
+ "Getting random number to determine the table index at runtime
+ idx = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( ) min = 1
+ max = lines( methods ) )->get_next( ).
+
+ "Provide the exporting parameter with the random method name
+ meth = VALUE #( methods[ idx ]-name DEFAULT `METH_A` ).
+
+ "Data reference objects for the value parameter in the parameter table
+ DATA(ref_imp) = NEW string( `hi` ).
+ DATA(ref_exp) = NEW string( `hallo` ).
+ DATA(ref_ch) = NEW string( `salut` ).
+ DATA(ref_ret) = NEW string( `ciao` ).
+
+ "Filling the parameter tables
+ "Note: If the method signature has an importing parameter,
+ "it must be specified as exporting parameter here.
+ "Same is true for the exporting parameter in the signature
+ "that must be specified as importing parameter.
+
+ CASE meth.
+
+ WHEN `METH_A`.
+
+ ptab = VALUE #( ( name = 'A'
+ kind = cl_abap_objectdescr=>exporting
+ value = ref_exp )
+ ( name = 'B'
+ kind = cl_abap_objectdescr=>importing
+ value = ref_imp ) ).
+
+ WHEN `METH_B`.
+
+ ptab = VALUE #( ( name = 'C'
+ kind = cl_abap_objectdescr=>changing
+ value = ref_ch )
+ ( name = 'D'
+ kind = cl_abap_objectdescr=>returning
+ value = ref_ret ) ).
+
+ WHEN `METH_C`.
+
+ ptab = VALUE #( ( name = 'E'
+ kind = cl_abap_objectdescr=>exporting
+ value = ref_exp )
+ ( name = 'F'
+ kind = cl_abap_objectdescr=>importing
+ value = ref_imp ) ).
+
+ WHEN `METH_D`.
+
+ ptab = VALUE #( ( name = 'G'
+ kind = cl_abap_objectdescr=>changing
+ value = ref_ch )
+ ( name = 'H'
+ kind = cl_abap_objectdescr=>returning
+ value = ref_ret ) ).
+
+ ENDCASE.
+
+ ENDMETHOD.
+
+ METHOD fill_string.
+ dyn_meth_call_result = |Hallo { sy-uname }. The string was filled at { utclong_current( ) }.|.
+ ENDMETHOD.
+
+ METHOD get_dyn_syntax_elements.
+
+ "FROM clause
+ DATA(flight_tables) = VALUE string_table(
+ ( `ZDEMO_ABAP_CARR` ) ( `ZDEMO_ABAP_FLSCH` ) ( `ZDEMO_ABAP_FLI` ) ).
+
+ "Getting random number to determine the table index at runtime.
+ DATA(idx_table) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( )
+ min = 1
+ max = lines( flight_tables ) )->get_next( ).
+
+ syntax_elements-table = VALUE #( flight_tables[ idx_table ] DEFAULT `ZDEMO_ABAP_CARR` ).
+
+ "SELECT list
+ DATA(comp) = CAST cl_abap_structdescr(
+ cl_abap_typedescr=>describe_by_name( syntax_elements-table ) )->components.
+
+ "At least 3 components
+ DATA(idx_comp) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( )
+ min = 3
+ max = lines( comp ) )->get_next( ).
+
+ DELETE comp FROM idx_comp + 1 TO lines( comp ).
+
+ LOOP AT comp ASSIGNING FIELD-SYMBOL().
+ syntax_elements-select_list = syntax_elements-select_list && `, ` && -name.
+ ENDLOOP.
+
+ "Replacing initial comma
+ REPLACE PCRE `^,\s` IN syntax_elements-select_list WITH ``.
+
+ "WHERE clause
+ "Excluding the client field
+ DELETE comp WHERE name = 'MANDT'.
+
+ "A maximum of 4 fields are to be respected because that is the maximum of possible fields
+ "available in table zdemo_abap_carr (without the client field)
+ DATA(idx_where) = cl_abap_random_int=>create(
+ seed = cl_abap_random=>seed( )
+ min = 1
+ max = 4 )->get_next( ).
+
+ "In the example, the WHERE clause consists of an internal table of type string.
+ "The clause is set up with fields and only IS NOT INITIAL to be on the safe side for a
+ "somewhat 'meaningful' clause and in the interest of simplicity.
+ LOOP AT comp ASSIGNING FIELD-SYMBOL(