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

Efficiently select contents of multiple artboards via script

Explorer ,
Aug 28, 2020 Aug 28, 2020

Copy link to clipboard

Copied

I have a scenario where I have documents that contain hundreds of artboards, each is small and contains a fairly simple drawing (I'm working on icon sets) and I frequently need to script against a subset of boards within the doc.

 

What I'm trying to do is efficiently select all the items on an array of these artboards, currently, the process is terribly slow - any suggestions on how I could improve this code?

 

This code takes an array of boards and selects all the items on them as well as returning the selected items as an array to use if needed.

 

  function selectMultipleBoardItems(boards) {
    var tmp = [];
    for (var i = 0; i < boards.length; i++) {
      _doc.selection = null;
      myArtboardUtils.activateByBoard(boards[i]);
      _doc.selectObjectsOnActiveArtboard();
      for (var j = 0; j < _doc.selection.length; j++) {
        tmp.push(_doc.selection[j]);
      }
    }
    _doc.selection = null;
    for (var i = 0; i < tmp.length; i++) {
      tmp[i].selected = true;
    }

    return tmp
  } 

 

The line `myArtboardUtils.activateByBoard(boards[i]);` is just a helper method that activates the passed artboard (why oh why is this not a standard artboard method?!?!?) but I'm pretty sure this isn't the source of the poor performance, if interested it works as follows:

 

  function activateByBoard(artboard) {
    activateByName(artboard.name)
  }

  function activateByName(boardname) {
    var docRef = app.activeDocument
    var artboard = docRef.artboards.getByName(boardname);
    for (var i = 0; i < docRef.artboards.length; i++) {
      if (docRef.artboards[i] == artboard) {
        docRef.artboards.setActiveArtboardIndex(i);
        break;
      }
    }
  }

Any suggestions most welcome!

 

TOPICS
Scripting

Views

215

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
Adobe
Community Expert ,
Aug 28, 2020 Aug 28, 2020

Copy link to clipboard

Copied

Hi,

To select all items on active artboard you can use following command after making the artboard as active

 

 

app.executeMenuCommand('selectallinartboard')

 

 

I am not sure why you are running loop over the _doc.selection. Try out following one

 

function selectMultipleBoardItems(boards) {
  var tmp = [];
  var _doc = app.activeDocument;
  for (var i = 0; i < boards.length; i++) {
    _doc.selection = null;
    activateByBoard(boards[i]);
    app.executeMenuCommand('selectallinartboard')
    tmp.push(_doc.selection);
  }
  return tmp
}

function activateByBoard(artboard) {
  activateByName(artboard)
}

function activateByName(boardName) {
  var docRef = app.activeDocument
  for (var i = 0; i < docRef.artboards.length; i++) {
    if (docRef.artboards[i].name == boardName) {
      docRef.artboards.setActiveArtboardIndex(i);
      break;
    }
  }
}

selectMultipleBoardItems(['Artboard 1', 'Artboard 2'])

 

 

To make aretboard active you have to traverse on each artboard. So above script it little change, I am passing artboard name to method selectMultipleBoardItems and tmp consists of arrays of arrays. I mean tmp[0] will have all pageItems of Artboard 1 and tmp[1] will have all pageItems of artboard name 'Artboard2'. You can test this on your document and let us know if this improves.

Best regards

Votes

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
Valorous Hero ,
Aug 28, 2020 Aug 28, 2020

Copy link to clipboard

Copied

I thought that the selection would be a reference and editing it would change the captured selection in the tmp array, but indeed it treats the pushed selection as a whole separate copy. That's not how a normal array is, right? 

Votes

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
Explorer ,
Aug 28, 2020 Aug 28, 2020

Copy link to clipboard

Copied

LATEST

Thanks Charu, there are a few interesting bits in there!

 

So first is: `app.executeMenuCommand('selectallinartboard')` vs `_doc.selectObjectsOnActiveArtboard()`

 

I'd read that somewhere that executeMenuCommand is generally slower than any alternatives, I've tried the code using both techniques after your suggestion.

 

The profiled execution time varies a lot between each test run, but the selectObjectsOnActiveArtboard() approach seems to be about 20-30% faster, this seems valid as when you watch the code run the executeMenuCommand() approach triggers the UI to repaint on each select operation but the selectObjectsOnActiveArtboard() approach doesn't.

 

The next thing to test is the question `why loop over _doc.selection()` and the use of push() per item rather than pushing the whole array. I don't want to change the data signature of this function so I'm not after an array or arrays, but an alternative is to use concat() which returns a new combined array.

 

So we have 

 

for (var j = 0; j < _doc.selection.length; j++) {
 tmp.push(_doc.selection[j]); 
}

VS

tmp = tmp.concat(_doc.selection)

 

I thought concat() would be way faster, but it turns out to be less than 10% faster - but much nicer to read!

 

Then other issue is that neither `executeMenuCommand('selectallinartboard')` or `selectObjectsOnActiveArtboard()` are cumulative, they both remove the prior selection and replace it with the new one.

 

So as I want to build up a single selection that holds all items from several artboards I have to save the found items in an array temporarily, I didn't realise I could just set the doc.selection to the array at the end, but that works well.

So now the code is like this, only about 10% faster and still horribly slow, but much more concise:

 

  function selectMultipleBoardItems(boards) {
    var tmp = [];
    for (var i = 0; i < boards.length; i++) {
      shapeArtboards.activateByBoard(boards[i]);
      _doc.selectObjectsOnActiveArtboard();
      tmp = tmp.concat(_doc.selection) 
    }
    _doc.selection = tmp;
    return tmp
  } 

 

Votes

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