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!
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.
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?
Copy link to clipboard
Copied
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
}