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.
We can get the above information functionally and once we get the above information go to table SRGBTBREL
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.
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.
- 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.
- Using the INSTID B, call the function module SO_OBJECT_READ
- 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
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.
- Choose the file from the desktop and this can be done by some standard class methods or FM TMP_GUI_DIRECTORY_LIST_FILES
- Upload the file using the FM SO_OBJECT_UPLOAD and you will be getting the content
- Create the Folder ID using the FM SO_OBJECT_UPLOAD
- Use the Function Module SO_OBJECT_INSERT to insert the object in the repository
- 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.