Skip to Content
Author's profile photo Yes SAP Team

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:

  1. SO_OBJECT_UPLOAD
  2. SO_OBJECT_INSERT
  3. 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 drawfilep.

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

   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 sysubrc <> 0.

     CLEAR: cv_full_file_path.     “Indicate error.

     lv_subrc = sysubrc.

     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 drawfilep.    “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_rolebobjtype = ‘MESSAGE’.

* Build Object-key.

   CONCATENATE ls_folder_id

               ls_obj_idobjtp

               ls_obj_idobjyr

               ls_obj_idobjno

         INTO ls_obj_rolebobjkey.

   CONCATENATE iv_belnr iv_gjahr INTO ls_objectobjkey.

   ls_objectobjtype = 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 sysubrc <> 0.

     lv_subrc = sysubrc.

     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 drawfilep.    “Scanned file full-path

   DATA: lv_from_file  TYPE rlgrapfilename,

         lv_drive      TYPE pcfiledrive,

         lv_path       TYPE rlgrapfilename,

         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 sysubrc <> 0.

     lv_subrc = sysubrc.

     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 sysubrc <> 0.

     lv_subrc = sysubrc.

     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_structobject_key,

         lv_return_code    TYPE sysubrc,

         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 = sysubrc.

     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 drawfilep     “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 sysubrc <> 0.

     lv_subrc = sysubrc.

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

   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 drawfilep     “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 rlgrapfiletype,   ” VALUE ‘BIN’,

         lv_filelength        TYPE soxwddoc_length,

         lv_cancelled         TYPE sonvflag,

         lv_act_filetype      TYPE c,

         lv_act_filename      TYPE c,

         lv_act_objtype       TYPE soodkobjtp,

         lv_file_put_to_kpro  TYPE sonvflag,

         lv_complete_filename TYPE rlgrapfilename,

         lv_extension         TYPE rlgrapfilename,

         lv_name              TYPE rlgrapfilename,

         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 sysubrc <> 0.

     lv_subrc = sysubrc.

     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 sysubrc <> 0.

     lv_subrc = sysubrc.

     CONDENSE lv_subrc.

     MESSAGE i002(zmm_invoice_wf) WITH lv_subrc ‘File Details’(007).   “Error #& when calling “&” – please report.

     RETURN.

   ENDIF.

   ls_hd_changeobjpri   = ‘5’.      “Priority: 5 out of 10

   ls_hd_changeobjdes   = lv_name.

   ls_hd_changefile_ext = lv_extension.

   ls_hd_changeobjlen   = lv_filelength.

   ls_hd_changeextct    = ‘K’.    “lv_file_put_to_kpro.

   CONCATENATE ‘&SO_FILENAME=’ lv_name ‘.’ lv_extension INTO ls_objheadline. “#EC NOTEXT

   APPEND ls_objhead TO ct_objhead.

   CLEAR: ls_objhead.

   CONCATENATE ‘&SO_FORMAT=’ lv_type INTO ls_objheadline.   “#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 drawfilep     “Scanned file full-path

                         CHANGING cs_obj_id           TYPE soodk.

   DATA: lv_type       TYPE rlgrapfiletype,   ” 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                      = syuname

     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 sysubrc <> 0.

     lv_subrc = sysubrc.

     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:

  1. The code behind Form “scan_to_file” is the code we bought, so I didn’t paste it here.
  2. 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.
  3. 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.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Felipe Araujo de Carvalho
      Felipe Araujo de Carvalho

      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