Skip to main content
jonohunt
Known Participant
March 30, 2018
Answered

Script to remove hidden/unused Layer Effects?

  • March 30, 2018
  • 3 replies
  • 6748 views

Does anyone have, or know if it's possible to remove hidden/unused layer effects of selected layer(s) with a script? (Not on every layer in the document, only selected layers)

For example here I'd have to drag each unused effect to the trash can at the bottom

Would be great if you could remove the hidden ones while still leaving those that are visible via a script

Correct answer r-bin

This can be due to layer protection. Try this variant.

var r = new ActionReference();     

r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));  

r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt")); 

 

if (executeActionGet(r).hasKey(stringIDToTypeID("targetLayers"))) 

    { 

    var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers")); 

 

    var offset = 0; 

    try { activeDocument.backgroundLayer } catch (e) { offset = 1; } 

    var unlock_flag = false;

    var lock = false;

    var del_cnt = 0;

 

    for (var n = 0; n < list.count; n++) 

        { 

        var idx = list.getReference(n).getIndex(); 

 

        var r = new ActionReference();     

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerEffects"));  

        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

 

        if (!executeActionGet(r).hasKey(stringIDToTypeID("layerEffects"))) continue; 

 

        var d = executeActionGet(r).getObjectValue(stringIDToTypeID("layerEffects")); 

        var r = new ActionReference();     

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerLocking"));  

        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

        if (!unlock_flag) lock = executeActionGet(r).getObjectValue(stringIDToTypeID("layerLocking")).getBoolean(stringIDToTypeID("protectAll"));

        for (var i = 0; i < d.count; i++) 

            { 

            var key = d.getKey(i); 

            var type = d.getType(key); 

     

            if (type == DescValueType.OBJECTTYPE) 

                { 

                var enabled = d.getObjectValue(key).getBoolean(stringIDToTypeID("enabled")); 

     

                if (!enabled) 

                    { 

                    if (lock && !unlock_flag)

                        {

                        var d2 = new ActionDescriptor();

                        var d1 = new ActionDescriptor();

                        var d3 = new ActionDescriptor();

                        var r = new ActionReference();

                        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

                        d1.putReference( charIDToTypeID( "null" ), r );

                        d3.putBoolean( stringIDToTypeID( "protectAll" ), false);

                        d2.putObject( stringIDToTypeID( "layerLocking" ), stringIDToTypeID( "layerLocking" ), d3 );

           

                        d1.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "Lyr " ), d2 );

                        executeAction( charIDToTypeID( "setd" ), d1, DialogModes.NO );

                        unlock_flag = true;

                        }

                    var d2 = new ActionDescriptor(); 

                    var r = new ActionReference(); 

                    r.putClass(d.getClass(key)); 

                    r.putIndex(charIDToTypeID("Lyr "), idx + offset); 

                    d2.putReference(stringIDToTypeID("null"), r); 

                    executeAction(stringIDToTypeID("disableSingleFX"), d2, DialogModes.NO); 

                    ++del_cnt;

                    } 

         

                } 

            } 

        } 

    alert(del_cnt + " LayerEffects have been removed"); 

    } 

else 

    { 

    alert("no selected layers") 

    } 

3 replies

_wckdTall_
Inspiring
March 11, 2026

Is there a version of this that works for stacked layer effects that are the same type? Example 10 Color Overlays and 9 of them aren’t visible? ​@c.pfaffenbichler, I believe you looked into this, apologies as the shift over to the new forums have expunged that solution from my inbox.

