Skip to Content
Technical Articles
Author's profile photo K L S Srilekha K1712

Read GOS Attachment from business object and convert to xstring and Viceversa

INTRODUCTION:

In this blog post, we will learn how to convert a GOS attachment to xstring and vice versa.

What is GOS:

The GOS is a toolbar that provides different functions such as adding an attachment, creating a document link, displaying all the attachments etc. The attachments are not generic for that transaction but are specific for a particular SAP object.

Eg: See the screenshot below to know where is GOS toolbar located. GOS toolbar is highlighted.

Here we are taking ME21N as reference.

 

Part 1: Convert a GOS Attachment to xstring.

Part 2: Attach a document to GOS using xstring.

 

Here we will learn how to deal with 5 different types of attachments .

–>PDF

–>Text

–>Excel

–>Image

–>Word

 

PART – 1: CONVERT A GOS ATTACHMENT TO XSTRING

MAIN PART:

We are going to read the GOS attachments from a purchase requisition and convert it to xstring.

Let’s understand this process from below steps:

  1. Generate relationship records for the attachments of PR.

(Business object type – BUS2105 can be obtained from TCODE: SWO2 )

–> Check below screenshots to know how to get BO type of an SAP object from SWO2 (here we are seeing for PR)

Path:   SWO2 –> Material Management –>  Purchasing –> PurchaseRequisition –>  Passes to –> Req_overall

–>Double click on Req_Overall

–>Go inside any method or event to get BO Type

 

DATA : wa_object       TYPE sibflporb,
int_rel_options TYPE obl_t_relt,
wa_rel_options  TYPE obl_s_relt,
int_links       TYPE obl_t_link,
wa_links        TYPE obl_s_link.

wa_rel_options-low = 'ATTA'. "" Attachemnts
wa_rel_options-sign = 'I'.
wa_rel_options-option = 'EQ'.
APPEND wa_rel_options TO int_rel_options.

wa_object-instid = wa_pr_list-banfn.  (This is the PR number)
wa_object-typeid = 'BUS2105'. "" PR  
wa_object-catid  = 'BO'. "" Business Object
REFRESH int_links[].

TRY.
CALL METHOD cl_binary_relation=>read_links_of_binrels
EXPORTING
is_object           = wa_object          " Start object
it_relation_options = int_rel_options    " Link Types
ip_role             = 'GOSAPPLOBJ'       " Role type
IMPORTING
et_links            = int_links.         " Table with Relationship Records

CATCH cx_obl_parameter_error. " Incorrect Calling of Interface
CATCH cx_obl_internal_error.  " Internal Error of Relationship Service
CATCH cx_obl_model_error.     " Error with Model Roles
ENDTRY.

 

2.  Loop at links table to get the binary content of the attachments

DATA : lv_doc_id       TYPE sofolenti1-doc_id,
       int_cont_bin    TYPE TABLE OF solisti1,
       int_cont_solix    TYPE TABLE OF solix,
       wa_doc_data     TYPE sofolenti1.

LOOP AT int_links INTO wa_links.
lv_doc_id = wa_links-instid_b.

REFRESH int_cont_bin[].
REFRESH int_cont_solix[].

CALL FUNCTION 'SO_DOCUMENT_READ_API1'
EXPORTING
document_id                = lv_doc_id
IMPORTING
document_data              = wa_doc_data
TABLES
contents_hex               = int_cont_solix
object_content             = int_cont_bin
EXCEPTIONS
document_id_not_exist      = 1
operation_no_authorization = 2
x_error                    = 3
OTHERS                     = 4.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.

 

3. To convert binary data to xstring using FM SCMS_BINARY_TO_XSTRING.

–> Check whether int_cont_solix table is filled or not.

NOTE: For text document type ( wa_doc_data-obj_type) doesnt  give you proper document                size, hence multiply lines of int_cont_solix table with 255 to get correct size of text              document. For other document types ( Excel, Word, Image, PDF)  you can consider              value of variable (wa_doc_data-obj_type) as document size.

DATA: lv_lines TYPE char20,
      lv_doc_size     TYPE i,
      lv_xstring      TYPE xstring.

IF int_cont_solix IS NOT INITIAL.
   IF wa_doc_data-obj_type = 'TXT'.
     lv_lines = lines( int_cont_solix ) * 255.
     SHIFT lv_lines LEFT DELETING LEADING ' '.
     lv_doc_size = lv_lines.
   ENDIF.

"" Convert the binary data to Xstring
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lv_doc_size
IMPORTING
buffer       = lv_xstring
TABLES
binary_tab   = int_cont_solix
EXCEPTIONS
failed       = 1
OTHERS       = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.

–> If not convert (int_cont_bin) table to (int_cont_solix) using FM SO_SOLITAB_TO_SOLIXTAB to get document size.

