SAP GOS Objects Migration -Download/Upload

Introduction

Hello Guys, I myself Vivek with 16+ years of rich experience in SAP and specialized in SAP Fiori/UI5 Development.

My major focus will be in the digital transformation projects.

Eligible Readers

SAPUI5 developers, Consultants, Solution Architects and basically anyone is working on Digital Transformation Projects.

When the readers need this blog?

One of the pain point lies in migrating the documents attached to the GOS(Generic Object Services). Most of the older implementations will definitely have utilized the GOS services and migrating them is a cumbersome process.

Once of the ways of migrating the GOS Documents is via downloading and uploading the same. We have tried moving them via IDOCs, but was not a success story in our case the source and target document number varies.

How GOS is linked to a Document?

Let us take a Finance document from transaction FB03 or Service entry sheet from ML81N, Document number is the key and the object type (eg: BKPF, BUS2091) are the important factors.

Object%20Services

Object Services

We can get the above information functionally and once we get the above information go to table SRGBTBREL

Table

Table

Please use the above selection and RELTYPE ‘ATTA’ means GOS Document. If the RELTYPE is URL, then it is an external link attached to the document.

Table%20Fields

Table Fields

INSTID A is the document number field. If it ML81N, service entry sheet number is the INSTID A id. If it is finance document fro, FB03 then it will be <Company code>+<Document No>+<Fiscal Year> and this changes accordingly.

Also please pay attention to the field INSTID B which is the field makes relation to the content of the actual Binary of the file stored in table SOC3.

Now let us see the coding we have made to download the GOS attachment and sequence to be used.

  1. Get the Binary Relation between the document number and the GOS attachment using the instid A, typeid A and Catid A. This will get the INSTID B for the attachment.
  2. Using the INSTID B, call the function module SO_OBJECT_READ
  3. After getting the lt_objcont from the read function module, use the function module SO_OBJECT_DOWNLOAD to download the file.

I am presenting the code below with which you can download all the Business object types.

We have also modified the code for uploading a mapping file with old document number in ECC and New document number in S4HANA.

Download does not complete our job, We have to upload the same in the new system. Let’s continue in Part 2.

