Add Custom Stamp To PDFs using VBA

Bering

Board Regular
Joined
Aug 22, 2018
Messages
190
Office Version
  1. 2016
Platform
  1. Windows
Hello, I really hope you guys ca help me...
This macro loops through all the pdf files in the selected location and should add a custom stamp in the first page of each file. Of course it does not work!

I keep getting the runtime error 438 for jsObj.ExecuteJavaScript jsCommand

I manually applied the stamp using the JavaScript Console and it works perfectly.

Tried adding a little pause to allow the pdf to fully load as well as many little variations but nothing works.
I have Abobe Acrobat Pro 32 bits...

Thank you!!

VBA Code:
Option Explicit

Sub AddSavedSignatureStampToPDFs()
    Dim folderPath As String
    Dim fileName As String
    Dim AcroApp As Object
    Dim AVDoc As Object
    Dim PDDoc As Object
    Dim jsObj As Object
    Dim jsCommand As String
    Dim newFileName As String
    Dim maxRetries As Integer
    Dim retries As Integer

    ' Prompt user to select folder containing PDFs
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder Containing PDF Files"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "No folder selected. Exiting."
            Exit Sub
        End If
    End With

    ' Initialize Acrobat
    On Error Resume Next
    Set AcroApp = CreateObject("AcroExch.App")
    If AcroApp Is Nothing Then
        MsgBox "Could not initialize Adobe Acrobat. Make sure it's installed and accessible.", vbCritical
        Exit Sub
    End If
    AcroApp.Show
    On Error GoTo 0

    ' Loop through each PDF in the folder
    fileName = Dir(folderPath & "*.pdf")
    Do While fileName <> ""
        On Error Resume Next
        Set AVDoc = CreateObject("AcroExch.AVDoc")
        If AVDoc.Open(folderPath & fileName, "") Then
            On Error GoTo 0

            ' Wait for the document to fully render
            maxRetries = 10 ' Number of retries
            retries = 0
            Do While retries < maxRetries
                If AVDoc.IsValid Then Exit Do
                retries = retries + 1
                Application.Wait Now + TimeValue("0:00:01") ' Wait 1 second
            Loop

            If retries = maxRetries Then
                MsgBox "Document took too long to load: " & fileName, vbExclamation
                AVDoc.Close True
                fileName = Dir
                GoTo NextFile
            End If

            ' Get the PDDoc and JavaScript Object
            Set PDDoc = AVDoc.GetPDDoc
            Set jsObj = PDDoc.GetJSObject
            If jsObj Is Nothing Then
                MsgBox "Failed to get JavaScript object for file: " & fileName, vbExclamation
                AVDoc.Close True
                fileName = Dir
                GoTo NextFile
            End If

            ' JavaScript to apply the stamp
            jsCommand = "this.addAnnot({" & _
                        "page: 0," & _
                        "type: 'Stamp'," & _
                        "name: '6a833177-32c9-4264-b013-c39e5b959dda'," & _
                        "rect: [400, 400, 550, 500]" & _
                        "});"
            
            ' Execute the JavaScript command
            jsObj.ExecuteJavaScript jsCommand

            ' Save the updated PDF with "_Signed" appended to the filename
            newFileName = Replace(folderPath & fileName, ".pdf", "_Signed.pdf")
            PDDoc.Save &H1, newFileName

            ' Close the document
            AVDoc.Close True
        Else
            MsgBox "Failed to open file: " & fileName, vbExclamation
        End If
NextFile:
        fileName = Dir
    Loop

    ' Cleanup
    AcroApp.CloseAllDocs
    AcroApp.Exit
    Set AcroApp = Nothing

    MsgBox "Signature stamping complete.", vbInformation, "Done"
End Sub
 

Excel Facts

Control Word Wrap
Press Alt+Enter to move to a new row in a cell. Lets you control where the words wrap.
I think the Adobe documentation is a bit misleading with regard to JSObject. Under https://opensource.adobe.com/dc-acr...OLE_Support.html#using-the-jsobject-interface, it says:

"In precise terms, JSObject is an interpretation layer between an OLE automation client, such as a Visual Basic application, and the JavaScript functionality provided by Acrobat. From a developer’s point of view, programming JSObject in a Visual Basic environment is similar to programming in JavaScript using the Acrobat console."

From that one might think you could pass a JavaScript string to a JSObject method and it would interpret and execute the command.

Adding a stamp to a PDF should be achievable using JSObject.AddAnnot, however I've discovered that there's a bug in Acrobat whereby it always adds the 'Draft' stamp, regardless of the stamp type specified in the AP property. For example:

VBA Code:
            Dim annot As Object, props As Object
            Set annot = jsObj.AddAnnot()
            Set props = annot.getProps
            props.Type = "Stamp"
            annot.setProps props
            Set props = annot.getProps
            With props
                .page = 0
                .AP = "Approved"    'No error, but always adds the "Draft" stamp
                .rect = Array(400, 340, 550, 440)
                .Name = "Stamp2"
                .Author = "My Name"
            End With
            annot.setProps props

For your purpose, we can add a custom stamp using Acrobat's AFormAut library, which VBA links to using Set AForm = CreateObject("AFormAut.App") and then call the AForm.Fields ExecuteThisJavascript method with the JavaScript command string. Here's your modified code:

VBA Code:
Sub AddSavedSignatureStampToPDFs2()

    Dim folderPath As String
    Dim fileName As String
    Dim AcroApp As Object
    Dim AVDoc As Object
    Dim PDDoc As Object
    Dim AForm As Object 'or As AFORMAUTLib.AFormApp, with reference to AFormAut n.00 Type Library
    Dim jsCommand As String
    Dim newFileName As String
    
    ' Prompt user to select folder containing PDFs
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder Containing PDF Files"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "No folder selected. Exiting."
            Exit Sub
        End If
    End With
    
    ' Initialize Acrobat
    On Error Resume Next
    Set AcroApp = CreateObject("AcroExch.App")
    If AcroApp Is Nothing Then
        MsgBox "Could not initialize Adobe Acrobat. Make sure it's installed and accessible.", vbCritical
        Exit Sub
    End If
    AcroApp.Show
    On Error GoTo 0

    Set AVDoc = CreateObject("AcroExch.AVDoc")
    Set AForm = CreateObject("AFormAut.App")

    ' Loop through each PDF in the folder
    fileName = Dir(folderPath & "*.pdf")
    Do While fileName <> ""
        
        If AVDoc.Open(folderPath & fileName, "") Then

            ' Get the PDDoc
            Set PDDoc = AVDoc.GetPDDoc

            ' JavaScript to apply the stamp
            jsCommand = "this.addAnnot({" & _
                        "page:0, " & _
                        "type:'Stamp', " & _
                        "name:'6a833177-32c9-4264-b013-c39e5b959dda', " & _
                        "rect:[400, 400, 550, 500]" & _
                        "});"

            AForm.Fields.ExecuteThisJavascript jsCommand
            
            ' Save the updated PDF with "_Signed" appended to the filename
            newFileName = Replace(folderPath & fileName, ".pdf", "_Signed.pdf")
            PDDoc.Save &H1, newFileName

            ' Close the document
            AVDoc.Close True
        Else
            MsgBox "Failed to open file: " & fileName, vbExclamation
        End If
        
        fileName = Dir
    Loop

    ' Cleanup
    'AcroApp.CloseAllDocs
    'AcroApp.Hide
    AcroApp.Exit
    Set AcroApp = Nothing
    Set AVDoc = Nothing
    Set PDDoc = Nothing

    MsgBox "Signature stamping complete.", vbInformation, "Done"
    
End Sub
 
Upvote 0
Solution
I think the Adobe documentation is a bit misleading with regard to JSObject. Under https://opensource.adobe.com/dc-acr...OLE_Support.html#using-the-jsobject-interface, it says:

"In precise terms, JSObject is an interpretation layer between an OLE automation client, such as a Visual Basic application, and the JavaScript functionality provided by Acrobat. From a developer’s point of view, programming JSObject in a Visual Basic environment is similar to programming in JavaScript using the Acrobat console."

From that one might think you could pass a JavaScript string to a JSObject method and it would interpret and execute the command.

Adding a stamp to a PDF should be achievable using JSObject.AddAnnot, however I've discovered that there's a bug in Acrobat whereby it always adds the 'Draft' stamp, regardless of the stamp type specified in the AP property. For example:

VBA Code:
            Dim annot As Object, props As Object
            Set annot = jsObj.AddAnnot()
            Set props = annot.getProps
            props.Type = "Stamp"
            annot.setProps props
            Set props = annot.getProps
            With props
                .page = 0
                .AP = "Approved"    'No error, but always adds the "Draft" stamp
                .rect = Array(400, 340, 550, 440)
                .Name = "Stamp2"
                .Author = "My Name"
            End With
            annot.setProps props

For your purpose, we can add a custom stamp using Acrobat's AFormAut library, which VBA links to using Set AForm = CreateObject("AFormAut.App") and then call the AForm.Fields ExecuteThisJavascript method with the JavaScript command string. Here's your modified code:

VBA Code:
Sub AddSavedSignatureStampToPDFs2()

    Dim folderPath As String
    Dim fileName As String
    Dim AcroApp As Object
    Dim AVDoc As Object
    Dim PDDoc As Object
    Dim AForm As Object 'or As AFORMAUTLib.AFormApp, with reference to AFormAut n.00 Type Library
    Dim jsCommand As String
    Dim newFileName As String
   
    ' Prompt user to select folder containing PDFs
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder Containing PDF Files"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "No folder selected. Exiting."
            Exit Sub
        End If
    End With
   
    ' Initialize Acrobat
    On Error Resume Next
    Set AcroApp = CreateObject("AcroExch.App")
    If AcroApp Is Nothing Then
        MsgBox "Could not initialize Adobe Acrobat. Make sure it's installed and accessible.", vbCritical
        Exit Sub
    End If
    AcroApp.Show
    On Error GoTo 0

    Set AVDoc = CreateObject("AcroExch.AVDoc")
    Set AForm = CreateObject("AFormAut.App")

    ' Loop through each PDF in the folder
    fileName = Dir(folderPath & "*.pdf")
    Do While fileName <> ""
       
        If AVDoc.Open(folderPath & fileName, "") Then

            ' Get the PDDoc
            Set PDDoc = AVDoc.GetPDDoc

            ' JavaScript to apply the stamp
            jsCommand = "this.addAnnot({" & _
                        "page:0, " & _
                        "type:'Stamp', " & _
                        "name:'6a833177-32c9-4264-b013-c39e5b959dda', " & _
                        "rect:[400, 400, 550, 500]" & _
                        "});"

            AForm.Fields.ExecuteThisJavascript jsCommand
           
            ' Save the updated PDF with "_Signed" appended to the filename
            newFileName = Replace(folderPath & fileName, ".pdf", "_Signed.pdf")
            PDDoc.Save &H1, newFileName

            ' Close the document
            AVDoc.Close True
        Else
            MsgBox "Failed to open file: " & fileName, vbExclamation
        End If
       
        fileName = Dir
    Loop

    ' Cleanup
    'AcroApp.CloseAllDocs
    'AcroApp.Hide
    AcroApp.Exit
    Set AcroApp = Nothing
    Set AVDoc = Nothing
    Set PDDoc = Nothing

    MsgBox "Signature stamping complete.", vbInformation, "Done"
   
End Sub
Thank you so much for looking into this. I will give it a try and let you know as soon as possible
 
Upvote 0
I think the Adobe documentation is a bit misleading with regard to JSObject. Under https://opensource.adobe.com/dc-acr...OLE_Support.html#using-the-jsobject-interface, it says:

"In precise terms, JSObject is an interpretation layer between an OLE automation client, such as a Visual Basic application, and the JavaScript functionality provided by Acrobat. From a developer’s point of view, programming JSObject in a Visual Basic environment is similar to programming in JavaScript using the Acrobat console."

