Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Javascript watermark which uses list of inputted names to batch watermark a file

Community Beginner ,
Oct 01, 2020 Oct 01, 2020

Hi there, and thanks in advance for any advice.

 

I've written a simple script to ask the user for a name, watermark files with this input, and then save the file with the same input added to the filename.

 

As part of my job, it would be even more useful if I could input a list of names and batch watermark them at the same time.

 

My script so far is below. I have python and html/css experience, so I know vaguely how to do this: set the WaterName variable from the top of the list, run the watermark and saveAs commnads, then go back to line 2 of the list and repeat until there are no more names left.

 

But I'm new to Javascript in Acrobat and would really appreciate any tips.

 

Thanks,

Ben

 

// Ask user for Name

var dialogTitle = "Enter Name";
var WaterName = app.response("Watermark Text",
dialogTitle);

// Add watermark
event.target.addWatermarkFromText({
	cText: WaterName,
	nTextAlign:app.constants.align.center,
	cFont: "Arial",
	nScale: -1,
	nRotation: 45,
	nOpacity: 0.06
});


// Build File Name addition from Name
var cExt = (" - " + WaterName + ".pdf");

//Add the extension to the end of the file name 
var cDstName = event.target.documentFileName.replace(/\.pdf$/,cExt);

// Save the file
event.target.saveAs(cDstName);

 

TOPICS
How to
4.3K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
1 ACCEPTED SOLUTION
Community Expert ,
Oct 22, 2020 Oct 22, 2020

Very Very Close!

Both "event.target" and "this" always refers to the document being operated on by the batch process (i.e. Action), which is the original.  The script needs to work on the document opened with "app.openDoc".

Also, it should be opening it as "hidden"

 

var oDoc = app.openDoc({cPath:cDstPath,bHidden:true});

oDoc.addWatermarkFormText(...);

oDoc.saveAs(cDstPath);

oDoc.closeDoc();

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

View solution in original post

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 01, 2020 Oct 01, 2020

You're script looks great. So is the list of names used to watermark the same file multiple times? Or is each name to be used on a different file? 

Here's an article on string processing. 

https://acrobatusers.com/tutorials/splitting-and-rebuilding-strings/

 

Let's say that the list of names is applied to the same file. And lets say the names are entered as a comma separated list.

Then you'd write a loop like this

 

var WaterNames = app.response("Watermark Text",
dialogTitle);
var aNames = WaterNames.split(",");
for(var i=0;i<aNames.length;i++)
{
    WaterName = aNames[i];
  ... Same code as before ...
}

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 05, 2020 Oct 05, 2020

Thanks so much Thom. The original script was based on your own previous responses in this forum!

 

I've tried the script you suggest, and it works in prinicple, but there's one bug:

My script currently runs in Action Wizard as an Execute Javascript action, and runs its action on the file currently open. The result is that with this new String loop, the script gets the names, watermarks the first script, then performs the same watermarking action on the file it has just watermarked already. So the outputted files are cummulatively watermarked with more and more names from the list. How can I tell Adobe to SaveAs the file it has watermarked, then return to the original file it began with?

 

In answer to your question: yes, it's a list of names used to watermark a single file, saving a copy of the file for each recipient watermarked with their name. In an ideal world, the script would be able to process multiple files for multiple names. That is, I have two names (BEN, HARRY), and I have two files selected in Action Wizard by the user (file1.pdf, file2.pdf), and the script pumps out:

file1 - BEN.pdf

file1 - HARRY.pdf

file2 - BEN.pdf

file2 - HARRY.pdf

Using the current script, if I run the Action with more than one file selected, it just prompts me at each file for a new set of names. If it's possible to have Adobe do this on multiple files all at once, that would be great.

 

Finally, we tend to recieve names in lists delimited by a line break. Is there a way to tell Adobe to delimit by line break? If not, should I process the original list and replace line breaks with something Javascript can delimit?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2020 Oct 05, 2020

