One of the first tools I developed when I started programming PDF automation solutions full time was to populate hundreds of PDFs with data from an Excel spreadsheet that had been saved as a tab delimited text file. The solution loops through all of the rows in the text file, imports the field data, and saves a populated PDF for each row of data. It worked well and it worked fast.
Calculations Can Really Slow Down A Form’s Performance
As the customer continued to request more logic and calculations be built into the forms, performance suffered significantly. Every calculation in a PDF form runs every time the value of any field in that form changes. So if you imported 25 fields and there were 25 fields with calculations, those 25 calculations would run 25 times for each field of imported data. That’s 625 calculations per row of data. That’s a lot of hour glass icons, hang-ups, and Acrobat-is-not-responding’s. Something had to be done. What if there was a way to turn the calculations off, import the data, and run the calculations only once at the end? (There is. Keep reading.)
All I had to do was add three lines of simple code. One at the beginning of my import script, and two at the end. The following line of code suspends all calculations until they are turned back on:
this.calculate=false;
The following line of code turns the calculations back on and was inserted after my import script:
this.calculate=true;
When the calculations are turned back on, they don’t run until a field value changes, or they can be run by the following line of code, which I inserted after the line of code above:
this.calculateNow();
Without the calculations running after each field was imported, performance improved significantly and there was no more waiting frantically and wondering whether Acrobat was going to crash.
Fast Forward To A Recent Project
I was recently hired to write a script that would fill in 10 weeks worth of dates on a calendar after a date was selected in a date field. The calendar had 70 date fields (10 rows of 7 days). The form was sent to me with existing fields so all I had to do was add a validation script in the date field. I looked at the names of the fields that needed to be populated with dates and, unfortunately, they had no useable pattern. It looked like they had been created from one field using Create Multiple Copies and then one of those fields was used to create the rest with Create Multiple Copies again.
PRO TIP: When creating form fields that will be referenced in a script, taking a few minutes to put some thought into the field names will save you lots of time later and reduce errors.
I immediately asked the customer if it was okay to rename all of the fields. (I would’ve named them with the numbers 1 through 70 to create a usable pattern). This could’ve been done by creating one field and using (right-click) Create Multiple Copies, selecting 71 fields down and 1 field across, removing the first field with the .0 suffix, and then moving those fields into place in order. Unfortunately the customer did not want me to rename the fields. He was going to add this form to an existing form that referenced those field names.
Solution
I came up with the following solution to get around the lack of thoughtful field names:
I manually entered the values 1 through 70 into the fields in order.
I ran a script in the console that would search all field values for the numbers 1 through 70, then write the number and field name to the console, separated by a tab.
I copied the result and pasted it into Excel, ending up with a column of numbers and another column of corresponding field names.
The numbers were not in order so I sorted them from lowest to highest, ensuring they now went from 1 to 70. The field names were now in the correct order as they appeared in the form (left to right, row by row).
A wrote an Excel formula to create another column that had the field names in quotes, followed by commas.
I copied and pasted this column into my script and encased it in square brackets to create an array.
Instead of looping through fields that contained 1 through 70 in the names, I looped through the array (which had the random field names in the correct order).
The form worked flawlessly and would fill in the 70 dates immediately after selecting a date in the date field. I sent the form to the customer.
Feedback
The feedback from the customer was that the script I wrote worked perfectly in the form I had sent back. However, it did not work when those pages were added to an existing form. My first thought was that the other form contained a script error and the script was stopping before it could populate all the date fields. I asked the customer to check the console for errors. He stated that he had Acrobat Standard and not Acrobat Pro, so the keystroke shortcut (Ctrl +j) that I provided him would not open the console. Like Adobe Reader, Standard does not have a command to open the console, even though the console exists and can be used.
If you have a need to open the console in Reader or Standard, you download this free tool (must sign up for a free membership) that adds a menu item and toolbar button to the program that will open the console.
The customer did not want to send me the form but he didn’t mind letting me troubleshoot the form remotely.
Troubleshooting The Form
The first thing I did after testing the date field was create a button field with the following Mouse Up action script:
console.show();
Now I could open the console by clicking the button. There were no errors in the console. Now what?
I modified the script so it would insert the numbers 1 through 70 into the fields instead of dates to see if there was something in the date script that did not work with his version of Standard. The hourglass icon was spinning out of control. The script filled in the numbers but it seemed to take forever. "Do you have a lot of calculations in this form," I asked. "Yes" was his response.
I immediately closed the form without saving it to restore the original button script and remove the console-opening button. I modified my original validation script by inserting this.calculate=false at the beginning of the script to turn off all calculations, and I inserted this.calculate=true at the end of the script to turn the calculations back on. I also inserted this.calculateNow( ) at the end to run the calculations once in case there were any that were dependent on the calendar dates. Now when the user selected a date in the date field, the 70 dates populated correctly and immediately.
The customer directed me to another button field that had a mouse up action that checked approximately 50 check box fields. I saved the form before activating this button. Lots of hourglass action. I eventually had to do a hard shutdown of Acrobat Standard and reopen it. I inserted the script to turn off calculations at the beginning of his script and inserted the script to turn calculations back on at the end of his script. I also inserted the script to run the calculations at the end of the script because some of his other calculations were affected by this script. I saved the form and activated the button. The script ran flawlessly and without any delay.
Conclusion
If your form contains a lot of calculations and is running slowly, try turning off calculations at the beginning of repetitive scripts then turning them back on once those scripts have run. If you are new to JavaScript for Acrobat I invite you to check out my online course, and save yourself $100 by using the promo code JavaScriptPro.