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

Customized script to open/edit linked files is not working as expected

New Here ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

Dear community
I am at a loss here and can't find a solution. This is part of a script which opens linked InDesign files, changes the layer visibility on the documents placed in the opened links.

 

If I put an alert() somewhere between opening and saving the document, everything works fine. If I remove the alert() I get an error, telling me that the file is already open.  The error points to the last command in the changeLayerVisibility() Function: layer.currentVisibility = checklist[ft][k].checkedState;

 

I'm thinking it has something to do with async or timeouts. The alert slowing the process, allowing the loop to finish. But I can't understand why it would ever try to open the same file again...

 

Here's the relevant part of the script. I hope someone sees where I'm going wrong. If not I can try to create a reduced version of the thing.

 

function changeNestedLayers(linksArr) {
  var thisLink,
      thisFile,
      thisFileName,
      thisDoc;

  for (var l = 0; l < linksArr.length; l++) {
    thisLink = linksArr[l];
    thisFile = File(thisLink.filePath);
    thisFileName = thisFile.fullName;
    thisDoc = app.open(thisFile, true);

    var currentLink, 
        currentLinkname,
        currentLayer,
        currentChecklistItem;

    for(var s = 0; s < thisDoc.links.length; s++) {
      currentLink = thisDoc.links[s];
      currentLinkname = currentLink.parent.itemLink.name;

      if (currentLink.parent.constructor.name == "ImportedPage" && currentLink.parent.itemLink != null && currentLink.parent.itemLink.linkType == "InDesign Format Name") {

        if(hasSubstring(currentLinkname, "FiletypeA")) {
          changeLayerVisibility(currentLink, "FiletypeA");
          count++;
        }
        else {
          changeLayerVisibility(currentLink, "FiletypeB");
          count++;
        }
      }
    }

    thisDoc.save(new File(thisFileName));
    thisDoc.close(SaveOptions.NO);

  }
}

function changeLayerVisibility(thisLink, filetype) {
  var ft = filetype.toLowerCase();
  var layer;
  for (var k = 0; k < layertypes[ft].length; k++) {
    layer = thisLink.parent.graphicLayerOptions.graphicLayers.item(layertypes[ft][k].name);
    if (layer.isValid) {
      layer.currentVisibility = checklist[ft][k].checkedState;
    }
  }
}

 

 

Thanks!

TOPICS
Scripting

Views

756

Likes

Translate

Translate

Report

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
Advisor ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

I was using similar approach in one of my tools to build catalogs from database - placing INDD files - but I've switched to PDF instead of INDD file - works quicker.

 

I'm not JS guy so can't help you with your code - but in case of linked files - of any type - you NEED to iterate the collection backwards as every change to the element on the links collection - moves it to the end - looks like InDesign removes original and creates new one - so you'll skip some and process some twice. 

Can automate anything - as long as it doesn't require A.I.

Likes

Translate

Translate

Report

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
New Here ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

Hey AdobeScripts, thanks for your reply.
In general our workflow with the placed INDD files works like charm. And we have a single source of truth which we can export when needed.
Iterating backwards... interesting. I remember rewriting the for loops to my liking when adapting the scripts. I quickly tried reversing the outermost loop. Doesn't change anything though. Also, I'm not iterating over the general links collection, but rather an array of collected links.
And the script works exactly as advertised IF there is any alert() somewhere between opening and saving the file. This is what's really bugging me...

Likes

Translate

Translate

Report

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
Advisor ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

But you ARE iterating through links collection?? 

 

quote

 

