Batch process script
Copy link to clipboard
Copied
Hello,
I came across this Batch process scripts and i am simply loving it. But after a while i came across one big problem, as script run breaks if choosen file is opened or not accessible. How could i get around this, so if file is already opened/not accessible script would simply wait 5 x 10 seconds and than continue trough other files in folder that were left to it. Offcourse if file is within this 50s closed/accessible script would simply continue foward like it was never in a loop / paused.
Any help or point in right direction would be highly appriciated.
Thanks a lot!
Copy link to clipboard
Copied
Hi there,
Try to add 'try-catch' block like so:
function ProcessAllInddDocs(inddFiles) {
startTime = new Date();
if (set.log) {
arr.push(GetDate());
if (set.rbScope == 2) arr.push("Book name: " + app.activeBook.name);
}
progressWin.show();
var pbCounter = 0;
progressBar.minvalue = 0;
progressBar.maxvalue = inddFiles.length;
for (var i = 0; i < inddFiles.length; i++) {
try {
inddFile = inddFiles;
progressBar.value = pbCounter++;
progressTxt.text = "Processing file - " + inddFile.displayName;
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
doc = app.open(inddFile);
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
ProcessDocument(doc, subFolders);
doc.close(SaveOptions.YES);
}
}
catch(err) {
$.writeln(err.message + ", line: " + err.line);
}
}
I wrote it at home so didn't encounter such a situation. I'll test it later today at work against some files open open by other users on a network drive.
Thanks for pointing this out.
— Kas
Copy link to clipboard
Copied
Basically this is not bug, but just something i came across in my workflow. I am on-the-go at the moment, but basically i get error when ever file is already opened over network drive by some other user and i am trying to run script over that file.
I think one solution would be (if possible) some kind of check box "Wait for opened files to close" of some sort, and when checked, script would wait/loop till file is accessible over network again and then properly continue from there.
Thank a lot!
Copy link to clipboard
Copied
I am sorry, I made a stupid mistake in my post 1. I was in a hurry getting ready to my work.
Here's a new version:
/* Copyright 2016, Kasyan Servetsky
November 24, 2016
Written by Kasyan Servetsky
e-mail: askoldich@yahoo.com
*/
//======================================================================================
var set, doc, subFolders, progressWin, progressBar, progressTxt, startTime, scriptFile, scriptFolder,
scriptName = "Batch process scripts - 1.2",
count = 0,
arr = [];
CreateDialog();
//===================================== FUNCTIONS ======================================
function Main() {
var inddFolder, inddFiles, inddFiles;
CreateProgressBar();
if (set.rbScope == 0 || set.rbScope == 1) {
startTime = new Date();
if (set.log) arr.push(GetDate());
progressWin.show();
if (set.rbScope == 0) { // active document
doc = app.activeDocument;
progressWin.show();
ProcessDocument(doc);
}
else if (set.rbScope == 1) { // all open documents
for (var d = 0; d < app.documents.length; d++) {
doc = app.documents
; ProcessDocument(doc);
}
}
}
else if (set.rbScope == 2) { // active book
inddFiles = GetFilesFromBook();
if (inddFiles.length == 0) ErrorExit("Found no InDesign documents in the active book.", true);
ProcessAllInddDocs(inddFiles);
}
else if (set.rbScope == 3 || set.rbScope == 4) {
inddFolder = Folder.selectDialog("Choose a folder with InDesign documents.");
if (inddFolder == null) exit();
if (set.rbScope == 3) { // folder
inddFiles = inddFolder.getFiles("*.indd");
}
else if (set.rbScope == 4) { // folder and subfolders
inddFiles = GetAllInddFiles(inddFolder);
}
if (inddFiles.length == 0) ErrorExit("Found no InDesign documents in the selected folder.", true);
ProcessAllInddDocs(inddFiles);
}
progressWin.close();
var endTime = new Date();
var duration = GetDuration(startTime, endTime);
var report = count + ((count == 1) ? " document was" : " documents were") + " processed.\n(time elapsed: " + duration + ")";
if (set.log) {
arr.push("\r=========================================================\r" + report + "\r=========================================================\r\r\r");
var text = arr.join("\r");
WriteToFile(text);
}
alert("Finished. " + report, scriptName);
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function ProcessAllInddDocs(inddFiles) {
startTime = new Date();
if (set.log) {
arr.push(GetDate());
if (set.rbScope == 2) arr.push("Book name: " + app.activeBook.name);
}
progressWin.show();
var pbCounter = 0;
progressBar.minvalue = 0;
progressBar.maxvalue = inddFiles.length;
for (var i = 0; i < inddFiles.length; i++) {
try {
inddFile = inddFiles;
progressBar.value = pbCounter++;
progressTxt.text = "Processing file - " + inddFile.displayName;
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
doc = app.open(inddFile);
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL;
ProcessDocument(doc, subFolders);
doc.close(SaveOptions.YES);
}
catch(err) {
$.writeln(err.message + ", line: " + err.line);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function ProcessDocument(doc) {
if (doc.name.match(/^Backup_/) != null) return; // Skip backups
if (set.log) arr.push("\r------------------------------------------\rDocument name: " + doc.name + "\rDocument path: " + File(doc.filePath).fsName + "\r");
if (set.backUp) { // Create a backup copy
var file = new File(doc.filePath.absoluteURI + "/Backup_" + doc.name);
if (file.exists) { // Don't overwrite existing files
var increment = 1;
while (file.exists) {
file = new File(doc.filePath.absoluteURI + "/Backup_" + increment++ + "_" + doc.name);
}
}
doc.fullName.copy(file.fsName);
}
count++;
RunScripts();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function RunScripts() {
var jsxFile;
if (set.rbScript == 0) {
app.doScript(scriptFile, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "\"" + scriptName + "\" Script");
if (set.log) arr.push("Script: " + scriptFile.displayName);
}
else {
var jsxFiles = scriptFolder.getFiles("*.jsx");
if (set.log) arr.push("Scripts:");
for (var i = 0; i < jsxFiles.length; i++) {
jsxFile = jsxFiles;
app.doScript(jsxFile, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "\"" + scriptName + "\" Script");
if (set.log) arr.push(" " + jsxFile.displayName);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetAllInddFiles(folder) {
var files = [],
fileList = folder.getFiles(),
i, file;
for (i = 0; i < fileList.length; i++) {
file = fileList;
if (file instanceof Folder) {
files = files.concat(GetAllInddFiles(file));
}
else if (file instanceof File && file.name.match(/\.indd$/i)) {
files.push(file);
}
}
return files;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetSubFolders(folder) {
var file,
fileList = folder.getFiles();
for (var i = 0; i < fileList.length; i++) {
file = fileList;
if (file instanceof Folder) {
subFolders.push(file.fsName);
GetSubFolders(file);
}
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetArrayIndex(arr, val) {
for (var i = 0; i < arr.length; i++) {
if (arr == val) {
return i;
}
}
return -1;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetFilesFromBook() {
var bookContent, file,
activeBook = app.activeBook,
files = [];
for (var i = 0; i < activeBook.bookContents.length; i++) {
bookContent = activeBook.bookContents;
if (bookContent.status != BookContentStatus.MISSING_DOCUMENT) {
file = new File(bookContent.fullName);
files.push(file);
}
}
return files;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function CreateDialog() {
var jsxFiles;
//~ app.insertLabel("Kas_" + scriptName, "");
GetDialogSettings();
var isFile = (set.rbScript == 0) ? true : false; // file, or set of scripts in the folder
if (scriptFolder != null) {
jsxFiles = scriptFolder.getFiles("*.jsx");
}
var w = new Window("dialog", scriptName);
w.p1 = w.add("panel", undefined, "Process:");
w.p1.orientation = "column";
w.p1.alignment = "fill";
w.p1.alignChildren = "left";
// Scope
w.p1.rb0 = w.p1.add("radiobutton", undefined, "active document");
if (app.documents.length == 0) w.p1.rb0.enabled = false;
w.p1.rb1 = w.p1.add("radiobutton", undefined, "all open documents");
if (app.documents.length < 2) w.p1.rb1.enabled = false;
w.p1.rb2 = w.p1.add("radiobutton", undefined, "active book");
if (app.books.length == 0) w.p1.rb2.enabled = false;
w.p1.rb3 = w.p1.add("radiobutton", undefined, "documents in the selected folder");
w.p1.rb4 = w.p1.add("radiobutton", undefined, "documents in the selected folder and its subfolders");
if (set.rbScope == 0 && app.documents.length != 0) { // active document
w.p1.rb0.value = true;
}
else if (set.rbScope == 1 && app.documents.length > 1) { // all open documents
w.p1.rb1.value = true;
}
else if (set.rbScope == 2 && app.books.length != 0) { // active book
w.p1.rb2.value = true;
}
else if (set.rbScope == 3) { // documents in the selected folder
w.p1.rb3.value = true;
}
else { // documents in the selected folder and its subfolders
w.p1.rb4.value = true;
}
// What to run
w.p3 = w.add("panel", undefined, "What to run:");
w.p3.alignChildren = "left";
w.p3.alignment = "fill";
w.p3.rb0 = w.p3.add("radiobutton", undefined, "single script");
w.p3.rb0.onClick = UpdatePanel;
w.p3.rb1 = w.p3.add("radiobutton", undefined, "set of scripts");
w.p3.rb1.onClick = UpdatePanel;
function UpdatePanel() { // clicking a radio button switches between "scipt" and "set of scripts"
var fileObj;
if (this.text == "single script") {
isFile = true;
fileObj = scriptFile;
w.p4.text = "Script:";
if (fileObj == undefined || !fileObj.exists) {
w.p4.st.text = "No file has been selected";
}
}
else {
isFile = false;
fileObj = scriptFolder;
w.p4.text = "Folder with scripts:";
if (fileObj == undefined || !fileObj.exists) {
w.p4.st.text = "No folder has been selected";
}
}
UpdateWindow(fileObj);
}
if (isFile) {
w.p3.rb0.value = true;
}
else {
w.p3.rb1.value = true;
}
var fileObj = (isFile) ? scriptFile : scriptFolder;
// Scripts folder or a script panel
w.p4 = w.add("panel", undefined, ((isFile) ? "Script:": "Folder with scripts:"));
w.p4.alignment = "fill";
w.p4.st = w.p4.add("statictext");
if (fileObj == undefined || !fileObj.exists) {
w.p4.st.text = "No " + ((isFile) ? "file": "folder") + " has been selected";
}
else {
w.p4.st.text = TrimPath(fileObj.fsName);
w.p4.st.helpTip = fileObj.fsName;
}
w.p4.bt = w.p4.add("button", undefined, "Select...");
w.p4.bt.onClick = Select;
function Select() {
if (isFile) {
scriptFile = File.openDialog("Pick a script", "*.jsx");
if (scriptFile != null) {
UpdateWindow(scriptFile);
}
}
else {
scriptFolder = Folder.selectDialog("Pick a folder with scripts");
if (scriptFolder != null) {
jsxFiles = scriptFolder.getFiles("*.jsx");
if (jsxFiles.length == 0) {
alert("There are no scripts in the selected folder.", scriptName, true);
scriptFolder = undefined;
w.p4.st.text = "No " + ((isFile) ? "file": "folder") + " has been selected";
}
else {
UpdateWindow(scriptFolder);
}
}
}
}
function UpdateWindow(fileObj) {
if (fileObj != null && fileObj.exists) {
w.p4.remove(w.p4.st);
w.p4.remove(w.p4.bt);
w.p4.st = w.p4.add("statictext");
w.p4.st.text = TrimPath(fileObj.fsName);
w.p4.st.helpTip = fileObj.fsName;
w.p4.bt = w.p4.add("button", undefined, "Select...");
w.p4.bt.onClick = Select;
w.layout.layout(true);
}
}
w.p2 = w.add("panel", undefined, "Settings:");
w.p2.alignChildren = "left";
w.p2.alignment = "fill";
// Checkboxes
w.p2.cb1 = w.p2.add("checkbox", undefined, "Create log file on the desktop");
w.p2.cb1.alignment = "left";
w.p2.cb1.value = set.log;
w.p2.cb3 = w.p2.add("checkbox", undefined, "Backup original InDesign documents");
w.p2.cb3.alignment = "left";
w.p2.cb3.value = set.backUp;
// Buttons
w.buttons = w.add("group");
w.buttons.orientation = "row";
w.buttons.alignment = "center";
w.buttons.ok = w.buttons.add("button", undefined, "OK", {name:"ok" });
w.buttons.cancel = w.buttons.add("button", undefined, "Cancel", {name:"cancel"});
var showDialog = w.show();
if (showDialog == 1) {
set.log = w.p2.cb1.value;
set.backUp = w.p2.cb3.value;
if (w.p1.rb0.value == true) {
set.rbScope = 0;
}
else if (w.p1.rb1.value == true) {
set.rbScope = 1;
}
else if (w.p1.rb2.value == true) {
set.rbScope = 2;
}
else if (w.p1.rb3.value == true) {
set.rbScope = 3;
}
else if (w.p1.rb4.value == true) {
set.rbScope = 4;
}
if (w.p3.rb0.value == true) {
set.rbScript = 0;
}
else if (w.p3.rb1.value == true) {
set.rbScript = 1;
}
if (isFile) { // File
if (scriptFile == undefined) ErrorExit("No script has been selected", scriptName, true);
if (!scriptFile.exists) ErrorExit("Script '" + scriptFile.displayName + "' doesn't exist.", scriptName, true);
if (scriptFile instanceof File) {
set.scriptFilePath = scriptFile.fsName;
}
else {
set.scriptFilePath = null;
}
}
else { // Folder
if (scriptFolder == undefined) ErrorExit("No folder with scripts has been selected", scriptName, true);
if (!scriptFolder.exists) ErrorExit("Folder '" + scriptFolder.displayName + "' doesn't exist.", scriptName, true);
if (jsxFiles == undefined || jsxFiles.length == 0) ErrorExit("There are no scripts in the scripts folder.", scriptName, true);
if (scriptFolder instanceof Folder) {
set.scriptFolderPath = scriptFolder.fsName;
}
else {
set.scriptFilePath = null;
}
}
app.insertLabel("Kas_" + scriptName, set.toSource());
Main();
}
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDialogSettings() {
set = eval(app.extractLabel("Kas_" + scriptName));
if (set == undefined) {
set = { rbScope: 0, rbScript: 0, log: true, backUp: true };
}
else {
scriptFile = new Folder(set.scriptFilePath);
scriptFolder = new Folder(set.scriptFolderPath);
}
var tmp = set;
return set;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function CreateProgressBar() {
progressWin = new Window("window", scriptName); // global
progressBar = progressWin.add("progressbar", [12, 12, 350, 24], 0, undefined); // global
progressTxt = progressWin.add("statictext"); // global
progressTxt.bounds = [0, 0, 340, 20];
progressTxt.alignment = "left";
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDuration(startTime, endTime) {
var str;
var duration = (endTime - startTime)/1000;
duration = Math.round(duration);
if (duration >= 60) {
var minutes = Math.floor(duration/60);
var seconds = duration - (minutes * 60);
str = minutes + ((minutes != 1) ? " minutes, " : " minute, ") + seconds + ((seconds != 1) ? " seconds" : " second");
if (minutes >= 60) {
var hours = Math.floor(minutes/60);
minutes = minutes - (hours * 60);
str = hours + ((hours != 1) ? " hours, " : " hour, ") + minutes + ((minutes != 1) ? " minutes, " : " minute, ") + seconds + ((seconds != 1) ? " seconds" : " second");
}
}
else {
str = duration + ((duration != 1) ? " seconds" : " second");
}
return str;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function GetDate() {
var date = new Date();
if ((date.getYear() - 100) < 10) {
var year = "0" + new String((date.getYear() - 100));
}
else {
var year = new String((date.getYear() - 100));
}
var dateString = (date.getMonth() + 1) + "/" + date.getDate() + "/" + year + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
return dateString;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function TrimPath(path) {
var theFile = new File(path);
if (File.fs == "Macintosh") {
var trimPath = "..." + theFile.fsName.split("/").splice(-3).join("/");
}
else if (File.fs == "Windows" ) {
var trimPath = ((theFile.fsName.split("\\").length > 3) ? "...\\" : "") + theFile.fsName.split("\\").splice(-3).join("\\");
}
return trimPath;
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function WriteToFile(text) {
var file = new File("~/Desktop/" + scriptName + ".txt");
file.encoding = "UTF-8";
if (file.exists) {
file.open("e");
file.seek(0, 2);
}
else {
file.open("w");
}
file.write(text);
file.close();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
function ErrorExit(error, icon) {
alert(error, scriptName, icon);
exit();
}
//--------------------------------------------------------------------------------------------------------------------------------------------------------
Copy link to clipboard
Copied
The forum software is misbehaving, or maybe my previous post was too long.
I just tested the new version using a folder with 5 files located on a network drive: two of them are open on another machine.
Before
I used the three sample 'clean-up' script for testing
After
This is not the final version yet. I have some ideas on improving it: e.g. maybe it makes sense to add an error logging feature so that the user would know why some document weren't processed, like so:
Cannot open the document “TEST:_Today:Test:Q_1239_005.indd”. You may not have permission or the document may be open already.
When I make a new version, I'll update it on my site.
I'm open to suggestions and new ideas: feel free to post them here in this thread.
— Kas
Copy link to clipboard
Copied
WOW! This works like charm once error occurs within processing of scripts!
One part of my main problem was that once error occured, script will still continue to go ahead not looking back which files it missed processing. I was trying to customize your script with some sleep function of my own, but was not successful to the point of usability.
However, i had in mind some upgrade/function in form of check box "Wait for opened files to close" of some sort, and when checked, script would wait/loop till individual file is accessible over network again - and offcourse then properly continue from where it stoped/looped.
Offcourse this is problem only when a lot of files and scripts are in question, as it would be very hard to follow which scripts were procesed and on which files. Eventually i will get there with my knowledge/learning, but as always any help is appreciated in this direction till then.
Thanks a lot!
Copy link to clipboard
Copied
I've made a new version of the batch processor script. It's a major update: eliminated a potential of clashing global variables, added new features. I left a couple of global variables which can be accessed from the scripts executed by the batch processor:
- gEventLog — for events (non-error) messages
- gErrorLog — for error messages
Both are arrays of text elements and you can 'push' into them your own messages from your scripts. These messages will appear in the log file on the desktop. See the 'Package' sample script here. I commented out these variables so that the script could be used as a stand alone one. If you outcomment them, you'll see the messages sent from the 'internal' script in the log. In this way, the script should keep working despite whatever error occurs along the way, but you'll be able to track down what and when went wrong in the log.
—Kas

