Skip to Content

There could be many scenarios where we may have to deal with documents attached to the pdf form (SAP Interactive form). I had a particular scenario where end user fills in form and along with this; he is required to attach scanned copies of documents (like marriage certificate). Similarly there could be multiple attachments. Application would need to process interactive form with its attachments. Now this not only involves determining list of all the attachments but also to read those. This was challenging and I ventured on the journey to explore attachment related features of interactive form.

 

Attaching docs to PDF form – Let’s first understand how documents can be attached to interactive form. In Adobe Reader 7.0, navigate to ‘Tools –> Commenting –> Attach a file as comment’ menu.

 

image

 

Now after you browse to the relevant document, File Attachment Property box pops up. Using this box, you can define whether the document should be attached as an attachment or paperclip etc. You can give author data also in this box.

 

 

image

 

 

After attachment, the file will appear in the Attachments tab of the file.

 

image

 

Application – 

PDF with attached Document:

 

 

image

 

 

 

After uploading the form in backend, application would determine the list of documents attached to the form.

 

image

 

User can click on the document name, and respective document will be opened.

Later, it can be printed or saved locally.

 

 

image

 

 

 

Step by Step approach:Now lets understand the step by step approach.

Layout Design: Assuming you’ve logged in NWDS (NW Developer Studio) and created a view, please follow below steps – 

 

  • Add FileUpload UI element in the layout of the view.

  • Add a table, which will show the list of attachments in the form.

  • Add a button, after clicking on it, PDF file would be read.

 

image

 

 

Context Design:

  • Create a value node Attachment of cardinality 1..n 
  • Create two value attribute under this node DocContent and DocName of type com.sap.ide.webdynpro.uielementdefinitions.Resource and string respectively.
  • Create a value node Tablenode
  • Add value attributes Data, Description, FileName, MimeType of type binary, String, String and String respectively.
  •  

     

     

    image

     

     

Bind values DocContent to FileUpload.Data, FileUpload.resource and DocName to

FileUpload.filename.

  

Bind the Table of the view to the Tablenode node of the context. Bind FileName,

Description and MimeType to respective columns.  

 

Now, in the onAction property of the button in layout assign ShowAttachment method.  

 

Add the following code in ShowAttachment method. In this method: 

 

Logic: 

    a)       Read the PDF in fileResource variable of type IWDResource.

    b)       Convert PDF into Binary file, and add it to the table P_Rawtab.

    c)       Pass the table to BAPI Zrfc_Get_Attachment_List, and execute the BAPI.

    d)       After successful execution of the BAPI, list of attachment is returned in

    table L_Attachments.

    e)       Bind the table to Tablenode of the context.

      

     

     

*******************************************************************************************

Code: 

