<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener('load', function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <div id="navbar-iframe-container"></div> <script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script> <script type="text/javascript"> gapi.load("gapi.iframes:gapi.iframes.style.bubble", function() { if (gapi.iframes && gapi.iframes.getContext) { gapi.iframes.getContext().openChild({ url: 'https://www.blogger.com/navbar.g?targetBlogID\x3d34883048\x26blogName\x3dYour+Friendly+ABAPer\x26publishMode\x3dPUBLISH_MODE_BLOGSPOT\x26navbarType\x3dBLUE\x26layoutType\x3dCLASSIC\x26searchRoot\x3dhttp://friendlyabaper.blogspot.com/search\x26blogLocale\x3den_US\x26v\x3d2\x26homepageUrl\x3dhttp://friendlyabaper.blogspot.com/\x26vt\x3d-4712760677496349421', where: document.getElementById("navbar-iframe-container"), id: "navbar-iframe" }); } }); </script>

Oh my GOS!

Behold, here comes another 3-letter abbreviation from the creators of SAP - GOS or Generic Object Services. Unlike some other abbreviations, such as USCIS (United States Citizenship and Immigration Services) or MVS (Motor Vehicle Services), this one is not a tool of oppression and actually does provide service of some sort.

GOS manifests its presence in SAP systems in the form of an inconspicuous button on certain transaction screens. In this particular example (see picture) it is transaction VF02 - Billing Document Change (note that you have to enter a document number and hit Enter key first). If you click on this button, either a menu or a toolbar will open (depending on whether you click on the right or the left part of the button), but both provide the same functionality. By using it, one can add attachments, notes, URLs, start the workflow, check the IDocs for the document and what's not. For instance, with this button it would be possible to attach a PDF file (say, a scanned invoice with the customer's signature) to the corresponding billing document (e.g. invoice) in SAP. This is, of course, just an example, there are actually quite a few things you can do with it. Naturally, at some point the users will find out about this and they will want you to do their work and to write a program that will read their mind and attach their deep thoughts in a proprietary format to the SAP documents. But fear not - even though the mind-reading SAP module probably won't be out until at least ECC 7.0 (or whatever they decide to call it), the rest can be successfully accomplished in good old ABAP.

Actually almost all of the work has been done for us already by Mr. Ram Manohar Tiwari, who kindly posted a very nice code sample in an SDN blog. He even provided a non-object version in the second installment of the blog for the release-challenged or OO-phobic (which kind of includes me).

As much as I was hoping that I'll just copy-paste the code and be done with it, this did not happen. From the blog comments it seemed that many others ran into the same problem (more on that later), yet no one, including the author, could provide a solution. Now I had to get to the bottom of this!

When I'm re-reading the Mr. Tiwari's blog now, it seems that he's explaining everything rather well, but when I saw it for the first time, it wasn't nearly as clear. So let's see if we can dumb it down a notch. The second code sample (with FMs, not classes/methods) to me is easier to use and explain, so I'll go with that. Also all this GOS stuff can be done with other documents and objects, but I'll use the specific example with creating a non-plain-text attachment for an invoice for illustration purposes.

The starting point: we have an invoice 90052466 in SAP and we have, say, a Word document (.doc) file on a server. The goal is to somehow attach that file to the invoice by running a program. To do so, we'll perform the following steps.

