For some options in Acrobat’s form editor, you can select multiple fields and then apply the same option to all selected fields. This works for example for the “read-only” flag, or the display options. It does however not work for things like formatting/keystroke/validation/calculation scripts.
It’s relatively easy to assign e.g. a custom validation script to many form fields in a PDF form via JavaScript. I do that all the time to cut down on manually editing fields. The following script validates that a text field contains data in a specific format:
Let’s assume we want to use the following script for all fields that contain a product number in a specific format, three upper case characters followed by a dash and three or four digits:
var re = /^[A-Z]{3}-[0-9]{3,4}$/; if (event.value != "") { event.rc = re.test(event.value); }
To assign this to all fields that have a name that starts with “product.” (e.g. product.124, product.999 and so on), we can use the following script:
var script = "var re = /^[A-Z]{3}-[0-9]{3,4}$/;\n" + "if (event.value != \"\") {\n" + "\tevent.rc = re.test(event.value);\n" + "}"; for (var i=0; i<this.numFields; i++) { var fName = this.getNthFieldName(i); if (fName.indexOf("product.") == 0) { this.getField(fName).setAction("Validate", script); } }
That’s straight forward, the only potential problem is that the script needs to be formatted so that it is a valid JavaScript string (e.g. by escaping all quotes and some other special characters, replacing line breaks with ‘\n’ and so on). But, what if we want to use not a custom validation script, but one of the built-in formatting functions or range validations that Acrobat supports. Take a look at this one:
This is a standard numeric format option for a value with two decimal places. How can we apply that to a number of fields in one operation? Yes, we can reimplement this in JavaScript, but what if I don’t want to go through the trouble of doing that, especially because Acrobat already knows how to do that?
The good news is that behind the scenes, even these built-in functions are handled via JavaScript. We just never see the actual script because Acrobat actually parses the scripts, and if it recognizes one of the built-in functions, it does not display the custom script dialog, it just says “that’s a number with two decimals”…
So, how do we find the script that Acrobat applies in the background? More good news: The tool to do that is built right into Acrobat Pro as well (unfortunately, not into Acrobat Standard): It’s the pre-flight tool.
Let’s create a quick sample document, add one form field, and apply the formatting routine from the screenshot above. Now bring up Preflight (e.g. Tools>Print Production>Preflight in Acrobat XI and DC) and select the menu item “Browse Internal PDF Structure…” in the “Options” menu:
This will show us the “guts” of the PDF file. For the following, we need to know that form fields are stored in the “Annoys” dictionary on the page level. The following screen shot shows the structure of the PDF file with the relevant dictionaries expanded:
We are looking for the “Page>Annots>N>AA” dictionary entry with “N” being the annotation number. In this case – because we only have one form field in our document, this is straight forward: We are using the annotation #0. In the “AA” dictionary, we see a number of different entries. If we are dealing with a formatting command, we usually see two items: The actual format script and a keystroke script.
The “AA” dictionary entry is describes in table 220 in the PDF specification (ISO 32000-2008), which points to table 194 for an explanation of the different trigger events. For the following, we will only consider the formatting, keystroke, validation and calculation triggers. They are defined (in this order) by the keys “F”, “K”, “V” and “C”.
In this case, we see two entries for “F” and “K”. Both have to dictionary entries on their own: “S” and “JS”. The “S” key indicates what type of action is saved in this dictionary. In our case, “JavaScript” indicates that we have indeed a script, and the “JS” key contains the actual script.
We find these two scripts: The formatting script looks like this:
AFNumber_Format(2, 0, 0, 0, "", true);
And the keystroke script is this:
AFNumber_Keystroke(2, 0, 0, 0, "", true);
Both scripts call an internal function. We could now play around with the options on the formatting dialog to figure out what the different parameters mean. This old page on Planet PDF has some additional information: http://www.planetpdf.com/forumarchive/125041.asp
For what we want to do, it’s sufficient to know what the scripts actually are, without fully understanding what exactly they do: If it’s good enough for Acrobat, it’s good enough for me đŸ™‚
– if you do that, just make sure that you do not modify anything in these scripts.
To assign these two scripts to the Format and Keystroke triggers, we can use the following few lines of code:
var f = this.getField("SomeField"); f.setAction("Format", "AFNumber_Format(2, 0, 0, 0, \"\", true);"); f.setAction("Keystroke", "AFNumber_Keystroke(2, 0, 0, 0, \"\", true);");
You can of course combine this with a look that looks for certain fields, matching a certain pattern and then apply this change only to those fields. This can be done in e.g. an Action, or a Custom Command (see my previous post about Custom Commands for more information).
We have not discussed the validation and calculation scripts that Acrobat might add. The process is the same, all we need to do is either look for the “V” key for a validation script, or the “C” key for a calculation script (e.g. a simple field notation script or one of the simple calculation methods).
This is a very simple way to automate something that otherwise requires quite a bit of clicking and pasting of information.
This is awesome! Thank you! I have spent couple of hours looking for this information and you have written this so beautifully.