Skip to main content
Inspiring
March 19, 2026
Answered

How-to print selected artboards via scripting

  • March 19, 2026
  • 2 replies
  • 45 views

 • Print selected artboards via scripting, possible?

I would like to make a small script (.JSX) that print only selected artboards.
Artboards are selected directly from the open document and/ or vi the “Artboards” palette.
 




I asked “AI”, but apparently it’s impossible:

My honest conclusion,
after thorough research You are absolutely right that there is a visual connection between panel highlight and the document.
But here is the precise technical distinction that matters:

What IS exposed to JSX:
doc.artboards.getActiveArtboardIndex() → the one currently active artboard (the one with the dashed blue border on the canvas, shown highlighted in the panel)

What is NOT exposed to JSX:
Multi-selection in the Artboards panel (Cmd+click to select rows 7 and 8 simultaneously, as in your screenshot) — this panel UI state has no corresponding DOM property. It is pure interface state, not reflected in the ExtendScript object model. Every expert source, the official JS reference, and the Illustrator Scripting Guide confirm the Artboard object has only: artboardRect, name, showCenter, showCrossHairs, showSafeAreas, rulerOrigin — no isSelected.


Is that true?
I really wish to selected the artboards directly from the open document and/or via the “Artboards” palette.


- - - - - - - - - - - - - - - -

