19 Replies Latest reply on Dec 21, 2015 1:20 PM by charlespl

    SetLock and getLock methods in VBA

    charlespl

      Hello community,

       

      This is my first post here and I have a couple of question for you concerning a very particular point : I need to add a signature field that would lock all other fields in my form whe signed. I don't want to sign yet, just to add the field. This is quite simple when doing it manually, it's just a radio button to change in the properties of this field:

      Capture.PNG

       

      My problem is : I would like to do it using Javascript /VBA (JSObject). I'm able to add the field, but not to execute the getlock nor the setLock methods, so signing this field don't change anything to the rest of the fields.

       

      Here is my code : !

      Sub AddSignature()
      
      Dim AcroApp As Acrobat.CAcroApp
      Set AcroApp = CreateObject("AcroExch.App")
      Dim docuPDF As Acrobat.CAcroPDDoc
      Set docuPDF = CreateObject("AcroExch.PDDoc")
      Dim jso As Object
      Dim path As String
      Dim position(3) As Integer
      path = Application.GetOpenFilename("PDF Files (*.pdf), *.pdf", 1, "Choose your file")
      
      
      If docuPDF.Open(path) Then
          Set jso = docuPDF.GetJSObject 
          If Not jso Is Nothing Then
              Dim f As Object
              Dim oLock As Object
              
              position(0) = 414   
              position(1) = 73   
              position(2) = 526   
              position(3) = 40   
              
              Set f = jso.addfield("Signature1", "signature", 0, position)
              Set oLock = f.getLock()  '<---This is here my code stops working : "Object requiered" erreur
              Set oLock.Action = "All"
              If f.setlock(oLock) Then
                  MsgBox "It worked"
              Else
                  MsgBox "Nope"
              End If
      
              Set oLock = Nothing
              Set f = Nothing
              
          End If
      End If
      Set jso = Nothing
      Set AcroApp = Nothing
      Set docuPDF = Nothing
      End Sub
      

       

      (inspiration : http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/js_developer_guide.pdf#page= 82)

       

      My code stop working when I try to get the oLock object of my signature. If I try to read it in another procedure, I'm only able to get something if the property as been manually entered.

       

      Any clues? Would I ever be able to use the setLock method or should I better look towards the setAction method to transform all fields to readOnly (How to lock a fillable pdf from within Adobe Reader (Acrobat Reader))? If I choose the setAction path, what would be the event I need to call (e.g. "MouseUp" or else) ?

       

      Thanks for all of your answers.

        • 1. Re: SetLock and getLock methods in VBA
          charlespl Level 1

          I found a workaround based on user. I'm sure it won't work 100% of the time, but, hey, it's better than 0%, no? The user would need to check the Lock Document property when he will sign it.

          capt.jpg

          However, if you still have a JavaScript way, I'm still looking for it.

          • 2. Re: SetLock and getLock methods in VBA
            George_Johnson MVP & Adobe Community Professional

            It's possible to configure a signature field so that that check box is selected and can't be deselected. For example:

             

            getField("Signature1").signatureSetSeedValue({lockDocument: true, flags: 128});

             

            If you want to use the setAction method instead so you can configure which fields are set to read-only using a custom JavaScript, you'd use the Format event, something like:

             

            sJS = "getField(\"Text1\").readonly = true;";

            getField("Signature1").setAction("Format", sJS);


            The script to set all fields to read-only would be different, but you should get the idea.

            • 3. Re: SetLock and getLock methods in VBA
              charlespl Level 1

              George,

               

              Thanks for your answer, but, how can I create this "SeedValue Generic Object" (http://help.adobe.com/livedocs/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/wwhelp/wwhimpl/js/html/ wwhelp.htm?href=JS_API_AcroJSP…) in VBA? (i.e. how can I specify the "{lockDocument: true, flags: 128}" parameter of signatureSetSeedValue method?)

               

              This is the very same problem as my original question : I can't create a "Lock object" (http://help.adobe.com/livedocs/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/wwhelp/wwhimpl/js/html/ wwhelp.htm?href=JS_API_AcroJSP…) for the setLock method unless it has already been fully defined in the .PDF file (manually).

               

               

              On the "setAction" way to do the job, I can't even compile or I get an error...

               

              This doesn't compile :

              Field.setaction("Format", "getField(" & Chr(34) & "Passes1" & Chr(34) & ").readonly = true;")

               

              This compile, but when executed, I get a "mismatch" error :

              dim g as object (If this is a Variant, I get the same error)

              set g = Field.setaction("Format", "getField(" & Chr(34) & "Passes1" & Chr(34) & ").readonly = true;")


              Same thing here (compile, but mismatch error) :

              dim sJs as Variant (or String...)

              sJS =  Field.setaction("Format") = "getField(" & Chr(34) & "Passes1" & Chr(34) & ").readonly = true;"

              Set g = Field.setAction("Format", sJS)

               

               

              This compile, but a get a "Missing required Argument" error

              Field.setAction("Format")

               

               

               

              How about that  : http://help.adobe.com/livedocs/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/wwhelp/wwhimpl/js/html/ wwhelp.htm?href=JavaScript_Sec…

              How can I use this OLE command ?

               

                      Dim AcroForm As Object

                      Set AcroForm = CreateObject("AFormAut.App")

                      AcroForm.Field("Signature1").setjavascriptaction("Format", sJS)

               

              When I try this (How do I auto-populate an Acrobat form from Excel?), I get an error on AFORMAUTLib.Field (User-defined type not defined)...

               

               

              Frankly, I really don't know what to do more...So thanks in advance.

              • 4. Re: SetLock and getLock methods in VBA
                George_Johnson MVP & Adobe Community Professional

                Rather than use all of the VBA, I have found it easier to use the Fields.ExecuteThisJavaScript method, especially if you place the code in a folder-level JavaScript file, which allows you to deal with any security-related limitations.

                • 5. Re: SetLock and getLock methods in VBA
                  charlespl Level 1

                  I've changed my whole approach. Now I'm using the AFormAutLib reference, so no need for the JSObject.

                   

                  I've been able to do a couple of things. including sending very basic Javascript commands to Acrobat using Fields.ExecuteThisJavaScript like show a pop-up, play a sound, but nothing related to the Lock object of the signature yet...

                   

                  Sub Manip()
                  Dim AcroApp As Object
                  Set AcroApp = CreateObject("AcroExch.App")
                  Dim docuPDF As Object
                  Set docuPDF = CreateObject("AcroExch.PDDoc")
                  
                  If docuPDF.Open(path) Then
                      docuPDF.OpenAVDoc ("")
                      AcroApp.Show
                      Dim AcroForm As AFORMAUTLib.AFormApp
                      Set AcroForm = CreateObject("AFormAut.App")
                      Dim Field As AFORMAUTLib.Field
                      Dim Fields As AFORMAUTLib.Fields
                      
                      Set Fields = AcroForm.Fields
                      Dim sJS As String
                      sJS = "app.alert({cMsg:" & Chr(34) & "Hello World" & Chr(34) & ", cTitle:" & Chr(34) & "Acme Testing Service" & Chr(34) & ", nIcon: 2, nType: 2});"
                      Fields.ExecuteThisJavascript (sJS) 'this produce a pop-up.
                      Fields.ExecuteThisJavascript(app.beep(0)) 'this produce an error sound.
                  
                       Field = Fields.add("Signature1", "signature", 0, 100, 430, 250, 405)
                       Field.setJavascriptAction "up", app.alert(" & Chr(34) & "Signing this form will make any futures changes impossible" & Chr(34) & ") ;"
                       Field.setJavascriptAction "format", 'This is the code I need to make all other fields locked
                  
                      Set Fields = Nothing
                      Set Field = Nothing
                      Set AcroForm = Nothing
                  End If
                  Set DocuPDF = Nothing
                  Set AcroApp= Nothing
                  End Sub
                  

                   

                  Trust me I'm the kind of guys who prefer to learn to fish instead over being given a fish, but this time, I feel a little overwhelmed... It has been four days since I'm bugged on this particular problem. So could you help me by giving me a little code extract instead of only giving me direction in which way to look ? I just need a JavaScript code to either change the Lock Object properties of my Signature field or a small routine to change the readonly property of my variable number of fields... I'm begging you... I'm desperate...

                   

                  Thanks a lot in advance.

                  • 6. Re: SetLock and getLock methods in VBA
                    Test Screen Name Most Valuable Participant

                    Don't forget that the JavaScript you execute this way can be the complete program, not just fragments.

                    • 7. Re: SetLock and getLock methods in VBA
                      Test Screen Name Most Valuable Participant

                      Hmm, I don't see the difficulty, because I don't understand why your process is so convoluted. I'm not saying it is wrong, just that I don't understand it.

                       

                      There seems to be a very simple statement early on


                      getField("Signature1").signatureSetSeedValue({lockDocument: true, flags: 128});

                       

                      My starting position would be -- just run that with ExecuteThisJavascript . If that isn't what you need, please let us know why. If it is what you need, but that doesn't work, I'd like to see the code which is trying to do that and failing, and what it says in the console when you run it.

                      • 8. Re: SetLock and getLock methods in VBA
                        charlespl Level 1

                        If I try to enter getField("Signature1").signatureSetSeedValue({lockDocument: true, flags: 128}); directly in the console and CTRL + ENTER, I get an undefined error :

                        Capture.PNG

                        When I try to execute Javascript in my VBA code, I get a Security error...


                        Code :

                        Set Field = Fields.Add("Signature1", "signature", 0, 504,  735, 584, 725)

                        Field.SetJavaScriptAction "up", "app.alert(" & Chr(34) & "Signing this form will make any futures changes impossible" & Chr(34) & ") ;"

                        sJS = "getField(" & Chr(34) & "Signature1" & Chr(34) & ").signatureSetSeedValue({lockDocument: true, flags: 128});"

                        Fields.ExecuteThisJavascript (sJS)

                         

                        The SetJavascriptAction method works (I get an alert, when clicking on the field),  but this is the error I get when I try the ExecuteThisJavaScript :

                        Capture.PNG

                         

                        Any clues ? Thanks !

                        • 9. Re: SetLock and getLock methods in VBA
                          Test Screen Name Most Valuable Participant

                          undefined is not an error (in PDF, it is in PostScript, unhelpfully). Acrobat prints the result. Since this is a void method, there is no result and it prints "undefined". So, that's good.

                           

                          Not clear that you can put this on an action. Or, why you need to? Why don't you just do it once? It's going to need fancy magic to make it work on a button, with startup level JavaScript.

                          • 10. Re: SetLock and getLock methods in VBA
                            charlespl Level 1

                            My workflow (why I need to lock the signature): I have an Excel file containing data. I interpret these data and produce a PDF file. Then I add some form fields (according to my data) to be filled by my supplier. Then I want these fields to be locked after my supplier signs it, to avoid any changes and miscommunication between us. Once this file has been signed, there's nothing else to be done with it, except looking at it.

                             

                            I did some experiments with my files and my console. (I get really better at this, once I understood that undefined doesn't mean error )

                            1- This script works when executed from the console :

                            var f = getField("Signature1");
                            var oLock = {action:"All",fields:[]};
                            f.setLock(oLock);
                            
                            

                             

                            2- This doesn't work when executed from my VBA code :

                            sJS = "var f = this.getField(" & Chr(34) & "Signature1" & Chr(34) & ");" & Chr(13) & Chr(9) & _
                                  "var oLock = {action:" & Chr(34) & "All" & Chr(34) & " ,fields:[]};" & Chr(13) & Chr(9) & _
                                  "f.setLock(oLock);"
                            Fields.ExecuteThisJavascript(sJS)
                            
                            

                            This is the error I get :

                            Capture.PNG

                             

                            3 - With signatureSetSeedValue ways, I get the same thing, it works when done with the console:

                            this.getField("Signature1").signatureSetSeedValue({lockDocument: true, flags: 128});
                            

                             

                            4- But not from my code :

                            sJS = "this.getField(" & Chr(34) & "Signature1" & Chr(34) & ").signatureSetSeedValue({lockDocument: true, flags: 128});"
                            Fields.ExecuteThisJavascript (sJS)
                            
                            

                            I get the same error :

                            Capture.PNG

                             

                            Is there a way to work around these security settings ? Perhaps AddDocJavaScript method (http://help.adobe.com/livedocs/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/wwhelp/wwhimpl/js/html/ wwhelp.htm?href=JavaScript_Sec…) and then call this function when all fields are added to this document ? As previously stated by Georges, how can I place this script in a folder-level ?

                            • 11. Re: SetLock and getLock methods in VBA
                              charlespl Level 1

                              I've found a workaround that would work, but it raises a couple of new problems. When the user is prompted to sign, Acrobat asks to save the document and then, the script execute itself. The user than sees the fields being in read-only, but they aren't in the file that was saved. He has to save the document again because the script that locked the fields was executed after the save... Even if I try to save the file automatically in my script, I get a security related error...

                               

                              Dim AcroApp As Acrobat.AcroApp
                              Set AcroApp = CreateObject("AcroExch.App")
                              Dim docuPDF As Acrobat.AcroPDDoc
                              Set docuPDF = CreateObject("AcroExch.PDDoc")
                              Dim path As String
                              path = Application.GetOpenFilename("PDF Files (*.pdf), *.pdf", 1, "Choose your file")
                              
                              If docuPDF.Open(path) Then
                                  docuPDF.OpenAVDoc ("")
                                  AcroApp.Show
                                  Dim AcroForm As AFORMAUTLib.AFormApp
                                  Set AcroForm = CreateObject("AFormAut.App")
                                  Dim Field As AFORMAUTLib.Field
                                  Dim Fields As AFORMAUTLib.Fields
                                 
                                  Set Fields = AcroForm.Fields
                                  Dim sJS As String
                                  Set Field = Fields.Add("Signature1", "signature", 0, 504, 735, 584, 725)
                                  sJS = "for (var i = 0; i < this.numFields; i++) {" & Chr(13) & Chr(9) & _
                                              "var fname = this.getNthFieldName(i);" & Chr(13) & Chr(9) & _
                                              "this.getField(fname).readonly = true; // makes all fields readonly" & Chr(13) & Chr(9) & _
                                          "}"  & Chr(13) & Chr(9) & _
                                          "var SavePath = this.path;" & Chr(13) & Chr(9) & _
                                          "this.saveAs(SavePath)"
                              
                                  Field.SetJavaScriptAction "format", sJS
                              
                              Set docuPDF = Nothing
                              Set AcroForm = Nothing
                              Set Fields = Nothing
                              Set Field = Nothing
                              End Sub
                              

                               

                              My problem is still whole : How to get around these security permissions ?

                              • 12. Re: SetLock and getLock methods in VBA
                                Bernd Alheit Adobe Community Professional & MVP

                                Look at the documentation of the method saveAs.

                                • 13. Re: SetLock and getLock methods in VBA
                                  charlespl Level 1

                                  I give up

                                  The user would have to check the "Lock this document after signing". That's it, that's all.

                                  Thanks for your help though.

                                  • 14. Re: SetLock and getLock methods in VBA
                                    charlespl Level 1

                                    I can't put this code in a folder level script, as the creation of this file is going to be executed by a lot of different people. I can't make them install a file manually in such a particular location. Even using the app.get("user","javascript") method is privileged, so an automated creation of this folder level level script would require a folder level script...

                                    • 15. Re: SetLock and getLock methods in VBA
                                      Test Screen Name Most Valuable Participant

                                      Does it really not work if you do this once as part of your form preparation? I haven't used this method, but it seems that it should. Just doing it as part of the manual form design or whatever?

                                      • 16. Re: SetLock and getLock methods in VBA
                                        charlespl Level 1

                                        Nope. It doesn't work. Always the same security-related error... I'm not a software guy, I'm a mechanical engineer that tries to build tools to simplify everybody's life. I'm sure there are things that I don't understand, but anyhow, I moved on and I'm now trying to do other things.

                                        Thanks,

                                        • 17. Re: SetLock and getLock methods in VBA
                                          Test Screen Name Most Valuable Participant

                                          No, I meant to run it in a way that doesn't have a security issue, such as from the console. You have a form, run it from the console, form fixed, job done? I'm probably missing something important.

                                          • 18. Re: SetLock and getLock methods in VBA
                                            charlespl Level 1

                                            Yes, it would, but it's not just a one time deal. It would need to be done every time very create a file (i.e. couple of times a day). I would have to teach to everybody to use the console...It's quite complicated, better to show them the UI way. The goal of my tool was to have an efficient way to communicate with my supplier, the Lock after signature was more a "nice-to-have" feature than a required one.

                                            • 19. Re: SetLock and getLock methods in VBA
                                              charlespl Level 1

                                              Hello gang !

                                              I was able to succeed to about 50% ! I found a part of my answer here : http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/Acro6JSGuide.pdf#page=73 only to get problems little after.

                                               

                                              I get over the security warnings, everything is setup correctly, but it's not working as it should. Let me show you: If I click on the signature field after it has been created, then it shows this :

                                              Capture.PNG

                                              (like it won't lock the document after signing), but, when I go to see the properties of the signature field (without signing it), in editing mode, on the Signed tab, I get:

                                              Capture.PNG

                                              Then I click close, not modifying anything and go back to the form and see :

                                              Capture.PNG

                                              Any thoughts ? It's like the Schrodinger's cat : as long as you don't check its state, its not fixed

                                              To me it seems to be a bug on Adobe side... I've attached a "virgin" file (I did not check the properties yet), so you can see by yourself : File2.pdf - Google Drive

                                               

                                              I found a part of my answer here : http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/Acro6JSGuide.pdf#page=73

                                               

                                              Here is my fully working example :

                                              (References needed : Acrobat and AFormAut )

                                               

                                              Sub Test()
                                              Dim AcroApp As Acrobat.AcroApp
                                              Set AcroApp = CreateObject("AcroExch.App")
                                              
                                              Dim docuPDF As Acrobat.AcroPDDoc
                                              Set docuPDF = CreateObject("AcroExch.PDDoc")
                                              
                                              Dim path As String
                                              
                                              path = Application.GetOpenFilename("PDF Files (*.pdf), *.pdf", 1, "Choose the PDF file to be modify")
                                              
                                              
                                              If docuPDF.Open(path) Then
                                                  docuPDF.OpenAVDoc ("")
                                                  AcroApp.Show
                                                  Dim AcroForm As AFORMAUTLib.AFormApp
                                                  Set AcroForm = CreateObject("AFormAut.App")
                                                  Dim Field As AFORMAUTLib.Field
                                                  Dim Fields As AFORMAUTLib.Fields
                                                
                                                  Set Fields = AcroForm.Fields
                                                  Set Field = Fields.Add("Signature1", "signature", 0, 504, 735, 584, 725)
                                                
                                                  Dim sJS As String
                                                  sJS = "AFSignature_Format(" & Chr(34) & "All" & Chr(34) & ", new array(" & Chr(34) & Chr(34) & "));)"
                                                
                                                  Field.SetJavaScriptAction "format", sJS
                                              
                                                  path = Left(path, Len(path) - 4) & 2 & ".pdf"
                                                  If docuPDF.Save(PDSaveFull, path) = False Then
                                                      MsgBox "Cannot save the modified document"
                                                  End If
                                              
                                              End If
                                              Set AcroForm = Nothing
                                              Set docuPDF = Nothing
                                              Set Fields = Nothing
                                              Set Field = Nothing
                                              Set AcroApp = Nothing
                                              End Sub
                                              
                                              

                                               

                                              I also try using the JSObject and get the same Schrodinger's cat paradox...

                                               

                                              Thanks !