SAP GOS Objects Migration -Download/Upload

Introduction

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 Services

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

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 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 for upload template

Download does not complete our job, We have to upload the same in the new system.

This is like the reverse process of the downloading GOS attachments.

Flow is as below.

  1. Choose the file from the desktop and this can be done by some standard class methods or FM TMP_GUI_DIRECTORY_LIST_FILES
  2. Upload the file using the FM SO_OBJECT_UPLOAD and you will be getting the content
  3. Create the Folder ID using the FM SO_OBJECT_UPLOAD
  4. Use the Function Module SO_OBJECT_INSERT to insert the object in the repository
  5. Now connect the object to the Document by creating a relationship using the function module BINARY_RELATION_CREATE_COMMIT

If you are looking for creating a log table on the files that are being uploaded using the program, it is pretty simple and you can add the same.

Code as follows

REPORT zbc_gos_attch_upload.

DATA: lt_file_table TYPE filetable,
      lv_dir        TYPE salfile-longname,
      lt_file       TYPE TABLE OF  sdokpath,
      lv_file_count TYPE i,
      lt_dir        TYPE TABLE OF  sdokpath.
DATA: lt_goslog TYPE TABLE OF zgos_log,
      ls_goslog TYPE zgos_log.

DATA: lv_rc          TYPE i,
      lv_action      TYPE i,
      lv_len         TYPE so_doc_len,
      lt_content     TYPE soli_tab,
      ls_fol_id      TYPE soodk,
      ls_obj_id      TYPE soodk,
      ls_obj_data    TYPE sood1,
      lt_objhead     TYPE STANDARD TABLE OF soli,
      lv_ext         TYPE string,
      lv_fname       TYPE string,
      lv_path        TYPE string,
      lv_path1       TYPE string,
      lv_filename    TYPE string,
      ls_note        TYPE borident,
      lv_ep_note     TYPE borident-objkey,
      ls_object      TYPE borident,
      lo_objhead     TYPE REF TO cl_bcs_objhead,
      lv_object_type TYPE soodk-objtp,
      lv_put_to_kpro TYPE sonv-flag,
      i_objectno     TYPE string,
      i_otype        TYPE string,
      lv_filetype    TYPE rlgrap-filetype.
*********************************************************************************************************
***Selection of upload folder
*********************************************************************************************************
SELECTION-SCREEN: BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-000.
  SELECTION-SCREEN COMMENT 1(30) TEXT-003 FOR FIELD p_path.
  PARAMETERS      : p_path TYPE string LOWER CASE OBLIGATORY.
SELECTION-SCREEN: END   OF BLOCK b1.
*SELECTION-SCREEN: BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-001.
* SELECTION-SCREEN COMMENT 1(30) TEXT-004 FOR FIELD p_file.
*    PARAMETERS: p_file  TYPE string LOWER CASE OBLIGATORY.
*    PARAMETERS: p_otype TYPE char24 DEFAULT 'BKPF'.
*SELECTION-SCREEN: END   OF BLOCK b2.
************************************************************************
* 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         = 'Select the Folder to upload the files'
    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
************************************************************************
START-OF-SELECTION.
DATA: lv_root_dir TYPE salfile-longname.
lv_root_dir = p_path.
  DATA(lv_dir1) = 'C:\Users\VS0005\Desktop\GOS Upload'.
  CALL FUNCTION 'TMP_GUI_DIRECTORY_LIST_FILES'
    EXPORTING
      directory  = lv_root_dir
      filter     = '*.*'
    IMPORTING
      file_count = lv_file_count
*     DIR_COUNT  =
    TABLES
      file_table = lt_file_table
      dir_table  = lt_dir
    EXCEPTIONS
      cntl_error = 1
      OTHERS     = 2.
  IF sy-subrc <> 0.
  ENDIF.
  IF lt_dir IS NOT INITIAL. "Root 1
*Reading of files for each object folder
    LOOP AT lt_dir INTO DATA(ls_dir).
*lv_dir = 'C:\Users\VS0005\Desktop\GOD Testing\1000\660\0048115569'.
*lv_dir = 'C:\Users\VS0005\Desktop\GOD Testing\1000\660\0048115569'.
*CONCATENATE lv_path '\' lv_file INTO lv_dir..
      DATA: lv_fold TYPE salfile-longname.
      CONCATENATE p_path '\' ls_dir-pathname into lv_fold.
      CALL FUNCTION 'TMP_GUI_DIRECTORY_LIST_FILES'
        EXPORTING
          directory  = lv_fold  "ls_dir-pathname
          filter     = '*.*'
        IMPORTING
          file_count = lv_file_count
*         DIR_COUNT  =
        TABLES
          file_table = lt_file_table
          dir_table  = lt_dir
        EXCEPTIONS
          cntl_error = 1
          OTHERS     = 2.
      IF sy-subrc <> 0.
* Implement suitable error handling here
      ENDIF.
*   Logic to add to multiple attachments
      IF lt_file_table IS NOT INITIAL.
        CLEAR: i_objectno,i_otype.
        SPLIT ls_dir-pathname AT '_' INTO i_objectno i_otype.
        LOOP AT lt_file_table ASSIGNING FIELD-SYMBOL(<lfs_file>).
          CLEAR: lv_path, lv_filename, lv_fname, lv_ext, lv_len, lt_content, ls_fol_id,
               ls_obj_data, ls_obj_id, ls_note, lo_objhead, lv_object_type,lv_put_to_kpro,
               lv_filetype, lt_objhead .
          CONCATENATE lv_fold '\' <lfs_file>-filename into lv_path.
          BREAK-POINT.

          TRY .
