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

Adjust script to add artboard guides instead of document guides

Engaged ,
Feb 08, 2025 Feb 08, 2025

I have this script that someone shared with me a while ago to add guides to a selection, but when working with artboards, it creates document guides, not artboard guides. Is it possible to change that?

 

// Add guides to selection.jsx

//@target Photoshop

if (app.documents.length) {
    // Get doc.
    var doc = app.activeDocument;
    if (doc.selection) {
        // Get bounds of selection.
        var bounds = doc.selection.bounds;
        doc.selection.deselect();
        // Add guides to match bounds of selection.
        doc.guides.add(Direction.VERTICAL, bounds[0]);
        doc.guides.add(Direction.HORIZONTAL, bounds[1]);
        doc.guides.add(Direction.VERTICAL, bounds[2]);
        doc.guides.add(Direction.HORIZONTAL, bounds[3]);
    } else {
        alert("Make a selection");
    }
} else {
    alert("Open a document");
}
TOPICS
Actions and scripting , macOS
272
Translate
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 ,
Feb 08, 2025 Feb 08, 2025

@TiagoRocha I would assume so...so couldn't you replace the document with artboards?


// Add guides to selection within the active artboard.jsx

//@target Photoshop

if (app.documents.length)

  { var doc = app.activeDocument;

  if (doc.selection.length > 0) { // Check if something is selected

      var selectedArtboard = doc.artboards.activeArtboard; // Get the active artboard

      if (selectedArtboard) { // Ensure an artboard is active

           var bounds = doc.selection.bounds;

           // Convert selection bounds to artboard coordinates

           var artboardBounds = selectedArtboard.artboardRect;

           var left = bounds[0] - artboardBounds[0];

           var top = bounds[1] - artboardBounds[1];

           var right = bounds[2] - artboardBounds[0];

           var bottom = bounds[3] - artboardBounds[1];

          
           doc.selection.deselect(); 

           // Add guides RELATIVE to the artboard

           selectedArtboard.guides.add(Direction.VERTICAL, left);

           selectedArtboard.guides.add(Direction.HORIZONTAL, top);        

           selectedArtboard.guides.add(Direction.VERTICAL, right);

           selectedArtboard.guides.add(Direction.HORIZONTAL, bottom);

 

      } else {

           alert("No active artboard found. Please select an artboard.");

      }

 

      } else  {

           alert("Make a selection within an artboard.");

      }

 

} else {

   alert("Open a document");

}

Or something like that?

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

@creative explorer â€“ Unfortunately, the app.activeDocument.artboards property is only valid for Adobe Illustrator's ExtendScript DOM and doesn't exist in Adobe Photoshop's ExtendScript DOM. If the source of this code was a generative AI "hallucination", it would be good to vote it down to help train the AI platform in question.

Translate
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 ,
Feb 08, 2025 Feb 08, 2025

@TiagoRocha 

 

I don't believe that the DOM has been updated for artboard guides, which leaves AM code.

 

The cleaned SL plugin output shows the following for canvas guides:

 

