0
votes

I'm a fairly new programmer. I'm attempting something pretty advanced, but I enjoy a good challenge. :~) I'm using Adobe's ESTK (ExtendScript Toolkit) to write a complex script for InDesign CS6. I've gone through most of the tutorials and have learned quite a bit, but I have run into a wall now.

I need the script to detect whether a certain folder meets a certain criteria, and if it does, to delve into that folder, count all of its subfolders, and open each of the .indd files in each of those subfolders, in turn, performing tasks on each one. I have only just started the script today and this is what I've got so far:

var getDataDialog = app.dialogs.add({name:"Job Info"});
with(getDataDialog){
    // Add a dialog column.
    with(dialogColumns.add()){
        // Create the order number text edit box.
        var orderNumTextEditBox = textEditboxes.add({minWidth:80});
        }
    }
// Show the dialog box.
var dialogResult = getDataDialog.show();
if(dialogResult == true){
    // Get the order number and put it in the variable "orderNum".
    var orderNum = orderNumTextEditBox.editContents;
    // Get the first three numbers of the order number and put it in "orderPrefix".
    var orderPrefix = orderNum.substr(0,3);
    // Remove the dialog box from memory.
    getDataDialog.destroy();
    // Store the folder prefix into "folderPrefix".
    var folderPrefix = "/g/ ArtDept/JOBS/" + orderPrefix + "000-" + orderPrefix + "999/"
    // Open the document with the order number.
    var myDoc = app.open(File(folderPrefix + orderNum + " Folder/" + orderNum + ".indd"), true);
    }
else{
    getDataDialog.destroy();
    }

So, if the order number entered is "405042", it will look in the "405000-405999" folder, then into the packaged folder called "405042 Folder", then open the .indd file inside that. Trouble is, we sometimes have several packages within a folder. For example, we might have:

405000-405999/405007/405007_N10/405007_N10.indd
405000-405999/405007/405007_C12/405007_C12.indd
405000-405999/405007/405007_Orange/405007_Orange.indd

I would want the script to open up each of those files, in turn, and perform some tasks on them. I'm certain that it's possible, but I just need to know how to code it.

1
Your topic is already pretty complex. So there is no simple answer to that. You should have a look into these things: Recursion in JavaScript codecademy.com/courses/javascript-lesson-205 Files in ExtendScript jongware.mit.edu/Js/pc_File.html Folders in ExtendScript jongware.mit.edu/Js/pc_Folder.html Hope that helps a bit. - fabianmoronzirfas
Can you possibly draw your directory structure out a little more? - Josh Voigts
Thank you for the links, @fabiantheblind; I will check them out as soon as I have time and hopefully learn more. Yes, this is definitely going to wind up being a complex script, so it's my trial by fire. - Sturm
@JoshVoigts--Hopefully these two images can make things more clear. If you are familiar with InDesign, you know that when you package a project, it saves the .indd file, along with font files, links, etc. in a folder called "<filename> Folder". (Curse these comment limits...) - Sturm
@JoshVoigts (continued...)--With that in mind, this first image shows what it looks like when we package a file called 405006, for example. If we have a project with a bunch of packages, then they are saved in a parent folder with that project's number. This second image shows just such a project, number 405007. I hope these clear things up for you a little better than my incorrect file structure I posted in the original question. - Sturm

1 Answers

2
votes

If I understand your problem correctly, there are two parts:

Part 1: Find a certain folder meeting certain criteria. (Looks like you've got this covered.)

Part 2: For each InDesign document that is a descendant of this folder, open it and do some processing to it.

In the sample below, I've labeled where you should add the code that finds the top folder and the code that manipulates each document. If you run the sample as-is, it will use the script's parent folder as the top folder, and for each descendant document it will simply log its name.

// TODO: (Part 1) Put code here that determines the top folder.
var topFolder = (new File($.fileName)).parent; // Change me. Currently the script's folder.
forEachDescendantFile(topFolder, doStuffIfdocument); // Don't change this line.

/**
 * Does stuff to the document.
 */
function doStuff(document) {
    // TODO: (Part 2) Put code here to manipulate the document.
    $.writeln("Found document " + document.name);
}

/**
 * Opens the given file if it ends in ".indd". Then calls doStuff().
 * 
 * @param {File} oFile
 */
function doStuffIfdocument(oFile) {
    if (matchExtension(oFile, "indd")) {
        var document = app.open(oFile);
        try {
            doStuff(document);
        }
        finally {
            document.close(SaveOptions.YES);
        }
    }
}

/**
 * Calls the callback function for each descendant file of the specified folder.
 * The callback should accept a single argument that is a File object.
 * 
 * @param {Folder} folder The folder to search in.
 * @param {Function} callback The function to call for each file.
 */
function forEachDescendantFile(folder, callback) {
    var aChildren = folder.getFiles();
    for (var i = 0; i < aChildren.length; i++) {
        var child = aChildren[i];
        if (child instanceof File) {
            callback(child);
        }
        else if (child instanceof Folder) {
            this.forEachDescendantFile(child, callback);
        }
        else {
            throw new Error("The object at \"" + child.fullName + "\" is a child of a folder and yet is not a file or folder.");
        }
    }
}

/**
 * Returns true if the name of the given file ends in the given extension. Case insensitive.
 *
 * @param {File} iFile
 * @param {String} sExtension The extension to match, not including the dot. Case insensitive.
 * @return {boolean}
 */
function matchExtension(iFile, sExtension) {
    sExtension = "." + sExtension.toLowerCase();
    var displayName = iFile.displayName.toLowerCase();
    if (displayName.length < sExtension.length) {
        return false;
    }
    return displayName.slice(-sExtension.length) === sExtension;
}