*         method to split directory and filename
              cl_bcs_utilities=>split_path( EXPORTING iv_path = lv_path IMPORTING ev_path = lv_path1 ev_name = lv_filename ).
*         method to split filename to name & extension
              cl_bcs_utilities=>split_name( EXPORTING iv_name = lv_filename IMPORTING ev_name = lv_fname ev_extension = lv_ext ).
            CATCH cx_bcs.
              CLEAR: lv_path,lv_path1,lv_filename, lv_fname, lv_ext.
          ENDTRY.
          IF lv_path IS NOT INITIAL.
            CALL FUNCTION 'SO_OBJECT_UPLOAD'
              EXPORTING
                filetype                = lv_filetype
                path_and_file           = lv_path
                no_dialog               = 'X'
              IMPORTING
                filelength              = lv_len
                act_filetype            = lv_filetype
                act_objtype             = lv_object_type
                file_put_to_kpro        = lv_put_to_kpro
              TABLES
                objcont                 = lt_content
              EXCEPTIONS
                file_read_error         = 1
                invalid_type            = 2
                x_error                 = 3
                object_type_not_allowed = 4
                kpro_insert_error       = 5
                file_to_large           = 6
                OTHERS                  = 7.
            ##NEEDED
            IF sy-subrc <> 0.
*         Implement suitable error handling here
            ENDIF.
            lo_objhead = cl_bcs_objhead=>create( lt_objhead[] ).
            lo_objhead->set_filename( lv_filename ).
            lo_objhead->set_format( lv_filetype ).
            lo_objhead->set_vsi_profile( cl_bcs_vsi_profile=>get_profile( ) ).
            lt_objhead[] = lo_objhead->mt_objhead.

*       get the folder id where to add attachment for the BO
            ##FM_SUBRC_OK
            CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
              EXPORTING
                region    = 'B'
              IMPORTING
                folder_id = ls_fol_id
              EXCEPTIONS
                OTHERS    = 1.
            ##NEEDED
            IF sy-subrc <> 0.

            ENDIF.
            ls_obj_data-objdes   = lv_fname.
            ls_obj_data-file_ext = lv_object_type.
            ls_obj_data-objlen   = lv_len.
            IF NOT lv_put_to_kpro IS INITIAL.
              ls_obj_data-extct = 'K'.
            ENDIF.

*       add the attachment data to the folder
            ##FM_SUBRC_OK
            CALL FUNCTION 'SO_OBJECT_INSERT'
              EXPORTING
                folder_id             = ls_fol_id
                object_type           = 'EXT'
                object_hd_change      = ls_obj_data
              IMPORTING
                object_id             = ls_obj_id
              TABLES
                objhead               = lt_objhead
                objcont               = lt_content
              EXCEPTIONS
                active_user_not_exist = 35
                folder_not_exist      = 6
                object_type_not_exist = 17
                owner_not_exist       = 22
                parameter_error       = 23
                OTHERS                = 1000.
            ##NEEDED
            IF sy-subrc <> 0.

            ENDIF.
            ls_object-objkey  = i_objectno. "'1000238392'.
            "gs_lporb-instid.
            ls_object-objtype = i_otype. "'BUS2091'.
            "gs_lporb-typeid.
            ls_note-objtype   = 'MESSAGE'.

            CONCATENATE ls_fol_id-objtp ls_fol_id-objyr ls_fol_id-objno ls_obj_id-objtp ls_obj_id-objyr ls_obj_id-objno INTO ls_note-objkey.

*       link the folder data and BO for attachment in gos
            ##FM_SUBRC_OK
            CALL FUNCTION 'BINARY_RELATION_CREATE_COMMIT'
              EXPORTING
                obj_rolea    = ls_object
                obj_roleb    = ls_note
                relationtype = 'ATTA'
              EXCEPTIONS
                OTHERS       = 1.
            ##NEEDED
            IF sy-subrc <> 0.

            ENDIF.


          ENDIF.
          CLEAR <lfs_file>.
            CLEAR: ls_goslog.
        ls_goslog-busobj = i_otype.
        ls_goslog-cat = 'U'.
        ls_goslog-ddate = sy-datum.
        ls_goslog-dtime = sy-uzeit.
        ls_goslog-filename = lv_fname.
        ls_goslog-filetype = lv_object_type.
        ls_goslog-objectid = i_objectno.
        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.
        ENDLOOP.
      ENDIF.
      clear:ls_dir.
    ENDLOOP.
  ENDIF.
*&---------------------------------------------------------------------*
*& Form f4_p_file
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      <-- P_FILE
*&---------------------------------------------------------------------*
FORM f4_p_file CHANGING p_upfile TYPE string..
*----------------------------------------------------------------------*
* Description:
* -----------
* -
*----------------------------------------------------------------------*

************************************************************************
* Declaration                                                          *
************************************************************************

*--- 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.

In the above program we tried uploading all the document under a folder and folder name is the combinqtion of Document number and the Object Type e.g 100025445565852022-BKPF

This way it is easier to upload lot of files pertaining to a document.