Skip to main content
Inspiring
December 22, 2021
Answered

Renumber/Reorder artboard scripting

  • December 22, 2021
  • 1 reply
  • 1762 views

So, typically I'll Frankenstein some js to do some simple scripting. Most cases I'll find enough parts and peices to wrestle Illustrator in to submission. Context first, I build digital assets for all mediums and prep these artwork libraries as a single, multi artboard file. I name all the Artboards (ABs) and save as with the checkbox for each artboard as a separate file. Great. Sprinkle in some more actions and scripts. However, when i save the artboards as individual files, AI remembers the AB location on the pasteboard. So if you zoom out, the 1 AB each file is *NOT* beautifully centered on the Pasteboard (PB). The manual way I have to fix this imperfection is as follows:

1. Add x2 new blank ABs of the same size

2. Rearrange original AB to position *2* in the AB palette

3. Choose Rearrage All from the CONTROL BAR at top as either 3 rows or 3 columns leaving the original AB dead center

4. Delete x2 blank ABs

I've been able to script up to step 1 only. The current script I'm using will create a new blank AB with a dummy extension at the end of the name so i can then easily delete them later. It's step 2 I can't crack, is there a way to script renumbering/reordering ABs? I can't find any documentation on Artboard number/order in the AI scripting dictionaries...

 

This topic has been closed for replies.
Correct answer Inventsable

We can programmatically trigger a Rearrange Artboards menu action via app.executeMenuCommand and we could try to get your original plan working but we may not need to do it that way. Here's an approach that shows every step of the process:

 

// Generic utilities to make JSX more like modern JS:
function get(type, parent) {
    if (arguments.length == 1 || !parent) parent = app.activeDocument;
    var result = [];
    if (!parent[type]) return result;
    for (var i = 0; i < parent[type].length; i++) result.push(parent[type][i]);
    return result;
}
Array.prototype.forEach = function (callback) {
    for (var i = 0; i < this.length; i++) callback(this[i], i, this);
};

// Our main function
function centerArtboard() {
    // First we find the active artboard:
    var activeBoard =
        app.activeDocument.artboards[
            app.activeDocument.artboards.getActiveArtboardIndex()
        ];
    // Then we iterate every pageItem and recreate it's relative x/y Transform values:
    var list = getPageItemRelativePositions(activeBoard);

    // We need to know our width and height to offset the rect as centered:
    var rect = activeBoard.artboardRect,
        width = rect[2] - rect[0],
        height = -(rect[3] - rect[1]);

    // And since Pasteboard coordinates are absolute, we can center an artboard like so:
    activeBoard.artboardRect = [
        -(width / 2),
        height / 2,
        width / 2,
        -(height / 2),
    ];
    // A rect is the following: [left, top, right, bottom]
    // Because the centerpoint of the Pasteboard is x0 y0 or [0, 0],
    // a 200x200 artboard would become [-100, 100, 100, -100]

    // And since we calculated the transform values as Top-Left in our list, we need these two updated coordinates:
    var left = activeBoard.artboardRect[0],
        top = activeBoard.artboardRect[1];

    // Then we feed our original list into a function that adds the new set of coordinates to each item offset:
    repositionPageItemsViaOffsets(list, left, top);
}

function getPageItemRelativePositions(artboard) {
    var list = [],
        rect = artboard.artboardRect;
    // This is syntactical sugar to make an AI collection into a normal array then
    // further create a basic (for var = 0; i < list.length; i++) loop:
    get("pageItems").forEach(function (item) {
        // Item here is the PageItem object
        list.push({
            // All we need is the unique identifier from this item:
            uuid: item.uuid,
            // Along with the current Transform value as if top-left corner:
            offset: [item.position[0] - rect[0], item.position[1] - rect[1]],
        });
    });
    return list;
}

function repositionPageItemsViaOffsets(list, x, y) {
    // Standard for loop again:
    list.forEach(function (data) {
        // Identify the item from our UUID to access it's properties
        var item = app.activeDocument.getPageItemFromUuid(data.uuid);
        // Then add our offset to the TL corner of our current artboard:
        item.position = [data.offset[0] + x, data.offset[1] + y];
        // And we're done, items are now placed in original positions
    });
}

centerArtboard();

 

 