1. Read the file into memory. For that we can use OPEN DATASET if the file is on a server or FM GUI_DOWNLOAD if the file is on a local PC (e.g. on your laptop's C: drive). Don't worry that it's a Word file - if you use the binary mode, it will be OK.
2. Get a "folder ID" by calling SO_FOLDER_ROOT_ID_GET. Now this part is rather confusing (does this FM actually create a folder somewhere?), but just look at it this way - you're getting an address of where your file contents will be stored in SAP, that's all.
3. Put the file into that "folder" by calling SO_OBJECT_INSERT. The content of the file is passed to this function module in a table.
4. The FM SO_OBJECT_INSERT will give you the "object ID" for your file. At this point your file is already stored somewhere in the depths of SAP Office (read the OSS note 904711 to find more, if you wish) and the last step is to link this "object ID" to the invoice. To do so, we call the FM BINARY_RELATION_CREATE_COMMIT.

But, dig this, there is no VBELN parameter or anything like that, right? So how does it know to link to the invoice? Well, for you it's an invoice, but for GOS it's just an abstract "object" with "object type" and "object key". "Object type" is sort of a type identifier, it starts with 'BUS' followed by 4 digits (e.g. BUS2037 for invoice or BUS2012 for purchase order). But "object key" in our case is the invoice number (VBELN), leading zeroes and all.

How do I know that invoice is BUS2037? Funny you should ask... I'm sure there is a transaction where you can see all those "BUSes", but here is what I do. Go to ST05, activate the trace with filter by your user ID. Then go to transaction VF02 and create an attachment. Now go back to ST05, deactivate the trace and display it.

On the list you will most likely see something like this (do Ctrl-F and type in BUS to search for this line):
SELECT WHERE "MANDT" = '100' AND "SAP_OBJECT" = 'BUS2037' AND "OBJECT_ID" LIKE '0090052466%'

See? Now not only we know what the type is, but also what the object key should look like.

The last piece of magic that separates this post from being just an SDN blog's rip-off is the crucial step, which was sort of overlooked by Mr. Tiwari. After running the copy/pasted code sample (with few adjustments), the .DOC attachment was created successfully, but Word could not open it. And this is not very useful, isn't it? Something was obviously wrong with the file content interpretation in SAP... After a futile attempt to debug the GOS button in transaction, I turned to search on SDN and OSS for anything related to the binary file conversion. Luckily, rather soon I stumbled upon the function module SO_CONVERT_CONTENTS_BIN. After being inserted between OPEN DATASET and FM SO_OBJECT_INSERT, it finally forced the evil Word to open the attachment as the nature intended. I didn't think I would ever be so happy to see the words 'Test line number 1' in my life!

Since, apparently, some SDN blog readers were able to use the code, I guess that this issue might affect only the ECC 6.0 release and/or the Unicode systems. So try the code without the SO_CONVERT_CONTENTS_BIN FM first, maybe it will work for you.

Other adjustments that I made in the original code (apart from the general clean-up):
1) OPEN DATASET has to be in either TRY... ENDTRY or CATCH SYSTEM-EXCEPTIONS (in older releases) to avoid short dumps if there is some problem with the file.
2) Parameters include the file name (P_FILE) and the attachment title (P_DESC). The title is just sort of the attachment's name displayed in the attachment list, as on the picture here. The file name should look something like \\sapcoredev01\nice_basis_guy_created_this_folder_for_me\test.doc. Note that the program derives the extension from the last 3 characters of the file name, but you may also pass the extension as a parameter. In this case P_FILE could be of type STRING, to make life easier.
3) The field ls_obj_data-objlen is, naturally, the object's total length in characters. Since I'm using a 255-character field for the file contents, then I just multiply number of lines in the table by 255. On SDN you'll see many examples where people are trying to get the exact number and they calculate number of lines minus 1, then they add the number of characters in the last line, etc. This is completely unnecessary.

So here is my homage, if you will, to Mr. Tiwari's blog:
PARAMETERS: p_key TYPE swo_typeid OBLIGATORY,
p_type TYPE swo_objtyp OBLIGATORY,
p_file TYPE c LENGTH 100 OBLIGATORY,
p_desc TYPE so_obj_des OBLIGATORY.

DATA: ls_fol_id TYPE soodk,
ls_obj_id TYPE soodk,
ls_obj_data TYPE sood1,
ls_folmem_k TYPE sofmk,
ls_note TYPE borident,
ls_object TYPE borident,
lv_ep_note TYPE borident-objkey,
lv_offset TYPE i.

DATA: it_objhead TYPE STANDARD TABLE OF soli,
it_content LIKE STANDARD TABLE OF soli,
wa_content LIKE soli.

ls_object-objkey = p_key.
ls_object-objtype = p_type.

TRY.
OPEN DATASET p_file FOR INPUT IN BINARY MODE.
WHILE sy-subrc = 0.
READ DATASET p_file INTO wa_content.
APPEND wa_content TO it_content.
ENDWHILE.
CLOSE DATASET p_file.
CATCH cx_sy_file_access_error.
MESSAGE 'Error reading file' TYPE 'E'.
ENDTRY.

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

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

ls_obj_data-objsns = 'O'.
ls_obj_data-objla = sy-langu.
ls_obj_data-objdes = p_desc.
lv_offset = STRLEN( p_file ) - 3.
ls_obj_data-file_ext = p_file+lv_offset(3).
ls_obj_data-objlen = LINES( it_content ) * 255.

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.
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.
ELSE.
MESSAGE 'Not OK' TYPE 'I'.
RETURN.
ENDIF.

IF sy-subrc = 0.
MESSAGE 'OK' TYPE 'I'.
ELSE.
MESSAGE 'Not OK' TYPE 'I'.
ENDIF.

In case you're wondering, this code may also be put in an RFC-enabled function module if, for example, you'd like to create the attachments from outside of SAP. In this case instead of using the file name, you may just directly pass the file contents to the FM in a table. For that table, use type SOLIX_TAB, which is a RAW format and convert it to SOLI_TAB by using SO_SOLIXTAB_TO_SOLITAB. Naturally, you won't need OPEN DATASET anymore, just start with step # 2 above.

