Adobe Acrobat and VBA – An Introduction

Here is another topic that comes up every now and then: How can I “talk” to Adobe Acrobat from e.g. MS Excel via VBA? I’ll try to give an introduction into that subject in this document. I will only discuss the basics, but I’m open for suggestions about what part to discuss next. So keep the comments coming.

More after the jump…

The Warning Upfront

Before we get too deep into this, let me say this: I am not a VBA expert. I do not program in VBA or VB. All I know about VB is from googling a few things and looking at sample code. It does help that I’ve programmed in many (make that a capital ‘M’ Many) programming languages, and at the end most of them share enough characteristics that once you know one, you know all of them… But still, don’t consider my VB programs to be at an expert level. I only use the samples to demonstrate general methods. It’s up to you to fill in all the missing details (e.g. exception handling).

Resources

All this information is available in one form or another in Adobe’s SDK documentation. Before you read any further, click on this link and take a look at what they have available.

There are (at least) two documents that are required reading if you want to use Acrobat from within your VBA code:

If you want to utilize the VB/JavaScript bridge, you also should read the JavaScript related documents:

All of these documents can also be accessed via Adobe’s online documentation system. In order to find the documents I’ve listed above, you need to expand the tree on the left side of the window for the “JavaScript” and “Acrobat Interapplication Communication” nodes.

There is always more than one way…

There are two ways your program can interact with Acrobat. One is more direct than the other, but both require the same mechanism to get things started…
You can either use the “normal” IAC (Inter Application Communication) interface, which is basically a COM object that your program loads and uses to communicate with Acrobat, or you can use the VB/JavaScript bridge, which allows access to Acrobat’s JavaScript DOM. The latter case still requires that your program first establishes a connection to Acrobat via IAC.

Let’s get the party started

As I mentioned before, regardless of how we want to remote control Adobe Acrobat from VB, we need to establish a connection to it’s COM object (or OLE server). You may have noticed that I always talk about “Adobe Acrobat”, and not the “Adobe Reader”. What I’m presenting here is valid for the Adobe Acrobat, Reader only supports a small subset of features. To learn more about what the differences are, see the IAC Developer Guide. For the purpose of this document, I will use MS Excel 2007 and Adobe Acrobat 9 Pro. As long as you have a version of Acrobat that is compatible with the version of VBA that you are using, you should be able to follow along without any problems.

Preparing MS Excel 2007

When you install Office 2007 or Excel 2007, make sure that you select the Visual Basic Editor component, otherwise you will not be able to write VBA code. This is different than all the versions up to 2007. Once installed, you need to add the “Developer” tab to the ribbon. This is done on the Excel Options dialog, under the Popular category:

excel_options.png

Once that is done, you should see the “Developer” tab as part of the ribbon:

developer_tab.png

Our First Button

Open a new document and select the Developer tab. Then go to the Insert control and place a button on your document. This will pop up the “Assign Macro” dialog, just click on the “Add” button, which will bring up the VBA editor. Nothing special so far.

Before we can use any of Acrobat’s functionality, we need to make sure that VBA knows about the Acrobat objects. On the VBA dialog, select the “Tools>References” menu item. On the dialog that pops up, make sure that the TLB for your version of Acrobat is selected. This is what it looks like for my system:

references.png

Now we can add code that references the Acrobat objects to our button handler. Of course, before we do that, we need to decide what our button is actually supposed to trigger. Let’s start with something simple – let’s combine two PDF documents and save the result as a new document.

I’ll present the whole program first, and will then explain the different parts.

Sub Button1_Click()

    Dim AcroApp As Acrobat.CAcroApp

    Dim Part1Document As Acrobat.CAcroPDDoc
    Dim Part2Document As Acrobat.CAcroPDDoc

    Dim numPages As Integer

    Set AcroApp = CreateObject("AcroExch.App")

    Set Part1Document = CreateObject("AcroExch.PDDoc")
    Set Part2Document = CreateObject("AcroExch.PDDoc")

    Part1Document.Open ("C:\temp\Part1.pdf")
    Part2Document.Open ("C:\temp\Part2.pdf")

    ' Insert the pages of Part2 after the end of Part1
    numPages = Part1Document.GetNumPages()

    If Part1Document.InsertPages(numPages - 1, Part2Document,
		0, Part2Document.GetNumPages(), True) = False Then
        MsgBox "Cannot insert pages"
    End If

    If Part1Document.Save(PDSaveFull, "C:\temp\MergedFile.pdf") = False Then
        MsgBox "Cannot save the modified document"
    End If

    Part1Document.Close
    Part2Document.Close

    AcroApp.Exit
    Set AcroApp = Nothing
    Set Part1Document = Nothing
    Set Part2Document = Nothing

    MsgBox "Done"

