Four Methods for Automatic Number Incrementing PDF Stamps
Each method has its advantages. Only one does not have any of the disadvantages.
There are at least four methods for creating automatic number incrementing dynamic PDF stamps. Each methods has its pros, and three have cons. This article will compare four of those methods for the following criteria:
1) Whether a folder level JavaScript file is required.
2) Ability to store and maintain separate numbers across different documents.
3) Ability to reset the "next" number.
4) Ability to use on encrypted, password protected files that prevent changing the document. It is assumed the encryption details do not prevent commenting, because no stamp will work with this type of encryption.
The four methods are as follows:
1) Counting stamps
2) Global variable number storage
3) Form field number storage
4) Annotation number storage
It is doubtful that any of these methods will work with non-Adobe PDF programs due their inability to interact with the document being stamped. You can read about this here.
Take the Acrobat Pro/JavaScript eLearning Course Acrobat Like a Pro
Counting Stamps
The stamp counting method cannot reset the number because the method counts the stamps in the document. The number of the stamps is the number of the stamps. There is no folder level JavaScript file required. It has the ability to maintain separate numbers in separate documents because it counts the stamps in each document. It can be used on encrypted files as long as they don't prevent commenting.
The method is pretty simple. When the stamp is activated, a script counts the number of stamps of the same type in the document and adds one to that total. This number is then set as the field value of the number field of the stamp file. Here's the script:
var num=1; //Line 1
var ess=event.source.source; //Line 2
if(ess.getAnnots()) //Line 3
{ //Line 4
var anot=ess.getAnnots(); //Line 5
for(var i=0; i<anot.length; i++) //Line 6
{ //Line7
if(anot[i].AP==event.source.stampName) //Line8
{num++} //Line 9
} //Line 10
} //Line 11
event.value=num; //
Script Breakdown
Line 1: Define the variable num as 1. If there are no stamps yet, the first one applied will be number 1.
Line 2: Define the variable ess as event.source.source (the document being stamped).
Line 3: Conditional statement that tests whether there are any annotations in the document. Omitting this condition will cause an error in the rest of the script if there are no annotations. The rest of the script that increments the number does not need to run if there are no annotations. The number will be 1.
Line 4: Opening curly brace to contain the script that runs if condition is true.
Line 5: Define the variable anot as the array of annotations in the document.
Line 6: Start a loop that will loop through all annotations in the document.
Line 7: Opening curly brace for loop functions.
Line 8: Conditional statement that tests whether the AP property of the annotation is the same as the stampName property of the stamp in use. The AP property is the same as the stampName property, but in different states. The AP property is after the stamp has been placed. The stampName property is while the stamp is being placed.
Line 9: If the previous statement is true, increment the number by 1.
Line 10: Closing curly brace to close out the loop.
Line 11: Closing curly brace to close out the annotation test condition.
Line 12: Set the value of the field containing the script to the num variable value.
Global Variable Storage
This method stores the running number in a global variable and increases the number by one every time the stamp is applied. A global variable can be set as persistent, meaning it will be maintained through multiple sessions of the Adobe application. This method does not allow for a separate set of numbers for separate documents, as the global variable is not document specific. It can be reset for a new document, but if the user goes back to a previous document, the number sequence of that document will not apply. Access to the global variable requires a trusted function in a folder level script. It will work on encrypted documents.
Here's an example of a trusted function with a global variable that would be stored in the application JavaScripts folder:
stmpNumber = app.trustedFunction( function () //Line 1
{ //Line 2
app.beginPriv(); //Line 3
if(global.stmpNmb==undefined) //Line 4
{ //Line 5
global.stmpNmb=1; //Line 6
return 1; //Line 7
} //Line 8
else //Line 9
{ //Line 10
global.stmpNmb=Number(global.stmpNmb)+1; //Line 11
return global.stmpNmb; //Line 12
} //Line 13
app.endPriv(); //Line 14
}) //Line 15
Script Breakdown
Lines 1 – 3: Define the trusted function.
Line 4: Conditional statement tests whether the global variable global.stmpNmb is undefined.
Line 5: Opening curly brace to contain the script that runs if the undefined statement is true.
Line 6: If the statement is true, define the value of the global variable global.stmpNmb as 1.
Line 7: Return 1 from the function.
Line 8: Curly brace to close the script that runs when the undefined statement is true;
Line 9: else – sets another script to run if the undefined statement is false.
Line 10: Opening curly brace to contain the script to run if the statement is false.
Line 11: Add 1 to the global variable value. Global variable values are strings, so use a Number constructor to avoid concatenation of 2 numbers (2 + 1 = 21, instead of 3).
Line 12: Return the global variable value from the function.
Line 13: Return the global variable from the function.
Lines 14-15: Close out the trusted function.
There's another part to this script: the calculation script that runs when the stamp is applied, that calls the function.
event.value= stmpNumber();
Form Field Storage
The field storage method creates a form field that stores a number value. While Adobe Reader does not have a user interface for creating form fields, they can be created with a script, so this method will work with Reader. Since each document will have its own form field the numbers can be different for different documents. It won't work with encrypted documents that prevent changing the document because creating a form field is a change to the document that is prohibited with this common level of encryption. Here's the script:
var ess = event.source.source; //Line 1
if(!ess.getField("Storage")) //Line 2
{ //Line 3
var f=ess.addField("Storage","text",0,[0,0,0,0]); //Line 4
f.setAction('Validate','event.target.defaultValue=event.value'); //Line 5
f.value=1; //Line 6
event.value=1; //Line 7
} //Line 8
else //Line 9
{ //Line 10
ess.getField("Storage").value = ess.getField("Storage").value+1; //Line 11
event.value=ess.getField("Storage").value; //Line 12
} //Line 13
Script Breakdown
Line 1: Define the variable ess as the document being stamped (event.source.source).
Line 2: Test whether the document being stamped does not contain a field called Storage.
Line 3: Opening curly brace to contain the script that runs if the test is true.
Line 4: Create a text field called Storage on the first page of the document being stamped and define the field as the variable f.
Line 5: Set a validation script (event.target.defaultValue=event.value) for the created field. The purpose of this script is to avoid the value being cleared if the document has a reset button. The field's default value will change to the field's value every time the field's value changes. When a field is reset if reverts to its default value.
Line 6: Set the field's value to 1.
Line 7: Set the value of the number field of the stamp to 1.
Line 8: Curly brace to close out the script when the condition is true.
Line 9: Start another script for when the condition is false by using the term else.
Line 10: Opening curly brace for a script to run if the condition is false.
Line 11: Set the value of the storage field to the value of the storage field plus one.
Line 12: Set the value of the number field of the stamp to the value of the storage field.
Line 13: Curly brace to close out the script.
Annotation Number Storage
This method is similar to the field storage method, except an annotation is created instead of a form field and the number is stored in the annotation. Annotations don't have values like fields, so the number is stored in the subject property of the annotation. Unlike the field storage method, this method will work with encrypted documents that prevent changing the document, as long as the encryption does not prevent commenting – in which case no stamps would function with the document anyway. Here's the script:
var ess=event.source.source; //Line 1
if(!ess.getAnnot(0,"Storage")) //Line 2
{ //Line 3
ess.addAnnot({ //Line 4
type:"Square", //Line 5
page:0, //Line 6
name:"Storage", //Line 7
subject:1, //Line 8
rect:[0,0,0,0] //Line 9
}); //Line 10
event.value=1; //Line 11
} //Line 12
else //Line 13
{ //Line 14
ess.getAnnot(0,"Storage").subject=Number(ess.getAnnot(0,"Storage").subject)+1; //Line 15
event.value=Number(ess.getAnnot(0,"Storage").subject); //Line 16
} //Line 17
Script Breakdown
Line 1: Define the variable ess as the document being stamped (event.source.source).
Line 2: Test whether the document being stamped does not contain an annotation name
Storage on the first page of the document.
Line 3: Opening curly brace to contain the script that runs if the test is true.
Line 4: Create an annotation on the document being stamped:
Line 5: Annotation is a square.
Line 6: Annotation is on the first page of the document.
Line 7: Annotation's name is Storage.
Line 8: The subject of the annotation is 1.
Line 9: The rect of the annotation is [0,0,0,0] so it is not visible.
Line 10: Close out the creation of the annotation.
Line 11: Set the value of the stamp's number field to 1.
Line 12: Curly brace to close out the script when the condition is true.
Line 13: Start another script for when the condition is false by using the term else.
Line 14: Opening curly brace for a script to run if the condition is false.
Line 15: Set the subject of the Storage annotation to the subject of the Storage annotation plus 1. Use a number constructor to avoid string concatenation instead of number addition (1 + 1 = 11, instead of 2).
Line 16: Set the value of the stamp's number field to the value of the subject of the annotation and use a number constructor to avoid concatenation.
Line 17: Curly brace to close out the script.
Resetting The Number
For all examples except the Counting Stamps method, the “next number” can be reset. A trigger is required. A popup dialog when the stamp is applied is probably not a good idea because the popup would have to appear every time the stamp is applied, which would slow down the repetitive stamping process. A custom menu item or toolbar button should be used, which requires a folder level script that runs each time the Adobe program is opened. The function would simply write the new value to either the global variable, the storage field value, or the storage annotation subject, depending on which method is used.
Shameless Plug
www.pdfautomationstation.com sells the most flexible Exhibit Stamp on the market.
www.pdfautomationstation sells 200 number incrementing stamps in one.