var c2t = function (s) {
	return app.charIDToTypeID(s);
};
var s2t = function (s) {
	return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
descriptor2.putUnitDouble(s2t("position"), s2t("pixelsUnit"), 175); // Position
descriptor2.putEnumerated(s2t("orientation"), s2t("orientation"), s2t("vertical")); // "Horizontal" or "Vertical"
descriptor2.putEnumerated(s2t("kind"), s2t("kind"), s2t("document"));
reference.putIndex(s2t("good"), 1);
descriptor2.putReference(s2t("null"), reference);
descriptor.putObject(s2t("new"), s2t("good"), descriptor2);
reference2.putClass(s2t("good"));
descriptor.putReference(s2t("null"), reference2);
descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetCanvas")); // Canvas guides
executeAction(s2t("make"), descriptor, DialogModes.NO);

 

While artboard guides shows this:

 

var c2t = function (s) {
    return app.charIDToTypeID(s);
};
var s2t = function (s) {
    return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var descriptor2 = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
descriptor2.putUnitDouble(s2t("position"), s2t("pixelsUnit"), 175); // Position
descriptor2.putEnumerated(s2t("orientation"), s2t("orientation"), s2t("vertical")); // Horizontal or Vertical
descriptor2.putEnumerated(s2t("kind"), s2t("kind"), s2t("document"));
reference.putIndex(s2t("good"), 5);
descriptor2.putReference(s2t("null"), reference);
descriptor2.putInteger(c2t("GdCA"), 0); // ?
descriptor2.putInteger(c2t("GdCR"), 255); // ?
descriptor2.putInteger(c2t("GdCG"), 74); // ?
descriptor2.putInteger(c2t("GdCB"), 74); // ?
descriptor.putObject(s2t("new"), s2t("good"), descriptor2);
reference2.putClass(s2t("good"));
descriptor.putReference(s2t("null"), reference2);
descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetSelectedArtboard")); // Artboard guides
executeAction(s2t("make"), descriptor, DialogModes.NO);

 

The "guideTarget" of "guideTargetCanvas" vs.  "guideTargetSelectedArtboard" is obvious to me, however, I have no idea what significance the following four lines have, except that they appear to be critical:

 

descriptor2.putInteger(c2t("GdCA"), 0); // ?
descriptor2.putInteger(c2t("GdCR"), 255); // ?
descriptor2.putInteger(c2t("GdCG"), 74); // ?
descriptor2.putInteger(c2t("GdCB"), 74); // ?

 

The values don't appear to be consistent with either the artboard or canvas size or coordinates. The values appear to be close but not exact to the current preferences/settings for artboard guide colour.

Translate
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 ,
Feb 08, 2025 Feb 08, 2025

@TiagoRocha 

 

I have made some refinements to the original script while I was adjusting it for artboard guides:

 

/* 
Add guides to selection.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/adjust-script-to-add-artboard-guides-instead-of-document-guides/m-p/15141437
*/

#target Photoshop

if (app.documents.length) {

	app.activeDocument.suspendHistory("Add Guides to Selection", "main()");

	function main() {

		// Get active document
		var doc = app.activeDocument;

		// Store the current ruler units
		var originalUnits = app.preferences.rulerUnits;

		// Set units to pixels
		app.preferences.rulerUnits = Units.PIXELS;

		var selectionBounds = null;
		try { selectionBounds = activeDocument.selection.bounds; } catch (e) { }
		if (selectionBounds) {

			try {

				// Get bounds of selection
				var bounds = doc.selection.bounds;

				// Deselect after getting bounds
				doc.selection.deselect();

				// Add guides to match bounds of selection
				doc.guides.add(Direction.VERTICAL, bounds[0]);
				doc.guides.add(Direction.HORIZONTAL, bounds[1]);
				doc.guides.add(Direction.VERTICAL, bounds[2]);
				doc.guides.add(Direction.HORIZONTAL, bounds[3]);

			} catch (e) {
				alert("Error creating guides: " + e);

			} finally {
				// Restore original ruler units
				app.preferences.rulerUnits = originalUnits;
			}

		}
		else {
			alert("Make a selection");
		}
	}

} else {
	alert("Please open a document");
}

 

While this is the script that you asked for adding artboard guides, as opposed to canvas guides.

 

Note: The guide colour has to be hard coded into the script, I have used 128rgb as a placeholder. I'll need to see if it's possible to pick up on the preferences/settings for the artboard guide colour rather than hard-coding in the colour.

 

/*
Add Artboard Guides to Selection.jsx
Stephen Marsh
v1.0 - 9th February 2025
https://community.adobe.com/t5/photoshop-ecosystem-discussions/adjust-script-to-add-artboard-guides-instead-of-document-guides/m-p/15141437
*/

#target Photoshop

if (app.documents.length) {

    app.activeDocument.suspendHistory("Add Artboard Guides to Selection", "main()");

    function main() {

        // Check if the active layer is an artboard, alternatively one could also use a basic layerSet check
        if (isArtboard() === true) {

            // Get active document
            var doc = app.activeDocument;

            // Store the current ruler units
            var originalUnits = app.preferences.rulerUnits;

            // Set units to pixels
            app.preferences.rulerUnits = Units.PIXELS;

            var activeSelection = null;
            try { activeSelection = doc.selection.bounds } catch (e) { }
            if (activeSelection) {

                try {

                    // Trim to transparent pixels to ensure that the bounds are correct
                    doc.trim(TrimType.TRANSPARENT, true, true, true, true);

                    // Get bounds of selection
                    var bounds = doc.selection.bounds;

                    // Deselect after getting bounds
                    doc.selection.deselect();

                    // Add guides to match bounds of selection
                    artboardGuides(bounds[0].value, "vertical");
                    artboardGuides(bounds[1].value, "horizontal");
                    artboardGuides(bounds[2].value, "vertical");
                    artboardGuides(bounds[3].value, "horizontal");

                } catch (e) {
                    alert("Error creating guides: " + e);

                } finally {
                    // Restore original ruler units
                    app.preferences.rulerUnits = originalUnits;
                }

            }
            else {
                alert("Make a selection");
            }
        } else {
            alert("Please select an artboard");
        }
    }

} else {
    alert("Please open a document");
}


// Helper Functions

function artboardGuides(thePosition, theOrientation) {
    var c2t = function (s) {
        return app.charIDToTypeID(s);
    };
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var descriptor2 = new ActionDescriptor();
    var reference = new ActionReference();
    var reference2 = new ActionReference();
    descriptor2.putUnitDouble(s2t("position"), s2t("pixelsUnit"), thePosition); // Position
    descriptor2.putEnumerated(s2t("orientation"), s2t("orientation"), s2t(theOrientation)); // Horizontal or Vertical
    descriptor2.putEnumerated(s2t("kind"), s2t("kind"), s2t("document"));
    reference.putIndex(s2t("good"), 5);
    descriptor2.putReference(s2t("null"), reference);
    descriptor2.putInteger(c2t("GdCA"), 0); // Alpha?
    descriptor2.putInteger(c2t("GdCR"), 128); // Red
    descriptor2.putInteger(c2t("GdCG"), 128); // Green
    descriptor2.putInteger(c2t("GdCB"), 128); // Blue
    descriptor.putObject(s2t("new"), s2t("good"), descriptor2);
    reference2.putClass(s2t("good"));
    descriptor.putReference(s2t("null"), reference2);
    descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetSelectedArtboard")); // Artboard guides
    executeAction(s2t("make"), descriptor, DialogModes.NO);
}

function isArtboard() {
    // modified from a script by greless with hints from jazz-y!
    // returns true or false
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
        var options = executeActionGet(r);
        return options.hasKey(stringIDToTypeID('artboard')); // test for the required key
    } catch (e) {
        //alert(e);
    }
}

 

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

@Stephen Marsh You have an issue with your script. You might not have tried a file with multiple artboards and a layer not included in the artboards.  With AM code, a marquee will be created with bounds of the overall document, but a guide will use the artboard boundries. So your guides will be off.

ChuckUebele_0-1739119419795.pngexpand image

ChuckUebele_1-1739119598507.pngexpand image

 

 

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

@Chuck Uebele 

 

Thanks, no I didn't think to test for such an edge-case. I hate scripting artboards.

 

EDIT: Ah, it's not just an empty artboard, a second artboard has issues.

 

I put in an explicit check to ensure that an artboard was selected and also a trim to transparency to account for canvases that haven't been "shrink-wrapped".

 

What would be the workaround? Saving with shrink wrap on before adding the guides? Looping over all top level layerSets and checking if their length was zero, then adding a temporary layer and or content?

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

I don't know what a workaround would be yet. Your method works for one dartboard, but I haven't tested 2 artboards. The trouble is that a marquee will be based off the document boundaries whereas a guide will be bases off an artboard's, no matter which is selected in the layer panel. To make matters worse, when you get the bounds of the dartboard. It's always 0, 0 for the top and left. It's not based on the document edges, so you can't compensate for the artboard's offset. Only thing that i can think of is to create a filled layer at the boundaries inside the artboard, then move it outside the artboard. Then you could get the AB's boundaries. 

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

@Chuck Uebele 

 

I have this AM code from @Rune L-H

 

// Artboard bounds - by Rune L-H
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var artBoardRect = executeActionGet(ref).getObjectValue(stringIDToTypeID("artboard")).getObjectValue(stringIDToTypeID("artboardRect"));
var artBoardRectWidth = new UnitValue(artBoardRect.getDouble(stringIDToTypeID("right")) - artBoardRect.getDouble(stringIDToTypeID("left")), "px");
var artBoardRectHeight = new UnitValue(artBoardRect.getDouble(stringIDToTypeID("bottom")) - artBoardRect.getDouble(stringIDToTypeID("top")), "px");
artBoardRectWidth = parseInt(artBoardRectWidth);
artBoardRectHeight = parseInt(artBoardRectHeight);

 

And this one is from you:

 

function artboard_rectangle(layer) {
/*
https://community.adobe.com/t5/photoshop-ecosystem-discussions/photoshop-scripting-artboard-size-values/td-p/13255332
by Chuck Uebele
*/
    try {
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("artboard"));
        if (layer) r.putIdentifier(stringIDToTypeID("layer"), layer.id);
        else r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        var d = executeActionGet(r).getObjectValue(stringIDToTypeID("artboard")).getObjectValue(stringIDToTypeID("artboardRect"));
        var bounds = new Array();
        bounds[0] = d.getUnitDoubleValue(stringIDToTypeID("left"));
        bounds[1] = d.getUnitDoubleValue(stringIDToTypeID("top"));
        bounds[2] = d.getUnitDoubleValue(stringIDToTypeID("right"));
        bounds[3] = d.getUnitDoubleValue(stringIDToTypeID("bottom"));
        return bounds;
    } catch (e) {
        alert("An artboard must be selected!");
    }
}

 

