ABAP in Practice - Type Conversion
How would you perform this type conversion in ABAP? A practical example and a suggested solution.
Table of contents
In this article we will look at a practical example and how the problem can be easily implemented using Modern ABAP.
Introduction
The challenge is to convert a selection table of type RSSELECT into a selection from the gateway. There is a major structural change in this. The source table is flat and the target table pre-structures the select options in a deep structure.
On the left side of the image is our source structure, the target is the table on the right.
Preparation
In preparation, we create an executable class in the system, define the types we need and generate some sample data that we can use for testing.
CLASS zcl_bs_demo_practice_typ_conv DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
TYPES ts_rsselect TYPE rsselect.
TYPES tt_rsselect TYPE STANDARD TABLE OF ts_rsselect WITH EMPTY KEY.
TYPES tt_result TYPE /iwbep/t_mgw_select_option.
METHODS convert_type
IMPORTING it_rsselect TYPE tt_rsselect
RETURNING VALUE(rt_result) TYPE tt_result.
ENDCLASS.
CLASS zcl_bs_demo_practice_typ_conv IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lt_source) = VALUE tt_rsselect(
( fieldnm = 'IDENT' sign = 'I' option = 'EQ' low = 'A10' )
( fieldnm = 'DATE' sign = 'I' option = 'BT' low = '20240501' high = '20240520' )
( fieldnm = 'IDENT' sign = 'I' option = 'BT' low = 'A11' high = 'A15' )
( fieldnm = 'NAME' sign = 'E' option = 'EQ' low = 'Meier' )
( fieldnm = 'NAME' sign = 'E' option = 'EQ' low = 'Scholz' )
( fieldnm = 'TIME' sign = 'I' option = 'GE' low = '190000' ) ).
DATA(lt_result) = convert_type( lt_source ).
ENDMETHOD.
METHOD convert_type.
ENDMETHOD.
ENDCLASS.
Task
Your task would now be to implement the CONVERT_TYPE method. The method receives the filled source table via IT_RSSELECT and RT_RESULT must be filled.
Hint: In the next section we will go into the solution, if you want to do the task yourself first, you should pause here.
Solution
How can we solve this problem with Modern ABAP? To do this, we first use a loop to iterate over the transferred data. Here we can work with an inline declaration to save ourselves the trouble of defining the variable.
LOOP AT it_rsselect INTO DATA(ls_rsselect).
ENDLOOP.
In the next step we have to create a new row in the table if it does not already exist, otherwise we would read the row to extend it in the last step. We could map both cases separately, but depending on the complexity we would generate a lot of redundant coding. Therefore, in the first step we try to read the existing row from the table and assign the result to a new reference. This would give us a pointer with which we can make changes directly in RT_RESULT. If the entry is not found because it is new, the exception CX_SY_ITAB_LINE_NOT_FOUND is triggered. In this case, we would only insert our key via INSERT and also the pointer of the reference LR_MAPPED. In both cases, LR_MAPPED now points to the line that we want to edit.
TRY.
DATA(lr_mapped) = REF #( rt_result[ property = ls_rsselect-fieldnm ] ).
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( property = ls_rsselect-fieldnm ) INTO TABLE rt_result REFERENCE INTO lr_mapped.
ENDTRY.
Finally, we can append the remaining data to the table with the SELECT_OPTIONS. To do this, we map the data inline using CORRESPONDING and append the result to our reference. Since we are not working with a copy of the table row here, but with a reference, we save ourselves the MODIFY of the RESULT table.
INSERT CORRESPONDING #( ls_rsselect ) INTO TABLE lr_mapped->select_options.
Complete example
In this section you will find the final class with the developed method and you can compare the example with your implementation.
CLASS zcl_bs_demo_practice_typ_conv DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
PRIVATE SECTION.
TYPES ts_rsselect TYPE rsselect.
TYPES tt_rsselect TYPE STANDARD TABLE OF ts_rsselect WITH EMPTY KEY.
TYPES tt_result TYPE /iwbep/t_mgw_select_option.
METHODS convert_type
IMPORTING it_rsselect TYPE tt_rsselect
RETURNING VALUE(rt_result) TYPE tt_result.
ENDCLASS.
CLASS zcl_bs_demo_practice_typ_conv IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
DATA(lt_source) = VALUE tt_rsselect(
( fieldnm = 'IDENT' sign = 'I' option = 'EQ' low = 'A10' )
( fieldnm = 'DATE' sign = 'I' option = 'BT' low = '20240501' high = '20240520' )
( fieldnm = 'IDENT' sign = 'I' option = 'BT' low = 'A11' high = 'A15' )
( fieldnm = 'NAME' sign = 'E' option = 'EQ' low = 'Meier' )
( fieldnm = 'NAME' sign = 'E' option = 'EQ' low = 'Scholz' )
( fieldnm = 'TIME' sign = 'I' option = 'GE' low = '190000' ) ).
DATA(lt_result) = convert_type( lt_source ).
ENDMETHOD.
METHOD convert_type.
LOOP AT it_rsselect INTO DATA(ls_rsselect).
TRY.
DATA(lr_mapped) = REF #( rt_result[ property = ls_rsselect-fieldnm ] ).
CATCH cx_sy_itab_line_not_found.
INSERT VALUE #( property = ls_rsselect-fieldnm ) INTO TABLE rt_result REFERENCE INTO lr_mapped.
ENDTRY.
INSERT CORRESPONDING #( ls_rsselect ) INTO TABLE lr_mapped->select_options.
ENDLOOP.
ENDMETHOD.
ENDCLASS.
Conclusion
Many roads lead to Rome and that would also apply to the solution of the task. With Modern ABAP, the solution can be implemented with little effort. If you have a completely different solution, post the contents of the CONVERT_TYPE method as an alternative in the comments.