for(var s = 0; s < thisDoc.links.length; s++) {
      currentLink = thisDoc.links[s];

 

 

Yes, you're creating a reference to the item on the links collection - but anything you do to this reference - will modify original object - reference is just for your convenience. 

 

I've had the same problem with the need for alert() in the script I was converting from VBA to JS - script to format Kanji - but I've no idea what was the problem 😞

Can automate anything - as long as it doesn't require A.I.

Likes

Translate

Translate

Report

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
New Here ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

Yes, you are right. I was referring to the outer loop, since I think the problem lies there somewhere. But also reversing the loop you mentioned doesn't change anything.

 

But good to hear you had the same issue — just too bad you couldn't figure it out either 😉

Likes

Translate

Translate

Report

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 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

Hi @Christoph Senn , we can’t test your snippet, but have you tried adding some writeIn trace statements to check the file and link names in the debug console?

 

//before the thisDoc.save line
$.writeln(thisDoc.name)

//at the beginning of the changeLayerVisibility function
$.writeln(thisLink.name)

 

Likes

Translate

Translate

Report

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
New Here ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

Hey @rob day , thanks for the input. I haven't tried any writeln statements, since there's no toolkit anymore and I have been a bit reluctant to change from my current editor to Visual Studio... But might be a good moment to give it a try.

 

Still I find it strange that it works perfectly if there simply is an alert somewhere...

Likes

Translate

Translate

Report

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 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

I would give it a try, the install is a bit tricky but in the end it is better than ESTK. The thing that tripped me up at first was the required .json file at the root of your scripts folder, and the built-in Explorer/Finder. I use this for the launch.json file, but I still don’t fully understand how it works, so someone else might have a better version:

 

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Session", 
      "type": "extendscript-debug",
      "request": "launch",
      "hostAppSpecifier": "indesign",
      "engineName": "session",
    }
    {
      "name": "Main", 
      "type": "extendscript-debug",
      "request": "launch", 
      "hostAppSpecifier": "indesign",
      "engineName": "main",
    }
  ],
  "compounds": [
    {
      "name": "Session/Main",
      "configurations": ["Session", "Main"],
      "preLaunchTask": "${defaultBuildTask}",
      "stopAll": true
    }
  ]
}

 

 

 

 

Likes

Translate

Translate

Report

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
New Here ,
Oct 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

I quickly gave it a try. So far resulting in two InDesign crashes. I'll give your launch.json a try. Thanks!

Likes

Translate

Translate

Report

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 25, 2022 Oct 25, 2022

Copy link to clipboard

Copied

@Christoph Senn I would definitely recommend moving to VSCode. It is an excellent IDE in my opinion. You need to install the ExtendScript Debugger.

 

This is my launch.json for Indesign scripting:

{
    "type": "extendscript-debug",
    "request": "attach",
    "name": "Start debugger—IND",
    "hostAppSpecifier": "indesign",
    "bringToFront": false,
    "engineName": "Main",
    "debugLevel": 1 /* 0 - No debugging. 1 - Break on breakpoints, errors, or exceptions. 2 - Stop at the first executable line. */
}

It uses the "attach" request, which means you start the debugger once, and then when you run your scripts from VSCode it uses the same debugger instance.

 

I also have these in my user settings.json file:

"debug.console.closeOnEnd": true,
"debug.internalConsoleOptions": "neverOpen",
"debug.openDebug": "neverOpen",
"debug.toolBarLocation": "docked",

 

And last, but not least, I have these in my keybindings.json file:

{
    "key": "f5",
    "command": "-workbench.action.debug.start",
    "when": "debuggersAvailable && debugState == 'inactive'"
},
{
    "key": "cmd+r",
    "command": "extension.extendscript-debug.evalInAttachedHost",
    "args": {
        "debugLevel": 1,
        "bringToFront": false
    }
},
{
    "key": "cmd+shift+r",
    "command": "extension.extendscript-debug.evalInAttachedHost",
    "args": {
        "debugLevel": 1,
        "bringToFront": true
    }
},
{
    "key": "cmd+.",
    "command": "extension.extendscript-debug.haltInHost",
    "when": "inDebugMode",
},
{
    "key": "ctrl+.",
    "command": "workbench.action.debug.stop",
    "when": "inDebugMode"
},

