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

Batch converting layers on insets...So close, but need help!

Explorer ,
Jun 22, 2023 Jun 22, 2023

Hi--I found a free Javascript online that ALMOST does what I want it to.  But it appears to be missing (for me) the most important feature.  I'm hoping that someone here can modify it for me or point me towards something that will accomplish the task.  (The original author seems to have been offline since 2019.)

 

What I want to create is a document made up of several placed external files.  Each placed file is multi-lingual, with translations contained on separate layers. For example, each placed file has English text on layer EN, French text on layer FR, Spanish text on layer ES, etc.  My goal is to run the script while in the "parent" document--allowing me to choose the desired translated layer and have all of the placed files "flip" to the correct translation.  The script I found (text file version attached) ALMOST works...however, it does not seem to "batch" convert all the placed files at once. For example, I placed 3 files on the parent document as a test, ran the script, and selected FR. It only "flipped" one of them.  The others stayed as I originally saved them, with all four layers showing.  I only got the other two to "flip" by selecting each one individually and running the script on each file.

 

What's missing from the attached script that won't allow me to run this and "flip" everything at once?  Can it be fixed easily?  Or is there a better solution?  I appreciate any help that I can get with this.  Thank you!  

 
TOPICS
Scripting
1.4K
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 ,
Jun 22, 2023 Jun 22, 2023

Hi @suep89793525, the script you linked by CrazyPanda is great, and I probably could have adjusted it to run the way you want, but it wasn't structured ideally for that, and anyway I always like to learn, so I have written my own version. Please give it a try. Hasn't been tested much, so please let me know here if you find a bug and I will fix. It should work with placed .ai, .pdf, and .indd files.

- Mark

 

 

/**
 * Sets layer visibility of all placed items in active document.
 * All layers are set to invisible, unless the layer name exists
 * in `settings.visibleLayerNames`
 * NOTES:
 * - Adjust the settings object if you want to pre-populate
 *   the layerNames and visibleLayer.
 * - Do not specify `layerNames` in settings if you want
 *   to choose from *every* layer in every placed item.
 * @author m1b
 * @discussion https://community.adobe.com/t5/indesign-discussions/batch-converting-layers-on-insets-so-close-but-need-help/m-p/13885184
 */

var settings = {
    // layerNames: ['EN', 'ES', 'FR'], // uncomment this to limit the choices
    visibleLayerNames: ['FR'],
    showUI: true,
};

function main() {

    var doc = app.activeDocument,
        items = getLinkedPdfs(doc),
        identifiers = [];

    if (items.length == 0) {
        alert("No suitable linked files in document.");
        return;
    }

    // keep a stringified identifier
    // to bypass a bug with indesign
    // that assigns a new id every
    // time layer visibility is updated
    for (var i = 0; i < items.length; i++)
        identifiers.push(stringify(items[i]));

    // if no layer names specified
    // in settings, collect them all
    settings.layerNames = settings.layerNames || getLayerNames(items);
    settings.visibleLayerNames = settings.visibleLayerNames || [];

    // show UI
    if (
        settings.showUI
        && chooseLayers(settings) == false
    )
        // user cancelled UI
        return;

    // set each layer's visibility
    for (var i = items.length - 1; i >= 0; i--) {

        if (!items[i].isValid)
            continue;

        var len = items[i].graphicLayerOptions.graphicLayers.length;
        items[i].graphicLayerOptions.updateLinkOption = UpdateLinkOptions.KEEP_OVERRIDES;

        for (var j = 0; j < len; j++) {

            // get the item each time (because of bug mentioned earlier)
            var item = itemByStringifier(getLinkedPdfs(doc), identifiers[i], stringify);

            if (item.isValid)
                item.graphicLayerOptions.graphicLayers[j].currentVisibility = indexOf(item.graphicLayerOptions.graphicLayers[j].name, settings.visibleLayerNames) !== -1;

        }
    }

};

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Set Layer Visibility');


/**
 * Returns array of linked pdf files.
 * @author m1b
 * @version 2023-06-24
 * @param {Document} doc - an Indesign Document.
 * @returns {Array<PageItem>}
 */
function getLinkedPdfs(doc) {

    var items = doc.links.everyItem().parent,
        linkedPdfs = [];

    for (var i = 0; i < items.length; i++)
        if (
            items[i].hasOwnProperty('pdfAttributes')
            && items[i].hasOwnProperty('graphicLayerOptions')
            && items[i].itemLink.status === LinkStatus.NORMAL
        )
            linkedPdfs.push(items[i]);

    return linkedPdfs;

};


/**
 * Gets a single item from array `items` based
 * on the result of a stringifier function.
 * @author m1b
 * @version 2023-06-23
 * @param {Array<PageItem>} items - an array of items from which to choose.
 * @param {String} identifier - the string to search for.
 * @param {Function} stringifier - a stringifying function.
 * @returns {PageItem}
 */
function itemByStringifier(items, identifier, stringifier) {

    for (var i = 0; i < items.length; i++)
        if (stringifier(items[i]) === identifier)
            return items[i];

};


/**
 * Generate a string just for the purpose
 * of identifying a particular linked item.
 * @author m1b
 * @version 2023-06-23
 * @param {PageItem} item - an Indesign placed item.
 * @returns {String}
 */
function stringify(item) {

    var str = '',
        delim = '|'

    if (
        item.itemLink
        && item.itemLink.filePath
    )
        str += item.itemLink.filePath + delim;

    if (item.graphicLayerOptions.graphicLayers.length > 0)
        str += item.graphicLayerOptions.graphicLayers.everyItem().name.join(delim) + delim;

    if (item.parentPage)
        str += item.parentPage.name + delim;

    return str;

};


