OK, let’s just forget about that old joke and concentrate on how to combine all three into something that is quite useful.
As I’ve described in one of my previous posting, it is quite easy to automate Acrobat from VB or VBA. So how does JavaScript fit into this picture? As you may know, Acrobat comes with a very powerful JavaScript engine that provides access to a lot of functionality – more functions actually than what you have access to from your VB program. So, if you want to access some of these features, but you are stuck with VB, how can you do that?
Adobe provides a VB/JavaScript bridge with Acrobat – the JSObject, and the Acrobat SDK describes how to use that feature.
There is quite a bit of good information in the documentation. When you access the online documentation, expand the tree to “Acrobat Interapplication Communication > Developing Applications Using Interapplication Communication > Using OLE > Using the JSObject interface”.
JavaScript
In this example, I want to illustrate how you can create a folder level JavaScript function, instantiate the JSObject, and then call the custom function and display the result in VB. My plan was to use the JavaScript code from my last posting, but I found one small problem in the way I wrote the code (it works fine as a standalone JavaScript program, but we cannot use it in the VB context), so here is it’s replacement:
function CountBookmarks(bkm, nLevel) { var count = 0; if (bkm.children != null) { count = bkm.children.length; for (var i = 0; i < bkm.children.length; i++) { count += CountBookmarks(bkm.children[i], nLevel + 1); } } return count; } function CountAllBookmarks() { console.clear(); console.show(); var n = CountBookmarks(this.bookmarkRoot, 0); console.println("Number of bookmarks found: " + n); return n; } // add the menu item app.addMenuItem({ cName: "countBookmarks", cUser: "Count Bookmarks", cParent: "Document", cExec: "CountAllBookmarks();", cEnable: "event.rc = (event.target != null);" });
Save this JavaScript program as a folder level JavaScript file and make sure that it works.
So, why can't we just implement the whole algorithm with the JSObject? The problem is with how VB handles objects that are actually JavaScript objects - in this case the root bookmark object. I cannot figure out how to access it's "children" property through the JSObject. That's the reason why I'm "cheating" by calling our custom JavaScript function - being able to do that is pretty cool IMHO.
The VB Part
We start out just like with any other VB program, by declaring some objects, initializing them and then it gets interesting...
Here is some sample code that shows how to initialize the JSObject, and how to call our own JavaScript function.
Create a button on an Excel spreadsheet again, and put the following code into the button handler callback (just like before).
Dim gApp As Acrobat.CAcroApp Dim gPDDoc As Acrobat.CAcroPDDoc Dim jso As Object Sub Button1_Click() Set gApp = CreateObject("AcroExch.App") Set gPDDoc = CreateObject("AcroExch.PDDoc") If gPDDoc.Open("c:\temp\test.pdf") Then Set jso = gPDDoc.GetJSObject MsgBox (jso.CountAllBookmarks()) End If End Sub
Now just make sure that you have a file c:\temp\test.pdf that has some bookmarks in it.
khk, I have been looking for how to do this for aa numbe rof hours this last week or so. your posting was really helpful. I tried your code / example… on my windows XP machine its falls over when I step inot the open first pdf line: Part1Document.Open (“C:tempPart1.pdf”)..
excel closes and the system wants to send a message to microosft.
any ideas whats wrong?
the type library is acrobat 8 on my system.
I checked in the register and AcroExch.PDDoc was there.
Paul
Thanks very much fot the info on Acrobat, JavaScript and VB. How would one go about to do the same with Photoshop, Javascript and VB?
I have created a VB6 app to copy photo files from mem cards and would like to extend it to include running Javascrips fot Photoshop.
Thanks.
Regards.
Ernst,
you can find information about Photoshop scripting here: http://www.adobe.com/devnet/photoshop/scripting/ and a tutorial for example here http://www.kirupa.com/motiongraphics/ps_scripting.htm
What exactly are you trying to accomplish with a Photoshop script?
Ah, now I’m getting it, you are asking if Photoshop also has a VB/JavaScript bridge… As far as I know, it does not support the same functionality. You can run JavaScripts via the DoJavaScript and DoJavaScriptFile functions, but it’s not bridged like in Acrobat. Does that help?
I just want to say you’re brilliant! Thanks.
I want to add a different sort of a beast into my vba code – and I’ve created the following function as a folder-level jscript.
function coder1 (){
var n = this.addAnnot({page:0,type:”Stamp”,rect:[100,100,350,350],AP:”#kZBRdNJ8NdlGCzWSCKIn3A”});
return n;
}
It doesnt work as intended, and I think it is due to my use of this onject. One solution would be to use a doc type variable as an input, but then how would I pass the doc type object into js from VBA? Any help would be greatly appreciated.
Maxim, the “JSObject” is your document object. You should be able to call “addAnnot()” for the JSObject – you may have to provide all the parameters, even the ones you are not using for this to work. Based on experience, the addAnnot() method is a bit tricky to get to work via VBA. Keep in mind that you can also use the OLE function to add annotations: http://help.adobe.com/en_US/acrobat/acrobat_dc_sdk/2015/HTMLHelp/index.html#t=Acro12_MasterBook%2FIAC_API_OLE_Objects%2FAddAnnot.htm
I am having trouble passing the AP property from VBA to excel. I have learned how to add a simple text annotation with OLE functions, but I cannot transmit the AP property of the Stamp type annotation.
Maxim, as I said, this is not trivial. Here is some sample code that adds the “Approved” stamp to a document:
Can you please help me to push digital signature to pdf fillable form from excel using vba as i have multiple pdfs forms with signature option and basis on region i have to publish digital signature on those pdfs using vba for excel
Sameer, this is well beyond the scope of what can be done in a reply to a blog post. If you are interested in my professional consulting services, please feel free to get in touch with me via email. My email address is on the About page.
Hi
I tried the code above, it always adds draft stamp,
Can we add ‘Approved’ stamp
Kiran, this is a bug in Acrobat: You cannot modify the stamp once it is placed, but you also cannot specify the stamp type at the time the stamp is placed. You will have to resort to Javascript to do that, and then call the Javascript from your VBA application.
KHK,
I came across your website and few codes for accessing information from a PDF file.
It’s awesome. The way you explain is superb.
I am looking for some VBA code to resolve one problem.
We have some 1000+ invoice copies in PDF format saved in some folder on our computer. Every month, the user has to open each of these pdf invoices (one by one) and insert the Delivery/Manufacturing site address and then save the PDF.
The delivery address for first 800 invoices is the same (say Address-A) while the address for the balance 200+ invoices is again same (say address-B).
Doing it manually takes almost one full day (about 9-10 hours).
I am a novice in Excel VBA coding and absolutely zero in Java.
However, browsing through the web (and of course your web-site too) I came to understand that this can be automated by writing some Excel VBA code (may be some support of Java script would be required.
Can you Help pls ?
Karl,
This is great! Is there any way to do the same with FoxIt Phantom PDF?
I’d like to automatically flatten documents using VBA and Phantom PDF and this seems like the way to go.
Mark, I don’t know enough about Foxit to answer your question. You may want to ask their customer support.