Skip to main content
jonathankemp
Inspiring
May 16, 2020
Answered

Best clean way to get number of selected layers within script.

  • May 16, 2020
  • 2 replies
  • 3974 views

So,

I'm looking for the best way to count the number of selected layers in a PS document.

 

I've been looking around and stumbled on this piece of code : https://graphicdesign.stackexchange.com/questions/104786/is-it-possible-to-count-the-number-of-layers-selected-in-photoshop

 

It does work, but it works by creating a new group before counting the layers, then undoing it all.  This fires a "Mk " event.  And since the script has an EventListenner looking out for "Mk " events, well... I get stuck in an endless loop...

 

Isn't there a simple and effective way to count the selected layers ?  Actually... I just need to know if there's more than one selected...

 

Many thanks.

 

J.

This topic has been closed for replies.
Correct answer jazz-y
s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayers'));
r.putEnumerated (s2t ('document'), s2t ('ordinal'), s2t ('targetEnum'));
n =  executeActionGet (r).hasKey(p) ?  executeActionGet (r).getList(p).count : 0;
alert (n)

2 replies

Charu Rajput
Community Expert
Community Expert
May 16, 2020

Hi,

This is another version of the script that you have shared above.

 

var doc = app.activeDocument;
var layers = doc.layers;

function getSelectedLayers() {
    var resultLayers = new Array();
    try {
        var idGrp = stringIDToTypeID("groupLayersEvent");
        var descGrp = new ActionDescriptor();
        var refGrp = new ActionReference();
        refGrp.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        descGrp.putReference(charIDToTypeID("null"), refGrp);
        executeAction(idGrp, descGrp, DialogModes.NO);
        for (var i = 0; i < app.activeDocument.activeLayer.layers.length; i++) {
            resultLayers.push(app.activeDocument.activeLayer.layers[i])
        }
        var id8 = charIDToTypeID("slct");
        var desc5 = new ActionDescriptor();
        var id9 = charIDToTypeID("null");
        var ref2 = new ActionReference();
        var id10 = charIDToTypeID("HstS");
        var id11 = charIDToTypeID("Ordn");
        var id12 = charIDToTypeID("Prvs");
        ref2.putEnumerated(id10, id11, id12);
        desc5.putReference(id9, ref2);
        executeAction(id8, desc5, DialogModes.NO);
        return resultLayers;
    } catch (e) {
        alert("No Layer selected or locked layer selected");
        return resultLayers;
    }
}
var selectedLayers = getSelectedLayers();
$.writeln(selectedLayers.length);

 

This will give you an array of selected layers. I hope this helps

 

Thanks

Best regards
Hot amateurs
Participant
November 7, 2020

This helped me a lot, thanks

jazz-yCorrect answer
Legend
May 16, 2020
s2t = stringIDToTypeID;
(r = new ActionReference).putProperty(s2t('property'), p = s2t('targetLayers'));
r.putEnumerated (s2t ('document'), s2t ('ordinal'), s2t ('targetEnum'));
n =  executeActionGet (r).hasKey(p) ?  executeActionGet (r).getList(p).count : 0;
alert (n)
Charu Rajput
Community Expert
Community Expert
May 16, 2020

Hi, This is a nice solution. Could you please explain me (just want to learn), how exactly it is working.

Highly appreciated!

 

Thanks

Best regards
c.pfaffenbichler
Community Expert
Community Expert
July 20, 2023

Thanks! In testing it out, I've also realized that the id and itemIndex don't let you manipulate the layer directly: for example app.activeDocument.layers[858] will produce an error for id and app.activeDocument.layers[858] will produce an error for id and app.activeDocument.layers[57] will produce an error for itemIndex specifically. I did find addSelectedLayer() from Flatten All Layers.jsx, which seems to bridge the gap. The script I'm currently working on, sizes the active layer based on the layer below. Ideally I'd be able to reference the second layer without selecting it, but I'm not sure that's necessary?

 

    ///////////////////////////////////////////////////////////////////////////////
    // From: Flatten All Layer Effects.jsx
    // Function: getSelectedLayers
    // Usage: creates and array of the currently selected layers
    // Input: <none> Must have an open document
    // Return: Array selectedLayers
    ///////////////////////////////////////////////////////////////////////////////
function addSelectedLayer( layerIndexOrName ) {
	try {
		var id243 = charIDToTypeID( "slct" );
		var desc46 = new ActionDescriptor();
		var id244 = charIDToTypeID( "null" );
		var ref44 = new ActionReference();
		var id245 = charIDToTypeID( "Lyr " );
		if ( typeof layerIndexOrName == "number" ) {
			ref44.putIndex( id245, layerIndexOrName );
		} else {
			ref44.putName( id245, layerIndexOrName );
		}
		desc46.putReference( id244, ref44 );
		var id246 = stringIDToTypeID( "selectionModifier" );
		var id247 = stringIDToTypeID( "selectionModifierType" );
		var id248 = stringIDToTypeID( "addToSelection" );
		desc46.putEnumerated( id246, id247, id248 );
		var id249 = charIDToTypeID( "MkVs" );
		desc46.putBoolean( id249, false );
		executeAction( id243, desc46, DialogModes.NO );
	}

 

 


Also what do you mean by »manipulate« exactly? 

Certain operations can be performed with AM-code by addressing a Layer via index or identifier, for some operations one has to select it first even with AM-code.