And, of course, it's not just for the Word .DOC files, .PDF will work just fine (I checked!), as well as the other file formats that SAP can read and digest. I've heard that this technique could be used to add, for example, photos to the employee files (haven't tried it myself though).

GOS has been available at least since the release 4.6, but it does require some setup in the system before you'll be able to see "the magic button". You'll find some information on this in SAP Help (see the link below), but I personally couldn't make much sense of it (please feel free to add a comment if you have more information on this). If you're having some issues with accessing GOS, I'd suggest to check with your Basis admin.

OSS notes of interest:

There is a rather scary number of the GOS-related OSS notes. Here are some notes that might be of interest to ABAP'ers:
927407 - Determining the content of GOS and SAPoffice documents
904711 - SAPoffice: Where are documents physically stored?
916512 - SAPoffice: Directory for upload/download/display
448074 - Calling generic object services from the dialog

Links:

SDN Blog GOS in Background - Part I
SDN Blog GOS in Background - Part II
GOS - SAP Help
How to Attach Documents to Any Custom Program Using GOS (SDN)

posted by Your Friendly ABAPer @ 11:08,
Direct link to this post

36 Comments:

At 8/1/09 00:56, Blogger krishna said...

hi,
Thanks for the nice.It helped me alot.I'm trying to attach '.PDF' documents from C: drive and using 'GUI_UPLOAD'. I was successfull in attaching it but when I try to open the attachment, it says the the file is corrupted.
Any ideas as where I'm going wrong.
thanks,
Krishna

 
At 8/1/09 01:07, Blogger krishna said...

hi,
I could able to resolve it. Thanks once again.
Great blog...
Krishna

 
At 23/9/09 08:47, Anonymous Anonymous said...

Hi Krishna ,

I am facing the same problem , can you tell me what did u do

 
At 23/9/09 09:37, Anonymous Your Friendly ABAPer said...

Not sure Krishna is following the comments, but I haven't had any issues with PDF files. Just make sure to use binary (BIN) file format.

 
At 19/10/09 05:29, Anonymous Anonymous said...

Thanks a lot for your coding and the great explanation; this helped me a lot.

If at all, the only thing I can add: When I uploaded the attachments, I found that I could not specify the owner and creation date different to me and today (a check inside the FM prevented this). The solution was easy (though dirty), setting sy-uname and sy-datum before the FM did the stuff.

Thanks again.

Robert

 
At 26/10/09 21:08, Anonymous Your Friendly ABAPer said...

You're welcome, Robert. By the way, if anyone has already upgraded to Office 2007, there are some tricks you might have to do for the 4-character attachments. I'll try to write a follow-up post on this soon.

 
At 13/11/09 12:25, Anonymous Anonymous said...

Yes, we are upgraded to Office 2007 and i have a problem in atttaching .docx and .xlsx files.
could you please tell us the trick to attach 4 character doc types.

Thanks in Advance.
Mahesh

 
At 30/11/09 17:04, Anonymous Anonymous said...

Hi Friendly ABAPer,

Could you please post the trick to upload 4 character document type?
(.docx, .xlsx etc)

Thanks again,

 
At 4/12/09 09:58, Anonymous YourFriendlyABAPer said...

Regarding the Office 2007 extensions please read the follow-up post).

 
At 12/1/10 17:59, Blogger Dominic said...

To find business objects, go to transaction SWO1. This will allow you to search for the different business object types and find them quickly and easily.

 
At 4/8/10 23:40, Blogger Naval Bhatt said...

Thanks Ram, this is a wonderful blog...

 
At 26/10/10 04:24, Anonymous Anonymous said...

thank you very much, world need more bloggers and more posts like this )

 
At 24/11/10 18:44, Anonymous Carlos said...

Hello mate.

I've been all day working with this code and is not working. :S Is there anything I have to configure before, or do you have any idea why this is not working?

Any help would be truly appreciated. Thanks in advance!

 
At 26/11/10 16:42, Anonymous Your Friendly ABAPer said...

Define "not working"?

 
At 16/12/10 01:29, Anonymous Anonymous said...

HI can u please help me with how to change link attached to A BO pro grammatically ?

 
At 28/2/12 09:03, Blogger Thomas said...

Hi,

I am uploading a PDF file through a web dynpro application. The WDP sends the file in XSTRING format to my FM. I am using SCMS_XSTRING_TO_BINARY to convert it to binary. I can see the file in the GOS dialog, but when I try to open it, I get an error saying the file is corrupted.

Any idea what the problem might be?
Thanks in advance,
Thomas

 
At 26/3/12 09:45, Anonymous Anonymous said...

Thanks a lot.
Muchas gracias.

 
At 11/10/12 06:15, Anonymous purplemommy said...