However, I haven't tested them in this context.

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

It looks like my script gets the correct bounds. I've writen so many scripts that I don't remember doing this. I'll have to see if it can be used to correct the issue.

Translate
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 ,
Feb 09, 2025 Feb 09, 2025

Well, with the help of @Stephen Marsh Here's a script that works. It doesn't have full error checking, so you have to make sure you have a selection made and an artboard selected.

#target photoshop
var doc = activeDocument

var abL = doc.activeLayer

// Store the current ruler units
var originalUnits = app.preferences.rulerUnits;

// Set units to pixels
app.preferences.rulerUnits = Units.PIXELS;

var activeSelection = null;
try { activeSelection = doc.selection.bounds } catch (e) { alert('A selection must be made')}

var abBounds = artboard_rectangle (abL)

var correctedOffset = [];
correctedOffset[0] = activeSelection[0].value-abBounds[0];
correctedOffset[1] = activeSelection[1].value-abBounds[1];
correctedOffset[2] = activeSelection[2].value-abBounds[0];
correctedOffset[3] = activeSelection[3].value-abBounds[1];


// Add guides to match bounds of selection
artboardGuides(correctedOffset[0], "vertical");
artboardGuides(correctedOffset[1], "horizontal");
artboardGuides(correctedOffset[2], "vertical");
artboardGuides(correctedOffset[3], "horizontal");