I use cmd+r to run a script without activating the host app (eg. if I just want to watch the console or debugger), and cmd+shift+r if I want to activate the host app (note that your scripts may activate the host app anyway if they show a dialog etc).

 

Well that's my set-up. I hope it gives you some idea of how to customize it to your preferences.

- Mark 

Likes

Translate

Translate

Report

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
New Here ,
Oct 26, 2022 Oct 26, 2022

Copy link to clipboard

Copied

Hey @m1b , thank you for your thorough guide. I'll definitely give this a try later, when I'm back on that task.

Likes

Translate

Translate

Report

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
New Here ,
Oct 26, 2022 Oct 26, 2022

Copy link to clipboard

Copied

Again, thanks. I've got the minimal setup now running (with just the launch.json). Will look into the more refined settings once I need it.

 

Okay, it is pretty nice to finally have a console for InDesign scripting! 😂

 

Now I just need to figure out why on earth it wants to open a file on that line...

Likes

Translate

Translate

Report

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 26, 2022 Oct 26, 2022

Copy link to clipboard

Copied

Hi Mark, where do you save the keybindings.json and settings.json files? In the hidden .vscode folder?

Likes

Translate

Translate

Report

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 26, 2022 Oct 26, 2022

Copy link to clipboard

Copied

Hi Rob, the easiest way to edit the "user settings" json file is by invoking the command palette (command-shift-P for me) and typing "settings", then choose "Open User Settings JSON". The file itself is stored in ~/Library/Application Support/Code/User/.

The keybindings.json file is also in that same folder (~/Library/Application Support/Code/User/). One way to open it is to choose Preferences > Keyboard Shortcuts and click the button at the right of the tab bar (for me at least) that looks like a document icon with a little swappy arrow—that switches between the json file and the UI. You can also try typing "keybindings" in the command palette (note you must remove the default ">" first) but you may only see the file there if you've opened it at least once already. Unfortunately you can't (yet) save project-level keybindings in the .vscode folder.

Another feature I would recommend is user snippets—type "snippets" in the command palette. They are a great time saver. Snippets are saved in the same user folder as above. Here's a useful example:

 

"For loop: Extendscript": {
    "prefix": "for",
    "body": [
        "for (var ${1:i} = 0; ${1:i} < ${2:items}.length; ${1:i}++) {\n    var ${3:item = ${2:items}[${1:i}];}$0\n}"
    ],
    "description": "An extendscript-flavoured for loop"
},
"For loop backwards: Extendscript": {
    "prefix": "for",
    "body": [
        "for (var ${1:i} = ${2:items}.length -1; ${1:i} >= 0 ; ${1:i}--) {\n    var ${3:item = ${2:items}[${1:i}];}$0\n}"
    ],
    "description": "An extendscript-flavoured for loop"
},

 

- Mark

Likes

Translate

Translate

Report

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 26, 2022 Oct 26, 2022

Copy link to clipboard

Copied

replace:

 

thisDoc.save(new File(thisFileName));
thisDoc.close(SaveOptions.NO);
 
with:
 
thisDoc.close(SaveOptions.YES);
 
thisDoc is already a document reference.
There's no need to save to a new file... even because thisFileName is the same parent file of the documentthisDoc. 

Likes

Translate

Translate

Report

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
New Here ,
Oct 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

Thanks for this input. Although I doubt it is the culprit. The error happens before that and it doesn't even get to the saving part.

 

A little background on why it is saved as a new file with the same name. This is a solution I came across for another script (which updates nested links). Nowadays InDesign gets updated fairly regularly, so files that have not been touched for a few weeks/months get opened as a copy and you need to save them again. You've certainly done this and you need to overwrite the file. Since they get opened as a copy ([converted]), they don't have their original filename and path information. That's why this gets stored before the file is opened.

Likes

Translate

Translate

Report

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
Advisor ,
Oct 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

The problem with "converted" file is only when they change a year / version - mid year / version updates do not do that. 