FIELD-SYMBOLS: <gt_data> TYPE table, <gs_data>.
DATA : gt_pod_xls TYPE TABLE OF zbc_gos_map_excl_st INITIAL SIZE 0.
DATA : gt_pod TYPE TABLE OF zbc_gos_map_excl_st INITIAL SIZE 0, gs_pod TYPE eprof_delv_in.
DATA: lt_goslog TYPE TABLE OF zgos_log, ls_goslog TYPE zgos_log.
TYPES: BEGIN OF ts_fin_att, foltp TYPE so_fol_tp, folyr TYPE so_fol_yr, folno TYPE so_fol_no, objtp TYPE so_obj_tp, objyr TYPE so_obj_yr, objno TYPE so_obj_no, brelguid TYPE oblguid32, roletype TYPE oblroltype, END OF ts_fin_att.
DATA: it_final_cont TYPE STANDARD TABLE OF ts_fin_att, is_final_cont TYPE ts_fin_att. ************************************************************************
* Class Definition
************************************************************************
CLASS lcl_po_attachments DEFINITION FINAL. PUBLIC SECTION. "Types Definition TYPES: BEGIN OF ts_attachment, foltp TYPE so_fol_tp, folyr TYPE so_fol_yr, folno TYPE so_fol_no, objtp TYPE so_obj_tp, objyr TYPE so_obj_yr, objno TYPE so_obj_no, brelguid TYPE oblguid32, roletype TYPE oblroltype, END OF ts_attachment, BEGIN OF ts_key, foltp TYPE so_fol_tp, folyr TYPE so_fol_yr, folno TYPE so_fol_no, objtp TYPE so_obj_tp, objyr TYPE so_obj_yr, objno TYPE so_obj_no, forwarder TYPE so_usr_nam, END OF ts_key,
* BEGIN OF ts_po,
* ebeln TYPE ekko-ebeln,
* bukrs TYPE ekko-bukrs,
* ekgrp TYPE ekko-ekgrp,
* END OF ts_po, BEGIN OF ts_po, ebeln TYPE zbc_gos_map_excl_st-old_key, bukrs TYPE zbc_gos_map_excl_st-new_key, ekgrp TYPE zbc_gos_map_excl_st-objtype, END OF ts_po, BEGIN OF ts_output, icon TYPE icon-id, ebeln TYPE zbc_gos_map_excl_st-old_key, bukrs TYPE zbc_gos_map_excl_st-new_key, ekgrp TYPE zbc_gos_map_excl_st-objtype, file(54) TYPE c, END OF ts_output, BEGIN OF ts_sood, objtp TYPE sood-objtp, objyr TYPE sood-objyr, objno TYPE sood-objno, objdes TYPE sood-objdes, extct TYPE sood-extct, file_ext TYPE sood-file_ext, objlen TYPE sood-objlen, END OF ts_sood, tt_sood TYPE HASHED TABLE OF sood WITH UNIQUE KEY primary_key COMPONENTS objtp objyr objno, tt_po TYPE TABLE OF ts_po, tt_attachment TYPE STANDARD TABLE OF ts_attachment WITH DEFAULT KEY, tt_output TYPE STANDARD TABLE OF ts_output WITH DEFAULT KEY. "Constants CONSTANTS: c_title TYPE string VALUE 'Select Folder Path to download the PO Attachments'. "Declarations DATA: ebeln TYPE ekko-ebeln, lv_tot TYPE i, lv_cur TYPE i, it_ekko TYPE tt_po, it_sood TYPE tt_sood, it_out TYPE tt_output, ls_ekko TYPE zbc_gos_map_excl_st, it_atta TYPE tt_attachment. *--- Local variables --------------------------------------------------* DATA: lv_filename TYPE localfile, lv_dref TYPE REF TO data. "Methods METHODS load. METHODS check_folderpath IMPORTING i_dirname TYPE string RETURNING VALUE(invalid_path) TYPE char1. METHODS get_sood IMPORTING lt_attachments TYPE tt_attachment RETURNING VALUE(lt_sood) TYPE tt_sood. METHODS get_po_attachments IMPORTING i_ekko TYPE ts_po
* i_ebeln TYPE zbc_gos_map_excl_st-old_key
* i_objid TYPE zbc_gos_map_excl_st-objtype "ekko-ebeln RETURNING VALUE(attachments) TYPE tt_attachment. METHODS get_po RETURNING VALUE(no_data) TYPE char1. PRIVATE SECTION. "Methods METHODS download_attachments IMPORTING i_sood TYPE sood "ts_sood i_ekko TYPE ts_po.
* METHODS display. METHODS set_desc IMPORTING field TYPE salv_s_ddic_reference-field table TYPE salv_s_ddic_reference-table length TYPE lvc_outlen col TYPE REF TO cl_salv_column_list. METHODS set_des IMPORTING short TYPE scrtext_s medium TYPE scrtext_m long TYPE scrtext_l length TYPE lvc_outlen col TYPE REF TO cl_salv_column_list.
ENDCLASS.

Selection Screen