/*
artboardGuides(bounds[0].value, "vertical");
artboardGuides(bounds[1].value, "horizontal");
artboardGuides(bounds[2].value, "vertical");
artboardGuides(bounds[3].value, "horizontal");
*/

app.preferences.rulerUnits = originalUnits;

function artboardGuides(thePosition, theOrientation) {
    var c2t = function (s) {
        return app.charIDToTypeID(s);
    };
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var descriptor2 = new ActionDescriptor();
    var reference = new ActionReference();
    var reference2 = new ActionReference();
    descriptor2.putUnitDouble(s2t("position"), s2t("pixelsUnit"), thePosition); // Position
    descriptor2.putEnumerated(s2t("orientation"), s2t("orientation"), s2t(theOrientation)); // Horizontal or Vertical
    descriptor2.putEnumerated(s2t("kind"), s2t("kind"), s2t("document"));
    reference.putIndex(s2t("good"), 5);
    descriptor2.putReference(s2t("null"), reference);
    descriptor2.putInteger(c2t("GdCA"), 0); // Alpha?
    descriptor2.putInteger(c2t("GdCR"), 128); // Red
    descriptor2.putInteger(c2t("GdCG"), 128); // Green
    descriptor2.putInteger(c2t("GdCB"), 128); // Blue
    descriptor.putObject(s2t("new"), s2t("good"), descriptor2);
    reference2.putClass(s2t("good"));
    descriptor.putReference(s2t("null"), reference2);
    descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetSelectedArtboard")); // Artboard guides
    executeAction(s2t("make"), descriptor, DialogModes.NO);
}

  function artboard_rectangle(layer) {
   try {
        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("artboard"));
        if (layer) r.putIdentifier(stringIDToTypeID("layer"), layer.id);
        else r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        var d = executeActionGet(r).getObjectValue(stringIDToTypeID("artboard")).getObjectValue(stringIDToTypeID("artboardRect"));
        var bounds = new Array();
        bounds[0] = d.getUnitDoubleValue(stringIDToTypeID("left"));
        bounds[1] = d.getUnitDoubleValue(stringIDToTypeID("top"));
        bounds[2] = d.getUnitDoubleValue(stringIDToTypeID("right"));
        bounds[3] = d.getUnitDoubleValue(stringIDToTypeID("bottom"));
        return bounds;
    } catch (e) {
        alert("An artboard must be selected!");
    }
}