ELSE.
CALL FUNCTION 'SO_SOLITAB_TO_SOLIXTAB'
EXPORTING
ip_solitab  = int_cont_bin
IMPORTING
ep_solixtab = int_cont_solix.
*
IF wa_doc_data-obj_type = 'TXT'.
   lv_lines = lines( int_cont_solix ) * 255.
   SHIFT lv_lines LEFT DELETING LEADING ' '.
   lv_doc_size = lv_lines.
ENDIF.
*
"" Convert the binary data to Xstring
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lv_doc_size
IMPORTING
buffer       = lv_xstring
TABLES
binary_tab   = int_cont_solix
EXCEPTIONS
failed       = 1
OTHERS       = 2.
IF sy-subrc <> 0.
* Implement suitable error handling here
ENDIF.
*
ENDIF.
ENDLOOP.

 

4.CONCLUSION:

The obtained lv_xstring value from FM – SCMS_BINARY_TO_XSTRING is the xstring value of the attachments.

 

PART 2: ATTACH A DOCUMENT TO GOS USING XSTRING

MAIN PART:

We are going to create an attachment using the xstring we have and attach it to any business object (Purchase order in this case)

Let’s understand this process from below steps:

  1. Get the values of xstring from your ztable. ( Here it_attach is our internal table containing values          of xstring.)

DATA lv_extensions TYPE char10.
DATA lv_file TYPE string.

LOOP AT it_attach INTO wa_attach WHERE po_number = wa_item1-po_number AND status IS INITIAL .
SPLIT wa_attach-po_att_name AT '.' INTO lv_file lv_extensions.

CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
EXPORTING
region                = c_b
IMPORTING
folder_id             = wa_fol_id
EXCEPTIONS
communication_failure = 1
owner_not_exist       = 2
system_failure        = 3
x_error               = 4
OTHERS                = 5.

Using FM SCMS_XSTRING_TO_BINARY convert the xstring values from internal table to binary content.

DATA : lv_solix_length TYPE i,
it_content TYPE solix_tab."content OF FILE STORAGE

CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer          = wa_attach-po_att
IMPORTING
output_length   = lv_solix_length
TABLES
binary_tab      = it_content. "binary.

 

2. Now convert the obtained binary content to text using FM  SO_SOLIXTAB_TO_SOLITAB.

DATA: lt_data TYPE soli_tab.

CALL FUNCTION 'SO_SOLIXTAB_TO_SOLITAB'
EXPORTING
ip_solixtab = it_content
IMPORTING
ep_solitab  = lt_data.

 

3. Now we should use a set of function modules to convert this text content into attachment and attach it to GOS.

–> SO_FOLDER_ROOT_ID_GET

Using this FM , you are getting an address of where your file contents will be stored in SAP.

–> SO_OBJECT_INSERT

This FM Stores the file into the folder obtained using FM SO_FOLDER_ROOT_ID_GET.  The content of the file is passed into this FM in a table (lt_data in this case).

The output of this FM will be the object ID of your file.

–> BINARY_RELATION_CREATE_COMMIT

At this point, your file is already stored somewhere in SAP. Now using this FM you will link your object ID to purchase order(PO is used in our example, you can use any business object).

 

DATA: wa_fol_id TYPE soodk,
      wa_object TYPE borident,
      wa_obj_data TYPE sood1, " OBJECT DEF AND CHANGE ATTRIBUTES
      ls_objhead TYPE soli,
      it_objhead TYPE STANDARD TABLE OF soli,
      wa_folmem_k TYPE sofmk, "folder content DATA
      wa_note TYPE borident, " bor OBJECT IDENTIFIER
      wa_object TYPE borident,
      lv_ep_note TYPE borident-objkey."“bor OBJECT KEY

CONSTANTS : c_bus2012 TYPE swo_objtyp VALUE 'BUS2012' ,
            c_atta(4) TYPE c VALUE 'ATTA',
            c_ext(3) TYPE c VALUE 'EXT',
            c_b(1) TYPE c VALUE 'B',
            c_x(1) TYPE c VALUE 'X',
            c_o(1) TYPE c VALUE 'O'.

CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
EXPORTING
region                = c_b
IMPORTING
folder_id             = wa_fol_id
EXCEPTIONS
communication_failure = 1
owner_not_exist       = 2
system_failure        = 3
x_error               = 4
OTHERS                = 5.

“Prepare exporting parameters for FM SO_OBJECT_INSERT

wa_object-objkey  = lv_samref_po. " PO number
wa_object-objtype = c_bus2012.    " bus number
*–
wa_obj_data-objsns   = c_o.     " sensitivity of object (o-standard)
wa_obj_data-objla    = sy-langu. " language
wa_obj_data-objdes   = lv_file. "iv_slug. " slug value – description
wa_obj_data-file_ext = lv_extensions.
wa_obj_data-objlen   = lines( lt_data ) * 255.