************************************************************************
* Initialization
************************************************************************
INITIALIZATION. DATA(ins_po_attachments) = NEW lcl_po_attachments( ).
************************************************************************
* Selection Screen
************************************************************************ SELECTION-SCREEN: BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-000. SELECTION-SCREEN COMMENT 1(30) TEXT-003 FOR FIELD p_file. PARAMETERS: p_file TYPE string LOWER CASE. PARAMETERS: p_otype TYPE char24 DEFAULT 'BKPF'.
* SELECT-OPTIONS : s_ebeln FOR ins_po_attachments->ebeln. PARAMETERS : p_path TYPE string LOWER CASE OBLIGATORY. SELECTION-SCREEN: END OF BLOCK b1.
************************************************************************
* At Selection-screen on Value-request for P_PATH
************************************************************************
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path. CALL METHOD cl_gui_frontend_services=>directory_browse EXPORTING window_title = ins_po_attachments->c_title CHANGING selected_folder = p_path EXCEPTIONS cntl_error = 1 error_no_gui = 2 not_supported_by_gui = 3 OTHERS = 4. IF sy-subrc <> 0. RETURN. ENDIF.
************************************************************************
* At Selection-screen on Value-request for P_FILE
************************************************************************
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file. PERFORM f4_p_file CHANGING p_file.
START-OF-SELECTION. ins_po_attachments->load( ).
************************************************************************
* Class Implementation
************************************************************************
CLASS lcl_po_attachments IMPLEMENTATION. METHOD get_po. CLEAR no_data.
* ls_ekko-old_key = '200075200019122013'.
* ls_ekko-new_key = '1000238392'.
* ls_ekko-objtype = 'BKPF'.
* APPEND ls_ekko TO it_ekko. IF <gt_data> IS ASSIGNED. UNASSIGN <gt_data>. ENDIF. IF <gs_data> IS ASSIGNED. UNASSIGN <gs_data>. ENDIF. * Create internal table and structure for data CREATE DATA lv_dref TYPE TABLE OF zbc_gos_map_excl_st. ASSIGN lv_dref->* TO <gt_data>. CREATE DATA lv_dref TYPE zbc_gos_map_excl_st. ASSIGN lv_dref->* TO <gs_data>. REFRESH : <gt_data>. lv_filename = p_file. BREAK-POINT. IF NOT lv_filename IS INITIAL. PERFORM get_excel_data_new USING lv_filename 'ZBC_GOS_MAP_EXCL_ST'. IF NOT gt_pod IS INITIAL. LOOP AT gt_pod INTO DATA(gs_pod). ls_ekko-old_key = gs_pod-old_key. ls_ekko-new_key = gs_pod-new_key. ls_ekko-objtype = gs_pod-objtype. APPEND ls_ekko TO it_ekko. ENDLOOP. ENDIF. ENDIF. ENDMETHOD. METHOD download_attachments. DATA(l_pr) = ( lv_cur * 100 ) / lv_tot. IF l_pr < 2. l_pr = 2. ENDIF. CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR' EXPORTING percentage = l_pr text = |{ l_pr }% =>{ i_ekko-ebeln }-{ i_sood-objdes }.{ i_sood-file_ext }|. DATA(ls_out) = VALUE ts_output( ). DATA(l_sortf) = CONV char30( |{ i_sood-objtp }{ i_sood-objyr }{ i_sood-objno }| ). DATA(lt_objcont) = VALUE soli_tab( ). BREAK-POINT. IMPORT objcont_tab TO lt_objcont[] FROM DATABASE soc3(dt) ID l_sortf. IF lt_objcont IS INITIAL. READ TABLE it_final_cont INTO is_final_cont WITH KEY objtp = i_sood-objtp objyr = i_sood-objyr objno = i_sood-objno. IF sy-subrc = 0. DATA: l_folderid TYPE soodk, l_objectid TYPE soodk. CONCATENATE is_final_cont-foltp is_final_cont-folyr is_final_cont-folno INTO l_folderid. l_objectid = l_sortf. DATA it_objcont TYPE STANDARD TABLE OF soli. CALL FUNCTION 'SO_OBJECT_READ' EXPORTING
* FILTER = folder_id = l_folderid
* FORWARDER = object_id = l_objectid
* OWNER =
* F_MAILER = ' '
* IMPORTING
* OBJECT_FL_DISPLAY =
* OBJECT_HD_DISPLAY =
* OBJECT_RC_DISPLAY = TABLES objcont = lt_objcont
* OBJHEAD =
* OBJPARA =
* OBJPARB = EXCEPTIONS active_user_not_exist = 1 communication_failure = 2 component_not_available = 3 folder_not_exist = 4 folder_no_authorization = 5 object_not_exist = 6 object_no_authorization = 7 operation_no_authorization = 8 owner_not_exist = 9 parameter_error = 10 substitute_not_active = 11 substitute_not_defined = 12 system_failure = 13 x_error = 14 OTHERS = 15. IF sy-subrc <> 0.
* Implement suitable error handling here ENDIF. ENDIF. ENDIF. IF sy-subrc = 0. CONCATENATE i_ekko-bukrs '_' p_otype INTO DATA(i_folder). DATA(filename) = |{ p_path }/{ i_folder }/{ i_sood-objdes }.{ i_sood-file_ext }|. DATA(filesize) = CONV soxwd-doc_length( i_sood-objlen ). DATA(lfilename) = VALUE string( ). CALL FUNCTION 'SO_OBJECT_DOWNLOAD' EXPORTING bin_filesize = filesize default_filename = filename filetype = 'BIN' path_and_file = filename extct = i_sood-extct no_dialog = abap_true IMPORTING act_filename = lfilename TABLES objcont = lt_objcont EXCEPTIONS file_write_error = 1 invalid_type = 2 x_error = 3 kpro_error = 4 OTHERS = 5. IF sy-subrc <> 0. ls_out-icon = icon_red_light.
***Create the Download Log************************* ELSE. ls_out-icon = icon_green_light. CLEAR: ls_goslog. ls_goslog-busobj = p_otype. ls_goslog-cat = 'D'. ls_goslog-ddate = sy-datum. ls_goslog-dtime = sy-uzeit. ls_goslog-filename = i_sood-objdes. ls_goslog-filetype = i_sood-file_ext. ls_goslog-objectid = i_ekko-ebeln. ls_goslog-userid = sy-uname. APPEND ls_goslog TO lt_goslog. TRY. MODIFY zgos_log FROM TABLE lt_goslog. CATCH cx_sy_open_sql_db INTO DATA(cx_sy_ref_is_initial). ENDTRY.
* INSERT zgos_log FROM TABLE lt_goslog. COMMIT WORK. CLEAR: ls_goslog. ENDIF. ELSE. ls_out-icon = icon_red_light. ENDIF. ls_out-bukrs = i_ekko-bukrs. ls_out-ebeln = i_ekko-ebeln. ls_out-ekgrp = i_ekko-ekgrp. ls_out-file = |{ i_sood-objdes }.{ i_sood-file_ext }|. APPEND ls_out TO it_out[]. CLEAR ls_out. ENDMETHOD. METHOD check_folderpath. CLEAR invalid_path. "Check the Folder path exists or not CALL METHOD cl_gui_frontend_services=>directory_exist EXPORTING directory = i_dirname RECEIVING result = DATA(result) EXCEPTIONS cntl_error = 1 error_no_gui = 2 wrong_parameter = 3 OTHERS = 4. IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. invalid_path = abap_true. ENDIF. ENDMETHOD. METHOD get_po_attachments. DATA(gs_lpor) = VALUE sibflporb( instid = i_ekko-ebeln catid = 'BO' typeid = p_otype ). "BKPF DATA(lt_options) = VALUE obl_t_relt( sign = 'I' option = 'EQ' ( low = 'ATTA' ) ( low = 'NOTE' ) ( low = 'URL' ) ). DATA(ls_attachment) = VALUE ts_attachment( ). DATA(ls_key) = VALUE ts_key( ). * TRY. CALL METHOD cl_binary_relation=>read_links_of_binrels EXPORTING is_object = gs_lpor it_relation_options = lt_options ip_role = 'GOSAPPLOBJ' ip_no_buffer = abap_false IMPORTING et_links = DATA(lt_links). DELETE lt_links[] WHERE typeid_b <> 'MESSAGE'. LOOP AT lt_links INTO DATA(ls_link). ls_key = ls_link-instid_b. MOVE-CORRESPONDING ls_key TO ls_attachment. ls_attachment-roletype = ls_link-roletype_b. IF ls_link-brelguid IS INITIAL. ls_attachment-brelguid = ls_link-relguidold. ELSE. ls_attachment-brelguid = ls_link-brelguid. ENDIF. APPEND ls_attachment TO attachments[]. it_final_cont[] = attachments[]. CLEAR ls_attachment. ENDLOOP. CLEAR it_atta[]. it_atta[] = attachments[]. CATCH: cx_obl_parameter_error INTO DATA(cx_obl_parameter_error), cx_obl_internal_error INTO DATA(cx_obl_internal_error), cx_obl_model_error INTO DATA(cx_obl_model_error). IF cx_obl_parameter_error IS BOUND. MESSAGE cx_obl_parameter_error->get_text( ) TYPE 'S' DISPLAY LIKE 'E'. CLEAR cx_obl_parameter_error. ENDIF. IF cx_obl_internal_error IS BOUND. MESSAGE cx_obl_internal_error->get_text( ) TYPE 'S' DISPLAY LIKE 'E'. CLEAR cx_obl_internal_error. ENDIF. IF cx_obl_model_error IS BOUND. MESSAGE cx_obl_model_error->get_text( ) TYPE 'S' DISPLAY LIKE 'E'. CLEAR cx_obl_model_error. ENDIF. ENDTRY. ENDMETHOD. METHOD set_des. col->set_short_text( short ). col->set_medium_text( medium ). col->set_long_text( long ). col->set_output_length( length ). ENDMETHOD. METHOD set_desc. DATA(value) = VALUE salv_s_ddic_reference( field = field table = table ). col->set_ddic_reference( value ). col->set_output_length( length ). ENDMETHOD. METHOD get_sood. CLEAR it_sood[]. SELECT * FROM sood INTO TABLE lt_sood[] FOR ALL ENTRIES IN lt_attachments[] WHERE objtp = lt_attachments-objtp AND objyr = lt_attachments-objyr AND objno = lt_attachments-objno. IF sy-subrc = 0. it_sood[] = lt_sood[]. ENDIF. ENDMETHOD. METHOD load. CLEAR it_out[]. IF check_folderpath( p_path ) = abap_true. RETURN. ENDIF. IF get_po( ) = abap_true. RETURN. ENDIF. lv_tot = lines( it_ekko[] ). LOOP AT it_ekko[] INTO DATA(ls_ekko). lv_cur = sy-tabix. CHECK NOT get_po_attachments( ls_ekko ) IS INITIAL. CHECK NOT get_sood( it_atta[] ) IS INITIAL. LOOP AT it_atta[] INTO DATA(ls_atta). READ TABLE it_sood[] INTO DATA(ls_sood) WITH KEY primary_key COMPONENTS objtp = ls_atta-objtp objyr = ls_atta-objyr objno = ls_atta-objno. CHECK sy-subrc = 0. download_attachments( i_sood = ls_sood i_ekko = ls_ekko ). ENDLOOP. ENDLOOP. CLEAR: it_ekko[], it_atta[], it_sood[]. CLEAR it_out[]. ENDMETHOD.
ENDCLASS.

