Attaching file to an object in the background
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:
- The user enter t-code MIRO (Enter Incoming Invoice), fills data for new Invoice, and save.
- Than the user enter t-code MIR4 (Display Invoice Document) with the newly created Invoice.
- In the MIR4 PF-STATUS we added button (using Enhancement Points),
which allow the user to scan the Invoice’s hard-copy. - Behind the button there is a code we bought for about 1,000USD from this web-site http://www.minipps.com/default.aspx.
This code activate the user’s scanner, and scan the file to a preconfigured location on her/his PC. - Now, in my code I have to attach the scanned file from that known location.
Basically, I used 3 FMs:
- SO_OBJECT_UPLOAD
- SO_OBJECT_INSERT
- BINARY_RELATION_CREATE_COMMIT
- For whatever unimaginable reason, I can’t attach a file, or even paste the code properly, so forgive for this site’s limitations 😕
- Read the Notes at the end.
This is the FM which is called from the button:
FUNCTION z_invoice_wf_scan_to_sap.
*”———————————————————————-
*”*”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.
And These are the Forms:
*———————————————————————-*
* 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:
- The code behind Form “scan_to_file” is the code we bought, so I didn’t paste it here.
- I had to activate Work-flow after the scanning and attaching, so basically the call to FM “SAP_WAPI_CREATE_EVENT” is not relevant to the issue.
- I used my Z-FM “Z_PC_SPLIT_COMPLETE_FILENAME“, but the original FM (PC_SPLIT_COMPLETE_FILENAME), or any other FM can be used.
I hope this will be useful.
Post any question and I’ll do my best to help.
Enjoy,
Ayal Telem.
Hey Ayal Telem, it worked!
Thanks for sharing it.
Seizing the opportunity, have you tried to attach files in MIRO directly from the spool? Do you know if it is possible?
Thanks in advance,
Felipe Carvalho