Attach Files to SAP Business Documents Using GOS – ABAP

In this article, we will see how to attach files to SAP business documents (objects) using Generic Object Services (GOS). First, we will understand the concept of GOS, then, how to use the GOS toolbox in GUI to attach files. Afterward, we’ll learn to implement an ABAP logic to attach a file interfaced through SAP Process Orchestration (SAP PI/PO) or SAP Cloud Platform Integration (CPI) from an external system. Finally, we will implement a custom ABAP program that can attach any type of file uploaded from your local PC to any SAP object.

If your requirement is to use ArchiveLink to store files, You can refer to the following articles,

Generic Object Services – GOS

Generic Object Services are a collection of common functionalities provided by SAP that business objects can reuse without having to implement ABAP codes. For example, GOS includes functionalities such as attaching a PDF to a document, entering a note, sending a document, starting a workflow, etc. The collection of these common functionalities provided by GOS is bundled together in the GOS toolbox for GUI mode use.

These common functionalities allow developers and SAP consultants to add them to any SAP business object with the minimum development effort.

GOS tool box with functionalities shown in SAP business document GUI
GOS Tool-Box in SAP GUI

In the screenshot above you can see the GOS toolbox and its function buttons displayed for SAP business object “credit memos”. What we will focus on in this article is the “create attachment” function of GOS.


How to Attach Files in GUI Using GOS

When the GOS is activated for an SAP business document type, you will be able to see the GOS toolbox from transactions related to that business object. For example, if GOS has been activated for sales orders, sales order change transaction VA02 and sales order display transaction VA03 will have the GOS toolbox.

Similarly, you can use the GOS toolbox for other business documents, such as Purchase Orders, Purchase Requisitions, Invoices, Accounting Documents, and even master data, such as Business Partner, Material Master, etc.

To attach a document, go to the desired transaction and click on the GOS toolbox, then click on “create” and then on “create attachment“. When a pop up appears, select the file location and click “ok”.

Attach file to a SAP business document in GUI mode using the toolbox
GOS create attachment in GUI mode

To view a list of files or notes attached to the object, use the option “Attachment List” on the toolbox.

GOS toolbox showing the attachment list
Attachment list of an SAP business document

Using GOS in Integration Scenarios

Let us assume a business scenario where Process Orchestration (SAP PI/PO) or Cloud Platform Integration (CPI) extracts files from an external sFTP location and routes them to SAP S4 HANA. In S4 HANA side, an ABAP program then attaches these files to corresponding business documents.

Following are a few examples of this type of integration scenario:

  • Attaching invoice PDF to SAP sales order
  • Attaching a picking list to SAP delivery note
  • Linking digital signature to SAP invoice

SAP middleware fetches the files and encodes them in base64 format. On PI/PO side, you can use a User-Defined Function or a Java Mapping to encode file content to base64. Then the middleware routes the encoded message in base64 to SAP Application Integration Framework (AIF). The base64 format of the content should be decoded and attached to the SAP business document.

scenario to illustrate the external file attachment to SAP business document. Files routed from FTP server to S4 HANA via PI/PO.
External file attachment to SAP document business scenario

File Attachment ABAP Program Flow in AIF and S4 HANA

Now we will look at the data processing logic in SAP S4 HANA and AIF. That is, how to design and implement the ABAP code necessary to process the base64-encoded file and attach it to the SAP object.

ABAP program logic to attach a file to a SAP business document. processing logic in ABAP.
ABAP program logic to attach an interfaced file to an SAP document

Use the following FMs in the given sequence to convert the base64-encoded content and attach the file to the SAP object

  1. The first step of the processing is to decode the base64 format to XString format. XString is a predefined ABAP internal data type that represents the file content in a byte format. We can use the FM SCMS_BASE64_DECODE_STR for this purpose.
  2. The second step is to convert the XString format of the file to BIN format. FM SCMS_XSTRING_TO_BINARY allows us to convert XString format to BIN format.
  3. The third step is to convert the BIN format to SO uni-code format using FM SO_CONVERT_CONTENTS_BIN.
  4. The forth step of the logic is to create the address where your file is saved. For this we will use FM SO_FOLDER_ROOT_ID_GET.
  5. Next step is to insert the file content to the address (folder ID) created in the previous step. Use the FM SO_OBJECT_INSERT for this purpose.
  6. Finally, call the FM BINARY_RELATION_CREATE_COMMIT to link the file attached with the SAP business object/document.
ABAP FMs to use to attach a file to SAP document in SAP S4 HANA.
FM flow of the ABAP logic in S4 HANA

Custom ABAP Program to Attach Files to SAP Documents

I was able to write a custom ABAP that showcases how to use some of the FMs I have described in the previous chapter. The purpose of the ABAP program is to attach any type of file uploaded from the local PC to an SAP business document, such as Sales Order, Delivery, Invoice, Account Document, etc.