The document(s) will be downloaded in the folder with name of the target Object Key read from the mapping file uploaded.

Read Excel

FORM get_excel_data_new USING p_filename TYPE localfile p_structure. *--- Local internal tables --------------------------------------------* DATA: lt_intern TYPE STANDARD TABLE OF alsmex_tabline, lt_intern_add TYPE STANDARD TABLE OF alsmex_tabline, lt_intern_del TYPE STANDARD TABLE OF alsmex_tabline, lt_fields_check TYPE STANDARD TABLE OF dd03l, lt_fields TYPE HASHED TABLE OF dd03l WITH UNIQUE KEY position, lt_fields_t TYPE ex_tab_dd03l. *--- Local structures -------------------------------------------------* DATA: ls_intern TYPE alsmex_tabline, ls_fields TYPE dd03l. *--- Local variables --------------------------------------------------* DATA: lv_err_hdr TYPE xflag, lv_index TYPE sy-tabix, lv_line(4) TYPE n. *--- Local field-symbols ----------------------------------------------* FIELD-SYMBOLS: <lv_value>. FIELD-SYMBOLS : <ls_pod> TYPE zbc_gos_map_excl_st, <ls_pod_xls> TYPE zbc_gos_map_excl_st, <ls_intern> TYPE alsmex_tabline, <ls_field> TYPE any. * PERFORM show_progress USING 20 text-p09. CALL FUNCTION 'ALSM_EXCEL_TO_INTERNAL_TABLE' EXPORTING filename = p_filename i_begin_col = 1 i_begin_row = 1 i_end_col = 3 i_end_row = 65536 TABLES intern = lt_intern
* TABLES
* intern = EXCEPTIONS inconsistent_parameters = 1 upload_ole = 2 OTHERS = 3. IF sy-subrc = 0. SORT lt_intern BY row col. DELETE lt_intern WHERE row = 1. LOOP AT lt_intern ASSIGNING <ls_intern>. AT NEW row. APPEND INITIAL LINE TO gt_pod_xls ASSIGNING <ls_pod_xls>. ENDAT. ASSIGN COMPONENT <ls_intern>-col OF STRUCTURE <ls_pod_xls> TO <ls_field>. <ls_field> = <ls_intern>-value. AT END OF row. APPEND INITIAL LINE TO gt_pod ASSIGNING <ls_pod>. MOVE-CORRESPONDING <ls_pod_xls> TO <ls_pod>.
* <ls_pod>-changd_by = sy-uname.
* <ls_pod>-chang_date = sy-datum.
* <ls_pod>-changd_at = sy-uzeit. ENDAT. <gt_data>[] = gt_pod[]. ENDLOOP. ENDIF.
ENDFORM.