From that one might think you could pass a JavaScript string to a JSObject method and it would interpret and execute the command.

Adding a stamp to a PDF should be achievable using JSObject.AddAnnot, however I've discovered that there's a bug in Acrobat whereby it always adds the 'Draft' stamp, regardless of the stamp type specified in the AP property. For example:

VBA Code:
            Dim annot As Object, props As Object
            Set annot = jsObj.AddAnnot()
            Set props = annot.getProps
            props.Type = "Stamp"
            annot.setProps props
            Set props = annot.getProps
            With props
                .page = 0
                .AP = "Approved"    'No error, but always adds the "Draft" stamp
                .rect = Array(400, 340, 550, 440)
                .Name = "Stamp2"
                .Author = "My Name"
            End With
            annot.setProps props

For your purpose, we can add a custom stamp using Acrobat's AFormAut library, which VBA links to using Set AForm = CreateObject("AFormAut.App") and then call the AForm.Fields ExecuteThisJavascript method with the JavaScript command string. Here's your modified code:

VBA Code:
Sub AddSavedSignatureStampToPDFs2()

    Dim folderPath As String
    Dim fileName As String
    Dim AcroApp As Object
    Dim AVDoc As Object
    Dim PDDoc As Object
    Dim AForm As Object 'or As AFORMAUTLib.AFormApp, with reference to AFormAut n.00 Type Library
    Dim jsCommand As String
    Dim newFileName As String
   
    ' Prompt user to select folder containing PDFs
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder Containing PDF Files"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "No folder selected. Exiting."
            Exit Sub
        End If
    End With
   
    ' Initialize Acrobat
    On Error Resume Next
    Set AcroApp = CreateObject("AcroExch.App")
    If AcroApp Is Nothing Then
        MsgBox "Could not initialize Adobe Acrobat. Make sure it's installed and accessible.", vbCritical
        Exit Sub
    End If
    AcroApp.Show
    On Error GoTo 0

    Set AVDoc = CreateObject("AcroExch.AVDoc")
    Set AForm = CreateObject("AFormAut.App")

    ' Loop through each PDF in the folder
    fileName = Dir(folderPath & "*.pdf")
    Do While fileName <> ""
       
        If AVDoc.Open(folderPath & fileName, "") Then

            ' Get the PDDoc
            Set PDDoc = AVDoc.GetPDDoc

            ' JavaScript to apply the stamp
            jsCommand = "this.addAnnot({" & _
                        "page:0, " & _
                        "type:'Stamp', " & _
                        "name:'6a833177-32c9-4264-b013-c39e5b959dda', " & _
                        "rect:[400, 400, 550, 500]" & _
                        "});"

            AForm.Fields.ExecuteThisJavascript jsCommand
           
            ' Save the updated PDF with "_Signed" appended to the filename
            newFileName = Replace(folderPath & fileName, ".pdf", "_Signed.pdf")
            PDDoc.Save &H1, newFileName

            ' Close the document
            AVDoc.Close True
        Else
            MsgBox "Failed to open file: " & fileName, vbExclamation
        End If
       
        fileName = Dir
    Loop

    ' Cleanup
    'AcroApp.CloseAllDocs
    'AcroApp.Hide
    AcroApp.Exit
    Set AcroApp = Nothing
    Set AVDoc = Nothing
    Set PDDoc = Nothing

    MsgBox "Signature stamping complete.", vbInformation, "Done"
   
End Sub
This works like a charm! Thank you so much for your help!!
 
Upvote 0
I think the Adobe documentation is a bit misleading with regard to JSObject. Under https://opensource.adobe.com/dc-acr...OLE_Support.html#using-the-jsobject-interface, it says:

"In precise terms, JSObject is an interpretation layer between an OLE automation client, such as a Visual Basic application, and the JavaScript functionality provided by Acrobat. From a developer’s point of view, programming JSObject in a Visual Basic environment is similar to programming in JavaScript using the Acrobat console."

