Purpose
Use the GuiXT OData API to
manage attachments

The SAP standard OData service API_CV_ATTACHMENT_SRV allows us to manage attachments for business objects. You can perform operations such as upload and download attachments, delete attachments, list attachments.

Business objects types and keys

To reference a specific business object, you need the SAP standard name for its type and information about the key; in particular, the key length, since the key often must be specified with leading zeros.

The following table lists the common SAP business object types and provides information about the corresponding key field:

Object BOR Type Key Field Length
Business Partner BUS1006 Business Partner Number 10
Equipment EQUI Equipment Number (EQUNR) 18
Goods Movement BUS2017 Material Document Number (MBLNR) + Fiscal Year (MJAHR, 4 digits, no exit) 10
Inbound Delivery BUS2015 Delivery Number (VBELN) 10
Incoming Invoice (Logistics Invoice Verification) BUS2081 Document Number (BELNR) 10
Maintenance Notification BUS2038 Notification Number (QMNUM) 12
Maintenance/Service Order BUS2007 Order Number (AUFNR) 12
Material BUS1001 Material Number (MATNR) 18
Purchase Order BUS2012 Purchasing Document Number (EBELN) 10
Purchase Requisition BUS2105 Purchase Requisition Number (BANFN) 10
Quality Notification BUS2078 Notification Number (QMNUM) 12
Quotation (Vendor Quotation) BUS2011 Purchasing Document Number (EBELN) 10
RFQ (Request for Quotation) BUS2010 Purchasing Document Number (EBELN) 10
Sales Inquiry BUS2030 Sales Document Number (VBELN) 10
Sales Order BUS2032 Sales Document Number (VBELN) 10
Sales Quotation BUS2031 Sales Document Number (VBELN) 10
Service Entry Sheet BUS2091 Service Entry Sheet Number 10
Service Notification BUS2080 Notification Number (QMNUM) 12

For master data, the object type is often the table name rather than a BUSxxxx code (e.g. EQUI, IFLOT, LFA1, KNA1). See transaction SWO1 (F4 on the object type field).

 

Upload an attachment

Example: Upload an attachment for a maintenance notification
// key structure for attachment upload
CreateStructure V[objkey] _
    BusinessObjectTypeName LinkedSAPObjectKey

// set key
Set V[objkey.BusinessObjectTypeName] "BUS2038"
Set V[objkey.LinkedSAPObjectKey] "000010000073"

// upload attachment
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/AttachmentContentSet" _
  headervariables:="objkey" _
  method:="POST" _
  fromFile:="G:\warehousedamages\parcel.png" 

The details of the uploaded attachment are set as follows:

In our example, we specified the 12-digit message number with leading zeros, as expected by the attachment service, e.g., "000010000073". If you have the number in an external format without leading zeros, for example, "10000073", the simplest solution is to have the GuiXT OData API perform the conversion:

Example: Upload an attachment for a maintenance notification
// key structure for attachment upload
CreateStructure V[objkey] _
     BusinessObjectTypeName LinkedSAPObjectKey

// set key
Set V[objkey.BusinessObjectTypeName] "BUS2038"
Set V[objkey.LinkedSAPObjectKey] "10000073"

// upload attachment
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/AttachmentContentSet" _
  headervariables:="objkey" _
  options:="conversionExitInput.LinkedSAPObjectKey=alpha:12" _
  method:="POST" _
  fromFile:="G:\warehousedamages\parcel.png" 

If you forget to perform this conversion, the OData service will not return an error message but will respond with "201 Created." You can then download the attachment, again with the incorrect message number, but you will not find it in SAP transaction IW22/IW23.

The situation is different if you make a typo in the object type and enter, for example, "BUSS2038." SAP then returns HTTP code "400 Bad Request" with an error message that GuiXT displays in the Script Editor:



The SAP error message is a bit misleading in this case, but it's probably still a good idea to check for any error messages whenever you call the GuiXT OData API. You can do this using the "message" parameter as follows:

Displaying an error message
// SAP message structure
CreateStructure V[msg] code message type target severity

// key structure for attachment upload
CreateStructure V[objkey] _ 
   BusinessObjectTypeName LinkedSAPObjectKey

// set key
Set V[objkey.BusinessObjectTypeName] "BUSS2038"
Set V[objkey.LinkedSAPObjectKey] "00010000073"

// upload attachment
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/AttachmentContentSet" _
  headervariables:="objkey" _
  method:="POST" _
  fromFile:="G:\warehousedamages\parcel.png" _
  message:="msg"

if V[msg.type=E]
  Message "E: &V[msg.message]" title="Attachment upload failed"
endif





In the following examples, we'll generally omit error handling so we can focus on the OData API.