Routine for folder selection of downloadµ

*--- Local internal tables --------------------------------------------* DATA: lt_dynp_values TYPE TABLE OF dynpread, lt_fields TYPE dynpread_tabtype, lt_files TYPE filetable. *--- Local stuctures --------------------------------------------------* DATA: ls_field LIKE LINE OF lt_fields. *--- Local variables --------------------------------------------------* DATA: lv_repid TYPE syrepid. ************************************************************************
* Programming *
************************************************************************ lv_repid = sy-repid. CALL FUNCTION 'DYNP_VALUES_READ' EXPORTING dyname = lv_repid dynumb = '1000' request = 'A' TABLES dynpfields = lt_fields EXCEPTIONS invalid_abapworkarea = 01 invalid_dynprofield = 02 invalid_dynproname = 03 invalid_dynpronummer = 04 invalid_request = 05 no_fielddescription = 06 undefind_error = 07. IF sy-subrc = 0. READ TABLE lt_fields INTO ls_field WITH KEY fieldname = 'P_FILE'. IF sy-subrc = 0. p_upfile = ls_field-fieldvalue. cl_gui_frontend_services=>file_open_dialog( EXPORTING default_filename = p_upfile file_filter = zcl_excel_common=>c_xlsx_file_filter CHANGING file_table = lt_files rc = sy-tabix EXCEPTIONS OTHERS = 1 ). IF sy-subrc = 0. READ TABLE lt_files INDEX 1 INTO p_upfile. IF sy-subrc <> 0. CLEAR : p_upfile. ENDIF. ENDIF. ENDIF. ENDIF. ENDFORM.

Please the structure matching the upload template

Structure%20for%20upload%20template

Structure for upload template

Download does not complete our job, We have to upload the same in the new system. Let’s continue in Part 2.

Hope this blog is informative.

Cheers,

Vivek