End Sub

Save the document. When prompted for a filename and a filetype, select the type of “Excel Macro-Enabled Workbook” – otherwise the program you just added will get stripped out of the file.

Make sure that there are two files named Part1.pdf and Part2.pdf in the c:\temp directory.

Click the button and enjoy…

After the program is done, there will be a new file C:\Temp\MergedFile.pdf on your disk. Open that in Acrobat, and verify that it indeed contains the results of concatenating the two source files.

So, how does it work?

The whole program is in a button handler.

Sub Button1_Click()
...
End Sub

Let’s now look at the different parts of that handler.

At first, we need to setup a bunch of objects that we will use further down the code:

    Dim AcroApp As Acrobat.CAcroApp
    Dim Part1Document As Acrobat.CAcroPDDoc
    Dim Part2Document As Acrobat.CAcroPDDoc
    Dim numPages As Integer

The first statement sets up an object of type Acrobat.CAcroApp – this reflects the whole Acrobat application. If you look through the documentation, you’ll see that there are a number of things that can be done on the application level (e.g. minimizing or maximizing the window, executing menu items, retrieve preference settings, closing the application, …). The next two lines declare two objects of type Acrobat.CAcroPDDoc – these reflect the two documents that we need to open.

There are two different document types available in the OLE part of IAC: The AVDoc and the PDDoc. An AVDoc is one that gets opened in Acrobat’s user interface, the user can navigate through it’s pages, and do anything that you can do with a PDF document when you double-click on it to open it in Acrobat. A PDDoc on the other hand gets opened in the background. Acrobat still has access to it, and can manipulate it, but the user does not see it. This is useful if a program should quietly do it’s work without showing the user what’s going on.

Every AVDoc has a PDDoc behind the scenes, and that object can be retrieved via the AVDoc.GetPDDoc method. A PDDoc only has an associated AVDoc if it is actually shown in Acrobat, however, we cannot retrieve that AVDoc object from within the PDDoc. This sounds complicated, but once you get more familiar with how these things are used, it becomes second nature.

We also need an integer object to store the number of pages in the first document.

    Set AcroApp = CreateObject("AcroExch.App")
    Set Part1Document = CreateObject("AcroExch.PDDoc")
    Set Part2Document = CreateObject("AcroExch.PDDoc")

In the next step, we initialize the three Acrobat related objects. Nothing special here.

    Part1Document.Open ("C:\temp\Part1.pdf")
    Part2Document.Open ("C:\temp\Part2.pdf")

Now that our objects are initialized, we can use the methods to do something with the objects. In order to merge files, we need access to both the source files, so we have to call the Open() method on both these objects. The key to success is to specify the whole path name, directory and filename.

    numPages = Part1Document.GetNumPages()

The method InsertPages requires that we specify after which page to insert the second document. Because we want to insert the pages after the last page of the first document, we need to find out how many pages we have in that document. The GetNumPages() method does return that information.

This is also, where it becomes a bit tricky: Acrobat starts to count the pages in a PDF document at zero. So, if we want to insert the pages after the first page in the document, we need to insert after page number zero. If we want to insert after the second page, we need to insert after page number one… Because we want to insert the pages after the last page of the first document, we need to insert the pages after (lastPage-1). Again, this is a bit confusing, but after a while it gets easier.

    If Part1Document.InsertPages(numPages - 1, Part2Document,
		0, Part2Document.GetNumPages(), True) = False Then
        MsgBox "Cannot insert pages"
    End If

This is where Acrobat does all it’s work. The parameters of the InsertPages method are described in the Interapplication Communication API Reference document: InsertPages

Now we only have to save the document, do some cleanup and exit our program:

    If Part1Document.Save(PDSaveFull, "C:\temp\MergedFile.pdf") = False Then
        MsgBox "Cannot save the modified document"
    End If

    Part1Document.Close
    Part2Document.Close

    AcroApp.Exit
    Set AcroApp = Nothing
    Set Part1Document = Nothing
    Set Part2Document = Nothing

    MsgBox "Done"

With these steps, and the information in the API documentation, you should be able to write simple programs.

I’ll document the VB/JavaScript bridge in my next posting.

This entry was posted in Acrobat, PDF and tagged , , , , , . Bookmark the permalink.

