Technical Articles
Use references in ABAP and get access from one object to another!
Everybody knows that references exist and what they do, but it’s actually rare to see someone getting advantage from their utility. Recently I faced quite common problem and references occured to be the ultimate solution. I think it’s very common and general issue, therefore you may find this article very useful (and fun of course, it’s ABAP).
Problem
In an ALV table user can select multiple rows. After the event is raised keys of rows are collected to the proxy query, details of selected rows are extracted:
mo_grid->get_selected_rows( IMPORTING et_index_rows = lt_index_rows ).
LOOP AT lt_index_rows ASSIGNING FIELD-SYMBOL(<fs_index_row>).
ASSIGN gt_table[ <fs_index_row>-index ] TO <fs_record>.
IF sy-subrc = 0.
APPEND CORRESPONDING #( <fs_record> ) TO lt_message_header.
ENDIF.
ENDLOOP.
lo_proxy=>read_details( EXPORTING it_message_headers = lt_message_header
RECEIVING rs_read_out = ls_read_out ).
Now those details need to be fetched into the table into selected rows. The simpliest approach is to loop again through selected indexes and modify rows with extracted details in the same order. But it’s not really robust, is it?
Grace solution
Why perform the same loop again and make our code not very efficient and not very stylish? ( ͡° ͜ʖ ͡°)
We could collect references to selected rows and perform necessary operations directly on them without the necessity to read the table again:
mo_grid->get_selected_rows( IMPORTING et_index_rows = lt_index_rows ).
LOOP AT lt_index_rows ASSIGNING FIELD-SYMBOL(<fs_index_row>).
ASSIGN gt_table[ <fs_index_row>-index ] TO <fs_record>.
IF sy-subrc = 0.
APPEND VALUE #( record = REF #( <fs_record> ) ) TO lt_reference_table.
APPEND CORRESPONDING #( <fs_record> ) TO lt_message_header.
ENDIF.
ENDLOOP.
lo_proxy=>read_details( EXPORTING it_message_headers = lt_message_header
RECEIVING rs_read_out = ls_read_out ).
And now:
LOOP AT lt_reference_table ASSIGNING FIELD-SYMBOL(<fs_reference>).
ASSIGN lt_read_out[ sy-tabix ] TO <fs_read_out>.
IF sy-subrc = 0.
<fs_reference>-record->* = CORRESPONDING #( <fs_read_out> ).
ENDIF.
ENDLOOP.
As you can see – extremely easy, incredibly useful. Use references guys!
Whole easy example for you to copy and paste:
TYPES: tt_i TYPE TABLE OF i WITH DEFAULT KEY,
tt_string TYPE TABLE OF string WITH DEFAULT KEY,
BEGIN OF ty_reference,
record TYPE REF TO string,
END OF ty_reference,
tt_reference TYPE STANDARD TABLE OF ty_reference WITH DEFAULT KEY.
DATA(lt_indexes) = VALUE tt_i( ( 1 ) ( 3 ) ( 7 ) ).
DATA(lt_table) = VALUE tt_string( ( |name1| ) ( |name2| ) ( |name3| ) ( |name4| ) ( |name5| ) ( |name6| ) ( |name7| ) ).
DATA(lt_reftab) = VALUE tt_reference( ).
lt_reftab = VALUE #( FOR i IN lt_indexes ( record = REF #( lt_table[ i ] ) ) ).
LOOP AT lt_reftab ASSIGNING FIELD-SYMBOL(<fs_row>).
<fs_row>-record->* = |{ <fs_row>-record->* }_ref|.
ENDLOOP.
LOOP AT lt_table ASSIGNING FIELD-SYMBOL(<fs_line>).
WRITE: / <fs_line>.
ENDLOOP.
I'v used references quite a few times for complex data structures where I need performance. It's good to keep it in mind.
Hello Andrzej,
in this context I would use an iterator that returns a reference variable.
best regards,
JNN
I haven't thought about that, good idea. Thank you for your insight!
Nice blog, thanks for sharing!
We need some kind of ABAP code translator though - we're on 7.31 and lots of code examples shared these days are in 7.4 syntax that don't pass a syntax check (obviously). 🙁 Downporting it is a pain in the back. No easy copy-paste for those stuck with older versions, unfortunately.
Really good idea Andrzej 🙂