Usually, when talking about attachments, we are thinking of someone who have to choose the file he want to attach,
and for this there are numerous posts.
I want to talk about a scenario where I know where the file is and I want to attach it to the object without user input.
Specific, the scenario I was facing was like this:
Basically, I used 3 FMs:
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(IV_BELNR) TYPE RE_BELNR
*" VALUE(IV_GJAHR) TYPE GJAHR
*" REFERENCE(IV_OBJTYPE) TYPE SWO_OBJTYP
*"----------------------------------------------------------------------
DATA: lv_full_file_path TYPE draw-filep.
PERFORM scan_to_file
USING iv_belnr
CHANGING lv_full_file_path.
CHECK lv_full_file_path IS NOT INITIAL.
PERFORM check_file_exist
CHANGING lv_full_file_path.
CHECK lv_full_file_path IS NOT INITIAL.
PERFORM attach_file
USING iv_belnr
iv_gjahr
iv_objtype
lv_full_file_path.
PERFORM delete_folder
USING lv_full_file_path.
PERFORM initiate_wf_event
USING iv_belnr
iv_gjahr.
ENDFUNCTION.
*----------------------------------------------------------------------*
* Form Check_File_Exist
*
* This function will if the scanned file exist.
* There is no way to tell if the user canceled the scanning from
* the results of the FMs and Methods under "Scan_File" form,
* so the only way to tell is check if the file exist.
*----------------------------------------------------------------------*
FORM check_file_exist
CHANGING cv_full_file_path TYPE draw-filep.
DATA: lv_file TYPE string,
lv_result TYPE abap_bool,
lv_subrc TYPE string.
* Convert to Method type.
lv_file = cv_full_file_path.
CALL METHOD cl_gui_frontend_services=>file_exist
EXPORTING
file = lv_file
RECEIVING
result = lv_result "X=file exist
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
wrong_parameter = 3
not_supported_by_gui = 4
OTHERS = 5.
* Error searching file.
IF sy-subrc <> 0.
CLEAR: cv_full_file_path. "Indicate error.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Checking File'(010). "Error #& when calling "&" - please report.
ENDIF.
* File does not exist.
IF lv_result <> 'X'.
CLEAR: cv_full_file_path.
MESSAGE i004(zmm_invoice_wf). "No documents scanned.
ENDIF.
ENDFORM. "Check_File_Exist
*----------------------------------------------------------------------*
* Form Attach_File
*
* This function will attach the scanned Invoice to the Invoice object.
*----------------------------------------------------------------------*
FORM attach_file
USING iv_belnr TYPE re_belnr "Ivoice number
iv_gjahr TYPE gjahr "Invoice year
iv_objtype TYPE swo_objtyp "Object type (BUS...)
iv_full_file_path TYPE draw-filep. "Scanned file full-path
DATA: lt_objcont TYPE STANDARD TABLE OF soli,
ls_folder_id TYPE sofdk,
ls_obj_id TYPE soodk,
ls_object TYPE borident,
ls_obj_roleb TYPE borident,
lt_objhead TYPE soli_tab,
ls_hd_change TYPE sood1.
DATA: lv_subrc TYPE string.
* Write UI message.
zcl_messages=>display_message( 'Attaching Invoice...' ). "#EC NOTEXT
PERFORM prepare_before_object_insert
USING iv_full_file_path
CHANGING ls_folder_id
lt_objcont.
PERFORM call_so_object_upload
USING ls_folder_id
iv_full_file_path
CHANGING lt_objcont
lt_objhead
ls_hd_change
ls_obj_id.
PERFORM call_so_object_insert
USING ls_folder_id
lt_objcont
lt_objhead
ls_hd_change
iv_full_file_path
CHANGING ls_obj_id.
ls_obj_roleb-objtype = 'MESSAGE'.
* Build Object-key.
CONCATENATE ls_folder_id
ls_obj_id-objtp
ls_obj_id-objyr
ls_obj_id-objno
INTO ls_obj_roleb-objkey.
CONCATENATE iv_belnr iv_gjahr INTO ls_object-objkey.
ls_object-objtype = iv_objtype.
CALL FUNCTION 'BINARY_RELATION_CREATE_COMMIT'
EXPORTING
obj_rolea = ls_object
obj_roleb = ls_obj_roleb
relationtype = 'ATTA'
EXCEPTIONS
no_model = 1
internal_error = 2
unknown = 3
error_message = 4
OTHERS = 5.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Attach Object'(005). "Error #& when calling "&" - please
ENDIF.
ENDFORM. "Attach_File
*----------------------------------------------------------------------*
* Form Delete_Folder
*
* This function will delete the folder that was created for the scanned
* file so to avoid filling up users drive quota.
*----------------------------------------------------------------------*
FORM delete_folder
USING iv_full_file_path TYPE draw-filep. "Scanned file full-path
DATA: lv_from_file TYPE rlgrap-filename,
lv_drive TYPE pcfile-drive,
lv_path TYPE rlgrap-filename,
lv_path_str TYPE string,
lv_file_str TYPE string,
lv_cmd_param TYPE string,
lv_rc TYPE i,
lv_subrc TYPE string.
* Convert to FM type.
lv_from_file = iv_full_file_path.
CALL FUNCTION 'Z_PC_SPLIT_COMPLETE_FILENAME'
EXPORTING
complete_filename = lv_from_file
path_separator = '\'
IMPORTING
drive = lv_drive
path = lv_path
EXCEPTIONS
invalid_drive = 1
invalid_extension = 2
invalid_name = 3
invalid_path = 4
separator_not_specified = 5
OTHERS = 6.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Find Folder'(008). "Error #& when calling "&" - please report.
RETURN.
ENDIF.
* Create Folder path.
CONCATENATE lv_drive ':' lv_path INTO lv_path_str.
* Create "RMDIR" command string.
CONCATENATE '"' lv_path_str '"' INTO lv_path_str. "Full path with quotes
CONCATENATE 'rmdir /q /s' lv_path_str INTO lv_cmd_param SEPARATED BY ' '. "RMDIR command with spaces
CONCATENATE '/C' '"' lv_cmd_param '"' INTO lv_cmd_param SEPARATED BY ' '.
CALL METHOD cl_gui_frontend_services=>execute
EXPORTING
application = 'cmd'
parameter = lv_cmd_param
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
bad_parameter = 3
file_not_found = 4
path_not_found = 5
file_extension_unknown = 6
error_execute_failed = 7
synchronous_failed = 8
not_supported_by_gui = 9
OTHERS = 10.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Delete Folder'(011). "Error #& when calling "&" - please report.
ENDIF.
ENDFORM. "Delete_Folder
*----------------------------------------------------------------------*
* Form Initiate_WF_Event
*
* This function will initiate a Work-flow event.
*----------------------------------------------------------------------*
FORM initiate_wf_event
USING iv_belnr TYPE re_belnr "Ivoice number
iv_gjahr TYPE gjahr. "Invoice year
DATA: lv_object_key TYPE swr_struct-object_key,
lv_return_code TYPE sy-subrc,
lv_subrc TYPE string.
* Build Object-key.
CONCATENATE iv_belnr iv_gjahr INTO lv_object_key.
CALL FUNCTION 'SAP_WAPI_CREATE_EVENT'
EXPORTING
object_type = 'BUS2081'
object_key = lv_object_key
event = 'startapproval'
commit_work = 'X'
IMPORTING
return_code = lv_return_code.
IF lv_return_code IS NOT INITIAL.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Initiate WF'(012). "Error #& when calling "&" - please report.
ENDIF.
ENDFORM. "initiate_wf_event
*----------------------------------------------------------------------*
* Form Prepare_Before_Object_Insert
*
* This function will prepare data before calling "SO_OBJECT_INSERT".
*----------------------------------------------------------------------*
FORM prepare_before_object_insert
USING iv_full_file_path TYPE draw-filep "Scanned file full-path
CHANGING cs_folder_id TYPE sofdk
ct_objcont TYPE soli_tab.
DATA: ls_objcont TYPE soli.
DATA: lv_subrc TYPE string.
* Get Folder properties.
CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
EXPORTING
region = 'B'
IMPORTING
folder_id = cs_folder_id
EXCEPTIONS
OTHERS = 0.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Folder ID'(003). "Error #& when calling "&" - please report.
RETURN.
ENDIF.
CONCATENATE '&KEY&' iv_full_file_path INTO ls_objcont-line.
APPEND ls_objcont TO ct_objcont.
ENDFORM. "Prepare_Before_Object_Insert
*----------------------------------------------------------------------*
* Form Call_SO_OBJECT_UPLOAD
*
* This function will call FM "SO_OBJECT_INSERT".
*----------------------------------------------------------------------*
FORM call_so_object_upload
USING is_folder_id TYPE sofdk
iv_full_file_path TYPE draw-filep "Scanned file full-path
CHANGING ct_objcont TYPE soli_tab
ct_objhead TYPE soli_tab
ls_hd_change TYPE sood1
cs_obj_id TYPE soodk.
DATA: ls_objhead TYPE soli,
lt_objcont TYPE STANDARD TABLE OF soli.
DATA: lv_type TYPE rlgrap-filetype, " VALUE 'BIN',
lv_filelength TYPE soxwd-doc_length,
lv_cancelled TYPE sonv-flag,
lv_act_filetype TYPE c,
lv_act_filename TYPE c,
lv_act_objtype TYPE soodk-objtp,
lv_file_put_to_kpro TYPE sonv-flag,
lv_complete_filename TYPE rlgrap-filename,
lv_extension TYPE rlgrap-filename,
lv_name TYPE rlgrap-filename,
lv_subrc TYPE string.
CALL FUNCTION 'SO_OBJECT_UPLOAD'
EXPORTING
filetype = lv_type
path_and_file = iv_full_file_path
no_dialog = 'X'
IMPORTING
filelength = lv_filelength
f_cancelled = lv_cancelled
act_filetype = lv_type
act_filename = lv_act_filename
act_objtype = lv_act_objtype
file_put_to_kpro = lv_file_put_to_kpro
TABLES
objcont = ct_objcont
EXCEPTIONS
file_read_error = 1
invalid_type = 2
x_error = 3
object_type_not_allowed = 4
kpro_insert_error = 5
error_message = 6
OTHERS = 7.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Object Upload'(006). "Error #& when calling "&" - please report.
RETURN.
ENDIF.
* Convert to FM compatible.
lv_complete_filename = iv_full_file_path.
CALL FUNCTION 'Z_PC_SPLIT_COMPLETE_FILENAME'
EXPORTING
complete_filename = lv_complete_filename
IMPORTING
extension = lv_extension
name = lv_name
EXCEPTIONS
invalid_drive = 1
invalid_extension = 2
invalid_name = 3
invalid_path = 4
separator_not_specified = 5
OTHERS = 6.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'File Details'(007). "Error #& when calling "&" - please report.
RETURN.
ENDIF.
ls_hd_change-objpri = '5'. "Priority: 5 out of 10
ls_hd_change-objdes = lv_name.
ls_hd_change-file_ext = lv_extension.
ls_hd_change-objlen = lv_filelength.
ls_hd_change-extct = 'K'. "lv_file_put_to_kpro.
CONCATENATE '&SO_FILENAME=' lv_name '.' lv_extension INTO ls_objhead-line. "#EC NOTEXT
APPEND ls_objhead TO ct_objhead.
CLEAR: ls_objhead.
CONCATENATE '&SO_FORMAT=' lv_type INTO ls_objhead-line. "#EC NOTEXT
APPEND ls_objhead TO ct_objhead.
ENDFORM. "Call_SO_OBJECT_UPLOAD
*----------------------------------------------------------------------*
* Form Call_SO_OBJECT_INSERT
*
* This function will call FM "SO_OBJECT_INSERT".
*----------------------------------------------------------------------*
FORM call_so_object_insert
USING is_folder_id TYPE sofdk
it_objcont TYPE soli_tab
it_objhead TYPE soli_tab
is_hd_change TYPE sood1
iv_full_file_path TYPE draw-filep "Scanned file full-path
CHANGING cs_obj_id TYPE soodk.
DATA: lv_type TYPE rlgrap-filetype, " VALUE 'BIN',
lv_subrc TYPE string.
CALL FUNCTION 'SO_OBJECT_INSERT'
EXPORTING
folder_id = is_folder_id
object_type = 'EXT'
object_hd_change = is_hd_change
owner = sy-uname
IMPORTING
object_id = cs_obj_id
TABLES
objcont = it_objcont
objhead = it_objhead
EXCEPTIONS
active_user_not_exist = 1
communication_failure = 2
component_not_available = 3
dl_name_exist = 4
folder_not_exist = 5
folder_no_authorization = 6
object_type_not_exist = 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
error_message = 15
OTHERS = 16.
IF sy-subrc <> 0.
lv_subrc = sy-subrc.
CONDENSE lv_subrc.
MESSAGE i002(zmm_invoice_wf) WITH lv_subrc 'Object Insert'(004). "Error #& when calling "&" - please report.
RETURN.
ENDIF.
ENDFORM. "Call_SO_OBJECT_INSERT
Note:
I hope this will be useful.
Post any question and I'll do my best to help.
Enjoy,
Ayal Telem.