This comment has been removed by a blog administrator.

 
At 11/10/12 06:16, Anonymous purplemommy said...

thank you very much for this code. this has worked for us in one requirement in QM. But the problem we're facing now is that, when we open some Q-Info records, the PDF attachments cannot be opened.

do you have any idea why is this happening? has anyone of you encountered the same problem?

 
At 10/4/13 12:54, Anonymous Anonymous said...

hi,
itz a great blog..i hav a problem in so_document_insert..it gives me the error of FOLDER_NO_AUTHORIZATION.
how do ideal with it? plz reply asap ifposibl..i hav urgent project deadlines

 
At 15/11/13 09:33, Anonymous Anonymous said...

Just a hint if you use
gui_upload (fm or class)
you should set
filetype = 'BIN'
read_by_line = ''
CHANGING
data_tab = lt_content[].
and one more thing it is better
to use 'BINARY_RELATION_CREATE'
commit can be done outside your local execution.

 
At 15/1/14 05:50, Blogger Sushant Ranade said...

You are truly a Friendly ABAPER mate... Hats off to you... :)

 
At 12/9/14 04:12, Blogger Patrick Dean said...

Love the friendly style - thanks for doing this and keep up the good work.
ATB. P.

 
At 6/10/14 08:17, Anonymous Anonymous said...

Hi, i am trying to attach a .csv file, the program is working fine....and i checked table SOOD and found my document there.....but i cant see attachment in my sales order.BUS2032.

...means there is no attachment in SO.
Please let me know what i am missing.

 
At 29/1/15 08:13, Anonymous Anonymous said...

Thank you for your useful post!
By the way, the BUS... is actually
a code of a sap business object, and those are managed in transaction SWO1

 
At 4/11/15 06:08, Blogger Marcos Melo said...

Hi,
Thank you very much for your help.
If you neeed some help you can count with me: marcosmelo@gmai.com
Att, Marcos / BRAZIL

 
At 5/11/15 13:14, Anonymous Anonymous said...

Hi,
I need to create note as attachment for IW32. Can you help me in acheiving this? It is very urgent requirement.

Venu

 
At 20/1/16 02:59, Blogger Unknown said...

one of the great blog i have read thanks a lot bud saved me something well just curious which type of files it can support like i have uploaded a text file but when i download it from attachment i get special characters so can you please guide me which type of files this code will upload it without changing its content and what to do for the files that are changed.

 
At 25/1/16 02:25, Blogger Unknown said...

Hi ,

Thanks for your help it helped me a lot . i have some issues which file formats does this support ?? and what if somebody upload a duplicate file it is duplicated there i dont want to duplicate it i want it to overwrite the previous attachment . waiting for your help

 
At 15/9/16 04:27, Blogger Jeevan nileshwar said...

Hi Friendly ABAPer,

My attachment comes from a middle ware(PI) and is in an xString format. how to attach this through custom program?

 
At 10/10/16 09:26, Anonymous Anonymous said...

Thanks, it helped a lot.. valuable post.

 
At 30/11/16 07:27, Anonymous Anonymous said...

Dear Frindly Abaper,

Thanks for such an informative blog post.

I am facing a problem, my .pdf file is coming from a dot net application and they are creating it using HTML (for formatting) and in textual format.

Scanned imaged pdf files are successfully uploaded and viewed in the attachment but the problem is coming in the first type of pdf files, which are created using HTML. It is showing an error of corrupt file.

I guess the problem is with the binary format but I am not sure as how to handle those type of file, please help.

Regards,
Prameet

 
At 30/11/16 23:38, Anonymous Friendly ABAPer said...

Prameet, PDF is PDF, it does not matter how it was created. When you get the right data in binary format it'll open. I can only guess that you are not actually given the correct PDF data by the external application.

You might want to get the story straight (e.g. I couldn't understand what "using HTML ... and in textual format" really means) and ask on SCN.

 
At 8/2/17 23:47, Anonymous Anonymous said...

Dear Friendly ABAPer ..... thanks for the post ..... I have a problem in converting pdf data from byte mode Xstring to binary format .... please suggest some FM to convert PDF data stored in a table in xstring byte mode.

Regards,
Prameet

 
At 7/3/17 15:55, Blogger elizabeth james said...

Hi All,

I have implemented the same code but unable to open the PDF file attached.
getting error saying not supported file type. Could you please let me know how to fix this?

 
At 13/3/17 18:06, Anonymous Friendly ABAPer said...

All, look at the date - this blog is almost 10 years old. I have moved on and am not able to answer your questions or update the code. Please search for newer options (classes?) for GOS development and post any questions on SCN.

With this in mind, I have to lock any further comments. Thank you for the feedback but this blog will no longer be updated, sorry!

 

Post a Comment

Links to this post:

Create a Link

<< Home