I recently wanted to write a report that would compare data between different systems (e.g. customizing or transactional data). I found the function module “RFC_READ_TABLE”, which delivers data from other systems. The where-clause, which can easily be passed into the options parameter, is essential, especially when comparing transactional data, as one does not want to have all of the data returned in one call for performance reasons.
I soon stumbled upon a limitation. This standard function module does not properly support packed fields and everything was out. I was checking the internet and found this nice SDN thread, which describes a solution. However, it does not include enough detail. After playing around a bit, I think I have tamed the beast.
There were a couple of issues, mainly the one that the length of the fields differs accordingly to their type and the offset to know where to start looking for the next needed to consider the length as well.
DATA lt_where TYPE rsds_where_tab. “ where clause for selection DATA lt_nametab1 TYPE STANDARD TABLE OF rfc_db_fld. “ will be left blank DATA lt_raw_tab TYPE TABLE OF veri_raw. “ buffer table with raw data DATA lt_field TYPE TABLE OF x031l. “ field description DATA lv_x TYPE xstring. DATA lv_str TYPE string. DATA lv_char TYPE char2048. DATA lv_offset TYPE roffset. DATA lv_length TYPE outlength. FIELD-SYMBOLS <ls_raw_line> TYPE veri_raw. FIELD-SYMBOL <fld> TYPE any. FIELD-SYMBOL <fld_tar> TYPE any. * Get raw data from a different system CALL FUNCTION RFC_READ_TABLE' DESTINATION p_dest EXPORTING query_table = p_tabnam TABLES options = lt_where fields = lt_nametab1 data = lt_raw_tab EXCEPTIONS others = 7. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 DISPLAY LIKE 'I'. ENDIF. * Get table description e.g. from target system or current system, here current system is sufficent lv_tabnam = p_tabnam. CALL FUNCTION 'DD_GET_NAMETAB' EXPORTING tabname = lv_tabnam get_all = 'X' TABLES x031l_tab = lt_field EXCEPTIONS others = 0. * Loop over the raw data needs to be done because packed fields are giving hassles LOOP AT lt_raw_tab ASSIGNING <ls_raw_line>. * get the string for the raw data lv_x = <ls_raw_line>. CALL FUNCTION 'HR_RU_CONVERT_HEX_TO_STRING' EXPORTING xstring = lv_x IMPORTING cstring = lv_str. * Move to character string lv_char = lv_str. * Clear some variables CLEAR <line2>. CLEAR lv_offset. * Loop over each field of the table LOOP AT lt_field ASSIGNING <field>. * Assign the target field ASSIGN COMPONENT <field>-fieldname OF STRUCTURE <line> TO <fld_tar>. “ <line> is a fieldsymbol which is assigned to a structure corresponding to the table * Determine the length of the field accordingly to type IF <field>-exid eq 'P'. “packed field lv_length = <field>-digits. ELSEIF <field>-exid eq 'b'. “integer field lv_length = <field>-exlength. ELSE. lv_length = <field>-dblength. ENDIF. IF lv_length EQ 0. “don’t processes if length is zero e.g. include description continue. ENDIF. * Get the field value ASSIGN lv_char+lv_offset(lv_length) TO <fld>. * Assign to target field <fld_tar> = <fld>. * Adjust length for next field ADD lv_length TO lv_offset. ENDLOOP. * Append line to compare table APPEND <line> TO <tab>. ENDLOOP.
Please note: The function module itself does an authority check and from my perspective it is the responsibility of the developer and administrator to ensure that the RFC destinations are set up properly, so that a logon is enforced. Otherwise this function module can be abused to read data from a system where the user is not supposed to poke around…