c.pfaffenbichler
Community Expert
Community Expert
March 21, 2026
// remove hidden layer styles;
// partly based on code by michael l hale;
// 2025, use it at your own risk;
if (app.documents.length > 0) {
// revert;
//executeAction( stringIDToTypeID( "revert" ), undefined, DialogModes.NO );
// get desc;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
if (layerDesc.hasKey(stringIDToTypeID('layerEffects')) == true) {
var effectsDesc = layerDesc.getObjectValue(stringIDToTypeID('layerEffects'));
var theEff = checkDesc3 (effectsDesc, false);
//alert ("\n"+theEff.join("\n\n"));
////////////////////////////////////
// delete layers styles;
var desc217 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
desc217.putReference( stringIDToTypeID( "null" ), ref1 );
executeAction( stringIDToTypeID( "disableLayerFX" ), desc217, DialogModes.NO );
////////////////////////////////////
// create anew;
var desc5 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty( stringIDToTypeID( "property" ), stringIDToTypeID( "layerEffects" ) );
ref1.putEnumerated( stringIDToTypeID( "layer" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
var effectsDescNew = new ActionDescriptor();
// process the styles;
for (var m = theEff.length-1; m >= 0; m--) {
switch (effectsDesc.getType(effectsDesc.getKey(m))) {
case DescValueType.BOOLEANTYPE:
//alert( effectsDesc.getBoolean(effectsDesc.getKey(m)));
break;
case DescValueType.CLASSTYPE:
//alert( effectsDesc.getClass(effectsDesc.getKey(m)));
break;
case DescValueType.DOUBLETYPE:
//alert( effectsDesc.getDouble(theDesc.getKey(m)));
break;
case DescValueType.ENUMERATEDTYPE:
//alert( (typeIDToStringID(effectsDesc.getEnumerationValue(effectsDesc.getKey(m)))+"_"+typeIDToStringID(effectsDesc.getEnumerationType(effectsDesc.getKey(m)))));
break;
case DescValueType.INTEGERTYPE:
//alert( effectsDesc.getInteger(effectsDesc.getKey(m)));
break;
// lists;
case DescValueType.LISTTYPE:
var listStuff = evaluateList (effectsDesc.getList(stringIDToTypeID(theEff[m][1])));
var listResult = new Array;
for (var x = 0; x < listStuff.length; x++) {
listResult.push(checkList01 (listStuff[x], false));
};
var list01 = new ActionList();
var theCounter = 0;
// check for disabled styles;
for (var y = 0; y < listResult.length; y++) {
// multiple gradient overlays appear to need a last hidden one that does not appear in the layers panel;
if (listResult[y][0][1] == true) {
theCounter++;
var theNumber = y
};
if (listResult[y][0][1] == true || y == listResult.length-1) {
list01.putObject(stringIDToTypeID( theEff[m][1].replace("Multi", "" )), effectsDesc.getList(effectsDesc.getKey(m)).getObjectValue(y) );
}
};
if (theCounter == 1) {
// alert alert alert
effectsDescNew.putObject( stringIDToTypeID( theEff[m][1].replace("Multi", "") ), stringIDToTypeID( theEff[m][1].replace("Multi", "") ), effectsDesc.getList(effectsDesc.getKey(m)).getObjectValue(theNumber) );
} else {
// set a new list;
effectsDescNew.putList( stringIDToTypeID( theEff[m][1]/*.replace("Multi", "" )*/ ), list01 );
};
break;
// objects;
case DescValueType.OBJECTTYPE:
var enabled = effectsDesc.getObjectValue(effectsDesc.getKey(m)).getBoolean(stringIDToTypeID("enabled"));
if (enabled == true) {
effectsDescNew.putObject( stringIDToTypeID( theEff[m][1] ), stringIDToTypeID( theEff[m][1] ), effectsDesc.getObjectValue(effectsDesc.getKey(m)) );
};
break;
case DescValueType.REFERENCETYPE:
//alert( effectsDesc.getReference(effectsDesc.getKey(m)));
break;
case DescValueType.STRINGTYPE:
//alert( effectsDesc.getString(effectsDesc.getKey(m)));
break;
case DescValueType.UNITDOUBLE:
effectsDescNew.putUnitDouble( stringIDToTypeID( theEff[m][1] ), effectsDesc.getUnitDoubleType(effectsDesc.getKey(m)), effectsDesc.getUnitDoubleValue(effectsDesc.getKey(m)) );
break;
default:
break;
};
};
// set the new lists;
////////////////////////////////////
desc5.putReference( stringIDToTypeID( "null" ), ref1 );
desc5.putObject( stringIDToTypeID( "to" ), stringIDToTypeID( "layerEffects" ), effectsDescNew );
executeAction( stringIDToTypeID( "set" ), desc5, DialogModes.NO );
////////////////////////////////////
};
};
////////////////////////////////////
////// get list values //////
function evaluateList (aList) {
var listStuff = new Array;
for (var x = 0; x < aList.count; x++) {
var theType = aList.getType(x);
switch (theType) {
case DescValueType.ALIASTYPE:
listStuff.push( aList.getPath(x));
break;
case DescValueType.BOOLEANTYPE:
listStuff.push( aList.getBoolean(x));
break;
case DescValueType.CLASSTYPE:
listStuff.push( aList.getClass(x));
break;
case DescValueType.DOUBLETYPE:
listStuff.push( aList.getDouble(x));
break;
case DescValueType.ENUMERATEDTYPE:
listStuff.push( aList.getEnumerationValue(x));
break;
case DescValueType.INTEGERTYPE:
listStuff.push( aList.getInteger(x));
break;
case DescValueType.LISTTYPE:
listStuff.push( aList.getList(x));
break;
case DescValueType.OBJECTTYPE:
listStuff.push( (aList.getObjectValue(x)));
break;
case DescValueType.RAWTYPE:
listStuff.push( aList.getReference(x));
break;
case DescValueType.REFERENCETYPE:
listStuff.push( aList.getReference(x));
break;
case DescValueType.STRINGTYPE:
listStuff.push( aList.getString(x));
break;
case DescValueType.UNITDOUBLE:
listStuff.push( aList.getUnitDoubleValue(x));
break;
default:
break;
};
};
return listStuff
};
////// based on code by michael l hale //////
function checkDesc3 (theDesc, theAlert) {
var c = theDesc.count;
var str = new Array;
for(var i=0;i<c;i++){ //enumerate descriptor's keys
str.push([i, typeIDToStringID(theDesc.getKey(i)), theDesc.getType(theDesc.getKey(i)), getValues (theDesc, i)]);
};
if (theAlert == true) {alert("desc\n\n"+str.join("\n\n"));
return};
return str
};
////// check //////
function getValues (theDesc, theNumber) {
switch (theDesc.getType(theDesc.getKey(theNumber))) {
case DescValueType.BOOLEANTYPE:
return theDesc.getBoolean(theDesc.getKey(theNumber));
break;
case DescValueType.CLASSTYPE:
return theDesc.getClass(theDesc.getKey(theNumber));
break;
case DescValueType.DOUBLETYPE:
return theDesc.getDouble(theDesc.getKey(theNumber));
break;
case DescValueType.ENUMERATEDTYPE:
return (typeIDToStringID(theDesc.getEnumerationValue(theDesc.getKey(theNumber)))+"_"+typeIDToStringID(theDesc.getEnumerationType(theDesc.getKey(theNumber))));
break;
case DescValueType.INTEGERTYPE:
return theDesc.getInteger(theDesc.getKey(theNumber));
break;
case DescValueType.LISTTYPE:
return theDesc.getList(theDesc.getKey(theNumber));
break;
case DescValueType.OBJECTTYPE:
return (theDesc.getObjectValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getObjectType(theDesc.getKey(theNumber))));
break;
case DescValueType.REFERENCETYPE:
return theDesc.getReference(theDesc.getKey(theNumber));
break;
case DescValueType.STRINGTYPE:
return theDesc.getString(theDesc.getKey(theNumber));
break;
case DescValueType.UNITDOUBLE:
return (theDesc.getUnitDoubleValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getUnitDoubleType(theDesc.getKey(theNumber))));
break;
default:
break;
};
};
////// based on code by michael l hale //////
function checkList01 (theDesc, theAlert) {
var c = theDesc.count;
var str = new Array;
for(var i=0;i<c;i++){ //enumerate descriptor's keys
str.push([typeIDToStringID(theDesc.getKey(i)), getValues (theDesc, i)]);
if (theDesc.getType(theDesc.getKey(i)) == DescValueType.OBJECTTYPE) {
str.push(checkList01 (theDesc.getObjectValue(theDesc.getKey(i)), false).join("\n"))
};
};
if (theAlert == true) {alert("desc\n\n"+str.join("\n\n"));
return};
return str
};

 