Before you get too excited, this assumes that there's only a single artboard and that all pageItems (regardless of what artboard they're currently in) should be repositioned the same as that target artboard. If you try running this with an export script it will likely not work for you unless you run the above per file. That's not ideal and it'd be better to export artboards and recenter them all with a single script, but that's not really what you were asking above so I've only done it for one of the result files.

1 reply

Inventsable
InventsableCorrect answer
Legend
December 22, 2021

We can programmatically trigger a Rearrange Artboards menu action via app.executeMenuCommand and we could try to get your original plan working but we may not need to do it that way. Here's an approach that shows every step of the process:

 

// Generic utilities to make JSX more like modern JS:
function get(type, parent) {
    if (arguments.length == 1 || !parent) parent = app.activeDocument;
    var result = [];
    if (!parent[type]) return result;
    for (var i = 0; i < parent[type].length; i++) result.push(parent[type][i]);
    return result;
}
Array.prototype.forEach = function (callback) {
    for (var i = 0; i < this.length; i++) callback(this[i], i, this);
};

// Our main function
function centerArtboard() {
    // First we find the active artboard:
    var activeBoard =
        app.activeDocument.artboards[
            app.activeDocument.artboards.getActiveArtboardIndex()
        ];
    // Then we iterate every pageItem and recreate it's relative x/y Transform values:
    var list = getPageItemRelativePositions(activeBoard);

    // We need to know our width and height to offset the rect as centered:
    var rect = activeBoard.artboardRect,
        width = rect[2] - rect[0],
        height = -(rect[3] - rect[1]);

    // And since Pasteboard coordinates are absolute, we can center an artboard like so:
    activeBoard.artboardRect = [
        -(width / 2),
        height / 2,
        width / 2,
        -(height / 2),
    ];
    // A rect is the following: [left, top, right, bottom]
    // Because the centerpoint of the Pasteboard is x0 y0 or [0, 0],
    // a 200x200 artboard would become [-100, 100, 100, -100]

    // And since we calculated the transform values as Top-Left in our list, we need these two updated coordinates:
    var left = activeBoard.artboardRect[0],
        top = activeBoard.artboardRect[1];

    // Then we feed our original list into a function that adds the new set of coordinates to each item offset:
    repositionPageItemsViaOffsets(list, left, top);
}

function getPageItemRelativePositions(artboard) {
    var list = [],
        rect = artboard.artboardRect;
    // This is syntactical sugar to make an AI collection into a normal array then
    // further create a basic (for var = 0; i < list.length; i++) loop:
    get("pageItems").forEach(function (item) {
        // Item here is the PageItem object
        list.push({
            // All we need is the unique identifier from this item:
            uuid: item.uuid,
            // Along with the current Transform value as if top-left corner:
            offset: [item.position[0] - rect[0], item.position[1] - rect[1]],
        });
    });
    return list;
}

function repositionPageItemsViaOffsets(list, x, y) {
    // Standard for loop again:
    list.forEach(function (data) {
        // Identify the item from our UUID to access it's properties
        var item = app.activeDocument.getPageItemFromUuid(data.uuid);
        // Then add our offset to the TL corner of our current artboard:
        item.position = [data.offset[0] + x, data.offset[1] + y];
        // And we're done, items are now placed in original positions
    });
}

centerArtboard();

 

 

Before you get too excited, this assumes that there's only a single artboard and that all pageItems (regardless of what artboard they're currently in) should be repositioned the same as that target artboard. If you try running this with an export script it will likely not work for you unless you run the above per file. That's not ideal and it'd be better to export artboards and recenter them all with a single script, but that's not really what you were asking above so I've only done it for one of the result files.

Inspiring
December 22, 2021

Wow, much appreciated. I think this is nearly what I needed, and I *think* why it isn't quite working is because pasteboard rulers aren't strictly absolute. Historically in AI, before multiple ABs, you only had one coordinate system, and it could be set to your AB or off of it onto the PB somewhere. Now, with multiple artboards, even if you switch to global ruler settings, the 0,0 point can still be anywhere on the PB. Unless there is an internal coordinate system that the UI doesn't access. The script you so kindly help to write will move the AB and contents to the offset center position of the global 0,0 position. Problem is, 0,0 is not right in the middle and I don't know how to make it so. See my problem in a GIF, the ruler is set by the relative position of the AB from the save out;

I could fix it by using the GLOBAL RULER setting in my original working file and ensure its set to PB 0,0 and then the dominoes fall from there. I think.

What do you think?