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

Script to merge all layers with same certain names

New Here ,
Feb 14, 2023 Feb 14, 2023

Copy link to clipboard

Copied

Could someone help me with a script that will merge all layers with the same name, but only for certain hard coded names?

 

For example a file might contain 20 layers named "layerA", 30 layers named "layerB" and 40 layers named "layerC" > but only "layerA" and "layerB" should be merged, not "layerC". Its fine if this is hard coded into the script.

 

The big issue is that the script should iterate through all layers in the document only once, since my document has 10k layers iterating through all layers for each different name is too slow.

 

Is there a way to iterate only once through the document and use that iteration to create a dictionary that contains all groups of layers with the same name? This would then establish O(1) access for a given name, and I could then hard code a bunch of names that I want to merge.

 

Could someone help me code this? I am at a loss with the adobe script language, thanks in advance!

TOPICS
Actions and scripting

Views

3.5K

Translate

Translate

Report

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

correct answers 1 Correct answer

People's Champ , Feb 22, 2023 Feb 22, 2023
 

because I have 10k layers and it takes too long to do that

By jack284003085p35

 

How did you manage to create 10k layers?

When the number of layers is more than 8000, problems begin with the file, not to mention the fact that adding new layers manually will not work.

Try this script. I would like to see your timings.

It won't be possible to do it faster.

 

var layers = get_layers();

merge_layers(layers, "Layer 1");
merge_layers(layers, "Layer 1 copy");