_wckdTall_
Inspiring
March 27, 2026

This works perfectly, Thanks again!

Legend
April 2, 2018

Try

var r = new ActionReference();   

r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));

r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));

if (executeActionGet(r).hasKey(stringIDToTypeID("targetLayers")))

    {

    var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers"));

    var offset = 0;

    try { activeDocument.backgroundLayer } catch (e) { offset = 1; }

    for (var n = 0; n < list.count; n++)

        {

        var idx = list.getReference(n).getIndex();

        var r = new ActionReference();   

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerEffects"));

        r.putIndex(charIDToTypeID("Lyr "), idx+offset);

        if (!executeActionGet(r).hasKey(stringIDToTypeID("layerEffects"))) continue;

        var d = executeActionGet(r).getObjectValue(stringIDToTypeID("layerEffects"));

        for (var i = 0; i < d.count; i++)

            {

            var key = d.getKey(i);

            var type = d.getType(key);

   

            if (type == DescValueType.OBJECTTYPE)

                {

                var enabled = d.getObjectValue(key).getBoolean(stringIDToTypeID("enabled"));

   

                if (!enabled)

                    {

                    var d2 = new ActionDescriptor();

                    var r = new ActionReference();

                    r.putClass(d.getClass(key));

                    r.putIndex(charIDToTypeID("Lyr "), idx + offset);

                    d2.putReference(stringIDToTypeID("null"), r);

                    executeAction(stringIDToTypeID("disableSingleFX"), d2, DialogModes.NO);

                    }

       

                }

            }

        }

    }