With SAP HDM (Harmonized Document Management), you can specify which archive document types are permitted for each business object type and which type is set as the default. Here is an example (equipments):



If we upload an attachment without explicitely specifying the archive document type, it will be saved as "YP2" (Manuals). To have it saved as "GOS", add the DocType to the key fields:

Specifying the DocType
// key including DocType "GOS"
CreateStructure V[objkey] _
   BusinessObjectTypeName LinkedSAPObjectKey DocumentInfoRecordDocType
Set V[objkey.BusinessObjectTypeName] "EQUI"
Set V[objkey.LinkedSAPObjectKey] "210100091"
Set V[objkey.DocumentInfoRecordDocType] "GOS"

// upload attachment
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/AttachmentContentSet" _
  headervariables:="objkey" _
  method:="POST" _
  options:="conversionExitInput.LinkedSAPObjectKey=alpha:18" _
  fromFile:= _
    "G:\EquipmentDocuments\MaintenanceInstructions.210100091.pdf"





Read an attachment list

Example: Read and display the customer attachments
// attachment info
CreateStructure V[attachmentinfo] _
  FileName CreatedByUserFullName CreationDateTime 

// attachment list
CreateTable V[attachmentlist] include=V[attachmentinfo]

// parameters
CreateStructure V[objkey] _
     BusinessObjectTypeName LinkedSAPObjectKey
Set V[objkey.BusinessObjectTypeName] "KNA1"
Set V[objkey.LinkedSAPObjectKey] "1000260"


//read attachment list
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/GetAllOriginals" _
  parameters:="objkey" _
  options:="conversionExitInput.LinkedSAPObjectKey=alpha:10" _
  result:="attachmentlist" 


// display attachment list
Table	(8,91)	(15,167)	title="Attachments"  _ 
  name="attachmentlist"  fixedColumns=3 	
Column "File" size=40 name="FileName" -readOnly
Column "Uploaded by" size=20 name="CreatedByUserFullName" -readOnly
Column "Date" size=10 name="CreationDateTime" -readOnly

 



Download and display an attachment

We extend the previous example, allowing the user to select an attachment and to display it in a separate window. For the download we need the full attachment key.

GuiXT Script: Download and display a customer attachment
// attachment key needed for downloading
CreateStructure V[attachmentkey] _
  DocumentInfoRecordDocType DocumentInfoRecordDocNumber _
  DocumentInfoRecordDocVersion DocumentInfoRecordDocPart  _
  LogicalDocument ArchiveDocumentID  LinkedSAPObjectKey _
  BusinessObjectTypeName

// attachment info
CreateStructure V[attachmentinfo] _
  FileName CreatedByUserFullName CreationDateTime 

// attachment list
CreateTable V[attachmentlist] _
  include=V[attachmentkey] include=V[attachmentinfo]


// parameters
CreateStructure V[objkey] BusinessObjectTypeName LinkedSAPObjectKey
Set V[objkey.BusinessObjectTypeName] "KNA1"
Set V[objkey.LinkedSAPObjectKey] "1000260"


//read attachment list
CallVB guinet.odata.execute _
  service:= _
   "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/GetAllOriginals" _
  parameters:="objkey" _
  options:="conversionExitInput.LinkedSAPObjectKey=alpha:10" _
  result:="attachmentlist" 


// display attachment list
Table	(8,91)	(15,167)	title="Attachments"  _
  name="attachmentlist"   -singleRowSelection fixedColumns=3
Column "File" size=40 name="FileName" -readOnly
Column "Uploaded by" size=20 name="CreatedByUserFullName" -readOnly
Column "Date" size=10 name="CreationDateTime" -readOnly

// button to display the attachment
PushButton	(6,91)	_
  "Display attachment" _
  process="display_attachment.txt"



InputScript display_attachment.txt
// determine the selected attachment
Set V[k] 0
label next_row

// no row left?
if not V[k<&V[attachmentlist.rowcount]]
  Return "W: Please select an attachment" -statusline
endif

Set V[k] &V[k] + 1

// selected ? else try next row
if not  V[attachmentlist.stat.rowselection.&V[k]]
  goto next_row
endif

// read attachment key and info
ReadRow V[attachmentkey] table=V[attachmentlist] index=&V[k]
ReadRow V[attachmentinfo] table=V[attachmentlist] index=&V[k]

// read attachment
CallVB guinet.odata.execute _
  service:= _
    "sap/opu/odata/sap/API_CV_ATTACHMENT_SRV/AttachmentContentSet" _
  toTempFile:="tempfile" _
  key:="attachmentkey"

// display attachment
Start "&V[tempfile]"

Return

 

  Components  InputAssistant + GuiXT Controls