*******************************************************************************************

    IPrivateAttachment_ApplView.IAttachmentElement element = wdContext.currentAttachmentElement();

    try {

    IWDMessageManager msgManager = wdComponentAPI.getMessageManager();

    IWDResource fileResource = wdContext.currentAttachmentElement().getDocContent();

    if (fileResource == null) {                        

    msgManager.reportException(“Can’t Read the Document”,false);

    } else {

    String fileName;

    String fileType = fileResource.getResourceType().getFileExtension().toUpperCase();

    if (“PDF”.equals(fileType)

    //Just I have added some validation, you can remove this

    || “DOC”.equals(fileType)

    || “RTF”.equals(fileType)

    || “XLS”.equals(fileType)) { 

    element.setDocName( element.getDocContent().getResourceName()); 

    } else {

    msgManager.reportWarning(“Document type could not be uploaded”);

    }

    fileName = wdContext.currentAttachmentElement().getDocName();

    InputStream fileStream = fileResource.read(false);

    Zrfc_Get_Attachment_List_Input attach_Input =  new Zrfc_Get_Attachment_List_Input();

    int fileSize = 0;

    byte[] lineContents = new byte[255];

    int numBytesRead = 0;

    do {

    numBytesRead = fileStream.read(lineContents);

    if (numBytesRead > 0) {

    fileSize += numBytesRead;

    Zstru_Raw255 attach = new Zstru_Raw255();

    attach.setRaw255(lineContents);

    attach_Input.addP_Rawtab(attach);

    Arrays.fill(lineContents, (byte) 0);

    }

    } while (numBytesRead > 0);

          wdContext.nodeZrfc_Get_Attachment_List_Input().bind(attach_Input);

          wdContext.currentZrfc_Get_Attachment_List_InputElement().modelObject()

.execute();

    wdContext.nodeOutput_RFC().invalidate();

    int size = wdContext.nodeL_Attachments_Out().size();

    IPrivateAttachment_ApplView.ITableNodeElement tableele;

    IPrivateAttachment_ApplView.ITableNodeNode node = wdContext.nodeTableNode();

    for (int i = 0; i<size; i++) {

    tableele = node.createTableNodeElement();

    tableele.setFileName( wdContext.nodeL_Attachments_Out()

    .getL_Attachments_OutElementAt(i).getFilename());

    tableele.setDescription(wdContext.nodeL_Attachments_Out()

    .getL_Attachments_OutElementAt(i).getDescription());                             

    tableele.setMimeType(wdContext.nodeL_Attachments_Out()

    .getL_Attachments_OutElementAt(i).getMimetype());                             

    tableele.setData(wdContext.nodeL_Attachments_Out()

    .getL_Attachments_OutElementAt(i).getData());                              

    node.addElement(tableele);

    }

    msgManager.reportSuccess(“Document uploaded sucessfully. “);              

    }

    } catch (Exception ex) {

    wdComponentAPI.getMessageManager()

    .reportException(“Error in Reading Document ” +

    ex.getMessage(),false);           

    }

     

=======================================================================

 

Create one more action OpenAttachment, for showing the attachment. Convert fielname column of the table to LinktoAction. Assign action OpenAttachment to the onAction property of the LinktoAction element.

Logic and Code for the method OpenAttachment is as followed: 

Logic: 

     a)  Read the selected row of the table using getTreeSelection method of the table.

     b)  According to the file extension, call createCachedResource method of WDResourceFactory.

     c)  WDWebResourceType parameter can have value, according to the file extension.

In this case I have taken PDF, DOC and UNKNOWN.

     d)  Using resource.getUrl(0) and IWDWindow selected attachment is displayed in a different window. 

*******************************************************************************************

Code:             

*******************************************************************************************

try {

    IPrivateAttachment_ApplView.ITableNodeElement selnode =

    (IPrivateAttachment_ApplView.ITableNodeElement)

    wdContext.nodeTableNode().getTreeSelection();

    int name_len = selnode.getFileName().length();

    IWDResource resource;

    String file_ext = selnode.getFileName()

                                      .substring(name_len – 3, name_len);

    if (file_ext.toUpperCase().equals(“PDF”)) {

    resource =  WDResourceFactory.createCachedResource(

    selnode.getData(), selnode.getFileName(), WDWebResourceType.PDF);

    }else if(file_ext.toUpperCase().equals(“DOC”)){

    resource = WDResourceFactory.

                               createCachedResource

    (selnode.getData),selnode.getFileName(), WDWebResourceType.DOC);

    }else{

    resource = WDResourceFactory.

                               createCachedResource

    (selnode.getData(), selnode.getFileName(), WDWebResourceType.UNKNOWN);

    }

    IWDWindow window = wdComponentAPI.getWindowManager()

    .createNonModalExternalWindow(resource.getUrl(0),

    selnode.getFileName());

    window.show();

    } catch (Exception ex) {                  

    wdComponentAPI.getMessageManager().reportException(“Error in Opening File “,false);

    }

 ======================================================

A custom BAPI is called for reading the attachment of the Interactive form.