Can automate anything - as long as it doesn't require A.I.

Likes

Translate

Translate

Report

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 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

Nowadays InDesign gets updated fairly regularly, so files that have not been touched for a few weeks/months get opened as a copy and you need to save them again.

 

Hi @Christoph Senn , Your use of the .fullName property might be causing a problem. Document’s have a .converted property, so if I open a document where .converted returns true, and try to get .fullName, I get the error Unsaved documents have no full name:

 

 

 

 

var doc = app.activeDocument;
$.writeln(doc.converted)

//if doc.converted returns true doc.fullName throws an error—
//Unsaved documents have no full name.
var fp = doc.fullName;

 

 

 

 

I use .filepath + .fileName to overwrite converted files:

 

 

 

 

var doc = app.activeDocument;
var fp = doc.filePath;
var n = doc.name;

if (doc.converted) {
    doc.save (File(fp + "/" + n))
} else {
    doc.save()
}

 

 

 

 

Likes

Translate

Translate

Report

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
New Here ,
Oct 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

Hey @rob day. Yes, that's why I grab that filename before opening the doc. But the .converted property is interesting nonetheless and could simplify that. Only do it if it is a converted document. Otherwise just save as usual. Thanks!

Likes

Translate

Translate

Report

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
New Here ,
Oct 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

Which is basically what your snippet does!

Likes

Translate

Translate

Report

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 27, 2022 Oct 27, 2022

Copy link to clipboard

Copied

Yes, that's why I grab that filename before opening the doc

 

But, you are not getting the name—.fullName is the entire file path, .filePath is the file‘s container, and .name is the file name. So, maybe this would work:

 

 

function changeNestedLayers(linksArr) {
    var thisLink,
        thisFile,
        thisDoc;
  
    for (var l = 0; l < linksArr.length; l++) {
        thisLink = linksArr[l];
      
        //open the link using fullName, which is the entire path not the name
        thisDoc = app.open(File(thisLink.fullName), true);
      
        //the file path for the save below
        thisFile = thisDoc.filePath + "/" + thisDoc.name;
        
        //more code....


        
        if (thisDoc.converted) {
            thisDoc.save (File(thisFile))
        } else {
            thisDoc.save()
        }    
        thisDoc.close(SaveOptions.NO);
    }
}

 

 

Likes

Translate

Translate

Report

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
New Here ,
Nov 01, 2022 Nov 01, 2022

Copy link to clipboard

Copied

Hey @rob day, finally I'm having time again to get back to this. Thanks for your input. But I don't think this is the problem. After all, if I take out everything between opening and saving/closing the file, everything works as expected. The Files get opened and saved.
I was mistakenly referring to filename in my previous reply, when I meant the full path and name. Which I get via:

thisFileName = thisFile.fullName;

And using this to save my file is essentially the same as constructing it from path and name afterwards as in your example:

thisFilePath = thisDoc.filePath + "/" + thisDoc.name;
// Changed var name to avoid confusion.

 However, I still like the idea of the conditional save involving .converted.

Likes

Translate

Translate

Report

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 ,
Nov 01, 2022 Nov 01, 2022

Copy link to clipboard

Copied

And using this to save my file is essentially the same as constructing it from path and name afterwards as in your example:

 

But when you open a converted file .fullName will throw an error when you try to get it—the document hasn’t been saved:

 

Screen Shot 34.png

 

 

 

 

Likes

Translate

Translate

Report

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
New Here ,
Nov 01, 2022 Nov 01, 2022

Copy link to clipboard

Copied

Yes. That's why I grabbed the full filepath and name before opening the link and creating the doc.

Likes

Translate

Translate

Report

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
New Here ,
Nov 01, 2022 Nov 01, 2022

Copy link to clipboard

Copied

Interesting. I now tried to create a simplified version including shareable indd files. And it throws me an error exactly when I try to open the file... arrgh. I think I'll have to take a step back again here.

Likes

Translate

Translate

Report

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