Skip to main content
Known Participant
January 16, 2023
Answered

Script to expand all groups not working if group is empty

  • January 16, 2023
  • 2 replies
  • 2673 views

Hey guys! I have this script that I found here in the community and I've already tested some others. They all close groups containing layers, but if the group is empty, the script stops.
Is there any way for this script to work even on empty groups? My client uses an automation and needs all groups open.
Thanks if anyone can help.

Ther script i am using is this:

// Expand ALL layer groups/sets
openAllLayerSets(app.activeDocument);

function openAllLayerSets(parent) {
    for (var setIndex = 0; setIndex < parent.layerSets.length; setIndex++) {
        app.activeDocument.activeLayer = parent.layerSets[setIndex].layers[0];
        openAllLayerSets(parent.layerSets[setIndex]);
    }
}

The error i get:

 

Correct answer jazz-y
quote

@Stephen Marsh, this is a recursive function. At the moment, saving the active layer and restoring the selection occurs every time it is called (for all nested groups), which seems redundant. You need to move these commands outside the function.

 

Thank you! You are of course correct. I wanted to keep it all in the function and didn't think about that!

 

I'll fix up the previous code and look into implementing your layer re-selection code.


1. Does not affect the visibility of layers

2. Expands all groups, including empty ones

3. Restores the selection of layers

4. Fast as possible

5. Not compatible with old versions of PS (seemingly less  CC 2017) due to the lack of properties 'hasBackgroundLayer' and 'targetLayersIDs' (can be adapted)

 

#target photoshop

activeDocument.suspendHistory('Expand all layerSets', 'openAllLayerSets()')

function openAllLayerSets() {
    var lr = new AM('layer'),
        doc = new AM('document'),
        currentSelection = doc.getProperty('targetLayersIDs'),
        layers = expandGroups(getLayersCollection());
    if (layers.length) {
        doc.selectLayers(layers)
        doc.deleteLayers(layers)
    }
    if (currentSelection.count) {
        var s = [];
        for (var i = 0; i < currentSelection.count; i++)
            s.push(currentSelection.getReference(i).getIdentifier())
        doc.selectLayers(s)
    } else doc.selectNoLayers()
    function expandGroups(layers, toDelete) {
        toDelete = toDelete ? toDelete : [];
        for (var a in layers) {
            if (layers[a].layerKind == 7) {
                if (layers[a].length) {
                    lr.selectLayers([layers[a][0].id])
                    expandGroups(layers[a], toDelete)
                }
                else {
                    lr.add()
                    lr.moveLayer(lr.getProperty('itemIndex', layers[a].id) - 2)
                    toDelete.push(lr.getProperty('layerID'))
                }
            }
        }
        return toDelete
    }
    function getLayersCollection() {
        var doc = new AM('document'),
            lr = new AM('layer'),
            indexFrom = doc.getProperty('hasBackgroundLayer') ? 0 : 1,
            indexTo = doc.getProperty('numberOfLayers');
        return layersCollection(indexFrom, indexTo)
        function layersCollection(from, to, parentItem, group) {
            parentItem = parentItem ? parentItem : [];
            for (var i = from; i <= to; i++) {
                var layerSection = lr.getProperty('layerSection', i, true).value;
                if (layerSection == 'layerSectionEnd') {
                    i = layersCollection(i + 1, to, [], parentItem)
                    continue;
                }
                var properties = {};
                properties.id = lr.getProperty('layerID', i, true)
                properties.visible = lr.getProperty('visible', i, true)
                properties.layerKind = lr.getProperty('layerKind', i, true)
                  if (layerSection == 'layerSectionStart') {
                    for (o in properties) { parentItem[o] = properties[o] }
                    group.push(parentItem);
                    return i;
                } else {
                    parentItem.push(properties)
                }
            }
            return parentItem
        }
    }
    function AM(target, order) {
        var s2t = stringIDToTypeID,
            t2s = typeIDToStringID;
        target = target ? s2t(target) : null;
        this.getProperty = function (property, id, idxMode) {
            property = s2t(property);
            (r = new ActionReference()).putProperty(s2t('property'), property);
            id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
                r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
            return getDescValue(executeActionGet(r), property)
        }
        this.selectLayers = function (IDList) {
            var r = new ActionReference()
            for (var i = 0; i < IDList.length; i++) {
                r.putIdentifier(s2t("layer"), IDList[i])
            }
            (d = new ActionDescriptor()).putReference(s2t("target"), r)
            d.putBoolean(s2t("makeVisible"), false)
            executeAction(s2t("select"), d, DialogModes.NO)
        }
        this.add = function () {
            (r = new ActionReference()).putClass(target);
            (d = new ActionDescriptor()).putReference(s2t("null"), r);
            executeAction(s2t("make"), d, DialogModes.NO);
        }
        this.moveLayer = function (to) {
            (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
            (d = new ActionDescriptor()).putReference(s2t('null'), r);
            (r1 = new ActionReference()).putIndex(s2t('layer'), to);
            d.putReference(s2t('to'), r1);
            executeAction(s2t('move'), d, DialogModes.NO);
        }
        this.selectNoLayers = function () {
            (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
            (d = new ActionDescriptor()).putReference(s2t('target'), r);
            executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
        }
        this.deleteLayers = function (IDList) {
            var r = new ActionReference()
            for (var i = 0; i < IDList.length; i++) {
                r.putIdentifier(s2t("layer"), IDList[i])
            }
            (d = new ActionDescriptor()).putReference(s2t("target"), r)
            executeAction(s2t("delete"), d, DialogModes.NO)
        }
        function getDescValue(d, p) {
            switch (d.getType(p)) {
                case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
                case DescValueType.LISTTYPE: return d.getList(p);
                case DescValueType.REFERENCETYPE: return d.getReference(p);
                case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
                case DescValueType.STRINGTYPE: return d.getString(p);
                case DescValueType.INTEGERTYPE: return d.getInteger(p);
                case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
                case DescValueType.DOUBLETYPE: return d.getDouble(p);
                case DescValueType.ALIASTYPE: return d.getPath(p);
                case DescValueType.CLASSTYPE: return d.getClass(p);
                case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
                case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
                default: break;
            };
        }
    }
}

 

 

2 replies

Legend
January 16, 2023

 

Expands even empty groups.

openAllLayerSets(app.activeDocument);

function openAllLayerSets(parent) {
    for (var setIndex = 0; setIndex < parent.layerSets.length; setIndex++) {
        if (parent.layerSets[setIndex].layers.length) {
            app.activeDocument.activeLayer = parent.layerSets[setIndex].layers[0];
            openAllLayerSets(parent.layerSets[setIndex]);
        } else {
            parent.layerSets[setIndex].artLayers.add()
            app.activeDocument.activeLayer = parent.layerSets[setIndex]
            openAllLayerSets(parent.layerSets[setIndex]);
            parent.layerSets[setIndex].layers[0].remove()
        }
    };
};

If this is not necessary, then it is better to heed the advice of the @c.pfaffenbichler 

rrprecAuthor
Known Participant
January 16, 2023

Worked perfectly, Thank @jazz-y 

c.pfaffenbichler
Community Expert
Community Expert
January 16, 2023

The easy way would be wrapping the affected part in a try-clause.