Skip to main content
jonohunt
Known Participant
Mar 30, 2018 1:46 PM UTC
Answered

Script to remove hidden/unused Layer Effects?

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

r-binCorrect answer
Legend
Apr 2, 2018 5:11 PM UTC

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") 

    } 

17 replies

_wckdTall_
Inspiring
Mar 11, 2026 6:48 PM UTC

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.

Translate
c.pfaffenbichler
Community Expert
Community Expert
Mar 21, 2026 11:40 AM UTC
// 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
};

 

Translate
_wckdTall_
Inspiring
Mar 27, 2026 5:21 PM UTC

This works perfectly, Thanks again!

Translate
Legend
Apr 2, 2018 11:58 AM UTC

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")

    }

Translate
jonohunt
jonohuntAuthor
Known Participant
Apr 2, 2018 1:56 PM UTC

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?

Translate
r-binCorrect answer
Legend
Apr 2, 2018 5:11 PM UTC

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") 

    } 

Translate
Jarda Bereza
Inspiring
Mar 30, 2018 9:05 PM UTC

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.

Translate
jonohunt
jonohuntAuthor
Known Participant
Apr 1, 2018 7:50 PM UTC

Thanks, I saw that

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

Translate
Jarda Bereza
Inspiring
Apr 1, 2018 8:27 PM UTC

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

Translate