/**
 * Returns index of obj in arr.
 * Returns -1 if not found.
 * @param {any} obj
 * @param {Array} arr
 * @returns {Number}
 */
function indexOf(obj, arr) {
    for (var i = 0; i < arr.length; i++)
        if (arr[i] === obj)
            return i;
    return -1;
};


/**
 * Collects array of layer names from linked pdf items.
 * @param {Array<PageItem>} items - the linked pdfs.
 * @returns {Array<String>}
 */
function getLayerNames(items) {

    var layerNames = [],
        already = {};

    for (var i = 0; i < items.length; i++)
        for (var j = 0; j < items[i].graphicLayerOptions.graphicLayers.length; j++)
            if (!already[items[i].graphicLayerOptions.graphicLayers[j].name]) {
                layerNames.push(items[i].graphicLayerOptions.graphicLayers[j].name);
                already[items[i].graphicLayerOptions.graphicLayers[j].name] = true;
            }

    return layerNames;

};


/**
 * Shows UI for selecting layers of document.
 * @author m1b
 * @version 2023-06-09
 * @param {Object} settings
 * @param {Document} settings.doc - an Indesign Document.
 */
function chooseLayers(settings) {

    var layerNames = settings.layerNames,
        selectedLayerNames = [],
        w = new Window("dialog { text:'Set Layer Visibility' }"),
        layersListBox = w.add("ListBox {alignment:['fill','fill'], properties:{multiselect:true, showHeaders:true, numberOfColumns:1, columnTitles:['Layer'] } }"),
        buttons = w.add("Group { orientation: 'row', alignment: ['right','bottom'], margins:[0,12,0,22] }"),
        cancelButton = buttons.add("Button { text:'Cancel', properties: { name:'cancel' } }"),
        okButton = buttons.add("Button { text:'Set Visibility', properties: { name:'ok' } }");

    // populate layers menu
    for (var i = 0; i < layerNames.length; i++)
        layersListBox.add('item', layerNames[i]);

    /**
     * Updates `selectedLayerNames`
     * when listbox selection changes.
     */
    layersListBox.onChange = function () {

        var sel = this.selection;
        selectedLayerNames = [];
        settings.layers = [];

        if (sel == null)
            return;

        for (var i = 0; i < sel.length; i++)
            selectedLayerNames.push(sel[i].text);

    };

    // set the initial selection
    var sel = [];
    for (var i = 0; i < settings.visibleLayerNames.length; i++) {
        var index = indexOf(settings.visibleLayerNames[i], settings.layerNames);
        if (index != -1)
            sel.push(index);
    }
    layersListBox.selection = sel;
    layersListBox.maximumSize.height = w.maximumSize.height - 200;;
    layersListBox.active = true;

    if (w.show() == 2)
        // user cancelled
        return false;

    // add the selected layers to settings object
    settings.visibleLayerNames = selectedLayerNames;

};

 

Edit 2023-06-24: added some error checking.

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
Explorer ,
Jun 23, 2023 Jun 23, 2023

Mark--Thank you so much!  I tested your script on my three-inset sample page and so far it works perfectly!  I'm going to try some other tests with AI and PDF files since our parent documents (spec sheets) also include these elements. My confidence level is high...but I'll defintely let you know if I run into any bugs along the way. Assuming all goes well, you have just saved me and my co-workers a tremendous amount of time and effort. Wow.  

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
Explorer ,
Jun 23, 2023 Jun 23, 2023

JS error.png

Hi again--I just tried to drop a multi-lingual AI file into my container document and got this error.  Any thoughts?

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 ,
Jun 23, 2023 Jun 23, 2023

Can you make a demo file for me to test with?

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
Explorer ,
Jun 23, 2023 Jun 23, 2023

Here you go.  The "container" file is Language Flip test; the others are insets.  For some reason I couldn't attach the dimensional image as an AI file (its original format) so I changed it to a SVG which you should be able to open in Illustrator.  Please let me know if you can work with these and what you find out.  Thank you!

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 ,
Jun 23, 2023 Jun 23, 2023

That's great thanks. Can you post the .ai file as a .pdf rather than a svg? You can either save as pdf or just change the file extension from .ai to .pdf. 

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
Explorer ,
Jun 23, 2023 Jun 23, 2023

Please try this one.  I did a "save as."

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 ,
Jun 23, 2023 Jun 23, 2023

Thanks @suep89793525, that's perfect. But I tried them out and couldn't find an error. I was able to do any combination of layer visibility that I tried. I have updated the script slightly with some extra error checking, such as if the linked file is missing or modified. Can you try it again (using the same demo file you posted here) and tell me which combination of layers gives the error?

- Mark

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
Explorer ,
Jun 26, 2023 Jun 26, 2023

Good morning, Mark--Do you have an updated version of the script that I can load onto my system?  If so, please send it and I will continue my tests.  Thanks!  -- Sue

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 ,
Jun 26, 2023 Jun 26, 2023

Hi Sue, the script above is the new version—I edited it. I it still doesn't work, please post a demo file that I can test with.

- Mark

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
Explorer ,
Jun 26, 2023 Jun 26, 2023
LATEST

I think you're on to something.  Initial tests look good. Wherever and whatever the bug was, that seems to have squashed it!  I'll play with this and continue my tests.  And, for future communication on this, perhaps we can take it offline to spare the Adobe masses.  🙂  You can find me here, so please shoot me an email if you agree:  suep@alto-shaam.com,

Thank you SO much for your help with this.  It's greatly appreciated.

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