This BAPI has following attributes: 

 

     

    Logic: 

     a)  Convert Binary string into XString using FM SCMS_BINARY_TO_XSTRING.

     b)  Create an instance of PDFObject class.

     c)  Call the method set_task_getattachments( ) of  PDFObject class for setting the task to get attachment.

     d)  After executing the class, use get_attachments( ) of  PDFObject class for getting list of attachment. 

         

    *******************************************************************************************

    Code:             

    *******************************************************************************************

                   Name: ZRFC_GET_ATTACHMENT_LIST 

    Import Parameters:  

    P_LENGTH                   TYPE    I                                   Size of Part File

    Export Parameters: 

    L_ATTACHMENTS         TYPE    TFPATTACHMENTS      Attachment List

    Tables:            

    P_RAWTAB                  LIKE     ZSTRU_RAW255           Structure of Raw255            

     

    Source Code: 

    *”———————————————————————-*”

    *”Local Interface:

    *”  IMPORTING*”     VALUE(P_LENGTH) TYPE  I OPTIONAL

    *”  EXPORTING*”     VALUE(L_ATTACHMENTS) TYPE  TFPATTACHMENTS

    *”  TABLES*”      P_RAWTAB STRUCTURE  ZSTRU_RAW255 OPTIONAL

    *”———————————————————————-    

    TYPE-POOLS slis.    

    DATA: l_len       TYPE i,         

    p_content   TYPE xstring,         

    c_ads       type rfcdest value ‘ADS’.    

    DATA: l_fp          TYPE REF TO if_fp,         

    l_pdfobj      TYPE REF TO if_fp_pdf_object,         

    l_pdf         TYPE xstring,         

    l_fpex        TYPE REF TO cx_fp_runtime,         

    l_layout      TYPE slis_layout_alv.    

    CALL FUNCTION ‘SCMS_BINARY_TO_XSTRING’     

    EXPORTING       

    input_length = p_length     

    IMPORTING       

    buffer       = P_content     

    TABLES       

    binary_tab   = p_rawtab[]     

    EXCEPTIONS       

    failed       = 1       

    OTHERS       = 2.   

    IF sy-subrc IS NOT INITIAL.     

    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno 

    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.   

    ENDIF. 

    * Get FP reference.   

    l_fp = cl_fp=>get_reference( ).    

    TRY.

    *     Create PDF Object.       

    l_pdfobj = l_fp->create_pdf_object( connection = c_ads ). 

    *     Set document.       

    l_pdfobj->set_document( pdfdata = p_content ). 

    *     Set task to get attachments.       

    l_pdfobj->set_task_getattachments( ). 

    *     Execute, call ADS.       

    l_pdfobj->execute( ). 

    *     Get result.       

     l_attachments = l_pdfobj->get_attachments( ).       

    CATCH cx_fp_runtime_internal

    cx_fp_runtime_system

    cx_fp_runtime_usage INTO l_fpex.  

    ENDTRY.  

To report this post you need to login first.

22 Comments