You can specify the SAP document you would like to attach the file to using two selection parameters:

  • Business Object Type – This corresponds to the SAP business object type. For example, BKPF for accounting documents, VBRK for invoices, VBAK for sales orders, LIKP for deliveries.
  • Document number – The SAP business object document number.

SAP business object type and corresponding document number should match in order for the program to work as expected.

selection screen of the ABAP program designed to attach a file uploaded from PC to SAP business document.
Selection screen of the custom ABAP program – attach a file

ABAP Code to Upload and Attach Files

Main Program

*&---------------------------------------------------------------------*
*& Report ZATTACH_FILE
*&---------------------------------------------------------------------*
*& Author: Isuru Fernando - SAPIntegrationHub.com
*&---------------------------------------------------------------------*
REPORT zattach_file.

DATA: gt_file_table TYPE filetable,   "Uploaded file information
      gt_content    TYPE soli_tab,    "Uploaded files content
      gs_fol_id     TYPE soodk,       "Folder ID
      gs_obj_id     TYPE soodk.       "Object ID

DATA: gv_ext   TYPE sood1-file_ext,   "File extension
      gv_fname TYPE sood1-objdes.     "File name

INCLUDE zattach_file_forms.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.

PARAMETERS: p_path  TYPE string OBLIGATORY.                    "File path

SELECTION-SCREEN END OF BLOCK b1.

SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-002.

PARAMETERS: p_botype TYPE tojtb-name OBLIGATORY DEFAULT 'VBRK', "Business object type
            p_doc_no TYPE vbeln OBLIGATORY.                     "Business document number

SELECTION-SCREEN END OF BLOCK b2.


INITIALIZATION.


AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_path.

  PERFORM open_file_dialog USING p_path.            "Open file upload dialog box


START-OF-SELECTION.

  PERFORM upload_file USING p_path.                  "Upload file

  PERFORM convert_to_bin.                            "Convert file content to BIN

  PERFORM get_folder_root_id.                        "Get folder ID

  PERFORM split_file_path USING p_path.              "Find file extension and file name

  PERFORM sap_office_object USING p_doc_no.          "Create SAP office object

  PERFORM create_binary_relation USING p_doc_no p_botype. "Link office object and doucment

Include

*&---------------------------------------------------------------------*
*& Include          ZATTACH_FILE_FORMS
*&---------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*& Form OPEN_FILE_DIALOG
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM open_file_dialog USING p_path.

  DATA: ls_file_table LIKE LINE OF gt_file_table,
        lv_rc         TYPE i.

  CLEAR p_path.
  REFRESH: gt_file_table.
  CALL METHOD cl_gui_frontend_services=>file_open_dialog
    EXPORTING
      window_title     = 'Select File'
      default_filename = '*.pdf'
      multiselection   = 'X'
    CHANGING
      file_table       = gt_file_table
      rc               = lv_rc.

  READ TABLE gt_file_table INDEX 1 INTO ls_file_table.
  p_path = ls_file_table-filename.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form UPLOAD_FILE
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM upload_file USING p_path.

  DATA:    lv_len TYPE i.

  CALL FUNCTION 'GUI_UPLOAD'
    EXPORTING
      filename   = p_path
      filetype   = 'BIN'
    IMPORTING
      filelength = lv_len
    TABLES
      data_tab   = gt_content.

  PERFORM exception.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form CONVERT_TO_BIN
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM convert_to_bin .

  CALL FUNCTION 'SO_CONVERT_CONTENTS_BIN'
    EXPORTING
      it_contents_bin = gt_content[]
    IMPORTING
      et_contents_bin = gt_content[].

  PERFORM exception.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form GET_FOLDER_ROOT_ID
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM get_folder_root_id .

  CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
    EXPORTING
      region    = 'B'
    IMPORTING
      folder_id = gs_fol_id
    EXCEPTIONS
      OTHERS    = 1.

  PERFORM exception.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form SAP_OFFICE_OBJECT
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM sap_office_object USING p_vbeln.

  DATA:
    ls_obj_data TYPE sood1,
    lt_objhead  TYPE STANDARD TABLE OF soli.


  ls_obj_data-objsns   = 'O'.
  ls_obj_data-objla    = sy-langu.
  ls_obj_data-objdes   = gv_fname.
  ls_obj_data-file_ext = gv_ext.
  ls_obj_data-objlen   = lines( gt_content ) * 255.
  CONDENSE ls_obj_data-objlen.

  CALL FUNCTION 'SO_OBJECT_INSERT'
    EXPORTING
      folder_id             = gs_fol_id
      object_type           = 'EXT'
      object_hd_change      = ls_obj_data
    IMPORTING
      object_id             = gs_obj_id
    TABLES
      objhead               = lt_objhead
      objcont               = gt_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.

  PERFORM exception.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form CREATE_BINARY_RELATION
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM create_binary_relation USING p_vbeln p_botype.

  DATA:
    ls_folmem_k TYPE sofmk,
    ls_note     TYPE borident,
    lv_ep_note  TYPE borident-objkey,
    ls_object   TYPE borident.

  ls_object-objkey = p_vbeln.
  ls_object-objtype = p_botype.
  ls_note-objtype   = 'MESSAGE'.

  CONCATENATE gs_fol_id-objtp gs_fol_id-objyr gs_fol_id-objno gs_obj_id-objtp gs_obj_id-objyr gs_obj_id-objno INTO ls_note-objkey.

  CALL FUNCTION 'BINARY_RELATION_CREATE_COMMIT'
    EXPORTING
      obj_rolea    = ls_object
      obj_roleb    = ls_note
      relationtype = 'ATTA'
    EXCEPTIONS
      OTHERS       = 1.

  PERFORM exception.