Watermarks are tricky since they add page content. A better approach for your requirement is to palce a form field at the bottom of the page the first time though the loop. Then, change the text in the form field. This is much more efficient than re-watermarking the same document. 

 

Here's an article on field placment:

https://www.pdfscripting.com/public/PDF-Page-Coordinates.cfm

 

You can split a string on anything. Line breaks are either "\n" or "\r", depending on what setup the data in the first place. A regular expression will work for both.

https://www.pdfscripting.com/public/Pattern-Matching-with-Regular-Expressions.cfm

 

Try this:

var aNames = WaterNames.split(/[\r\n]+/);
Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 06, 2020 Oct 06, 2020

Thanks Thom. That's interesting. I am looking at Form Fields now as an option. Out of interest:

 

So once a watermark is placed using AddWatermarkFromText, there is no way to change it/remove it using Javascript? (e.g. through ChangeWatermark or something)? That could be a route.

 

Or I could build the file selection into the script rather than make it an Action in Action Wizard, so that I could use the script to close the newly saved, watermark file, and reopen the original clean file?

 

Thanks,

Ben

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2020 Oct 06, 2020

Nope, watermarks can't be removed through a script. Only added. So you have the correct methodoloty. Save/close the changed file, and reopen the original un-watermarked file. 

 

Using watermarks like this is very inefficient. It's so much easier to use a form field. 

 

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 08, 2020 Oct 08, 2020

Ah that's a shame. Is it inefficient because it has to close and reopen files while it runs?

 

One thing I'm struggling with is making the form fields have the same appearance as a watermark. Sorry to keep asking questions, but if you have any tips on how to achieve the same visuals as the watermark I've written, that would be great (e.g. 100% of page size, centred, 45 degrees rotated, and low opacity). I can't work out how to write positioning as a percentage in form fields, or make it so that it's less intrusive as text.

 

Thanks

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 08, 2020 Oct 08, 2020

For the parameter you've described you'll need to use a Text Annotation. Annotations can be arbitrarily rotated Fields can only be rotated at 90 degree increments.  

 

A good way to figure out exactly what Annotation parameters you'll need is to place one manually on a PDF Page, just like you want it. Then select the annot, then run this code in the console window. 

 

for(var nm in selectedAnnots[0]){

   if((typeof(selectedAnnots[0][nm]) != "function") && (typeof(selectedAnnots[0][nm]) != "object"))

       console.println(nm + " = " + selectedAnnots[0][nm]);

}

 

This will print out all of the annotations properties that are settable, except for the positioning rectangle. 

 

 

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 21, 2020 Oct 21, 2020

Hi Thom

I've tried all different solutions you have suggested and have found them really hard to make work - the text annotations simply don't look right on the page for our purposes - it's too obvious that they're not watermarks. I have ended up trying to return to the original plan - establish the open file, ask for a list of names, then loop the watermark function by opening and closing the right file. I know it's not efficient, but the lists are never more than 10 names long, so it seems like the way to go.

 

The script I'm trying is below, and it's still not working. The result is still a set of docs with the list of names watermarked on top of one another, and an alert message 'The current action is not yet complete. Do you want to exit this action?'.

 

I think the problem is that the loop is still looping the watermark function on an already watermarked document, and then it is not closing the document until the script is complete. And it seems like closeDoc in this context breaks the script out of the action?

 

Am I doing something wrong in the 'for' function? Is there a way to close and reopen the document within the looping 'for' section?

 

Many thanks in advance

 

//Establish Open File
var CurPDF = this.path;

// Prompt user for the list
var WaterNamePlu = app.response({ cQuestion: "Enter Watermark Text", cTitle: "Watermark text"});
//Parse list
var aNames = WaterNamePlu.split(",");