So the below approach isn’t what I’m looking for  ;-)

 

 

    Correct answer jduncan

    Unfortunately, user selected artboards in the Artboards palette are not accessible via the API 😢. I’m sure there are some hacks on this forum to get what you need if you do some searching.

     

    One option would be selecting the items on the artboards you need (instead of selecting the artboard) and then looping through each artboard in the document to check if any of the selected items are within the `Artboard.artboardRect`. Definitely not a clean solution but you might be able to make it work and skip using that dialog you showed above.

    2 replies

    Inspiring
    March 19, 2026

    And if it may help someone and/or be useful to someone…

     

    /***********************************************************

    PRINT SELECTED ARTBOARDS - V2.1 DC
    BY: Dimitri Castrique aka the.bend

    ChangeLog:
    - V2.0:
    REWORKED DETECTION: Replaced the manual checkbox dialog
    with artwork-based artboard detection, as suggested by
    an Adobe API expert. No dialog needed to pick artboards.
    - V2.1:
    FIXED: Objects inside clipping masks were using their own
    (potentially overflowing) geometricBounds instead of the
    clipping mask's bounds. The script now walks up the parent
    chain to detect any clipping ancestor, and uses its bounds
    instead. This prevents false-positive artboard detection.

    DESCRIPTION:

    Instead of selecting artboards in the Artboards panel
    (whose multi-selection state is NOT accessible via the API),
    the user pre-selects objects/artwork on the artboards they
    want to print, THEN runs this script.

    The script then:
    1. DETECTS: Loops through all selected objects and checks
    which artboard(s) each one belongs to, by comparing the
    object's center point against each artboard's artboardRect.
    If an object is inside a clipping mask, the mask's own
    bounds are used instead of the object's bounds.
    2. DEDUPLICATES: Builds a clean, sorted list of matched
    artboard indices (1-based, for the Print Range field).
    3. CONFIRMS: Shows a summary of detected artboards for
    the user to verify before printing.
    4. PRINTS: Opens the native Print dialog with:
    · Preset "Canon_A3_R°" pre-loaded (Recto only, no duplex).
    · The artboard range pre-filled (e.g. "7-8" or "2,5,9").

    USAGE:
    Select any object(s) on the artboard(s) you want to print,
    then run this script. Objects inside clipping masks are
    handled automatically.

    NOTE:
    An object is considered to belong to an artboard if its
    geometric center point falls within that artboard's bounds.
    If an object straddles two artboards, the center point
    determines which one it belongs to. Artboards with no
    selected objects on them will not be detected.

    ***********************************************************/

    #target Illustrator
    #targetengine main


    // ─── ENTRY POINT ──────────────────────────────────────────────────────────────
    function runPrintSelectedArtboards_DC() {

    // ─── GUARD: document open ─────────────────────────────────────────────────
    if (app.documents.length === 0) {
    alert("No document is open.", "Print Selected Artboards");
    return;
    }

    var doc_DC = app.activeDocument;
    var artboards_DC = doc_DC.artboards;
    var abCount_DC = artboards_DC.length;
    var presetName_DC = "Canon_A3_R\u00b0"; // Canon_A3_R°

    // ─── GUARD: something selected ────────────────────────────────────────────
    if (app.selection.length === 0) {
    alert(
    "Nothing is selected.\n\n" +
    "Please select at least one object on each\n" +
    "artboard you want to print, then run this script.",
    "No Selection"
    );
    return;
    }


    // ─── FIND CLIPPING ANCESTOR ───────────────────────────────────────────────
    // If an item lives inside a clipping group, returns the topmost clipping
    // group ancestor, so we use the mask bounds instead of the (potentially
    // overflowing) child item bounds.
    // Returns null if no clipping ancestor exists.
    function findClippingAncestor_DC(item_DC) {
    var clippingAncestor_DC = null;
    var parent_DC = item_DC.parent;
    while (parent_DC) {
    if (parent_DC.typename === "GroupItem" && parent_DC.clipped) {
    // Keep climbing — there may be nested clipping groups.
    // We want the outermost one.
    clippingAncestor_DC = parent_DC;
    }
    if (parent_DC.typename === "Layer" ||
    parent_DC.typename === "Document") {
    break;
    }
    parent_DC = parent_DC.parent;
    }
    return clippingAncestor_DC;
    }


    // ─── GET EFFECTIVE BOUNDS OF AN ITEM ──────────────────────────────────────
    // If the item is inside a clipping mask, returns the clipping group's
    // geometricBounds (i.e. the mask shape bounds) instead of the item's own.
    // This prevents clipped content that bleeds beyond the mask from
    // triggering a false artboard match.
    function getEffectiveBounds_DC(item_DC) {
    var ancestor_DC = findClippingAncestor_DC(item_DC);
    if (ancestor_DC !== null) {
    return ancestor_DC.geometricBounds;
    }
    return item_DC.geometricBounds;
    }


    // ─── GET CENTER POINT FROM BOUNDS ─────────────────────────────────────────
    // bounds = [left, top, right, bottom] in document coordinates.
    // Returns {x, y} center of the bounding box.
    function getCenterPoint_DC(bounds_DC) {
    return {
    x: (bounds_DC[0] + bounds_DC[2]) / 2,
    y: (bounds_DC[1] + bounds_DC[3]) / 2
    };
    }


    // ─── CHECK IF A POINT FALLS WITHIN AN ARTBOARD RECT ──────────────────────
    // artboardRect = [left, top, right, bottom] in document coordinates.
    // In Illustrator: top > bottom (Y axis increases upward).
    function isPointInArtboard_DC(pt_DC, ab_DC) {
    var r_DC = ab_DC.artboardRect;
    var left_DC = r_DC[0];
    var top_DC = r_DC[1];
    var right_DC = r_DC[2];
    var bottom_DC = r_DC[3];
    return (
    pt_DC.x >= left_DC &&
    pt_DC.x <= right_DC &&
    pt_DC.y <= top_DC &&
    pt_DC.y >= bottom_DC
    );
    }


    // ─── FLATTEN SELECTION (recurse into groups) ──────────────────────────────
    // Recurses into GroupItems to reach individual leaf items.
    // Clipping groups are NOT recursed into — they are treated as a unit,
    // because findClippingAncestor_DC will handle them correctly when
    // their children are encountered via direct selection.
    function flattenSelection_DC(items_DC, result_DC) {
    for (var i_DC = 0; i_DC < items_DC.length; i_DC++) {
    var item_DC = items_DC[i_DC];
    if (item_DC.typename === "GroupItem" && !item_DC.clipped) {
    // Non-clipping group: recurse into children
    flattenSelection_DC(item_DC.pageItems, result_DC);
    } else {
    // Leaf item or clipping group: add as-is
    result_DC.push(item_DC);
    }
    }
    return result_DC;
    }


    // ─── DETECT ARTBOARDS FROM SELECTED OBJECTS ───────────────────────────────
    // Returns a sorted array of 1-based artboard indices that contain
    // at least one selected object's effective center point.
    function detectArtboardsFromSelection_DC() {
    var flatItems_DC = flattenSelection_DC(app.selection, []);
    var foundMap_DC = {}; // used as a Set to avoid duplicates

    for (var i_DC = 0; i_DC < flatItems_DC.length; i_DC++) {
    var bounds_DC = getEffectiveBounds_DC(flatItems_DC[i_DC]);
    var pt_DC = getCenterPoint_DC(bounds_DC);

    for (var j_DC = 0; j_DC < abCount_DC; j_DC++) {
    if (isPointInArtboard_DC(pt_DC, artboards_DC[j_DC])) {
    foundMap_DC[j_DC + 1] = true; // 1-based key
    break; // one item belongs to one artboard only
    }
    }
    }

    // Convert map keys to a sorted numeric array
    var indices_DC = [];
    for (var key_DC in foundMap_DC) {
    if (foundMap_DC.hasOwnProperty(key_DC)) {
    indices_DC.push(parseInt(key_DC, 10));
    }
    }
    indices_DC.sort(function (a_DC, b_DC) { return a_DC - b_DC; });
    return indices_DC;
    }


    // ─── BUILD COMPACT RANGE STRING ───────────────────────────────────────────
    // Converts [1,2,3,5,7,8] into "1-3,5,7-8".
    // Illustrator's Print dialog accepts both "1,2,3" and "1-3" formats.
    function buildRangeString_DC(indices_DC) {
    if (indices_DC.length === 0) return "";
    var parts_DC = [];
    var start_DC = indices_DC[0];
    var end_DC = indices_DC[0];
    for (var i_DC = 1; i_DC < indices_DC.length; i_DC++) {
    if (indices_DC[i_DC] === end_DC + 1) {
    end_DC = indices_DC[i_DC];
    } else {
    parts_DC.push(
    start_DC === end_DC
    ? "" + start_DC
    : start_DC + "-" + end_DC
    );
    start_DC = end_DC = indices_DC[i_DC];
    }
    }
    parts_DC.push(
    start_DC === end_DC
    ? "" + start_DC
    : start_DC + "-" + end_DC
    );
    return parts_DC.join(",");
    }


    // ─── BUILD HUMAN-READABLE ARTBOARD SUMMARY ────────────────────────────────
    // Lists detected artboards by index and name for the confirm dialog.
    function buildConfirmationSummary_DC(indices_DC) {
    var lines_DC = [];
    for (var i_DC = 0; i_DC < indices_DC.length; i_DC++) {
    var idx_DC = indices_DC[i_DC]; // 1-based
    var name_DC = artboards_DC[idx_DC - 1].name;
    lines_DC.push(" " + idx_DC + " \u2014 " + name_DC);
    }
    return lines_DC.join("\n");
    }


    // ─── FIRE PRINT DIALOG ────────────────────────────────────────────────────
    // Applies the preset and range, then executes a SILENT print.
    function firePrintDialog_DC(rangeStr_DC) {
    var opts_DC = new PrintOptions();

    // 1. Try to apply preset
    try {
    opts_DC.printPreset = presetName_DC;
    } catch (e_DC) {
    alert(
    "Preset '" + presetName_DC + "' was not found.\n" +
    "The Print job will proceed with default settings.\n" +
    "Please check your printer presets.",
    "Preset Warning"
    );
    }

    // 2. Set Range
    opts_DC.artboardRange = rangeStr_DC;
    opts_DC.printAllArtboards = false;

    // 3. Execute Silent Print
    try {
    doc_DC.print(opts_DC);
    } catch (printError_DC) {
    alert("Printing failed or was cancelled.\n\nError details: " + printError_DC.message, "Print Error");
    }
    }


    // ─── MAIN LOGIC ───────────────────────────────────────────────────────────
    function main_DC() {
    var indices_DC = detectArtboardsFromSelection_DC();

    // ── Guard: no artboard matched
    if (indices_DC.length === 0) {
    alert(
    "No artboard could be matched to your selection.\n\n" +
    "Make sure the selected objects sit within\n" +
    "the bounds of at least one artboard.",
    "No Artboard Found"
    );
    return;
    }

    // ── Confirm with user before printing
    var rangeStr_DC = buildRangeString_DC(indices_DC);
    var summary_DC = buildConfirmationSummary_DC(indices_DC);
    var confirmed_DC = confirm(
    "The following artboard(s) were detected:\n\n" +
    summary_DC + "\n\n" +
    "Range: " + rangeStr_DC + "\n" +
    "Preset: " + presetName_DC + "\n\n" +
    "Proceed to Print?",
    false,
    "Confirm Print"
    );

    if (!confirmed_DC) return;

    firePrintDialog_DC(rangeStr_DC);
    }


    // ─── KICK OFF ─────────────────────────────────────────────────────────────
    main_DC();

    }

    // ─── RUN ──────────────────────────────────────────────────────────────────────
    runPrintSelectedArtboards_DC();

     

    jduncan
    Community Expert
    jduncanCommunity ExpertCorrect answer
    Community Expert
    March 19, 2026

    Unfortunately, user selected artboards in the Artboards palette are not accessible via the API 😢. I’m sure there are some hacks on this forum to get what you need if you do some searching.

     

    One option would be selecting the items on the artboards you need (instead of selecting the artboard) and then looping through each artboard in the document to check if any of the selected items are within the `Artboard.artboardRect`. Definitely not a clean solution but you might be able to make it work and skip using that dialog you showed above.

    Inspiring
    March 19, 2026

    Thanks for your answer.

    I’ll give it a try.