You must be Logged on to comment or reply to a post.

  1. Prabhakaran TK
    Hi Amit,

    Good Work..

        We created a BAPI with the same code given by you. When I tried to call the BAPI (from java Application) with the PDF(with Attachments), I am not getting any rows in the output. i.e. It says that, no attachments found in the PDF file.But there are attachments in that PDF file given as input to the BAPI.

        I tried the same WebDynpro application also, but same result.

        Then, we created an output parameter(say P_CONTENT), which returns the same content(PDF with attachments) which was given as input. When I run the java application, I am able to get the same PDF file in that output parameter(P_CONTENT), and open it also.

       It’s clear that, the BAPI is getting the correct PDF content, but not able to get those attachments within PDF file.
       
       Can you tell me, Where the problem is?

    Thanks & Regards,
    Prabhakar.

    (0) 
    1. Amit Rai Post author
      Hi Prabhakar,

      Please check the value of parameter p_length in FM ‘SCMS_BINARY_TO_XSTRING’. Value of p_length should be size of p_content.

      Hope this helps,
      Amit

      (0) 
  2. Jeroen Cosijnse
    Hi Amit,

    Good blog about extracting Attachments. I ‘ve a question about how you can set open the PDF to enable add an Attachment. When I generate a PDF with Readerrights this seems not enough.

    Kind regards,
    Jeroen Cosijnse

    (0) 
    1. Amit Rai Post author
      Thanks Jeroen,

      Adding attachments feature is avaliable from Adobe 7.0.9 version, and your PDF should be dynamic.

      (0) 
  3. Hanoz Tarapore
    Hi Amit,

    Thanks for this excellent blog.

    However, its major drawback is that we need to go to the backend R/3 to extract the attachemnts from the pdf. It requires creation of JCos, RFCs etc.

    PDFObjects are available in webdynpro for Java as well. So, there has to be a way to replicate the attachment-extracting functionality (that you achieved in R/3), in webdynpro for java too!!.

    Please post it here, if you have managed to achieve the same using only webdynpro for java.

    Regards,
    Hanoz T

    (0) 
  4. Thomas Mocker
    Hi, great work. I have one question about it. What will be the solution for the following:

    In the PDF are two input fields that shall contain the filename (e.g. browser functionality “Browse”) and behind this input field a button “Add attachment”. When pressing this button, a file-open-dialog shall appear. The selected filename shall be written into the input field and the file shall be stored as attachment.

    How can this be solved?

    Best Regards.

    Thomas

    (0) 
    1. Amit Rai Post author
      Thanks Thomas,

      But Browser button is still not available in PDF. You have to use standard toolbar for attaching a file to the PDF.

      Regards,
      Amit

      (0) 
  5. joemol koshy
    Hi Amit,
    This doc is of great help to me but am facing an error when i use it. You have used ZSTRU_RAW55 in the Tables parameter for the FM. Can you please tell how this structure is defined?
    (0) 
  6. Anantharam Subramanian
    Hi,
       Could you please let me know about the structure ZSTRU_RAW255 within the BAPI. Please let me know how to define it in the backend. Also I have adobe reader 7.0. But I do not see the option “Attachment with comments” under the menu “Tool”. Could you please help?

    thanks

    (0) 
    1. Amit Rai Post author
      First, you search for a structure of RAWSTRING with length of 255, if you find it, then you can use it instead of ZSTRU_RAW255. Otherwise, you can create this structure in backend using SE11 transaction.

      And from Attachment option is available after Adobe 7.0.9 version.

      (0) 
  7. Hanoz Tarapore
    Hi Amit,

    My requirement is to allow deletion of attachements within the form, for users with specific roles.

    Is it possible to selectively enable/disable the deletion button in the attachments-tab?

    Regards,
    Hanoz

    (0) 
  8. Sandra Rossi
    Hi Amit,

    thx for the blog, it was useful (I used ABAP).

    You are talking about adding file as a comment (Tools | Commenting | Attach a file as a comment), but there is also an option (Document | Attach file).

    If I use the option you mention, I can’t read it via get_attachments abap method, but I can get it via get_annotations method. Unfortunately, I also get all types of annotations, in XML format, and binary files (attached as comments) are compressed (FlateDecode).

    If I use the option Document | Attach file, then I get the file successfully with get_attachments abap method.

    Do you have an idea why there are these differences?

    Thx
    sandra

    PS: 1) My system is 7.0 SP 13, and adobe reader is 8.1.2
    2) something else : I get a null pointer exception if there is no file attached in com.adobe.ads.operation.GetAttachments.processAllAttachments. Hopefully, it can be handled in ABAP, but I am not able to differentiate this error from any other error.

    (0) 
  9. Joan Lee Hwee Nee
    Dear Amit,

       Thx for the post, i would like to know where does the attachments being saved? after the user attach a file in the adobe form, then where does the attachment store at?  Is it possible if i wanted to store the documents at another server? Thank you

    Regards,
    Joan

    (0) 
    1. Amit Rai Post author
      Hi Joan,

      In table  l_attachments we have a field of type XSTRING, this contains your attachment. There are some standard function modules available that can be used for storing the attachment at any other server.

      Hope this helps,
      Amit

      (0) 

Leave a Reply