71 Responses to Adobe Acrobat and VBA – An Introduction

  1. Pingback: Karl Heinz Kremer’s Ramblings » Acrobat, JavaScript and VB walk into a bar…

  2. Arne Grunert says:

    Hi, I am using Vista x64 and Office 2007.

    I get an errror in this part of the code:

    If Part1Document.InsertPages(numPages – 1, Part2Document,
    0, Part2Document.GetNumPages(), True) = False Then

    Any idea?

  3. Jens says:

    Perfect! This was the part of code I was looking for.
    My code added the PDF’s in the wrong order.

    Thanks!

  4. bla says:

    Is supposed to be all 1 line, not 2.

  5. khk says:

    I don’t think that makes a difference – the interpreter will put the line back together.

  6. Vishy says:

    I don;t find acrobat in references. I only find Acrobat Type library.

  7. khk says:

    What version of Acrobat are you using?

  8. Mike says:

    I have tried to use the above code in an office 2003 macro, with Adobe 8 with no success.

    I had to change the open statements to openAVDoc statements otherwise excel crashes when trying to open the file. After this, the number of pages is not calculated as the result for numPages is still zero eventhough the doc has 32. This could be why the InsertPages line fails, but I cant seem to get the correct information in order to complete this step.

    In addition, can you simply open an excel or word file in acrobat and have the conversion take place at that time?

  9. MeAndI says:

    Thanks for this great intro,

    this even works with Excel2000 from VBA (Vb6…) if you select Acrobat.tlb (“Acrobat 7.0 Type Lib..” / “Acrobat”).
    Now, reading / searching for Text patterns in a pdf via script shouldn’t be that great problem anymore, or should it? ;D

  10. khk says:

    Define “great problem” 🙂 It’s not easy to get text information out of a PDF document. You can use the JavaScript bridge and use the word finder in JavaScript to get access to the text.

  11. heidi says:

    Hello, thank you for this code very useful. i would like to add page number at the bottom of my PDF created. Do you know how can i do this in VBA?

  12. khk says:

    You can add page numbers via the VB2JS bridge by adding a form field or a text box and filling it with the page number. As the last step you can then flatten the page to “burn in” the interactive content you just added in order to convert it to real PDF content. Let me know if you need more detailed instructions.

  13. reg says:

    Thank you. It took me all day to find this information. It looks like this will only work if you have full Acrobat. What happens if I write code and the people using my code only have Acrobat Reader?

  14. khk says:

    Adobe Reader supports only a small number of functions. You need to be familiar with Adobe’s API documentation to determine what’s available in Reader vs. the full Acrobat. If somebody only has Reader installed, your program will not work, because the functions available to Reader are in a separate type library.

  15. Gautier thomas says:

    Thanks a lot for this page…and its author
    It was really helpful 🙂

  16. Norman Dolph says:

    K H – !
    You are VALUABLE!

    and lucid as well
    thanks,

  17. Greg says:

    This is my first time visiting your blog, and I want to commend you on writing a great article. This is a good foundation for manipulating PDF’s via MS Office, and I learned a lot reading this. I hope you write about this more…

  18. Thanks for the code.Working great.

  19. Carlos Alberto says:

    If Part1.pdf has only one page, and Part2.pdf has only a page, too, apears the message “Cannot insert pages”. I appreciate your help to resolve that situation.

  20. Roger says:

    This has is great, it really fast tracked me into the world of Adobe Acrobat remote controlled by VBA. Many thanks! Rather than insert my focus is to replace some text in the PDF. Any suggestions?

  21. This is exactly what I needed to satisfy a request from a customer. I’m now modifying your procedure so that it can accept an array of . pdf filenames.

    If you’d like a copy of the modified procedure, just let me know.

  22. Brenda says:

    Is there any way to have the filenames appear as bookmarks?

  23. Samet says:

    Wow. that is very great thanks KH!

  24. jaime granado says:

    is there code where we can take specific pages from pdf 1 to merge into pdf 2 or delete all pages in pdf1 except specific pages? Also I would like to highlight certain text from pdf1 in the new merged file.
    Thanks,
    Jaime

  25. prat says:

    i have one pdf file having 2000 pages but i need to find some data in pdf get some data on the basis of searching and saved those data in excel. is this possible in VBA?. can you give me VBA code for that.

    Thanks,
    Prat

  26. Steve says:

    How could I combine 3 or more pdf files using this VBA code?

  27. Wayne Gunn says:

    Ive been trying to find a way to manipulate the menu system in acrobat to no avail. The menu item of interest is the ‘View/Page Display/Single Page Continuous’ menu, which can be either checked or unchecked. To get right into it, what I need to do is:
    1. Obtain a reference to the menu item
    2. Get its checked/unchecked status
    3. Check it if needed

    That seems straightforward but it’s been hell trying to get a straight answer from the acrobat forum, the one guy that keeps responding seems to have a vested interest in insisting that I go about the task his many other ways, none of which works.

    Is it possible to do this? Version 9
    Thanks

  28. Wayne Gunn says:

    Additionally, I am using VBA

  29. Larry says:

    Hi I am using VB Excell 2007, and the API setinfo member of AcroExch.PDDoc to set a Coustom property in a PDF as follows

    retval = Part1Document.SetInfo(“DocSummary”, CommentStg)

    However API is limiting the string value to 256 characters. I have verified that the len of CommentStg is 456 char however only the first 256 are sent to the PDF.
    Any Ideas why? I also verified that a custom property value can be greater than 256 chars. So I asume it is something in the API that has a limit. If so is thier a way around it?

    Thanks

  30. Karl Heinz Kremer says:

    Wayne, not every menu is exposed via the API. You can use the JavaScript method App.listMenuItems() to find out what menu items are actually exposed. You will then need to map the item you are interested in to the list of items you are getting. In this case, you want the “View” menu – the good news is that it’s actually available via the API. The Page Display options are “SinglePage”, “OneColumn”, “TwoPages”, “TwoColumns”. The problem however is that you cannot get the “Checked” status for these menu items. You can in a plug-in, but not from JavaScript or VBA. You can check them, but you cannot find out if the are checked or not.

  31. Karl Heinz Kremer says:

    Larry, I assume that this is a limit of the API. Because I am not working for Adobe, I don’t have any exposure to the reason why that is. When you check the API documentation for “GetInfo”, you’ll see that a maximum of 512 bytes are returned by that call. I assume that we are dealing with Unicode characters, and every character uses two bytes. That would give you those 256 characters. You might be able to go through the JavaScript bridge and use the JavaScript method to get access to the custom property.

  32. Shiva Prasad says:

    Hi,

    I have a problem with pdf file which is sometimes text running outside the set margins. Now, i need to find out these instances in the 600 pages pdf file. I hope this is possible to identify these issues by overlapping all pages of the document to one page so that we will get to know if there are any such instances in the file.

    Can someone please write code for me?

    Regards,
    Shiva

  33. Karl Heinz Kremer says:

    Shiva, I don’t think anybody will write code for you for free to do that. If you are interested in a professional solution, feel free to get in touch with me via email. That’s what I do for a living 🙂

  34. Niek says:

    Hello Karl Heinz,

    First of all, thanks for this post. I notice that it’s quite old, but I recently found it and it’s been a great help!
    I have written a small app using parts of your example. I’m working with Windows 7, Excel 2013 and Acrobat XI Pro. On this computer it’s working like a charm. However, on another computer with Windows 8, Office 365 (the download version, not the cloud version) and Acrobat XI pro, I get “cannot insert pages”. Strange thing is other elements of the link with Acrobat are working fine, for example part1Document.open, part1document.save, jso.addWatermarkFromText(…). Any ideas?

    Best regards,
    Niek

  35. Karl Heinz Kremer says:

    I don’t have access to Office 365, so I cannot test your setup. You could try to run the VBA code as pure VB (or VBScript) outside of Office 365 to see if the problem is caused by Office, or something else. Here is some sample code that shows how you can use VBScript: http://khkonsulting.com/2013/01/prevent-the-save-dialog-when-printing-to-the-adobe-pdf-printer/

  36. Niek says:

    Hi,

    Thanks for the reply! Turns out the problem was with the number of pages: I had set the first argument of InsertPages to 2 and the Part1Document on the second computer only had 1 page… kind of a silly mistake I guess. Thanks again for this post and for your help. IThe vbscript example is useful as well by the way!

    Niek

  37. Dash says:

    Hi,
    I used your code and it did what I want, but for two files as I am using your code as a sub and calling it in another sub.. I gave it two input for Part1Document and Part2Document.. My question is what if I wanted to make the input dynamic and add as many pdfs I want to without having to open each one by hard coding it?
    Thanks

  38. Karl Heinz Kremer says:

    Dash – that’s just regular VBA: Just create loop, find out what files you need to combine and call you function with the two filenames. Again, that’s just a VBA problem and has nothing to do with Acrobat or PDF. If you don’t know how to create a function with arguments and call that function from within a loop, get a good VBA introduction that teaches the function concept.

  39. Will says:

    Hello,

    I’m trying to write VBA code to merge a few hundred PDFs into one as it loops through all the sheets (containing hyperlinks to PDFs) in a workbook. Your code was a great help to get me started but my code is extremely slow merging just two files at a time. Is there a way to merge a huge amount of PDF files faster?

    I have this vision in my head of a pyramid structure. On the first level, file1 merge with file2, file3 merge with file4, etc. Then on the second level, the result of the merger of file1 & file2 merge with the result from the merge of file3 & file4, and so on …..

    Thanks for any advice.

  40. Karl Heinz Kremer says:

    Will,

    you can certainly do it this way. In general, automating Acrobat via VBA is fairly slow. Acrobat is mainly an application that is designed for a user to sit in front of the screen, pushing buttons. For a server like environment (e.g. processing a few hundred files fast), I would use a standalone application using a PDF library or toolkit that was designed for this use.

  41. Will says:

    Karl,

    Thanks for the quick reply.
    Can you recommend “a standalone application using a PDF library or toolkit that was designed for this use”?
    I value your expert advice as it will save me days (and probably some cash) to trial & error different things to find a solution.

    Thanks for your time.

  42. Karl Heinz Kremer says:

    Will, I would write an application based on ABCPdf for anything that needs to run on Windows. For other environments, I might use iText.

  43. Phan Thong says:

    Hi Karl,
    Could you please advise me my concern?
    I have a pdf file with secured property (without password). I would like to use VBA to remove security of PDF file but I have not much experience about that property in VBA code. please help to instruct me for my reference.

    I am greatly appreciate your help.
    Thanks,
    Thong.

  44. Karl Heinz Kremer says:

    Thong, This cannot be done with VB.

  45. Himanshu says:

    Hi,
    I am very new to the VBA coding, the very first line in your code is giving me an error. the line is ” Dim AcroApp As Acrobat.CAcroApp “. please can you tell me why it is not working for me.
    Thanks in advance for your help!

  46. Karl Heinz Kremer says:

    You need to add a reference to the Acrobat type library to you project. This is not specific to using Acrobat in your VBA program, it’s something that you will have to do for any external library. I did describe in my tutorial how to do that.

  47. Mark Curtis says:

    Acrobat Acrobat has a PDFBinder plug-in example in the lastest SDK. It uses AVConversionToPDFHandler to convert files to PDF. Adobe’s plug-in sample code is written in C. I’m looking for the VBA code to use AVConversionToPDFHandler.
    Can you help me ?

    Thanks,

    Mark

  48. Karl Heinz Kremer says:

    Mark, you cannot cross interfaces, which means you cannot use API functions from the plug-in interface in the IAC environment. The plug-in interface is the most powerful API in the Acrobat SDK, and neither the JavaScript nor the IAC interface come even close.

  49. Mark Curtis says:

    Thanks Karl for your quick response.

    Mark

  50. Hi Karl,

    I’m new in the VBA for excel. Thanks for the valuable information you publish here on your blog. I hope you can help me so I can take my next step forward to control adobe files out of my excel application.
    I’m using the following VBA code to open pdf (http://www.devhut.net/2010/09/09/vba-word-open-a-word-document/). This code works excelent but the file has to be closed and opened each time. If you do not close the pdf file is popping up again by the next call but it doesn’t navigate to the desired page in the file.
    I have printed already both adobe files you have listed but this makes the problem only bigger, I’m lost in all this to solve my problem, altough I feel I’m close to solve the problem.
    If the file is already open I need code for :
    – so VBA knows the file is already open or not / if not open I continue to open the file as indicated in the hyperlink above
    – if pdf is already open/ the pdf file has to pop up
    – the pdf file has to open on the correct page as sent to the function
    many thanks on forehand
    Danny Focquaert

  51. Karl Heinz Kremer says:

    Danny, I don’t think you need to check to see if a file is already open: If you try to open it again via VBA, it should just become the active document. The following script assumes that there are there files A.pdf, B.pdf and C.pdf in c:\temp – it will then randomly open (or activate it if it’s already open) one of these files, and go to a random page:

    Dim AcroApp As Acrobat.CAcroApp
    
    Private Sub CommandButton1_Click()
        Dim avDoc As Acrobat.CAcroAVDoc
        Dim avPageView As Acrobat.CAcroAVPageView
        Dim files(2) As String
        files(0) = "c:\temp\A.pdf"
        files(1) = "c:\temp\B.pdf"
        files(2) = "c:\temp\C.pdf"
        
        If (AcroApp Is Nothing) Then
            Set AcroApp = CreateObject("AcroExch.App")
        End If
        AcroApp.Show
        Set avDoc = CreateObject("AcroExch.AVDoc")
        Dim r As Integer
        ' open a random document
        r = Int((2 - 0 + 1) * Rnd + 0)
        Call avDoc.Open(files(r), "")
        Dim p As Integer
        ' go to a random page
        p = Int((10 - 1 + 1) * Rnd + 1)
        Set avPageView = avDoc.GetAVPageView
        avPageView.GoTo (p - 1)
        Set avPageView = Nothing
        Set avDoc = Nothing
    End Sub
    
  52. Miguel says:

    Hi I have been very useful code.
    I’m from Spain and I do not understand English. But with the translator, I will try to ask a question.
    As he could from access VBA insert in pdf a text box or what you have in memory the clipboard, and always on the first page.
    Thank you very much. A greeting.

  53. Karl Heinz Kremer says:

    Miguel, if you can access the clipboard contents via VBA, then you can create a text annotation with the that information. Take a look at the Doc.addAnnot() method, which you can call via the JSObject: http://help.adobe.com/en_US/acrobat/acrobat_dc_sdk/2015/HTMLHelp/index.html#t=Acro12_MasterBook%2FJS_API_AcroJS%2FDoc_methods.htm%23TOC_addAnnotbc-1&rhtocid=_6_1_8_23_1_0
    See my other posts about using the JSObject (e.g. here: http://khkonsulting.com/2009/03/acrobat-javascript-and-vb-walk-into-a-bar/ and here: http://khkonsulting.com/2010/09/reading-pdf-form-fields-with-vba/)

  54. Laura says:

    Tjis is one of the only posts I have found useful!

    One question, what if I have more than 2 pdfs I am combining?
    I am not great at VBA code and am having trouble with this.

    Thank you!

  55. Laura says:

    Nevermind, I figured it out…just read a little bit closer :).

    Thank you for this awesome post!

  56. Victor says:

    Hi Karl, when I export a pdf to excel, the picture in the document is not exported. It is posible to export with the picture? Or, how do I select a picture in a pdf and paste it in excel with vba. It is the only picture in the document.

  57. Karl Heinz Kremer says:

    Victor, this is a case of “it is what it is” – if something does not show up, there is usually no method to make it show up. There are not many controls that specify how the PDF should be converted to Excel. The ones that are available you can see when you bring up Acrobat’s preferences, then select the “Convert from PDF” category and select “Excel Workbook”. You cannot select and then copy and paste with VBA.

  58. pri says:

    Is there any way to have the filenames appear as bookmarks?

  59. Michele says:

    Hi,
    I’m trying to read the annotations of a pdf file.

    Dim AcrApp As Acrobat.Acroapp
    Dim AcrAvDoc As Acrobat.AcroAVDoc
    Dim pdDoc As Acrobat.CAcroPDDoc
    Dim Jso As Object
    Dim Annots as variant
    Dim Annot As Object
    Dim Props As Object

    Set AcrApp = New Acrobat.Acroapp
    Set AcrAvDoc = AcrApp.GetActiveDoc
    Set pdDoc = AcrAvDoc.GetPDDoc
    Set Jso = pdDoc.GetJSObject

    Jso.syncAnnotScan
    Set Annots = Jso.GetAnnots(0) ‘ I expect to read the annotations of the sheet no. 1

    but here the application stops here with an error… “Type not correspondent”
    There is anything wrong in the declaration of Annots?

    Thanks,
    Michele.

  60. Karl Heinz Kremer says:

    The “jso.getAnnots()” method returns an array of elements, not just one annotation, so you need to declare your “Annots” variable as a Variant():

    Dim Annots() As Variant

  61. Karl Heinz Kremer says:

    I don’t understand your question. Where would the filenames come from? Are you planning on concatenating different PDF files into one, and then having a bookmark that brings you to the first page of each document? You can do that by using the “createChild()” method in the bookmark object. You can find out more about this here: https://acrobatusers.com/tutorials/print/auto_bookmark_creation
    If you want to use this method within VBA, you have to use the JSObject to reference JavaScript methods.

  62. Michele says:

    Dear Karl,
    with reference to your answer of July 8, 2016 at 3:27 pm,
    I have modified the declaration of Annots as per your suggestion
    Sub ReadAnnotations()
    Dim AcrApp As Acrobat.Acroapp ‘Application Acrobat
    Dim AcrAvDoc As Acrobat.AcroAVDoc ‘Document actif dans Acrobat
    Dim pdDoc As Acrobat.CAcroPDDoc
    Dim page As Acrobat.CAcroPDPage
    Dim Jso As Object
    Dim Rect(3) As Integer
    Dim pageRect As Object
    Dim Annots() As Variant
    Dim Annot As Object
    Dim Props As Object
    Dim Color(0 To 3) As Variant

    Set AcrApp = New Acrobat.Acroapp
    Set AcrAvDoc = AcrApp.GetActiveDoc
    Set pdDoc = AcrAvDoc.GetPDDoc
    Set Jso = pdDoc.GetJSObject
    Jso.syncAnnotScan
    Set Annots = Jso.getannots(0)

    Now I have the following error at the same point: impossible to assign to the matrix.

    If I modify the last row in “Set Annots() = Jso.getannots(0)”, the error is the same “impossible to assign to the matrix”.

    Can you suggest where is the error?

    Thanks in advance,
    Michele.

  63. Michele Monaco says:

    Hi,
    although I have not yet found a solution to the correct usage of the GetAnnots method (refer to my previous post), I have another question regarding the creation of a new annotation type as “Polygon”.

    Here too I think to face a similar problem I have with the GetAnnots method.

    The vertices is defined as an array of array in the Acrobat Javascript API, but it is suggested the refer to the PDF Reference.
    In the PDF Reference 1.7 I found nothing more anyway
    Vertices – array – (Required) An array of numbers representing the alternating horizontal and vertical coordinates, respectively, of each vertex, in default user space.

    So I tried to implement the following procedure:

    Sub CreateNewAnnotationPolygon()
    Dim AcrApp As Acrobat.Acroapp ‘Application Acrobat
    Dim AcrAvDoc As Acrobat.AcroAVDoc ‘Document actif dans Acrobat
    Dim pdDoc As Acrobat.CAcroPDDoc
    Dim page As Acrobat.CAcroPDPage
    Dim Jso As Object
    Dim path As String
    Dim popupRect(3) As Integer
    Dim Rect(3) As Integer
    Dim PolVertices(1, 3) As Variant ‘ only four vertices are needed
    Dim pageRect As Object
    Dim Annot As Object
    Dim Props As Object
    Dim Color(0 To 3) As Variant

    Set AcrApp = New Acrobat.Acroapp
    Set AcrAvDoc = AcrApp.GetActiveDoc
    Set pdDoc = AcrAvDoc.GetPDDoc
    Set Jso = pdDoc.GetJSObject
    If Not Jso Is Nothing Then
    ‘ Get size for page 0 and set up arrays
    Set page = pdDoc.AcquirePage(0)
    Set pageRect = page.GetSize
    Rect(0) = 20 ‘ to define the position of the annotation
    Rect(1) = pageRect.y – 10
    Rect(2) = 20 ‘ actually I doubt if it is correct to define also rect(2) and rect(3)
    Rect(3) = pageRect.y
    PolVertices(0, 0) = 0
    PolVertices(1, 0) = 10
    PolVertices(0, 1) = 0
    PolVertices(1, 1) = 0
    PolVertices(0, 2) = 20
    PolVertices(1, 2) = 10
    PolVertices(0, 3) = 20
    PolVertices(1, 3) = 0
    ‘ Create a new Polygon annot
    Set Annot = Jso.AddAnnot
    Set Props = Annot.getprops
    Props.Type = “Polygon”
    Props.bordereffectIntensity = 1
    Props.Width = 1
    Annot.setProps Props
    ‘ Fill in a few fields
    Set Props = Annot.getprops
    Props.page = 0
    Props.Rect = Rect
    Props.Vertices = PolVertices ‘ HERE THE PROCEDURE STOPS WITH THE ERROR “Property not supported by the object”
    Props.Author = “Michele”
    Props.Subject = “Example Polygon shape”
    Color(0) = “RGB”
    Color(1) = 1#
    Color(2) = 0#
    Color(3) = 0#
    Props.StrokeColor = Color
    Annot.setProps Props
    pdDoc.Close
    ‘MsgBox “Annotation added”
    Else
    MsgBox “Failed to open”
    End If
    Set Annot = Nothing
    Set Props = Nothing
    Set page = Nothing
    Set pageRect = Nothing
    Set Jso = Nothing
    Set pdDoc = Nothing
    Set AcrAvDoc = Nothing
    Set AcrApp = Nothing
    End Sub

    Can you suggest where is the error?

    Thanks in advance,
    Michele.

  64. Karl Heinz Kremer says:

    Michele, I am sorry, but debugging your code is a bit outside of the scope of what I can do for free on my blog. If you need my professional help, feel free to get in touch with me via email. My email address is on the “About” page.

  65. Markus D. says:

    Hi Karl, found your blog while searching for a solution to check the orientation of the pages into a pdf-file. If i am opening the original file on screen some pages are in Orientation Landscape, some Portrait. I am using VBA to open the file and check each page with “getRotate”. The documentation told me this should return a value “in degrees”. The result is always the same, it is Zero. I hoped to get “90” or something else then Zero in case of Orientation Landscape. Am i wrong ? Here are the relevant parts of my code (or the parts i hope they are relevant)

    Dim AcroApp As Acrobat.CAcroApp
    Dim docu1 As Acrobat.CAcroPDDoc
    Dim docu1page As Acrobat.CAcroPDPage

    Set AcroApp = CreateObject(“AcroExch.App”)
    Set docu1 = CreateObject(“acroexch.pddoc”)
    docu1.Open (oFile.path)

    For i = 0 To docu1.GetNumPages() ‘to check each page in this document
    docu1.AcquirePage (i) ‘hopefully moves focus to this page
    Set docu1page = docu1.AcquirePage(i)
    Debug.Print “Seite ” & i & “, Ausrichtung ” & docu1page.GetRotate
    Next i

    Thank you in advance and of course thanks a lot for all the other informations on your page. (And sorry for my lousy english.)
    Markus

  66. Karl Heinz Kremer says:

    Markus, unfortunately it’s not that simple. A landscape page does not necessarily have a rotation applied to it. The rotation property is only applied to the page content, so if the page content does not have to be rotated, you will not find the rotation flag set to anything but 0. To make matters even more confusing, even with a portrait page, it is possible to see a page rotation applied. You will need to get the page size, and then compare width and height, and if the page width is greater than the height, you are looking at a landscape page.

  67. Markus D. says:

    Thank you so much, Karl Heinz. I will try to read out the pagesize as you described it. The first attempt failed (“Objekt unterstützt diese Eigenschaft oder Methode nicht”), but i think i will convince the System to tell me the things i need.

  68. Markus D. says:

    Hello once again, Karl Heinz. As you suggested i added a few lines to my code:

    Dim AcroExchPageSize As Object
    Set AcroExchPageSize = docu1page.GetSize
    Debug.Print “Höhe ” & AcroExchPageSize.y & ” Breite ” & AcroExchPageSize.x

    Works properly, thanks for your idea.

  69. Karl Heinz Kremer says:

    Markus, glad that you figured it out. I was just about to ask you about how you are trying to get the page size.

  70. Dave Moore says:

    I am trying to populate a form from ACCESS 2016 VBA with Acrobat DC Standard. I have the Acrobat 10.0 Type Library as a Reference and my code compiles.
    When I try to execute I error out on the SET APP = CreateObject(“AcroExch.app) with
    “Automation Error: Library Not Registered”. I have not found a solution and hoping you can help me. My code is”
    Sub TestPopulate()
    PopulateMembershipForm 70
    End Sub
    Public Function PopulateMembershipForm(ByVal lngRcdId As Long)
    Dim WshShell As Object
    Dim sValue As String ‘value to inser into form field
    Dim sAcord As String ‘File name and path of pdf form document
    Dim sSaveAs As String ‘name to save popllated file as
    Dim x As Object
    Dim jso As Object
    Dim val As Variant
    Dim APP As Acrobat.AcroApp
    Dim AVDOC As Acrobat.AcroAVDoc
    Dim PDDOC As Acrobat.AcroPDDoc

    Set dbs = DBEngine.Workspaces(0).Databases(0)
    sAcord = “C:\Users\Dave\Documents\KWVA\membership Recruitment\Acrobat Forms\TestFillForm.pdf”
    On Error GoTo errHandler
    ‘open pdf fillable form
    Set WshShell = CreateObject(“Wscript.Shell”)
    WshShell.Run “Acrobat.exe ” & sAcord

    Set APP = CreateObject(“AcroExch.app”)
    Set AVDOC = CreateObject(“AcroExch.AVDoc”)
    Set AVDOC = APP.GetActiveDoc
    Set PDDOC = AVDOC.GetPDDoc
    Set jso = PDDOC.GetJSObject

    strQry = “SELECT RcdId, FirstName, LastName, MI, Adddress, City, ST, Zip FROM dbo_tblMembershipList WHERE (RcdId = & lngrcdid) ”
    Set rst = dbs.OpenRecordset(strQry)
    If Not (rst.EOF) Then
    Set x = jso.getfield(“LastName”)
    val = rst!LastName
    x.Value = val
    Set x = jso.getfield(“FirstName”)
    x.Value = val

    PDDOC.Save 1, “C:\Users\Dave\Documents\KWVA\membership Recruitment\Acrobat Forms\TestFillForm” & lngRcdId & “.pdf”
    AVDOC.Close 1

    DoEvents
    APP.CloseAllDocs
    DoEvents
    APP.Exit

    ‘ fcloseapp “AcrobatSDIWindow”
    End If
    Set APP = Nothing
    Set AVDOC = Nothing
    Set PDDOC = Nothing
    Set jso = Nothing
    errHandler:
    MsgBox Err.Number & “: ” & Err.Description, vbOKOnly, “Error”

    Exit_PopulateMembershipForm:
    Exit Function

    End Function

  71. Karl Heinz Kremer says:

    Dave, I am not a VB expert, so I am not the right person to ask. However, I have one comment: I never start the Acrobat application – it should get launched automatically when you run code that requires Acrobat to be running. You may want to remove the lines that start Acrobat from our code. Once you have the reference to the Acrobat application, you can then open the document via the normal API calls.

Leave a Reply

Your email address will not be published. Required fields are marked *