else

    {

    alert("no selected layers")

    }

jonohunt
jonohuntAuthor
Known Participant
April 2, 2018

Thanks! I've tried it, but get the following error message:

- The command "Delete Layer Style" is not currently available.

Line: 40

->

executeAction(stringIDToTypeID("disableSinfleFX"),d2,DialogModes.NO);

Any idea how to fix that?

r-binCorrect answer
Legend
April 2, 2018

This can be due to layer protection. Try this variant.

var r = new ActionReference();     

r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));  

r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt")); 

 

if (executeActionGet(r).hasKey(stringIDToTypeID("targetLayers"))) 

    { 

    var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers")); 

 

    var offset = 0; 

    try { activeDocument.backgroundLayer } catch (e) { offset = 1; } 

    var unlock_flag = false;

    var lock = false;

    var del_cnt = 0;

 

    for (var n = 0; n < list.count; n++) 

        { 

        var idx = list.getReference(n).getIndex(); 

 

        var r = new ActionReference();     

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerEffects"));  

        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

 

        if (!executeActionGet(r).hasKey(stringIDToTypeID("layerEffects"))) continue; 

 

        var d = executeActionGet(r).getObjectValue(stringIDToTypeID("layerEffects")); 

        var r = new ActionReference();     

        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("layerLocking"));  

        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

        if (!unlock_flag) lock = executeActionGet(r).getObjectValue(stringIDToTypeID("layerLocking")).getBoolean(stringIDToTypeID("protectAll"));

        for (var i = 0; i < d.count; i++) 

            { 

            var key = d.getKey(i); 

            var type = d.getType(key); 

     

            if (type == DescValueType.OBJECTTYPE) 

                { 

                var enabled = d.getObjectValue(key).getBoolean(stringIDToTypeID("enabled")); 

     

                if (!enabled) 

                    { 

                    if (lock && !unlock_flag)

                        {

                        var d2 = new ActionDescriptor();

                        var d1 = new ActionDescriptor();

                        var d3 = new ActionDescriptor();

                        var r = new ActionReference();

                        r.putIndex(charIDToTypeID("Lyr "), idx+offset); 

                        d1.putReference( charIDToTypeID( "null" ), r );

                        d3.putBoolean( stringIDToTypeID( "protectAll" ), false);

                        d2.putObject( stringIDToTypeID( "layerLocking" ), stringIDToTypeID( "layerLocking" ), d3 );

           

                        d1.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "Lyr " ), d2 );

                        executeAction( charIDToTypeID( "setd" ), d1, DialogModes.NO );

                        unlock_flag = true;

                        }

                    var d2 = new ActionDescriptor(); 

                    var r = new ActionReference(); 

                    r.putClass(d.getClass(key)); 

                    r.putIndex(charIDToTypeID("Lyr "), idx + offset); 

                    d2.putReference(stringIDToTypeID("null"), r); 

                    executeAction(stringIDToTypeID("disableSingleFX"), d2, DialogModes.NO); 

                    ++del_cnt;

                    } 

         

                } 

            } 

        } 

    alert(del_cnt + " LayerEffects have been removed"); 

    } 

else 

    { 

    alert("no selected layers") 

    } 

Jarda Bereza
Inspiring
March 30, 2018

Check my scripts: Magic scripts for Photoshop

I have one for layer effects and one for smart filters. But it is for all layers in document. If you want skip some layers, you can lock them.

jonohunt
jonohuntAuthor
Known Participant
April 1, 2018

Thanks, I saw that

But really, I'm looking for a script that runs on the selected layers.

Jarda Bereza
Inspiring
April 1, 2018

You or somebody else could change my code. But I will not do it.