From that one might think you could pass a JavaScript string to a JSObject method and it would interpret and execute the command.

Adding a stamp to a PDF should be achievable using JSObject.AddAnnot, however I've discovered that there's a bug in Acrobat whereby it always adds the 'Draft' stamp, regardless of the stamp type specified in the AP property. For example:

VBA Code:
            Dim annot As Object, props As Object
            Set annot = jsObj.AddAnnot()
            Set props = annot.getProps
            props.Type = "Stamp"
            annot.setProps props
            Set props = annot.getProps
            With props
                .page = 0
                .AP = "Approved"    'No error, but always adds the "Draft" stamp
                .rect = Array(400, 340, 550, 440)
                .Name = "Stamp2"
                .Author = "My Name"
            End With
            annot.setProps props

For your purpose, we can add a custom stamp using Acrobat's AFormAut library, which VBA links to using Set AForm = CreateObject("AFormAut.App") and then call the AForm.Fields ExecuteThisJavascript method with the JavaScript command string. Here's your modified code:

VBA Code:
Sub AddSavedSignatureStampToPDFs2()

    Dim folderPath As String
    Dim fileName As String
    Dim AcroApp As Object
    Dim AVDoc As Object
    Dim PDDoc As Object
    Dim AForm As Object 'or As AFORMAUTLib.AFormApp, with reference to AFormAut n.00 Type Library
    Dim jsCommand As String
    Dim newFileName As String
   
    ' Prompt user to select folder containing PDFs
    With Application.FileDialog(msoFileDialogFolderPicker)
        .Title = "Select Folder Containing PDF Files"
        If .Show = -1 Then
            folderPath = .SelectedItems(1) & "\"
        Else
            MsgBox "No folder selected. Exiting."
            Exit Sub
        End If
    End With
   
    ' Initialize Acrobat
    On Error Resume Next
    Set AcroApp = CreateObject("AcroExch.App")
    If AcroApp Is Nothing Then
        MsgBox "Could not initialize Adobe Acrobat. Make sure it's installed and accessible.", vbCritical
        Exit Sub
    End If
    AcroApp.Show
    On Error GoTo 0

    Set AVDoc = CreateObject("AcroExch.AVDoc")
    Set AForm = CreateObject("AFormAut.App")

    ' Loop through each PDF in the folder
    fileName = Dir(folderPath & "*.pdf")
    Do While fileName <> ""
       
        If AVDoc.Open(folderPath & fileName, "") Then

            ' Get the PDDoc
            Set PDDoc = AVDoc.GetPDDoc

            ' JavaScript to apply the stamp
            jsCommand = "this.addAnnot({" & _
                        "page:0, " & _
                        "type:'Stamp', " & _
                        "name:'6a833177-32c9-4264-b013-c39e5b959dda', " & _
                        "rect:[400, 400, 550, 500]" & _
                        "});"

            AForm.Fields.ExecuteThisJavascript jsCommand
           
            ' Save the updated PDF with "_Signed" appended to the filename
            newFileName = Replace(folderPath & fileName, ".pdf", "_Signed.pdf")
            PDDoc.Save &H1, newFileName

            ' Close the document
            AVDoc.Close True
        Else
            MsgBox "Failed to open file: " & fileName, vbExclamation
        End If
       
        fileName = Dir
    Loop

    ' Cleanup
    'AcroApp.CloseAllDocs
    'AcroApp.Hide
    AcroApp.Exit
    Set AcroApp = Nothing
    Set AVDoc = Nothing
    Set PDDoc = Nothing

    MsgBox "Signature stamping complete.", vbInformation, "Done"
   
End Sub
Just wanted to add that the bug issue isn’t necessarily that it always applies the “Draft” stamp, but rather that it fails to fetch the specific stamp referenced in the name property and instead reuses the last one in the cache.
It’s annoying…
 
Upvote 0

Forum statistics

Threads
1,225,397
Messages
6,184,718
Members
453,254
Latest member
topeb

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top