Skip to main content
Inspiring
April 10, 2020
Answered

Add watermark with file name and page numbers using JavaScript

  • April 10, 2020
  • 4 replies
  • 6189 views

Hi. I'm trying to write a script for incorporation into a custom Action that can run on a batch of files. The goal is to add a watermark in the upper right-hand corner of all pages with:

  • Line 1: File ID = [file name without extension]
  • Line 2: Page # of 30

 

For example, for a pdf named 'MyFile.pdf' that contains 30 pages, the script would add the following text in the upper left corner of each page:

 

File ID = MyFile

Page # of 30

 

where # starts at 1 and increments by 1 on each subsequent page

 

See draft script below. As written, it only adds the watermark to the first page of the pdf. I've successfully created scripts to do each line of the watermark independently, but can't seem to figure out how to accomplish both into a single script. Any suggestions are very appreciated!

 

for (var p = 0; p < this.pageNum; p++);
var cMyText = "File ID = " + event.target.documentFileName.replace(/\.pdf$/i,"") + "\nPage " + (p+1) + " of " + numPages;
event.target.addWatermarkFromText({
	cText: cMyText,
	nFontSize:10,
	aColor: color.red,
	nHorizAlign:app.constants.align.left,
	nHorizValue: 36,
	nVertAlign:app.constants.align.top,
	nVertValue: -36,
	nStart: p
});

 

This topic has been closed for replies.
Correct answer dfunkalot

Here is another solution using a form field instead of a watermark. This works much faster and is a better solution for reasons described by @Thom_Parker. Thanks to Kas Thomas for the starter script.

 

/* Add File Name and Page Number */
var inch = 72;
for (var p = 0; p < this.numPages; p++) { 
 // put a rectangle at .25 inch, .25 inch 
  var aRect = this.getPageBox( {nPage: p} ); 
  aRect[0] += .25*inch;// from upper left corner of page 
  aRect[2] = aRect[0]+8*inch; // Make it 8 inch wide 
  aRect[1] -= .25*inch; 
  aRect[3] = aRect[1] - .5*inch; // and .5 inch high 
  var f = this.addField("p."+p, "text", p, aRect ); 
  f.textSize = 10;  // 10-pt type
  f.textColor = color.red; // use whatever color you want
  f.strokeColor = color.white; 
  f.textFont = font.Helv;
  f.multiline = true; // Make it multiline
  f.value = "File ID = " + this.documentFileName.replace(/\.pdf$/i,"") + "\nPage " + String(p+1) + " of " + this.numPages;  // page numbering is zero-based
  f.readonly = true;
} 

 

4 replies

dfunkalotAuthorCorrect answer
Inspiring
April 11, 2020

Here is another solution using a form field instead of a watermark. This works much faster and is a better solution for reasons described by @Thom_Parker. Thanks to Kas Thomas for the starter script.

 

/* Add File Name and Page Number */
var inch = 72;
for (var p = 0; p < this.numPages; p++) { 
 // put a rectangle at .25 inch, .25 inch 
  var aRect = this.getPageBox( {nPage: p} ); 
  aRect[0] += .25*inch;// from upper left corner of page 
  aRect[2] = aRect[0]+8*inch; // Make it 8 inch wide 
  aRect[1] -= .25*inch; 
  aRect[3] = aRect[1] - .5*inch; // and .5 inch high 
  var f = this.addField("p."+p, "text", p, aRect ); 
  f.textSize = 10;  // 10-pt type
  f.textColor = color.red; // use whatever color you want
  f.strokeColor = color.white; 
  f.textFont = font.Helv;
  f.multiline = true; // Make it multiline
  f.value = "File ID = " + this.documentFileName.replace(/\.pdf$/i,"") + "\nPage " + String(p+1) + " of " + this.numPages;  // page numbering is zero-based
  f.readonly = true;
} 

 

Participant
December 8, 2023

Hi gents. I know this post is a bit old, but I'm hoping you could help me add a line to this script to display/print the page label for each page in the PDF document. My scripting is amature at best as well, so any point in the right direction would be apprectiated. Thanks.  

Thom Parker
Community Expert
Community Expert
April 10, 2020

So I agree with JR. Use the free actions that already exist. You can modify the scripts to make them work the way you want.

 

But if you want to do this yourself, why are use a watermark?  The watermark is a rather top heavy way to do this. It has an issue your code doesn't deal with. A watermark creates an OCG layer. When you create the watermark on the next page, you replace/overwrite the last watermark OCG. A PDF file can have only one official watermark. You can read about it here. 

https://acrobatusers.com/tutorials/create_use_layers/

 

A much easier way to accomplish the same task is to use a form field. At the end the script can flatten the fields if you want them pushed into the page content, or the field can be set to readonly. 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
dfunkalotAuthor
Inspiring
April 11, 2020

Thanks @Thom_Parker. I see that you authored both of those Actions, as well as the tutorial that led me down the watermark route originally. Awesome! My JS skills are very amatuerish right now and I'm not yet ready to take on modifying your very impressive scripts. However, I see what you're saying about having multiple watermarks and will look into the form field approach. I did notice that my script runs very slowly. Do you know if using a form field would be faster? And is this example considered a form field?

Thom Parker
Community Expert
Community Expert
April 11, 2020

Yes, that script uses a form field. And I'm sur it would be faster then watermarking.

 

 

Thom Parker - Software Developer at PDFScriptingUse the Acrobat JavaScript Reference early and often
JR Boulay
Community Expert
Community Expert
April 10, 2020

The "Stamp and Number Document" and/or the "File Name Stamper" actions were made for you:

https://acrobatusers.com/actions-exchange/

Acrobate du PDF, InDesigner et Photoshopographe
dfunkalotAuthor
Inspiring
April 11, 2020

Thanks @JR_Boulay. I appreciate you pointing me to these tools, which are fantastic, adaptable for a wide range of needs, and are vastly more sophisticated than the script I was trying to write. For my specific use case though, I wanted to accomplish both in a single script and have it work on a batch of files without having to respond to a popup dialog for each file operated on by the Action. And my JS skills are not nearly advanced enough for me to modify those premade actions.

JR Boulay
Community Expert
Community Expert
April 11, 2020

You should be able to edit these actions, you can copy-paste the script from one to the other, and add a "tool" for Saving.

 

Acrobate du PDF, InDesigner et Photoshopographe
Bernd Alheit
Community Expert
Community Expert
April 10, 2020

Your for loop ends at the current page. For all pages you must use this.numPages

dfunkalotAuthor
Inspiring
April 11, 2020

Thanks @Bernd_Alheit. These were the clues I needed to solve the puzzle.

Participant
July 19, 2022

Qould this mean that the final code is 

for (var p = 0; p < this.numPages; p++);
var cMyText = "File ID = " + event.target.documentFileName.replace(/\.pdf$/i,"") + "\nPage " + (p+1) + " of " + numPages;
event.target.addWatermarkFromText({
	cText: cMyText,
	nFontSize:10,
	aColor: color.red,
	nHorizAlign:app.constants.align.left,
	nHorizValue: 36,
	nVertAlign:app.constants.align.top,
	nVertValue: -36,
	nStart: p
});

I'm looking to essentially do the same thing with very slightly different settings but I suck at java (at coding in general too)