ENDFORM.

*&---------------------------------------------------------------------*
*& Form SPLIT_FILE_PATH
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*&      --> P_PATH
*&      --> P_EXT
*&      --> P_FNAME
*&---------------------------------------------------------------------*
FORM split_file_path  USING    p_path.

  DATA: lv_filename TYPE pcfile-path.

  CHECK p_path IS NOT INITIAL.

  lv_filename = p_path.

  CALL FUNCTION 'PC_SPLIT_COMPLETE_FILENAME'
    EXPORTING
      complete_filename = lv_filename
*     CHECK_DOS_FORMAT  =
    IMPORTING
*     DRIVE             =
      extension         = gv_ext
*     NAME              =
      name_with_ext     = gv_fname
*     PATH              =
    EXCEPTIONS
      invalid_drive     = 1
      invalid_extension = 2
      invalid_name      = 3
      invalid_path      = 4
      OTHERS            = 5.

  PERFORM exception.

ENDFORM.
*&---------------------------------------------------------------------*
*& Form EXCEPTION
*&---------------------------------------------------------------------*
*& text
*&---------------------------------------------------------------------*
*& -->  p1        text
*& <--  p2        text
*&---------------------------------------------------------------------*
FORM exception .
  IF sy-subrc <> 0.
    MESSAGE ID     sy-msgid
          TYPE   sy-msgty
          NUMBER sy-msgno
          WITH   sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.

To summarize, we talked about the concept of GOS and GOS functionality in GUI mode in the first chapters. Next, we discussed how to design an ABAP logic that can process and attach files transferred via an interface. Then we looked at the FMs needed to decode base64 format and attach files to a business document. Finally, we implemented an ABAP program that can upload files from local PC and attach them to SAP business documents.

If you have any questions or comments, please post them below.

7 thoughts on “Attach Files to SAP Business Documents Using GOS – ABAP

  1. vipin saraika says:

    ABAP program logic to attach an interfaced file to an SAP document
    I have followed all the 6 steps to receive the XML payload from SuccessFactors and store it in SAP HR, requirement is to receive a JPG photo in decoded base64 format via CPI as XML payload and then store this employee photo in business object ‘PREL’.
    I have followed all the 6 steps mentioned by you for interfacing the document and tried running I don’t get any error in any of the function modules but the photo is also not saving in the business objet PREL can please someone help?

    • PallaviG says:

      I had similar issue when I tried above code, problem seems to be when the objkey is complete.
      Here the example was for SD invoice, VBRK unique key is document number.
      Though in my case, the value of object key was Document number+Document year. When passed, the program worked as expected.
      FM BINARY_RELATION_CREATE_COMMIT, Exporting param obj_rolea-objkey should be complete key. Try this,

  2. yoshit says:

    Hi Isuru,

    The attachment doesn’t work when trying the BKPF version of the code,
    However, the error message doesn’t give any feedback at all to point out what’s wrong.

    I think I’m using the wrong object type or key, but i have no way of identifying the error without an error message to start with.

    can ask if there is something you can add to put me into the right direction?

  3. Yoshi says:

    Hi Isuru,

    Thanks for this, it save me tons of hours for research, trial and error.
    but I just need to confirm, this only works for S4 right?

    My test program in R3 isnt attaching anything while the one in the S4 system doing ok.

  4. FABIAN ALVAREZ says:

    I have to attach a PDF to a PURCHASE ORDER.
    It does not work.
    Does not throw errors or exceptions.
    How do I create the Obj_id.

    will that?

  5. Daniel says:

    Hola, sabes que he implementado tu codigo funciona bien , pero cuando intento subir un archivo excel lo sube con caracteres extraños , es como si faltara algina codificacion, tienes alguna idea que pueda probar?

Leave a Reply

Your email address will not be published. Required fields are marked *