TRANSLATE wa_obj_data-file_ext TO UPPER CASE.
*
"DOC & XLS are having encoding issue and resulting in error while opening file. Hence changing to DOCX & XLSX
IF wa_obj_data-file_ext = 'DOC'.
CONCATENATE '&SO_FILENAME=' lv_file '.' 'DOCX' INTO ls_objhead-line.
ELSEIF wa_obj_data-file_ext = 'XLS'.
CONCATENATE '&SO_FILENAME=' lv_file '.' 'XLSX' INTO ls_objhead-line.
ELSE.

CONCATENATE '&SO_FILENAME=' wa_attach-po_att_name INTO ls_objhead-line.
ENDIF.
APPEND ls_objhead TO it_objhead.
*
"For TXT file ASC encoding should be used.

IF wa_obj_data-file_ext = 'TXT'.                                
ls_objhead-line = '&SO_FORMAT=ASC'.
ELSE.
ls_objhead-line = '&SO_FORMAT=BIN'.
ENDIF.

APPEND ls_objhead TO it_objhead.

CALL FUNCTION 'SO_OBJECT_INSERT'
EXPORTING
folder_id                  = wa_fol_id
object_type                = c_ext
object_hd_change           = wa_obj_data
IMPORTING
object_id                  = wa_obj_id
TABLES
objhead                    = it_objhead
objcont                    = lt_data
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
OTHERS                     = 15.

IF sy-subrc = 0 AND wa_object-objkey IS NOT INITIAL.
wa_folmem_k-foltp = wa_fol_id-objtp.
wa_folmem_k-folyr = wa_fol_id-objyr.
wa_folmem_k-folno = wa_fol_id-objno.
*/Please note: wa_fol_id and wa_obj_id are different work areas
wa_folmem_k-doctp = wa_obj_id-objtp.
wa_folmem_k-docyr = wa_obj_id-objyr.
wa_folmem_k-docno = wa_obj_id-objno.
lv_ep_note = wa_folmem_k.
wa_note-objtype = 'MESSAGE'.
wa_note-objkey = lv_ep_note.

CALL FUNCTION 'BINARY_RELATION_CREATE_COMMIT'
EXPORTING
obj_rolea      = wa_object
obj_roleb      = wa_note
relationtype   = c_atta
EXCEPTIONS
no_model       = 1
internal_error = 2
unknown        = 3
OTHERS         = 4.
*
IF sy-subrc EQ 0.
* Commit it
COMMIT WORK.
ENDIF.
ENDLOOP.

 

4. CONCLUSION:

When you open the business transaction, you can find these attachments under the purchase order.

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Sandra Rossi
      Sandra Rossi

      You indicate 5 types of files, but the solution works for all types:

      • "binary" ones: PDF, Excel/Word/etc. files Office Open XML (2007/.xlsx/.docx/etc.), images, ZIP, etc.
      • "text" ones: .txt, .csv or tab-delimited files (often incorrectly named "Excel" format), XML, JSON, etc.

      ("text" format is confusing, everything is binary, "text" just means that the whole file has a character encoding)

      After calling SO_DOCUMENT_READ_API1, you may simplify a lot - not sure if it works in your case but usually it works (NB: converting text to xstring means that you must choose a character encoding, below I chose arbitrarily UTF-8) :

      IF int_cont_solix IS NOT INITIAL.
        " binary file
        lv_xstring = cl_bcs_convert=>solix_to_xstring( IT_SOLIX = int_cont_solix IV_SIZE = wa_doc_data-doc_size ).
      ELSE.
        " text file to UTF-8
        lv_xstring = cl_bcs_convert=>txt_to_xstring( IT_SOLI = int_cont_bin IV_CODEPAGE = '4110'.
      ENDIF.
      

      and for writing the attachment, you could also simplify a lot (not completely sure) by calling SO_DOCUMENT_INSERT_API1, convert the xstring (below wa_attach-po_att) into it_content (solix_tab) and pass it_content to the parameter CONTENTS_HEX + pass xstrlen( wa_attach-po_att) to the parameter DOCUMENT_DATA-DOC_SIZE ; no need to test if the xstring represents binary or text.

      it_content = cl_bcs_convert=>xstring_to_solix( wa_attach-po_att ).

      NB: there are lots of other solutions, as you can see in all the blog posts, github, wiki, questions, etc., on this topic.

      Author's profile photo Santosh Kondepudi
      Santosh Kondepudi

      Thanks for the post, Could you please also let me know how to get the GOS attachment file name for the PR to get the extension so that i can pass the same into table.

       

      Thanks in advance,

      santosh