SAP Attachments Mass Extraction for Sales Documents (ABAP)
SAP4TECH » SAP Attachments Mass Extraction for Sales Documents (ABAP)
ABAP TUTORIALS
SAP Attachments Mass Extraction for Sales Documents (ABAP)
July 13, 2015 John
SAP Attachment: The following ABAP program sample is optimized to Mass extraction of SAP Attachments (GOS) for Sales Documents.
SAP Mass Attachments Extraction using ABAP.
The same ABAP Code can be user to mass extract Attachment for
FI Documents
PM Notifications
MM Material
The original post is SAP GOS Attachment Technical
Table of Contents
SAP Attachment : Miscellaneous Tips
Search Help for Directory Selection
The method cl_gui_frontend_services=>directory_browse offers to select a folder from presentation server ( local ).
The result SELECTED_FOLDER is the full path for a local directory.
Check if a file exists on presentation Server
The method cl_gui_frontend_services=>file_exist checks if a file exists locally ( on presentation server).
The result is initial if the file dosn’t exist.
Jump to the new ABAP Programming, check the following book: Mastering SAP ABAP: A complete guide to developing fast, durable, and maintainable ABAP programs in SAP
SAP Functions Modules Used for SAP Attachment
Here the list of the main SAP Function Modules & Methods used below in order to extract and to download Attachment
cl_gui_frontend_services=>directory_browse
This standard Method cl_gui_frontend_services=>directory_browse will retrieve list of local (desktop) folder.
In the most of cases, it is used to select a folder at presentation server as help search for local Directory Search .
cl_gui_frontend_services=>file_exist
This method cl_gui_frontend_services=>file_exist checks if a file exists already .
SO_OBJECT_DOWNLOAD
SO_OBJECT_DOWNLOAD function module will create a file from internal table in SAP to a given pathname.
ABAP Code for SAP Attachment Mass extraction
Let’s start with the Data declaration we need to Extract Attachment:
The second step is to define the Select Screen
The last step is the extraction of SAP Attachments:
ABAP
Generic export / import GOS attachments of business objects
FollowRSS feedLike
9 Likes 14,843 Views 5 Comments
Sometimes we have to copy legacy data from a SAP system to another one, and some types of data are less easy to copy than some others.
GOS attachments are stored on the SAP system. They can be added/managed from the Generic Object Services (GOS) dropdown menu.
GOS attachments are not so easy to copy. The purpose of this program is to allow the download of attachments from a source SAP sytem into binary files. The selection of attachments is done through the list of Business Objects corresponding to the selection.
Based on the Business Object type (like in transaction SWO1) the program retrieves the corresponding table and proposes a dynamic screen with all fields in this table. The user is able to specify selection parameters for this table.
For each found record in the table, the program checks the list of attachment and for each attachment it creates a binary file. The attributes of the attachment are stored directly into the file name by a concatenation using a special separator.
On the target SAP system, the program allows to upload the files and save them as attachments. The selection is based on the files names, this is a good solution to avoid uploading all files if they are not to be selected. The original file name is extracted from the concatenation.
The program demonstrates several technics:
how to handle dynamic selection based on dynamic criteria
how to upload a list of files from a directory
how to read/save GOS attachments
Here is the code and text elements are below:
REPORT zbc_gos_export_import LINE-SIZE 180.
*&---------------------------------------------------------------------*
*& REPORT ZBC_GOS_EXPORT_IMPORT
*&---------------------------------------------------------------------*
*& Author : François Henrotte
*&
*& Purpose : This program is used to
*& - extract and export selected attachments to local files
*& - import and create attachments from local files
*&---------------------------------------------------------------------*
* System fields for dynamic selection
INCLUDE rsdbcom4.
INCLUDE rsdbc1xx.
INCLUDE rssocons.
***
* Constants
***
CONSTANTS: gc_separator TYPE char4 VALUE '(&&)', "#EC NOTEXT
gc_sep_lengt TYPE i VALUE 4.
CONSTANTS: gc_def_path TYPE text40 VALUE 'C:\temp\', "#EC NOTEXT
gc_def_file TYPE text40 VALUE 'GOS*.*'. "#EC NOTEXT
***
* Types definition
***
TYPES: BEGIN OF ty_attach,
bor_id TYPE sibfboriid,
filen TYPE string,
bdata TYPE solix_tab,
END OF ty_attach,
tt_attach TYPE TABLE OF ty_attach.
***
* Data definition
***
DATA: wt_keyfields TYPE TABLE OF rpyboke,
ws_keyfields TYPE rpyboke,
w_title TYPE sy-title,
w_key TYPE sibfboriid.
DATA: ws_x030l TYPE x030l.
DATA: w_selid TYPE rsdynsel-selid,
wt_tables TYPE TABLE OF rsdstabs,
ws_tables TYPE rsdstabs,
ws_where TYPE rsds_where,
w_active TYPE i,
w_dbcnt TYPE i.
DATA: ws_varidyn TYPE rsvaridyn.
DATA: wt_attach TYPE tt_attach,
ws_attach TYPE ty_attach,
ws_bdata TYPE solix.
DATA: wt_sfile TYPE TABLE OF eps2fili,
ws_sfile TYPE eps2fili,
wt_files TYPE TABLE OF file_info,
ws_files TYPE file_info,
w_path TYPE string,
w_file TYPE string,
w_mess TYPE string,
w_fileid TYPE string,
w_where TYPE string,
w_index TYPE numc2,
w_count TYPE i.
DATA: ob_table TYPE REF TO data.
FIELD-SYMBOLS: <wt_table> TYPE STANDARD TABLE,
<w_field> TYPE any.
***
* Selection screen
***
SELECTION-SCREEN: BEGIN OF BLOCK obj WITH FRAME TITLE text-obj.
PARAMETERS: p_objtyp TYPE swo_objtyp OBLIGATORY.
SELECTION-SCREEN: END OF BLOCK obj.
SELECTION-SCREEN: BEGIN OF BLOCK b01 WITH FRAME TITLE text-b01.
PARAMETERS: p_exp RADIOBUTTON GROUP pro DEFAULT 'X'.
PARAMETERS: p_imp RADIOBUTTON GROUP pro.
SELECTION-SCREEN: SKIP,
BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (30) seltab FOR FIELD p_table,
POSITION 33.
PARAMETERS: p_table TYPE tabname.
SELECTION-SCREEN: PUSHBUTTON 65(4) selopt USER-COMMAND sel,
COMMENT 71(6) selcnt,
END OF LINE.
SELECTION-SCREEN: END OF BLOCK b01.
SELECTION-SCREEN: BEGIN OF BLOCK b03 WITH FRAME TITLE text-b03.
PARAMETERS: p_locl TYPE xflag AS CHECKBOX.
SELECTION-SCREEN: SKIP.
PARAMETERS: p_path TYPE string VISIBLE LENGTH 80 DEFAULT gc_def_path LOWER CASE,
p_file TYPE string VISIBLE LENGTH 80 DEFAULT gc_def_file LOWER CASE.
SELECTION-SCREEN: END OF BLOCK b03.
***
* Initialization
***
INITIALIZATION.
MOVE '@4G@' TO selopt.
MOVE %_p_table_%_app_%-text TO seltab.
IF sy-slset IS NOT INITIAL.
SUPPRESS DIALOG.
ENDIF.
***
* PBO
***
AT SELECTION-SCREEN OUTPUT.
IF w_active IS INITIAL.
CLEAR: selcnt.
ELSE.
WRITE w_active TO selcnt LEFT-JUSTIFIED.
ENDIF.
LOOP AT SCREEN.
IF screen-name = 'P_TABLE'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
***
* PAI
***
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_objtyp.
CALL FUNCTION 'RS_HELP_HANDLING'
EXPORTING
dynpfield = 'P_OBJTYP'
dynpname = '1000'
object = 'SOBJ'
progname = 'ZBC_GOS_EXPORT_IMPORT'
suppress_selection_screen = 'X'
variant = 'SAP&STANDARD'
EXCEPTIONS
OTHERS = 0.
AT SELECTION-SCREEN.
IF ws_x030l-tabname IS INITIAL
OR ws_x030l-tabname NE p_table.
PERFORM f_init_table.
ENDIF.
IF w_selid IS INITIAL.
PERFORM f_init_selections.
ENDIF.
IF sy-ucomm = 'SEL'.
* Display free selection dialog
CONCATENATE 'Selection in table'(sit) p_table
INTO w_title SEPARATED BY space.
CALL FUNCTION 'FREE_SELECTIONS_DIALOG'
EXPORTING
selection_id = w_selid
title = w_title
status = 1
as_window = 'X'
IMPORTING
expressions = dyn_sel-texpr
field_ranges = dyn_sel-trange
number_of_active_fields = w_active
TABLES
fields_tab = dyns_fields
EXCEPTIONS
OTHERS = 1.
IF sy-subrc EQ 0.
REFRESH gl_varidyn.
LOOP AT dyns_fields.
MOVE-CORRESPONDING dyns_fields TO ws_varidyn.
APPEND ws_varidyn TO gl_varidyn.
ENDLOOP.
ENDIF.
ENDIF.
***
* Start of selection
***
START-OF-SELECTION.
FORMAT RESET.
CLEAR w_path.
IF p_path(1) = '/'.
w_path = p_path.
IF w_path NP '*/'.
CONCATENATE w_path '/' INTO w_path.
ENDIF.
ELSEIF p_path(1) = '\'.
w_path = p_path.
IF w_path NP '*\'.
CONCATENATE w_path '\' INTO w_path.
ENDIF.
ELSE.
SELECT SINGLE dirname
FROM user_dir
INTO w_path
WHERE aliass = p_path.
IF sy-subrc NE 0.
SELECT SINGLE pathextern
FROM path
INTO w_path
WHERE pathintern EQ p_path
AND filesys EQ sy-opsys.
ENDIF.
IF w_path(1) = '/'.
IF w_path NP '*/'.
CONCATENATE w_path '/' INTO w_path.
ENDIF.
ELSEIF w_path(1) = '\'.
IF w_path NP '*\'.
CONCATENATE w_path '\' INTO w_path.
ENDIF.
ELSEIF w_path IS NOT INITIAL.
MESSAGE e002(rc).
ENDIF.
ENDIF.
IF w_path IS INITIAL.
MESSAGE e024(sg) WITH p_path sy-opsys.
ENDIF.
PERFORM f_create_table USING p_table.
PERFORM f_select_table.
IF p_exp IS NOT INITIAL.
LOOP AT <wt_table> ASSIGNING FIELD-SYMBOL(<ws_struc>).
CLEAR w_key.
LOOP AT wt_keyfields INTO ws_keyfields
WHERE refstruct = p_table.
ASSIGN COMPONENT ws_keyfields-reffield OF STRUCTURE <ws_struc> TO <w_field>.
CHECK sy-subrc = 0.
CONCATENATE w_key <w_field>
INTO w_key RESPECTING BLANKS.
ENDLOOP.
* Retrieve the contents of attachments
PERFORM f_read_attachments USING w_key
CHANGING wt_attach.
CLEAR w_index.
LOOP AT wt_attach INTO ws_attach.
CONCATENATE w_path p_file INTO w_file.
ADD 1 TO w_index.
CONCATENATE '' ws_attach-bor_id w_index ws_attach-filen
INTO w_fileid SEPARATED BY gc_separator.
REPLACE '.*' WITH space INTO w_file.
REPLACE '*' WITH w_fileid INTO w_file.
IF p_locl IS INITIAL.
OPEN DATASET w_file FOR OUTPUT IN BINARY MODE MESSAGE w_mess.
IF sy-subrc EQ 0.
LOOP AT ws_attach-bdata INTO ws_bdata.
TRANSFER ws_bdata TO w_file.
ENDLOOP.
IF sy-subrc = 0.
WRITE: / w_file.
ELSE.
* Implement suitable error handling here
ENDIF.
CLOSE DATASET w_file.
ELSE.
WRITE: / 'Error:', w_mess.
ENDIF.
ELSE.
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
* BIN_FILESIZE =
filename = w_file
filetype = 'BIN'
TABLES
data_tab = ws_attach-bdata
EXCEPTIONS
OTHERS = 1.
IF sy-subrc = 0.
WRITE: / w_file.
ELSE.
* Implement suitable error handling here
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.
ELSE.
IF p_locl IS INITIAL.
CALL FUNCTION 'EPS2_GET_DIRECTORY_LISTING'
EXPORTING
iv_dir_name = CONV eps2filnam( w_path )
file_mask = CONV epsfilnam( p_file )
IMPORTING
file_counter = w_count
TABLES
dir_list = wt_sfile
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
MESSAGE e012(ps).
ENDIF.
LOOP AT wt_sfile INTO ws_sfile.
ws_files-filename = ws_sfile-name.
ws_files-filelength = ws_sfile-size.
APPEND ws_files TO wt_files.
ENDLOOP.
ELSE.
cl_gui_frontend_services=>directory_list_files(
EXPORTING
directory = w_path
filter = p_file
files_only = abap_true
CHANGING
file_table = wt_files
count = w_count
EXCEPTIONS
OTHERS = 1 ).
IF sy-subrc NE 0.
MESSAGE e012(ps).
ENDIF.
ENDIF.
IF w_count NE 0.
LOOP AT wt_files INTO ws_files.
CHECK ws_files-filename CS gc_separator.
CLEAR ws_attach.
* Get file name and path
ws_attach-filen = ws_files-filename.
SHIFT ws_attach-filen LEFT UP TO gc_separator.
SHIFT ws_attach-filen LEFT BY gc_sep_lengt PLACES.
IF ws_attach-filen CS gc_separator.
ws_attach-bor_id = ws_attach-filen(sy-fdpos).
ELSE.
CONTINUE.
ENDIF.
* Log source file
WRITE: / ws_files-filename.
* Check if business object exists
READ TABLE <wt_table> WITH KEY (ws_keyfields-reffield) = ws_attach-bor_id TRANSPORTING NO FIELDS.
IF sy-subrc NE 0.
FORMAT COLOR COL_NEGATIVE.
WRITE: 'object ID'(oid), ws_attach-bor_id NO-GAP, 'not found'(nof).
FORMAT RESET.
CONTINUE.
ENDIF.
* Upload file
CONCATENATE w_path ws_files-filename INTO w_file.
IF p_locl IS INITIAL.
OPEN DATASET w_file FOR INPUT IN BINARY MODE MESSAGE w_mess.
IF sy-subrc EQ 0.
DO.
READ DATASET w_file INTO ws_bdata.
IF sy-subrc NE 0.
EXIT.
ENDIF.
APPEND ws_bdata TO ws_attach-bdata.
ENDDO.
CLOSE DATASET w_file.
ELSE.
WRITE: / 'Error:', w_mess.
ENDIF.
ELSE.
CALL FUNCTION 'GUI_UPLOAD'
EXPORTING
filename = w_file
filetype = 'BIN'
TABLES
data_tab = ws_attach-bdata
EXCEPTIONS
OTHERS = 1.
ENDIF.
IF sy-subrc = 0.
WHILE ws_attach-filen CS gc_separator.
SHIFT ws_attach-filen LEFT UP TO gc_separator.
SHIFT ws_attach-filen LEFT BY gc_sep_lengt PLACES.
ENDWHILE.
PERFORM f_create_attachment USING ws_attach.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
*&---------------------------------------------------------------------*
*& Form f_init_table
*&---------------------------------------------------------------------*
FORM f_init_table.
CALL FUNCTION 'RPY_OBJECTTYPE_READ'
EXPORTING
objecttype_id = p_objtyp
with_verbs = 'X'
with_parameters = ' '
with_exceptions = ' '
with_texts = ' '
with_formatted_documentation = ' '
with_sapscript_documentation = ' '
TABLES
keyfields = wt_keyfields
EXCEPTIONS
not_found = 1
permission_error = 2
OTHERS = 3.
IF sy-subrc = 0.
READ TABLE wt_keyfields INTO ws_keyfields INDEX 1.
IF sy-subrc = 0.
p_table = ws_keyfields-refstruct.
ENDIF.
ELSE.
MESSAGE e520(ol) WITH p_objtyp.
ENDIF.
* Prepare free selection on table
PERFORM f_table_def USING p_table.
REFRESH wt_tables.
ws_tables-prim_tab = p_table.
APPEND ws_tables TO wt_tables.
CLEAR w_selid.
ENDFORM. "f_init_table
*&---------------------------------------------------------------------*
*& Form f_init_selections
*&---------------------------------------------------------------------*
FORM f_init_selections.
* Init free selection dialog
CALL FUNCTION 'FREE_SELECTIONS_INIT'
EXPORTING
expressions = dyn_sel-texpr
IMPORTING
selection_id = w_selid
expressions = dyn_sel-texpr
number_of_active_fields = w_active
TABLES
tables_tab = wt_tables
fields_tab = dyns_fields
EXCEPTIONS
OTHERS = 0.
ENDFORM. "f_init_selections
*---------------------------------------------------------------------*
* FORM f_table_def *
*---------------------------------------------------------------------*
FORM f_table_def USING in_tabname.
CALL FUNCTION 'DDIF_NAMETAB_GET'
EXPORTING
tabname = in_tabname
IMPORTING
x030l_wa = ws_x030l
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
CLEAR ws_x030l.
ENDIF.
IF ws_x030l IS INITIAL.
MESSAGE e058(54) WITH in_tabname.
ELSEIF ws_x030l-tabtype NE 'T'.
MESSAGE e126(ba) WITH in_tabname.
ENDIF.
ENDFORM. "f_table_def
*---------------------------------------------------------------------*
* FORM f_create_table *
*---------------------------------------------------------------------*
FORM f_create_table USING in_tabname.
CREATE DATA ob_table TYPE TABLE OF (in_tabname).
IF sy-subrc = 0.
ASSIGN ob_table->* TO <wt_table>.
ELSE.
MESSAGE e515(rsdme) WITH in_tabname.
ENDIF.
ENDFORM. "f_create_table
*---------------------------------------------------------------------*
* FORM f_select_table *
*---------------------------------------------------------------------*
FORM f_select_table.
IF w_active = 0.
SELECT * FROM (p_table)
INTO CORRESPONDING FIELDS OF TABLE <wt_table>.
ELSE.
* Selection with parameters
CALL FUNCTION 'FREE_SELECTIONS_EX_2_WHERE'
EXPORTING
expressions = dyn_sel-texpr
IMPORTING
where_clauses = dyn_sel-clauses
EXCEPTIONS
expression_not_supported = 1
OTHERS = 2.
IF sy-subrc = 0.
READ TABLE dyn_sel-clauses INTO ws_where WITH KEY tablename = p_table.
IF sy-subrc = 0.
SELECT * FROM (p_table)
INTO CORRESPONDING FIELDS OF TABLE <wt_table>
WHERE (ws_where-where_tab).
ENDIF.
ENDIF.
ENDIF.
IF sy-dbcnt = 0.
WRITE: 'No record selected'(nrs).
STOP.
ELSE.
w_dbcnt = sy-dbcnt.
MESSAGE s058(oz) WITH w_dbcnt.
ENDIF.
ENDFORM. "f_select_table
*&---------------------------------------------------------------------*
*& Form F_CREATE_ATTACHMENT
*&---------------------------------------------------------------------*
FORM f_read_attachments USING in_obj_id TYPE sibfboriid
CHANGING ct_attach TYPE tt_attach.
DATA: ls_object TYPE sibflporb,
lt_links TYPE obl_t_link,
ls_attach TYPE ty_attach.
DATA: ls_sofolenti1 TYPE sofolenti1,
lv_doc_id TYPE sofolenti1-doc_id.
CLEAR ct_attach.
ls_object-instid = in_obj_id.
ls_object-typeid = p_objtyp.
ls_object-catid = sibf_catid_bo.
TRY.
cl_binary_relation=>read_links_of_binrel(
EXPORTING
is_object = ls_object
ip_relation = cl_gos_api=>c_atta
IMPORTING
et_links = lt_links ).
CATCH cx_obl.
CLEAR lt_links.
ENDTRY.
ls_attach-bor_id = in_obj_id.
LOOP AT lt_links ASSIGNING FIELD-SYMBOL(<ls_link>).
* 46 characters = folder + doc + forwarder
lv_doc_id = <ls_link>-instid_b(46).
CLEAR ls_attach-bdata.
* API1 returns the contents in binary format
CALL FUNCTION 'SO_DOCUMENT_READ_API1'
EXPORTING
document_id = lv_doc_id
IMPORTING
document_data = ls_sofolenti1
TABLES
contents_hex = ls_attach-bdata
EXCEPTIONS
OTHERS = 1.
IF sy-subrc = 0.
* Build the original filename based on name + extension
CONCATENATE ls_sofolenti1-obj_descr ls_sofolenti1-obj_type
INTO ls_attach-filen SEPARATED BY '.'.
APPEND ls_attach TO ct_attach.
ENDIF.
ENDLOOP.
ENDFORM. " F_READ_ATTACHMENTS
*&---------------------------------------------------------------------*
*& Form F_CREATE_ATTACHMENT
*&---------------------------------------------------------------------*
FORM f_create_attachment USING in_attach TYPE ty_attach.
DATA: ls_attachment TYPE zocs_claim_atta_single,
lv_dummy TYPE text132. "#EC NEEDED
* Target document id for Binary relationship
MOVE p_objtyp TO ls_attachment-id-objtype.
MOVE in_attach-bor_id TO ls_attachment-id-objkey.
CALL FUNCTION 'OWN_LOGICAL_SYSTEM_GET'
IMPORTING
own_logical_system = ls_attachment-id-logsys
EXCEPTIONS
OTHERS = 1.
CHECK sy-subrc = 0.
* Title
MOVE in_attach-filen TO ls_attachment-dscrp.
* Extension
SPLIT in_attach-filen AT '.' INTO lv_dummy ls_attachment-ext.
* Convert contents
CALL FUNCTION 'SO_SOLIXTAB_TO_SOLITAB'
EXPORTING
ip_solixtab = in_attach-bdata
IMPORTING
ep_solitab = ls_attachment-content.
* Create attachment
PERFORM f_gos_add_attachment CHANGING ls_attachment.
ENDFORM. " F_CREATE_ATTACHMENT
*&---------------------------------------------------------------------*
*& Form F_GOS_ADD_ATTACHMENT
*&---------------------------------------------------------------------*
FORM f_gos_add_attachment CHANGING cs_attachment TYPE zocs_claim_atta_single.
DATA: ls_folder_id TYPE sofdk.
DATA: ls_document TYPE sofmk.
DATA: ls_obj_id TYPE soodk.
DATA: ls_rel_doc TYPE borident.
DATA: ls_hd_dat TYPE sood1.
DATA: lt_objhead TYPE soli_tab.
CALL FUNCTION 'SO_FOLDER_ROOT_ID_GET'
EXPORTING
region = pa_fol
IMPORTING
folder_id = ls_folder_id
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
RETURN.
ENDIF.
* Init
MOVE cs_attachment-dscrp TO ls_hd_dat-objdes.
MOVE cs_attachment-size TO ls_hd_dat-objlen.
MOVE cs_attachment-ext TO ls_hd_dat-file_ext.
CALL FUNCTION 'SO_OBJECT_INSERT'
EXPORTING
folder_id = ls_folder_id
object_hd_change = ls_hd_dat
object_type = ext "PC Document
IMPORTING
object_id = ls_obj_id
TABLES
objcont = cs_attachment-content "Must be changing parameter!!!!
objhead = lt_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
OTHERS = 15.
IF sy-subrc NE 0.
RETURN.
ENDIF.
MOVE ls_folder_id-foltp TO ls_document-foltp.
MOVE ls_folder_id-folyr TO ls_document-folyr.
MOVE ls_folder_id-folno TO ls_document-folno.
MOVE ls_obj_id-objtp TO ls_document-doctp.
MOVE ls_obj_id-objyr TO ls_document-docyr.
MOVE ls_obj_id-objno TO ls_document-docno.
MOVE ls_document TO ls_rel_doc-objkey.
MOVE cl_gos_api=>c_message TO ls_rel_doc-objtype.
CALL FUNCTION 'BINARY_RELATION_CREATE'
EXPORTING
obj_rolea = cs_attachment-id
obj_roleb = ls_rel_doc
relationtype = cl_gos_api=>c_atta(4)
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
ROLLBACK WORK.
EXIT.
ENDIF.
WRITE: / ls_hd_dat-objdes.
COMMIT WORK AND WAIT.
ENDFORM. " F_GOS_ADD_ATTACHMENT
Text symbols:
B01 Process B03 Files NOF not found NRS No record selected OBJ BOR objects OID object ID SIT Selection in table
Selection texts:
P_EXP Export selection P_FILE Filename P_IMP Import files P_LOCL Local path (PC) P_OBJTYP Object Type P_PATH Path P_TABLE Table Name
Alert Moderator
Assigned tags
ABAP Development
GOS attachment export import
Related Blog Posts
Everything GOS (Generic Object Services)
By Philip Johnston, May 23, 2013
How to add Generic Object Services to your context menus
By Former Member, Aug 28, 2015
Read GOS (Generic Object Service) Picture Attachments and Display it into Adobe Form
By Abhijit Mandal, Feb 14, 2014
Related Questions
Printing PDF attachment FROM GOS into Smartform
By Former Member, Mar 20, 2013
Please tell me the name of the table where URLs are stored?
By Former Member, Mar 15, 2009
GOS Attachments do not get created at runtime in Content Respository
By Former Member, Nov 06, 2009
5 Comments
You must be Logged on to comment or reply to a post.
Jelena Perfiljeva
January 27, 2017 at 7:41 pm
Thank you for sharing! GOS is a very popular question, I'm sure this will be helpful to many. Bookmarked for reference.
Like(0)
Noriko Szilagy
October 16, 2017 at 5:34 pm
Hi.
I found this blog to be helpful as well. Will it be possible for you to share what is inside of the structure of "ZOCS_CLAIM_ATTA_SINGLE"?
Sincerely,
Noriko
Like(0)
Former Member
November 7, 2017 at 4:44 pm
ZOCS_CLAIM_ATTA_SINGLE - Type please..
Like(0)
Naas du Plessis
May 14, 2018 at 9:03 pm
I agree - very helpful article but it would be more helpful if we can see the ZOCS_CLAIM_ATTA_SINGLE structure.
Like(0)
François Henrotte Post author
August 28, 2018 at 12:49 pm
Like(1)
Generic Object Services (Upload, Download, List) Programatically
FollowRSS feedLike
8 Likes 22,755 Views 14 Comments
I recently found myself needing to write a web application that needed to interact with the attachments stored in Generic Object Services within SAP. The Generic Object Services are used throughout multiple application areas within SAP and have many features which include document (object) management. If you have ever seen this icon while using an SAP transaction, then you have the ability to use the Generic Object Services in the particular business process. My goal was to be able to create and download the documents from within my web application. In order to do this, I created some classes to help me. I will try to describe them below.
Note: You will always need the business object key data regarding which object type you are working with while coding for Generic Object Services. For example, if you were using Generic Object Services from transaction PA30 (Human Resources), the object key would be BUS1065. If you were using Generic Object Services in Orders (transaction IW33), the object key would be BUS2088. This key can easily be determined by placing a break point in class CL_BINARY_RELATION and method READ_LINKS_OF_BINRELS prior to executing the icon above. Or you can use transaction SWO1 to find Business Objects.
Getting Started: Create a Class to Build your Methods
First I created the following method: GOS_GET_FILE_LIST
This method allowed me to show a list of all files currently attached to the object I was working with. This method could be a wrapper around standard function module: BDS_GOS_CONNECTIONS_GET. If you call this method with your object key, you will retrieve a listing of all attachments. I chose to write the following method code instead:
method gos_get_file_list.
types: begin of ts_key, foltp type so_fol_tp, folyr type so_fol_yr, folno type so_fol_no, objtp type so_obj_tp, objyr type so_obj_yr, objno type so_obj_no, forwarder type so_usr_nam, end of ts_key,
begin of ts_attachment, foltp type so_fol_tp, folyr type so_fol_yr, folno type so_fol_no, objtp type so_obj_tp, objyr type so_obj_yr, objno type so_obj_no, brelguid type oblguid32, roletype type oblroltype, end of ts_attachment,
tt_attachment type table of ts_attachment.
data: ta_srgbtbrel type standard table of srgbtbrel, wa_srgbtbrel type srgbtbrel, lta_sood type standard table of sood, lwa_sood type sood, ltp_pathin(1000) type c, ltp_filename type string, ltp_sortfield type char30, lta_objcont type soli_tab, lta_attachments type tt_attachment, lwa_attachments like line of lta_attachments, lo_boritem type ref to cl_sobl_bor_item, lo_al_item type ref to cl_gos_al_item, li_link type ref to if_browser_link, ls_option type obl_s_relt, lt_options type obl_t_relt, ls_key type ts_key, ls_attachment type ts_attachment, lt_attachment type tt_attachment, lt_links type obl_t_link, ls_link type obl_s_link, lp_linkid type blnk_inst, gs_lpor type sibflporb.
if not objtype is initial and not objkey is initial. select * from srgbtbrel into table ta_srgbtbrel where instid_a eq objkey and typeid_a eq objtype and catid_a eq ‘BO’.
if sy-subrc eq 0. sort ta_srgbtbrel by instid_a typeid_a catid_a. delete adjacent duplicates from ta_srgbtbrel comparing instid_a typeid_a catid_a.
loop at ta_srgbtbrel into wa_srgbtbrel. clear: lt_attachment[], lta_attachments[].
gs_lpor-instid = wa_srgbtbrel-instid_a. gs_lpor-typeid = wa_srgbtbrel-typeid_a. gs_lpor-catid = wa_srgbtbrel-catid_a.
ls_option-sign = ‘I’. ls_option-option = ‘EQ’.
ls_option-low = ‘ATTA’. append ls_option to lt_options. ls_option-low = ‘NOTE’. append ls_option to lt_options. ls_option-low = ‘URL’. append ls_option to lt_options.
try. call method cl_binary_relation=>read_links_of_binrels exporting is_object = gs_lpor it_relation_options = lt_options ip_role = ‘GOSAPPLOBJ’ importing et_links = lt_links.
loop at lt_links into ls_link. case ls_link-typeid_b . when ‘MESSAGE’. ls_key = ls_link-instid_b. move-corresponding ls_key to ls_attachment. ls_attachment-roletype = ls_link-roletype_b. if ls_link-brelguid is initial. ls_attachment-brelguid = ls_link-relguidold. else. ls_attachment-brelguid = ls_link-brelguid. endif. append ls_attachment to lt_attachment. when others. continue. endcase. endloop. catch cx_obl_parameter_error . catch cx_obl_internal_error . catch cx_obl_model_error . catch cx_root. endtry. endloop.
lta_attachments[] = lt_attachment[]. check lines( lta_attachments ) > 0.
select * from sood into table lta_sood for all entries in lta_attachments where objtp = lta_attachments-objtp and objyr = lta_attachments-objyr and objno = lta_attachments-objno. if sy-subrc eq 0. t_attachments[] = lta_sood. es_return-text = ‘SUCCESS’. endif.
data rcode type i. data objhead_tab type table of soli. data objcont_tab type table of soli. data objpara_tab type table of selc. data objparb_tab type table of soop1. data sood_key type soodk. data hex_mode type sonv-flag. field-symbols <fs> type line of z_tt_sood.
loop at t_attachments assigning <fs>. if not ( <fs>-objtp is initial or <fs>-objyr is initial or <fs>-objno is initial ). concatenate <fs>-objtp <fs>-objyr <fs>-objno into sood_key.
perform socx_select in program sapfsso0 tables objhead_tab objcont_tab objpara_tab objparb_tab using sood_key hex_mode rcode. if rcode eq 0. data moff type i. data l_param_search type soli-line. data l_param_head type soli-line. data value type soli-line. data wa_objhead_tab like line of objhead_tab. data lt_url_tab type table of so_url. data ld_url_tab_size type sytabix. l_param_search = ‘&SO_FILENAME’. translate l_param_search to upper case. loop at objhead_tab into wa_objhead_tab. clear moff. find ‘=’ in wa_objhead_tab-line match offset moff. check sy-subrc = 0. l_param_head = wa_objhead_tab-line(moff). translate l_param_head to upper case. if l_param_head = l_param_search. add 1 to moff. value = wa_objhead_tab-line+moff. if not ( value is initial ). split value at ‘.’ into table lt_url_tab. describe table lt_url_tab lines ld_url_tab_size. if ld_url_tab_size gt 1. read table lt_url_tab index ld_url_tab_size into <fs>-acnam. endif. endif. endif. endloop. endif. endif. endloop. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘001’ i_v1 = ‘There are no Attachments on this Business Object’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘No Business Object and/or Key Specified’ receiving rs_return = es_return. endif.
endmethod.
Testing This Method:
Here is some report source code to test the method via a program:
report ztest_file_list.
data: ta_srgbtbrel type standard table of srgbtbrel, wa_srgbtbrel type srgbtbrel, lta_sood type standard table of sood, lwa_sood type sood.
parameters: p_key type swo_typeid obligatory default ‘000030026122’, p_type type swo_objtyp obligatory default ‘BUS2088’.
start-of-selection.
data: t_st_return type zvnt_st_return.
call method zcl_oh_my_gos=>gos_get_file_list exporting objtype = p_type objkey = p_key importing t_attachments = lta_sood changing es_return = t_st_return.
if t_st_return-code is initial. data dec_kb type p.
loop at lta_sood into lwa_sood. dec_kb = lwa_sood-objlen / 1024. if dec_kb < 1. dec_kb = 1. endif. write: / lwa_sood-objdes, dec_kb, ‘KB’. endloop. else. message t_st_return-text type ‘W’. endif.
Second I created the following method: GOS_ATTACH_FILE
This method allowed me to attach files to the object I was working with.
method gos_attach_file.
data: ls_object type borident, ls_obj_data type sood1, ls_obj_id type soodk, ls_fol_id type soodk, ld_filename type string, lt_url_tab type table of so_url, ld_url_tab_size type sytabix, ls_folmem_k type sofmk, lv_ep_note type borident-objkey, ls_note type borident.
data: it_objhead type standard table of soli.
ls_object-objtype = objtype. ls_object-objkey = objkey.
if not ls_object-objtype is initial and not ls_object-objkey is initial. call function ‘SO_CONVERT_CONTENTS_BIN’ exporting it_contents_bin = it_content[] importing et_contents_bin = it_content[]. if sy-subrc eq 0. call function ‘SO_FOLDER_ROOT_ID_GET’ exporting region = folder_region importing folder_id = ls_fol_id exceptions others = 1. if sy-subrc eq 0. if not file_name_with_path is initial. call function ‘SO_SPLIT_FILE_AND_PATH’ exporting full_name = file_name_with_path importing stripped_name = ld_filename. else. call function ‘SO_SPLIT_FILE_AND_PATH’ exporting full_name = file_name_no_path importing stripped_name = ld_filename. endif.
if sy-subrc eq 0. split ld_filename at ‘.’ into table lt_url_tab. describe table lt_url_tab lines ld_url_tab_size. if ld_url_tab_size gt 1. read table lt_url_tab index ld_url_tab_size into ls_obj_data-file_ext. read table lt_url_tab index 1 into ls_obj_data-objdes. else. clear ls_obj_data-file_ext. ls_obj_data-objdes = ld_filename. endif. ls_obj_data-objsns = ‘O’. ls_obj_data-objla = sy-langu. ls_obj_data-objlen = lines( it_content ) * 255.
data: wa_content type soli. clear wa_content. concatenate ‘&SO_FILENAME=’ ld_filename into wa_content. append wa_content to it_objhead.
call function ‘SO_OBJECT_INSERT’ exporting folder_id = ls_fol_id object_type = ‘EXT’ object_hd_change = ls_obj_data importing object_id = ls_obj_id tables objhead = it_objhead objcont = it_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.
if sy-subrc = 0 and ls_object-objkey is not initial. commit work and wait. ls_folmem_k-foltp = ls_fol_id-objtp. ls_folmem_k-folyr = ls_fol_id-objyr. ls_folmem_k-folno = ls_fol_id-objno. ls_folmem_k-doctp = ls_obj_id-objtp. ls_folmem_k-docyr = ls_obj_id-objyr. ls_folmem_k-docno = ls_obj_id-objno. lv_ep_note = ls_folmem_k. ls_note-objtype = ‘MESSAGE’. ls_note-objkey = lv_ep_note.
call function ‘BINARY_RELATION_CREATE_COMMIT’ exporting obj_rolea = ls_object obj_roleb = ls_note relationtype = ‘ATTA’ exceptions others = 1. if sy-subrc eq 0. es_return-text = ‘SUCCESS’. commit work and wait. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error Calling: BINARY_RELATION_CREATE_COMMIT’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error Calling: SO_OBJECT_INSERT’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error With File Name’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error Obtaining Root Folder ID’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error Converting Table Contents to Binary’ receiving rs_return = es_return. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘No Business Object and/or Key Specified’ receiving rs_return = es_return. endif.
endmethod.
Testing: Here is some sample code for a report program which will test the two methods above. It attaches a file to the key object specified and shows the before and after results:
report ztest_file_attach.
parameters: p_key type swo_typeid obligatory default ‘000030026122’, p_type type swo_objtyp obligatory default ‘BUS2088’, p_file type rlgrap-filename obligatory.
at selection-screen on value-request for p_file. call function ‘F4_FILENAME’ exporting program_name = syst-cprog dynpro_number = syst-dynnr field_name = ‘P_FILE’ importing file_name = p_file.
start-of-selection.
data: g_filename type string, g_attsize type wsrm_error-wsrm_direction, it_content like standard table of soli. data: ta_srgbtbrel type standard table of srgbtbrel, wa_srgbtbrel type srgbtbrel, lta_sood type standard table of sood, lwa_sood type sood. data: t_st_return type zvnt_st_return. data dec_kb type p.
* LIST call method zcl_oh_my_gos=>gos_get_file_list exporting objtype = p_type objkey = p_key importing t_attachments = lta_sood changing es_return = t_st_return.
if t_st_return-code is initial. loop at lta_sood into lwa_sood. dec_kb = lwa_sood-objlen / 1024. if dec_kb < 1. dec_kb = 1. endif.
write: / lwa_sood-objdes, dec_kb, ‘KB’. endloop. else. message t_st_return-text type ‘W’. endif.
* ATTACH move p_file to g_filename. call function ‘GUI_UPLOAD’ exporting filename = g_filename filetype = ‘BIN’ importing filelength = g_attsize tables data_tab = it_content exceptions file_open_error = 1 file_read_error = 2 no_batch = 3 gui_refuse_filetransfer = 4 invalid_type = 5 no_authority = 6 unknown_error = 7 bad_data_format = 8 header_not_allowed = 9 separator_not_allowed = 10 header_too_long = 11 unknown_dp_error = 12 access_denied = 13 dp_out_of_memory = 14 disk_full = 15 dp_timeout = 16 others = 17. if sy-subrc eq 0. data: l_file_name_with_path type avwctxcont.
move g_filename to l_file_name_with_path. call method zcl_oh_my_gos=>gos_attach_file exporting objtype = p_type objkey = p_key folder_region = ‘B’ file_name_with_path = l_file_name_with_path it_content = it_content importing es_return = t_st_return.
if t_st_return-code is initial. message t_st_return-text type ‘I’. else. message t_st_return-text type ‘W’. endif. endif.
* LIST call method zcl_oh_my_gos=>gos_get_file_list exporting objtype = p_type objkey = p_key importing t_attachments = lta_sood changing es_return = t_st_return.
if t_st_return-code is initial. write: /. loop at lta_sood into lwa_sood. dec_kb = lwa_sood-objlen / 1024. if dec_kb < 1. dec_kb = 1. endif.
write: / lwa_sood-objdes, dec_kb, ‘KB’. endloop. else. message t_st_return-text type ‘W’. endif.
Lastly, I created the following method: GOS_DOWNLOAD_FILE
This method allowed me download an attachment from the object I was working with. For simplicity, I will show how I downloaded the files from the GUI.
method gos_download_file.
data: ex type ref to cx_root, text type string. data: ltp_sortfield type char30, lta_objcont type soli_tab, ltp_pathfile(1000) type c, ltp_filename type string, ltp_binfilesize type so_doc_len.
try . concatenate attachment-objtp attachment-objyr attachment-objno into ltp_sortfield. import objcont_tab to lta_objcont from database soc3(dt) id ltp_sortfield.
if sy-subrc = 0. concatenate file_path ‘\’ attachment-objdes ‘.’ attachment-file_ext into ltp_pathfile.
replace ‘\\’ with ‘\’ into ltp_pathfile+2. translate ltp_pathfile using ‘/ ‘.
ltp_binfilesize = attachment-objlen.
call function ‘SO_OBJECT_DOWNLOAD’ exporting bin_filesize = ltp_binfilesize filetype = ‘BIN’ path_and_file = ltp_pathfile extct = attachment-extct no_dialog = ‘X’ importing act_filename = ltp_filename tables objcont = lta_objcont exceptions file_write_error = 1 invalid_type = 2 x_error = 3 kpro_error = 4 others = 5.
if sy-subrc <> 0. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error Calling: SO_OBJECT_DOWNLOAD’ receiving rs_return = es_return. else. es_return-text = ‘SUCCESS’. endif. else. call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = ‘Error With Object Import From DB’ receiving rs_return = es_return. endif. catch cx_root into ex. text = ex->get_text( ).
call method zcl_oh_my_gos=>log_msg exporting i_code = ‘021’ i_v1 = text receiving rs_return = es_return. endtry.
endmethod.
Testing: Here is some sample code for a report program which loops through all attachments of an object and downloads them.
report ztest_file_download.
data: ta_srgbtbrel type standard table of srgbtbrel, wa_srgbtbrel type srgbtbrel, lta_sood type standard table of sood, lwa_sood type sood.
parameters: p_key type swo_typeid obligatory default ‘000030026122’, p_type type swo_objtyp obligatory default ‘BUS2088’.
start-of-selection.
data: t_st_return type zvnt_st_return.