function isArtboard() {
    // modified from a script by greless with hints from jazz-y!
    // returns true or false
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
        var options = executeActionGet(r);
        return options.hasKey(stringIDToTypeID('artboard')); // test for the required key
    } catch (e) {
        //alert(e);
    }
}

function artboardGuides(thePosition, theOrientation) {
    var c2t = function (s) {
        return app.charIDToTypeID(s);
    };
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var descriptor2 = new ActionDescriptor();
    var reference = new ActionReference();
    var reference2 = new ActionReference();
    descriptor2.putUnitDouble(s2t("position"), s2t("pixelsUnit"), thePosition); // Position
    descriptor2.putEnumerated(s2t("orientation"), s2t("orientation"), s2t(theOrientation)); // Horizontal or Vertical
    descriptor2.putEnumerated(s2t("kind"), s2t("kind"), s2t("document"));
    reference.putIndex(s2t("good"), 5);
    descriptor2.putReference(s2t("null"), reference);
    descriptor2.putInteger(c2t("GdCA"), 0); // Alpha?
    descriptor2.putInteger(c2t("GdCR"), 128); // Red
    descriptor2.putInteger(c2t("GdCG"), 128); // Green
    descriptor2.putInteger(c2t("GdCB"), 128); // Blue
    descriptor.putObject(s2t("new"), s2t("good"), descriptor2);
    reference2.putClass(s2t("good"));
    descriptor.putReference(s2t("null"), reference2);
    descriptor.putEnumerated(s2t("guideTarget"), s2t("guideTarget"), s2t("guideTargetSelectedArtboard")); // Artboard guides
    executeAction(s2t("make"), descriptor, DialogModes.NO);
}
Translate
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 ,
Feb 11, 2025 Feb 11, 2025
LATEST

That's great @Chuck Uebele â€“ thanks for correcting my code!

 

@TiagoRocha â€“ Please mark Chuck's reply as a correct answer if works for you (it did for me).

 

P.S. There appears to be a duplicate artboardGuides function code block which can be removed.

Translate
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