function get_layers()
    {
    try {
      
...

Votes

Translate

Translate
Adobe
Community Expert ,
Feb 21, 2023 Feb 21, 2023

Copy link to clipboard

Copied

Please provide a clear description of the process and a sample file (feel free to downsample it drastically). 

How many groups of identically named Layers should be merged, what are the actual target-names, …? 

Votes

Translate

Translate

Report

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
New Here ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

i think I have it pretty well described in the post.

 

i want a script that I can hardcode something like:

 

var string = "layerA"

//code to merge all layers with name of string

 

result after running the script, all the layers that were named "layerA" are now merged into a single layer named "layerA".

 

BUT THERE CAN BE NO ITERATION, no for loop going over every single layer in the file to check if its named "layerA" ( because I have 10k layers and it takes too long to do that)

 

Maybe one iteration once to gather IDs of all layers, and then save that to a file that can be accessed to directly get the layers as if they were in an array, a surgical search instead of a brute force iteration everytime i want to merge a different name.

 

 

maybe its not possible

Votes

Translate

Translate

Report

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 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied


BUT THERE CAN BE NO ITERATION, no for loop going over every single layer in the file to check if its named "layerA" ( because I have 10k layers and it takes too long to do that)

What is that supposed to mean? 

How could you check the Layers’ names other than by checking the Layers’ names? 

 

Have you tested the AM code from your thread about selecting identically named layers yet? 

Votes

Translate

Translate

Report

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
New Here ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

are you by chance familiar with c# and dictionaries?

 

for example in c# if you can create a dictionary of hashset and doing something like dictionary[layerA] would instantly give a hashset that contains all the layers named "layerA" without iterating anything.

 

Of course I would have to first iterate once over the whole document to create such a dictionary that neatly groups layers like this for fast access, but after that dictionary is compiled I would never have to iterate again unless the document is changed

Votes

Translate

Translate

Report

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 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

I am not familiar with c#. 

 

But the image would be changed when you merge Layers so the dictionary would need amending because it would otherwise contain invalid entries, would it not? 

 

And again: 

Have you tested the AM code from your thread about selecting identically named layers yet? 

Likes

 

Votes

Translate

Translate

Report

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
People's Champ ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

 

because I have 10k layers and it takes too long to do that

By jack284003085p35

 

How did you manage to create 10k layers?

When the number of layers is more than 8000, problems begin with the file, not to mention the fact that adding new layers manually will not work.

Try this script. I would like to see your timings.

It won't be possible to do it faster.

 

var layers = get_layers();

merge_layers(layers, "Layer 1");
merge_layers(layers, "Layer 1 copy");

function get_layers()
    {
    try {
        $.hiresTimer;

        var layers = new Array();

        var r = new ActionReference();
        r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("count"));
        r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
        var count = executeActionGet(r).getInteger(stringIDToTypeID("count"));
        var n = 0; 
        if (!app.activeDocument.layers[app.activeDocument.layers.length-1].isBackgroundLayer) { n = 1; ++count; }

        for (var i = count-1; i >= n; i--)
            {
            var r = new ActionReference();
            r.putIndex(stringIDToTypeID("layer"), i);
            var d = executeActionGet(r);

            layers.push({id:d.getInteger(stringIDToTypeID("layerID")), name:d.getString(stringIDToTypeID("name"))});
            }

        alert("Scanned " + count + " layers in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");

        return layers;
        }
    catch (e) { alert(e); throw(e); }
    }

function merge_layers(layers, name)
    {
    try {
        $.hiresTimer;

        var len = layers.length;

        var cnt = 0;

        var r = new ActionReference();

        for (var i = 0; i < len; i++)
            {
            if (layers[i].name == name) { r.putIdentifier(stringIDToTypeID("layer"), layers[i].id); ++cnt; }
            }

        var d = new ActionDescriptor();
        d.putReference(stringIDToTypeID("null"), r);
        d.putBoolean(stringIDToTypeID("makeVisible"), false);
        executeAction(stringIDToTypeID("select"), d, DialogModes.NO); 

        alert("Selected " + cnt + " \"" + name + "\" in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");

        $.hiresTimer;

        executeAction(stringIDToTypeID("mergeLayersNew"), undefined, DialogModes.NO);

        alert("Merged " + cnt + " \"" + name + "\" in " + ($.hiresTimer/1000000).toFixed(2) + " seconds", "Timer");
        }
    catch (e) { alert(e); throw(e); }
    }

 

 

Votes

Translate

Translate

Report

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
People's Champ ,
Feb 23, 2023 Feb 23, 2023

Copy link to clipboard

Copied

LATEST
Replace the line 

 

if (!app.activeDocument.layers[app.activeDocument.layers.length-1].isBackgroundLayer) { n = 1; ++count; }

 

with

 

try { app.activeDocument.backgroundLayer; } catch(e) { n = 1; ++count; }

 

With a large number of layers, it works out extremely slowly.
 

Votes

Translate

Translate

Report

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 21, 2023 Feb 21, 2023

Copy link to clipboard

Copied

The layer name filter is often useful, which is the manual equivalent of scripting and the manual steps are not that taxing.

 

layer-name-filter.pngexpand image

Votes

Translate

Translate

Report

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
New Here ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

thanks, this of course solves the problem if i wanted to do it manually, but i want to automate it

Votes

Translate

Translate

Report

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 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

quote

thanks, this of course solves the problem if i wanted to do it manually, but i want to automate it


By jack284003085p35

 

You only mentioned the need to do this for 2 sets of named layers.

 

I understand, however, there is a cost/benefit to this.

 

It would take approx. 1 minute to do this manually. The manual steps are not onerous. Multiply this however many documents need to be processed.

 

Compared to the time spent by a volunteer developing the script.

Votes

Translate

Translate

Report

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
People's Champ ,
Feb 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

This works for LayerA and LayerB, but fails for LayerA and LayerAB.

Votes

Translate

Translate

Report

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 22, 2023 Feb 22, 2023

Copy link to clipboard

Copied

quote

This works for LayerA and LayerB, but fails for LayerA and LayerAB.


By r-bin

 

Just as well, the OP only has LayerA, LayerB and LayerC then! :]

 

All joking aside, there are indeed limitations to the native feature as you describe. 

 

Don't get me wrong, I'm all for a script if somebody has the time and knowledge to make it.

Votes

Translate

Translate

Report

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