for(var i=0;i<aNames.length;i++)
{
    
    WaterName = aNames[i];
    
	// Add watermark
    event.target.addWatermarkFromText({
        cText: WaterName,
        nTextAlign:app.constants.align.center,
        cFont: "Arial",
        nScale: -1,
        nRotation: 45,
        nOpacity: 0.06
    });

	// Build File Name addition from Name
    var cExt = (" - " + WaterName + ".pdf");

    //Add the extension to the end of the file name and create save path
    var cDstName = event.target.documentFileName.replace(/\.pdf$/,cExt);
    var cDstPath = "/Users/Ben/Desktop/" + cDstName;

    // Save the file and close
    event.target.saveAs(cDstPath); 
    event.target.closeDoc();
    
    // Open CleanFile
	app.openDoc(CurPDF);
    
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 21, 2020 Oct 21, 2020

You are quite close, the but order of the opererations need to be changed. The curretn code in the loop is watermarking the original PDF (event.target) and then closing it. 

The way to do this is to never touch the original document. Only watermark the document with the new name.

Here's the order of operations:

1) Save the original to the new name as a copy. It needs to be a copy so that the original that is currently open does not become the renamed file. Saving as a copy keeps them separate.

2) Open the copy. 

3) Watermark the copy

4) Close the copy.

 

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 22, 2020 Oct 22, 2020

Thanks Thom. That makes total sense. I have rejigged as you describe, but unfortunately there's still something not right - I am sure I've made a stupid mistake. My code is below. As it is, it is saving copies like this:

 

- "File1 - First name.pdf" - with no watermark

- "File2 - Second name.pdf" - with a watermark of the first name (!!?)

 

So it appears there's something wrong with the opening and closing of the newly saved copies.

Thanks

 

// Prompt user for the list
var WaterNamePlu = app.response({ cQuestion: "Enter Watermark Text", cTitle: "Watermark text"});
//Parse list
var aNames = WaterNamePlu.split(",");

//Loop the list till complete
for(var i=0;i<aNames.length;i++)
{
    
    WaterName = aNames[i];
    
    // Build File Name addition from Name
    var cExt = (" - " + WaterName + ".pdf");
    //Add the extension to the end of the file name and create save path
    var cDstName = this.documentFileName.replace(/\.pdf$/,cExt);
    var cDstPath = "/Users/Ben/Desktop/" + cDstName; 
    // Save the renamed copy
    this.saveAs({cPath:cDstPath, bCopy:true});
    
    app.openDoc(cDstPath);
    
    event.target.addWatermarkFromText({
        cText: WaterName,
        nTextAlign:app.constants.align.center,
        cFont: "Arial",
        nScale: -1,
        nRotation: 45,
        nOpacity: 0.06
    });
    
    // Save and close the renamed copy
    app.execMenuItem("Save");
    this.closeDoc();
    
}

 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 22, 2020 Oct 22, 2020

Very Very Close!

Both "event.target" and "this" always refers to the document being operated on by the batch process (i.e. Action), which is the original.  The script needs to work on the document opened with "app.openDoc".

Also, it should be opening it as "hidden"

 

var oDoc = app.openDoc({cPath:cDstPath,bHidden:true});

oDoc.addWatermarkFormText(...);

oDoc.saveAs(cDstPath);

oDoc.closeDoc();

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 23, 2020 Oct 23, 2020

Many many thanks Thom, that's it! And it's functioning well in Acrobat even with a rather long list - doesn't seem to be making it work too hard.

 

The only last bug is that - as I mentioned before - the names we're working with tend to come in line seperated lists, so I tried to use your tweak (var aNames = WaterNamePlu.split(/[\r\n]+/);). However, the app.response window doesn't seem to be able to receive a pasted list seperated by line spaces. Can these dialog boxes only handle single lines of text entry?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 23, 2020 Oct 23, 2020
LATEST

Yes, the "app.response" popup can only handle a single line in it's edit field.  You can however convert the line feeds into commas. 

 

var aNames = WaterNamePlu.split(/[\r\n]+/);

var strCommaList = aNames.join(",");

 

Thom Parker - Software Developer at PDFScripting
Use the Acrobat JavaScript Reference early and often

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines