5 Replies Latest reply on Jul 14, 2017 8:28 AM by chuckh3108771

    How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?


      With this script, I can perform batch signature:


      // Choose handler

      var manipulador = security.getHandler("Adobe.PPKLite");   


      // login -- change as appropriate

      manipulador.login("test123", "/D/Users/p004826/AppData/Roaming/Adobe/Acrobat/10.0/Security/Israel.pfx");


      // informations

      var myInfo = {password: "test123",

                          reason: "Salvar como teste",

                          mdp: "defaultAndComments"};


      //Invisible Sign





      cLegalAttest: "Certificado ussando o JavaScript",




      But, it accomplishes only with a .PFX file saved locally. I'm trying to find a way that makes the user to insert a card and enter a password to make the e-signature. Does anyone know any other way?

      Sorry for my bad english


      Thank you!!!

        • 1. Re: How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?
          israel_dfx86919000 Level 1

          Finally I managed to solve. Follows...


          /* Sign all documents asking password/PIN */

          /* By Israel */


          //If you want to see the result, uncomment




          // Starts security handler and logs in.

          var vPPKLiteHandler = security.getHandler(security.PPKLiteHandler, true); 


          //console.println("Logged: isLoggedIn="+vPPKLiteHandler.isLoggedIn);

          event.rc = vPPKLiteHandler.isLoggedIn;

          if (!event.rc) {

            app.alert("Login failed for signature - Signature in batch aborted.");

            throw "Login fail";}


          //signs the document, the certifyInvisibleSign routine already saved

          event.rc = this.certifyInvisibleSign(vPPKLiteHandler);

          //console.println("Resultado da assinatura: "+event.rc);

          if (!event.rc) {

            app.alert("Failed signing of the document "+this.documentFileName

                     +" - Signature in batch aborted.");

            throw "Fail to sign";}


          Note: This action can only be done by opening Acrobat X. After running, you can select the PDF file or select the directory containing the PDF files.

          Note2: Sorry for my bad english

          • 2. Re: How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?

            This is our Batch signing script, to run with "Action Wizard" on Acrobat.


            Attention to "appearance" of visible signature (in appearances.acrodata file), you must create an appearance called "BatchSigning" in Edit -> Preferences -> Security -> Appearances. The recommended setting is "No graphic", and only "Reason" displayed.

            Also, you must verify the default digital identity for signing on "Tools"->"Sign and Certify"->"More Sign and Certify"->"Security Settings", if the correct digital ID is set by default (with the pen icon at left side of name).


            If not, select the correct ID with mouse and set as default, in "Usage Options"->"Use for Signing".

            Also verify if the smart card is correctly inserted, and if all required drivers and softwares are installed.



            //Assinatura em lote - Batch signing - PDFs script for Adobe Acrobat Pro (tested w/10.1.14 release)

            ////////////////////////////////////-> 100 chars long lines <-/////////////////////////////////////

            //Acrobat batch sequence (JavaScript) to add a visible signature to all documents.

            //This script is called for each file on batch processing, in "action wizard".

            //A visible signature field is added above the last ocurrence of signer's complete name,

            //or at end of the document, if the name was not found.

            //Also, a visible annotation is added on the remaining pages, as a footer.

            //For use with A1 or A3 certificates, smartcard or token. Prompt for PIN once only.

            //By SSUP/CSUP/SETIN/TST (tst.jus.br) 2015-June

            //Uncomment "console" lines to see debug results


            //Constants (all named like cXxxYyy):

            //Dimensions, expressed in points (1/72 inch):

            var cSignHeight = 18; //height of signature field

            var cSignMinWidth = 200; //Minimum width of signature above the signer's name

            var cFooterHeight = 12; //height of signature/annotations on footers

            var cSgnFootWidth = 380; //width of signature on footer

            var cMm2Pt = 72/25.4; //multiplier to convert mm to points

            var cRepSize = [297*cMm2Pt, 210*cMm2Pt] //report in a landscape A4-size PDF

            var cRepMargin = 10*cMm2Pt; //with 10mm borders

            //Colors and text appearance:

            var cSgnFilColr = color.transparent; //fill color of signatures. Sign. bar=["RGB",0.63,0.76,0.84]

            var cSignColor = ["RGB", 0.25, 0.45, 0.55]; //text and outline color of signatures

            var cFootNotColr = ["RGB", 0.0, 0.2, 0.3]; //text and outline color of footer annotations

            var cFootNotOpct = 0.7; //opacity of footer annotations

            var cFooterTextSize = 9; //footer text size

            //Date formats:

            var cDateFmtSec = "dd/mm/yyyy HH:MM:ss"; //date format with seconds

            var cDateFmtMin = "dd/mm/yyyy HH:MM"; //date format without seconds

            //This is the "appearance" of visible signature (in appearances.acrodata file), you must

            //create an appearance with this name, in Edit -> Preferences -> Security -> Appearances.

            //The recommended setting is "No graphic", and only "Reason" displayed.

            var cSignAppce = "BatchSigning";

            //File and field names:

            var cReportFile = "/C/temp/BatchSigningResult_%s.pdf"; //report file name (template) "/C/temp/"??

            var cAnnotName = "BatchSignAnnotation_p"; //names of footer annotations

            //Maximum milliseconds elapsed (from last document) to consider which is in the same batch run:

            var cTimeOutMs = 1000;

            //Error messages:

            var cAbortMessage = "Batch signing aborted.";

            var cLoginFailMsg = "Login failure!";

            var cSignFailMsg = "Signing failure for document ";

            var cNameNotFoundMsg = "Signer's name was not found, signing on footer";

            var cAddAnnotLinkErrMsg = "(Error adding Link/Annotation on page %d: %s)";

            //Texts which will appear on signatures and footer annotations:

            var cSignReason = "Digital signature of %CN% at %DATE%, as in law ....."; //sign reason

            var cTestSigRsn = "Digital signature of %CN% only for testing"; //only for testing

            var cFooterAnnot = "Document certified by digital signature, as in law .....";

            var cRepMsgOkFirst = "OK, first signature.";

            var cRepMsgOkAlrSgn = "OK, but already had been signed by other person(s).";

            var cRepMsgSkipped = "Already signed by the same person, nothing to do.";

            //Instructions in case of fail of test sign:

            var cTSignFailMsg = "Failure on test signing!\nVerify the default digital identity for signing "

                              + "on \"Tools\"->\"Sign and Certify\"->\"More Sign and Certify\"->"

                              + "\"Security Settings\", if the correct digital ID is set by default "

                              + "(with the pen icon at left side of name).\nIf not, "

                              + "select the correct ID with mouse and set as default, in "

                              + "\"Usage Options\"->\"Use for Signing\".\nAlso verify if the smart card "

                              + "is correctly inserted, and if all required drivers and softwares are installed."

                              + "\nIf all appears OK, make a single signature to test and check.";

            //Report summary header (printf syntax):

            var cRepSummary = "Batch signing at %s\nCN=\"%s\" (%s)\n"

                            + "------------------------------------------------\n"

                            + "Results, and quantity of documents:\n"

                            + "%d - " + cRepMsgOkFirst + " - Signed over last ocurrence of signer's name.\n"

                            + "%d - " + cRepMsgOkFirst + " - " + cNameNotFoundMsg + ".\n"

                            + "%d - " + cRepMsgOkAlrSgn + " - Signed over last ocurrence of signer's name.\n"

                            + "%d - " + cRepMsgOkAlrSgn + " - " + cNameNotFoundMsg + ".\n"

                            + "%d - " + cRepMsgSkipped + "\n"

                            + "%d - With errors, or incomplete processing.\n"

                            + "------------------------------------------------\n"


            //trim function, does not exist on Acrobat 10

            if (!String.prototype.trim) {

              (function() {

                String.prototype.trim = function() {

                  return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,''); }; }

              )(); }


            //console "add-on" function, to print all properties of a object literal:

            console.printObjProps = function(paHeader, paProps) {


              for (var vProperty in paProps) this.println(vProperty+": "+paProps[vProperty]); };


            //function to prepare names to search for, cleaning confusing characters

            function normalizeName(paText) {

              if ((paText==null)||(typeof paText!="string")) return ""; //replace raises error if not a string

              paText = paText.replace(/[ÀÁÂÃÄÅàáâãäåª]/g,"A"); //clean AEIOU, N, Y, Ç

              paText = paText.replace(/[ÈÉÊË&èéêë]/g,"E");

              paText = paText.replace(/[ÌÍÎÏìíîï]/g,"I");

              paText = paText.replace(/[ÒÓÔÕÖòóôõöº]/g,"O");

              paText = paText.replace(/[ÙÚÛÜùúûü]/g,"U");

              paText = paText.replace(/[Ññ]/g,"N");

              paText = paText.replace(/[Ýý]/g,"Y");

              paText = paText.replace(/[Çç]/g,"C");

              paText = paText.replace(/[-_\.\t\n\r\v\f]/g," "); //separators to spaces

              paText = paText.replace(/[\s\uFEFF\xA0]{2,6}/g," "); //remove multiple spaces, up to 6

              paText = paText.trim();

              paText = paText.replace(/[^A-Z\s]/gi,""); //only letters and spaces are allowed

              return paText.toUpperCase(); }


            //function to get position of signature/annotation on footer, upper-left X Y and lower-right X Y

            function getPositionOnFooter(paPage) {

            var vBBox = this.getPageBox("BBox", paPage); //perimeter of actual visible content

            //console.println("BBox of page "+paPage+": "+vBBox);

            //look through all Fields and find the fields in this page outside BBox:

            var vNumFields = this.numFields;

            for (var vIField=0; vIField<vNumFields; vIField++) {

              var vFieldName = this.getNthFieldName(vIField);

              for (var vIWidget=0; ; vIWidget++) {

                var vFieldWidget = this.getField(vFieldName+"."+vIWidget);

                //console.println("Field "+vIField+"("+vFieldName+")."+vIWidget+" null?"+(vFieldWidget==null));

                if (vFieldWidget == null) break;

                try {

                  if ((vFieldWidget.hidden)||(vFieldWidget.display==display.hidden)) continue;

                  if (vFieldWidget.page!=paPage) continue;

                  vRect = vFieldWidget.rect; //expand the BBox

                  if (vRect[0]<vBBox[0]) vBBox[0] = vRect[0];

                  if (vRect[1]>vBBox[1]) vBBox[1] = vRect[1];

                  if (vRect[2]>vBBox[2]) vBBox[2] = vRect[2];

                  if (vRect[3]<vBBox[3]) vBBox[3] = vRect[3]; }

                catch (e) {} } }

            //look all annotations to find annotations outside BBox:

            var vAnnots = this.getAnnots(paPage);

            if (vAnnots == null) vNumAnnots = 0;

            else vNumAnnots = vAnnots.length;

            for (var vIAnnot=0; vIAnnot<vNumAnnots; vIAnnot++) {

              var vAnnot = vAnnots[vIAnnot];

              if (vAnnot.hidden) continue;

              vRect = convertULLRtoLLUR(vAnnot.rect); //expand the BBox

              //console.println(vAnnot.name+" on p."+vAnnot.page+" rect="+vAnnot.rect);

              if (vRect[0]<vBBox[0]) vBBox[0] = vRect[0];

              if (vRect[1]>vBBox[1]) vBBox[1] = vRect[1];

              if (vRect[2]>vBBox[2]) vBBox[2] = vRect[2];

              if (vRect[3]<vBBox[3]) vBBox[3] = vRect[3]; }

            //console.println("expanded BBox of page "+paPage+": "+vBBox);

            var vPosition = [vBBox[0], vBBox[3], vBBox[0]+cSgnFootWidth, vBBox[3]-cFooterHeight]; //below BBox

            //console.println("BBox-derived Footer: "+vPosition);

            vPosition = ensureIsOnPage(paPage, vPosition, cSgnFootWidth, cFooterHeight);

            //console.println("Corrected footer: "+vPosition);

            return vPosition; }


            //function to check and correct for positions outside ArtBox limits:

            function ensureIsOnPage(paPage, paPosition, paWidth, paHeight) {

            var vArtBox = this.getPageBox("Art", paPage); //limit to put visible content

            //console.println("ArtBox of page "+paPage+": "+vArtBox);

            //now check and correct for positions outside ArtBox limits:

            if (paPosition[0] < vArtBox[0]) { //left

              paPosition[0] = vArtBox[0];

              paPosition[2] = paPosition[0]+paWidth; }

            if (paPosition[2] > vArtBox[2]) { //rigth

              paPosition[2] = vArtBox[2];

              paPosition[0] = paPosition[2]-paWidth;

              if (paPosition[0] < vArtBox[0]) paPosition[0] = vArtBox[0]; }

            if (paPosition[1] > vArtBox[1]) { //top

              paPosition[1] = vArtBox[1];

              paPosition[3] = paPosition[1]-paHeight; }

            if (paPosition[3] < vArtBox[3]) { //bottom

              paPosition[3] = vArtBox[3];

              paPosition[1] = paPosition[3]+paHeight;

              if (paPosition[1] > vArtBox[1]) paPosition[1] = vArtBox[1]; }

            return paPosition; }


            //function to Convert quads in default user space to rotated User space used by Links and fields.

            function defaultToUserSpace(paPage, paCoords) {

              var vMatrix2D = (new Matrix2D).fromRotated(this, paPage);

              var vMatrInv = vMatrix2D.invert(vMatrix2D);

              return vMatrInv.transform(paCoords); }


            //convert a rectangle on format (upper-left X Y and lower-right X Y) used by boxes and fields

            //to (lower-left X Y and upper-right X Y), used by annotations

            function convertULLRtoLLUR(paRect) {

            return [paRect[0], paRect[3], paRect[2], paRect[1]]; }


            //look at persistent data (global object), to check if this run is a continue of a batch:

            function isContinuing() {

            if ((typeof global.gLastDate != "number") ||

                (typeof global.gIniDate != "object") ||

                (typeof global.gCntDocs != "number") ||

                (typeof global.gReport != "object") ||

                (typeof global.gRepDocs != "object") ||

                (typeof global.gRepSumm != "object") ||

                (typeof global.gRepSign != "object") ||

                (typeof global.gResult != "object")) return false;

            return (Math.abs(Date.now()-global.gLastDate) < cTimeOutMs); }


            //function to manage report: continues a batch processing, or starts a new report

            function manageReport(paContinuing) {

            //console.println("\nBEGIN "+this.documentFileName+" - Continuing="+paContinuing);

            if (paContinuing) {

              this.vRepLine += "\n";

              global.gCntDocs++; }

            else {

              global.gIniDate = new Date();

              global.gResult = {nFirstFound:0, nFstNotFound:0, nNotFstFound:0, nNotFstNotFnd:0,

                                 nSkipped:0, nIncomplete:0};

              global.gReport = app.newDoc(cRepSize[0], cRepSize[1]); //blank report

              global.gReport.layout = "SinglePage";

              global.gReport.zoomType = zoomtype.fitP;

              global.gReport.saveAs(util.printf(cReportFile, util.printd("yyyymmdd_HHMMss", global.gIniDate)));

              var vBox = global.gReport.getPageBox("Crop"); //get crop box and add margins

              vBox = [vBox[0]+cRepMargin, vBox[1]-cRepMargin, vBox[2]-cRepMargin, vBox[3]+cRepMargin];

              var vHeight = vBox[1]-vBox[3];

              var vWidth = vBox[2]-vBox[0];

              var vSep = cRepMargin/8; //separation between fields = 1/8 of margin

              //add docs report text field and adjust some attributes:

              global.gRepDocs = global.gReport.addField("docs", "text", 0,

                                       [vBox[0], vBox[1]-vHeight*0.5, vBox[2], vBox[3]]);

              global.gRepDocs.borderStyle = border.s;

              global.gRepDocs.lineWidth = 1;

              global.gRepDocs.doNotSpellCheck = true;

              global.gRepDocs.multiline = true; // Multiline

              global.gRepDocs.readonly = true;

              global.gRepDocs.strokeColor = color.black;

              global.gRepDocs.textSize = 9;

              //add summary report text field and adjust some attributes:

              global.gRepSumm = global.gReport.addField("summ", "text", 0,

                                       [vBox[0], vBox[1], vBox[0]+vWidth*0.8, vBox[1]-vHeight*0.5+vSep]);

              global.gRepSumm.borderStyle = border.s;

              global.gRepSumm.lineWidth = 1;

              global.gRepSumm.doNotSpellCheck = true;

              global.gRepSumm.multiline = true; // Multiline

              global.gRepSumm.readonly = true;

              global.gRepSumm.strokeColor = color.black;

              global.gRepSumm.textSize = 11;

              //add test signature field but don't sign it:

              global.gRepSign = global.gReport.addField("sign", "signature", 0,

                                       [vBox[0]+vWidth*0.8+vSep, vBox[1], vBox[2], vBox[1]-vHeight*0.1]);

              global.gRepSign.strokeColor = cSignColor;

              global.gRepSign.textColor = cSignColor;

              global.gRepSign.fillColor = cSgnFilColr;

              global.gRepSign.borderStyle = border.s;

              global.gCntDocs = 1; }

            //initial line information about document being processed:

            this.vRepLine += global.gCntDocs+" - "+this.documentFileName+" ("+this.numPages+"p)"; }


            //function to start security handler, login, and get info about the signer

            function getSignerInfo() {

            var vHandler = security.getHandler(security.PPKLiteHandler, true);


            if (!vHandler.isLoggedIn) throw cLoginFailMsg+"\n"+cAbortMessage;

            var vCert = vHandler.digitalIDs.oEndUserSignCert;

            //get the complete normalized name of certificate owner (the signer)

            var vSigner = normalizeName(vCert.subjectCN);

            var vNames = vSigner.split(" ");

            var vSignReason = cSignReason.replace("%CN%", vCert.subjectCN);

            vSignReason = vSignReason.replace("%DATE%", util.printd(cDateFmtMin, new Date()));


            return {handler:vHandler, cert:vCert, reason: vSignReason,

                    nName:vSigner, names:vNames, numNames:vNames.length}; }


            //function to increment counters and update report summary, saving it:

            function updateReportSummary(paIncrements) {

            if (paIncrements.nFirstFound!=null) global.gResult.nFirstFound += paIncrements.nFirstFound;

            if (paIncrements.nFstNotFound!=null) global.gResult.nFstNotFound += paIncrements.nFstNotFound;

            if (paIncrements.nNotFstFound!=null) global.gResult.nNotFstFound += paIncrements.nNotFstFound;

            if (paIncrements.nNotFstNotFnd!=null) global.gResult.nNotFstNotFnd += paIncrements.nNotFstNotFnd;

            if (paIncrements.nSkipped!=null) global.gResult.nSkipped += paIncrements.nSkipped;

            if (paIncrements.nIncomplete!=null) global.gResult.nIncomplete += paIncrements.nIncomplete;

            global.gRepSumm.value = util.printf(cRepSummary, util.printd(cDateFmtSec, global.gIniDate),

                                                this.vSigInfo.cert.subjectCN, this.vSigInfo.nName,

                                                global.gResult.nFirstFound, global.gResult.nFstNotFound,

                                                global.gResult.nNotFstFound, global.gResult.nNotFstNotFnd,

                                                global.gResult.nSkipped, global.gResult.nIncomplete);

            global.gReport.saveAs(global.gReport.path); }


            //function to sign the report document, to test if all is ready to sign the batch docs

            function doTestSigning() {

            global.gRepSumm.value = cTSignFailMsg; //if signature fails, the content will be this fail msg

            var vSignReason = cTestSigRsn.replace("%CN%", this.vSigInfo.cert.subjectCN);

            if (!global.gRepSign.signatureSign(this.vSigInfo.handler,

                                               {reason:vSignReason, appearance:cSignAppce}))

              throw cSignFailMsg; }


            //function to look through all Fields and find the signature fields

            function getExistingSignatures() {

            var vNumFields = this.numFields;

            var vSignatures = [];

            for (var vIField=0; vIField<vNumFields; vIField++) {

              var vFieldName = this.getNthFieldName(vIField);

              var vField = this.getField(vFieldName);

              if (vField == null) continue;

              if (vField.type != "signature") continue;

              var vSignInfo = vField.signatureInfo();

              if (vSignInfo == null) continue;

              //console.println("Field "+vFieldName+" rect:"+vField.rect+" signer's name:"+vSignInfo.name);

              //check if already signed by this same signer, and throw a specific error:

              if (normalizeName(vSignInfo.name) == normalizeName(this.vSigInfo.nName)) {

                updateReportSummary({nSkipped:1, nIncomplete:-1});

                event.rc = true; //don't abort the batch, only skip this document!

                throw util.printf(cRepMsgSkipped, this.vSigInfo.nName) } ;

              vSignatures.push(vFieldName); }

            return vSignatures; }


            //function to search for last ocurrence of signer's complete name within the document

            function getSignaturePosition() {

            var vFound = false;

            //console.println("Searching document, "+this.numPages+" page(s):");

            lSearch: for (var vIPage=this.numPages-1; vIPage>=0; vIPage--) {

              //for each page:

              var vArrayWords = [];

              var vArrPositions = [];

              var vNamesFound = 0;

              var vNumWords = this.getPageNumWords(vIPage);

              //console.println("Page "+vIPage+": "+vNumWords+" word(s)");

              //populate arrays with valid words and their respective positions on page (Nth)

              for (var vIWord=0; vIWord<vNumWords; vIWord++) {

                vTWord = normalizeName(this.getPageNthWord(vIPage, vIWord));

                if (vTWord.length > 0) {


                  vArrPositions.push(vIWord); } }

              var vNumWords = vArrayWords.length; //number of valid words on page

              //search the array of valid words (from end to begin) for signer's names in sequence

              for (vIWord=vNumWords-1; vIWord>=0; vIWord--) {

                if (vArrayWords[vIWord] == this.vSigInfo.names[this.vSigInfo.numNames-1-vNamesFound]) {


                  if (vNamesFound == this.vSigInfo.numNames) {

                    vFound = true;

                    break lSearch; } }

                else vNamesFound = 0; } }

            //calculate position of signature field above the signer's name

            if (vFound) {

              var vLeft = -1;

              var vRight = -1;

              var vTop = -1;

              for (var vIName=0; vIName<this.vSigInfo.numNames; vIName++) {

                var vPosName = vArrPositions[vIWord+vIName];

                var vQuads = this.getPageNthWordQuads(vIPage, vPosName)[0]; //coords of each name (words)

                //console.println(this.vSigInfo.names[vIName]+": p."+vIPage+"("+vPosName+") \""

                //               +this.getPageNthWord(vIPage, vPosName)+"\"");

                for (var vIPoint=0; vIPoint<=((vQuads.length-1)/2); vIPoint++) { //get the opposite corners

                  var vQuadX = vQuads[vIPoint*2];

                  var vQuadY = vQuads[vIPoint*2+1];

                  if (vQuadX<vLeft || vLeft<0) vLeft = vQuadX;

                  if (vQuadX>vRight || vRight<0) vRight = vQuadX;

                  if (vTop<vQuadY || vTop<0) vTop = vQuadY; } }

              if ((vRight-vLeft)<cSignMinWidth) {

                var vDif = (cSignMinWidth-(vRight-vLeft))/2;

                vRight += vDif;

                vLeft -= vDif; };

              //coordinates for signature, upper-left X Y and lower-right X Y

              vSignCoords = [vLeft, vTop+cSignHeight, vRight, vTop];

              vSignCoords = ensureIsOnPage(vIPage, vSignCoords, cSignMinWidth, cSignHeight); }

            else {

              //console.println("Signer's complete name was not found!");

              this.vRepLine += " - "+cNameNotFoundMsg;

              //set default position for signature field on the footer of last page:


              vSignCoords = getPositionOnFooter(vIPage); }

            return {found:vFound, page:vIPage, rect:vSignCoords}; }


            //function to add the annotations on footer of each page:

            function addAnnotations() {

            for (var vIPag2=this.numPages-1; vIPag2>=0; vIPag2--) {

              if (vIPag2 == this.vSigPos.page) continue; //don't create footer annotation on signature's page.

              var vAnnot = this.getAnnot(vIPag2, cAnnotName+vIPag2); // get previous annotation if exists

              if (vAnnot != null) {

                //console.printObjProps("Annot. "+cAnnotName+vIPag2+" already exists:", vAnnot.getProps());

                continue; } //already exists, skip page

              var vSignCoords = getPositionOnFooter(vIPag2); //create new annotation:

              //console.println("New annotation: p."+vIPag2+" coords: "+vSignCoords);

              try { //addAnnot may fail if security options prohibits new annotations

                vAnnot = this.addAnnot({page:vIPag2, type:"FreeText", rect:convertULLRtoLLUR(vSignCoords),

                                        opacity:cFootNotOpct, print:true, strokeColor:cFootNotColr,

                                        name:cAnnotName+vIPag2, fillColor:cSgnFilColr, width:1, style:"S",

                                        richDefaults:{alignment:1, textSize:cFooterTextSize,

                                                       textFont:font.Helv, textColor:cFootNotColr}});

                //text content must be set AFTER set richDefaults, to take effect!

                vAnnot.setProps({contents: cFooterAnnot, readOnly: true});

                //add links to signature panel over the footer annotations:

                if (this.signatureFieldNames.length == 0) { //only if document isn't already signed

                  var vLink = this.addLink(vIPag2, defaultToUserSpace(vIPag2, vSignCoords));

                  vLink.borderColor = cFootNotColr;

                  vLink.borderWidth = 0;

                  vLink.setAction("app.execMenuItem(\"ShowHideSignatures\");"); } }

              catch (e) {

                this.vRepLine += " "+util.printf(cAddAnnotLinkErrMsg, vIPag2, vError); } } }


            //function to search for a field name which does not already exists and add a new signature:

            function addSignature() {

            vIField = 0;

            do {


              vFieldName = "Signature"+vIField; 

              var vField = this.getField(vFieldName); }

            while (vField != null);

            //console.println("Coordinates of new signature field \""+vFieldName+"\": "+this.vSigPos.rect);

            vField = this.addField(vFieldName, "signature", this.vSigPos.page,

                                   defaultToUserSpace(this.vSigPos.page, this.vSigPos.rect));

            vField.strokeColor = cSignColor;

            vField.textColor = cSignColor;

            vField.fillColor = cSgnFilColr;

            vField.borderStyle = border.s;

            //sign the signature field and save (overwrite) the document, this is done by SignatureSign:

            if (!vField.signatureSign(this.vSigInfo.handler,

                                      {reason:this.vSigInfo.reason, appearance:cSignAppce}))

              throw cSignFailMsg+" "+this.documentFileName;

            //report the results:

            var vFound = Number(this.vSigPos.found);

            var vNotFnd = Number(!this.vSigPos.found);

            if (this.signatureFieldNames.length == 0) {

              updateReportSummary({nFirstFound:vFound, nFstNotFound:vNotFnd, nIncomplete:-1});

              this.vRepLine += " - "+cRepMsgOkFirst; }

            else {

              updateReportSummary({nNotFstFound:vFound, nNotFstNotFnd:vNotFnd, nIncomplete:-1});

              this.vRepLine += " - "+cRepMsgOkAlrSgn; } }


            //----------- BEGIN OF PROCESSING -----------


            event.rc = false; //if an error ocurs, the script won't run for next docs

            //almost all processing is within this try...catch statement:

            try {

              this.vRepLine = ""; //report line

              var vContinuing = isContinuing(); //check time elapsed since last run

              //start or continue the report:


              //get security and signer info, and do the test signing:

              this.vSigInfo = getSignerInfo();

              if (!vContinuing) doTestSigning();

              updateReportSummary({nIncomplete:1}); //document being processed is incomplete

              //search document for correct signature position:

              this.syncAnnotScan(); //read all annotations

              this.signatureFieldNames = getExistingSignatures();

              this.vSigPos = getSignaturePosition();

              //add annotations and signature to document:



              event.rc = true; //no error happened, enable run for next docs

              } //end of main try...catch

            catch (vError) { //get error message and put it on report:

              if (event.rc) this.vRepLine += " - "+vError; //not an aborting error: only displays for this doc

              else { //display error and abort batch processing

                var vLineNumber = "";

                if (typeof vError.lineNumber == "number") vLineNumber = " ("+vError.lineNumber+")";

                this.vRepLine += "\n"+vError+vLineNumber+"\n"+cAbortMessage;

                app.alert(vError+vLineNumber+" - "+cAbortMessage); } }


            //append this.vRepLine at end of report (and summary if aborting!):

            try {

              global.gRepDocs.value += this.vRepLine;

              if (!event.rc) global.gRepSumm.value = this.vRepLine+"\n--------------\n"+global.gRepSumm.value;


              global.gLastDate = Date.now(); } //save last datetime for processing control

            catch (vError) {

              if (event.rc) event.rc = false; //don't continue batch if was unable to append a report line

              else app.alert(this.vRepLine+" - "+vError.message+" - "+cAbortMessage); };

            //end of script

            • 3. Re: How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?
              jorgep37884552 Level 1

              I have a doubt...


              When I do this process manually I have a checkbox for "Lock Document After Signing".


              The script above cover this option? If not, what could I add to this code to do that?


              ps: Thanks in advance and sorry for my english!

              • 4. Re: How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?



                How can I disable the annotation in the footer and get the signature to show the same size and location is it shows on the summery auto generated pdf ?

                • 5. Re: How do I use Acrobat JavaScript to perform digital signature (e-sign) in multiple PDFs documents?

                  Sorry before hand I'm new to this, this sounds like something I can use. I have several PDF forms that I have to sign but it has to be signed on a specified line like line 22. Is there a way to do this.