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

Custom script for renaming artboards, with multiple elements

Explorer ,
Jan 17, 2023 Jan 17, 2023

Copy link to clipboard

Copied

I've read many of the posts already with similar questions and help, but I'm not finding what I ultimately need, and first probably need to know if it is even possible. 

 

I have PSD with many artboards. Each artboard has a single layer where an image will be place. I need a script, or script/action combo, to rename each artboard to a name that contains 3 elements:

1- Web## (this will be consistent through every PSD I have and the artboards will already have this element in the name. Ex: Web01, Web02, Web03
2- The next element (xx) will be the same for each artboard within the PSD, but different for each of the other PSDs. Ex: Keyword_Size_SKU
This could be a single step of bringing the name string into each document and putting it somewhere for a script to access, perhaps the name of a dummy artboard at the top of the stack.
3- The last element (yy) would be unique for each artboard. This last part of the Artboard's name (aside from the exporting filetype) would be the exact same as the single layer's name that is on that artboard.

With the attached example, the resulting artboard names would be:
1- Web01_Keyword_Size_SKU_ImageAB1.jpg
2- Web02_Keyword_Size_SKU_ImageAB2.jpg
3- Web03_Keyword_Size_SKU_ImageAB3.jpg
4- Web04_Keyword_Size_SKU_ImageAB4.jpg
5- Web05_Keyword_Size_SKU_ImageAB5.jpg

Screenshot 2023-01-17 at 4.00.37 PM.png
Does this even sound possible?
Thank you, all!

TOPICS
Actions and scripting , macOS

Views

2.0K

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

Community Expert , Jan 21, 2023 Jan 21, 2023

An updated 1.3 version using the code from @jazz-y  to reverse the parent layerSet child layers array.

 

/*
Rename Artboards Using A Specific Text Pattern.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/custom-script-for-renaming-artboards-with-multiple-elements/td-p/13498536
v1.3, 22nd January 2023, Stephen Marsh
*/

#target photoshop

  (function () {

    // Check for open doc
    if (app.documents.length > 0) {

      // Set the Keyword_Size_SKU naming variable
      var B
...

Votes

Translate

Translate
Adobe
Community Expert ,
Jan 17, 2023 Jan 17, 2023

Copy link to clipboard

Copied

@RRowe – This should be "easy enough"... Do you know how to script and just need some pointers?

 

Edit:

 

1) Will Web## always be at the beginning of the layer group name? Will it always be followed by an underscore separator?

 

2) Would you be happy to enter in (xx) via a prompt when the script is first run? Do you need to run this script multiple times as new layer groups are added during the lifecycle of the PSD file, or is this only needed once per PSD?

 

3) With  (yy) I'm guessing that you wish the script to add the extension. Can this be taken by the script from the parent layer group name, or manually entered via a prompt? Is it consistent for each group, such as all JPG, but on a different document it may be all PNG etc?

 

It looks like you will also be using Adobe Generator - Generate Image Assets, is that correct?

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
Explorer ,
Jan 17, 2023 Jan 17, 2023

Copy link to clipboard

Copied

Happy to hear that it sounds possible! I do not script, and usually can find the scripts I need here. I do have a friend who is pretty good and has helped me before with scripts specifically intended to use with PS, even though he never write code for that personally. So if I were to reach out to him, do you have any pointers of the basic idea to tackle this, and are there PS-specific things he would need to know to get the code correct?

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 ,
Jan 17, 2023 Jan 17, 2023

Copy link to clipboard

Copied

I have edited my previous post with some questions. You have done a good job so far of explaining what you are after... I should be able to script this for you once I fully understand the process. 

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
Explorer ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@Stephen_A_MarshYou are just incredible. I ran the script as is and as far as I can tell, it's working just as needed! My answers in blue below:

1) Will Web## always be at the beginning of the layer group name? Will it always be followed by an underscore separator?

Yes, that will always be at the very front of the file name. I typically would always use an underscore after that, and that can be part of the file name to begin with or it can be added in with teh script, whichever you recommend. For now, I'll keep it as part of the existing name, pre script running.

2) Would you be happy to enter in (xx) via a prompt when the script is first run? Do you need to run this script multiple times as new layer groups are added during the lifecycle of the PSD file, or is this only needed once per PSD?
Actually, this works great. I hadn't thought about this being something I could add in with a prompt, but that works perfectly for how this process will happen.

Ideally this will only be run once, and we can stick to that if needed. I can see how this could get messy if it was run multiple times. But that brings up a question: Does the script target, like Find & Replace, aspects of the original file name? So if those elements weren't there, like if the script had already run once before, will it throw an error or just skip that layer/artboard?

If it targets with a Find&Replace, then I probably need to change the elements of the original Artboard name. Instead of "xx" I will use "Keyword-SKU", and instead of "yy" I will use "OG-FileName". It's possible one of the SKUs will include 

"xx" or "yy" and I can see that that could mess up a Find&Replace.

 

3) With  (yy) I'm guessing that you wish the script to add the extension. Can this be taken by the script from the parent layer group name, or manually entered via a prompt? Is it consistent for each group, such as all JPG, but on a different document it may be all PNG etc?
I had anticipated that this extension would be prepopulated in the existing artboard name. Each PSD will be exporting consistent file types. Some will be uncompressed and some will be compressed, so those could be in the existing artboard name and then pretty much just stay that way. Any one-off alterations could be done manually, as needed. And as for now, they will always be JPGs. If that is tough to work as described, this could also be done via prompt, but integrated into the PSD to begin with is ideal. To be more clear, we will have about 5-6 master PSDs with consistent filetypes, sizes, and compression that we make copy after copy of, so getting those set up manually with details like that will be no problem.

 

It looks like you will also be using Adobe Generator - Generate Image Assets, is that correct?
Correct.

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
Explorer ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@Stephen_A_Marsh I have tested this and have seen that it works even if there are multiple layers on the artboard. In the renaming, it uses the very top layer's name and puts that into the artboard's name. If that is the case, would it be possible to have it use the bottom layer's name? I could see test layers potentially being layed over images at some point, but still needing the name extracted to be the image name (bottom layer).

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 ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

quote

@Stephen_A_Marsh I have tested this and have seen that it works even if there are multiple layers on the artboard. In the renaming, it uses the very top layer's name and puts that into the artboard's name. If that is the case, would it be possible to have it use the bottom layer's name? I could see test layers potentially being layed over images at some point, but still needing the name extracted to be the image name (bottom layer).


By @RRowe



Yes, your example only had one layer :]

 

Can you please illustrate via a screenshot of a multi-layer artboard and clearly mark which layer is to be used? It isn't that your explanation is hard to follow, I just want to be sure with a visual.

 

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 ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@RRowe – Thanks for the replies, they don't really affect how I created the script:

 

1) The script uses the variable characters from the beginning of the line, up until the first underscore.

 

2) Good question, I haven't tested running a second time over the first time...

 

3) The extension is currently hard-coded into the script, so will always be JPG. It could capture the extension from the original artboard name if required.

 

 

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
Explorer ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@Stephen_A_Marsh 
1) I have tested running the script a 2nd time and it seems to work just fine. It simply just repeats the process and if things have changed, like a new photo replacing an old one on a layer, it updates the name of the artboard accordingly!
2) Capturing the extention from the original artboard name would be ideal. They will always be jpgs, but some of them will need that compression extension, like 50%. So that would be in the original artboard name already.
3) Attaching a screen shot of the multi-layer scenario I mentioned. Two layers on a single artboard. Top layer is text (SCREEN) and bottom layer is image (ImageTest). Running the script now, the artboard would inheret the layer name "SCREEN" into its name, resulting in "04_Rename-Test2_SCREEN.jpg". The desired name would always come from the image layer, which will always be at the bottom. The desired name after running the script would be "04_Rename-Test2_ImageTest.jpg". 

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 ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@RRowe – Try the following script, answers to my previous questions may be required to improve the results:

 

/*
Rename Artboards Using A Specific Text Pattern.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/custom-script-for-renaming-artboards-with-multiple-elements/td-p/13498536
v1.0, 18th January 2023, Stephen Marsh
*/

#target photoshop

  (function () {

    // Check for open doc
    if (app.documents.length > 0) {

      // Set the Keyword_Size_SKU naming variable
      var B = prompt("Enter the Keyword_Size_SKU info:", "Keyword_Size_SKU");
      // Test if cancel returns null, then terminate the script
      if (B === null) {
        //alert('Script cancelled!');
        return;
      }

      // Main script function for single history step
      function main() {

        /* var currentLayer = activeDocument.activeLayer; */
        // Set the variable for the original layer/s selection
        // by jazz-y
        // get selected layers count with layers ID
        var s2t = stringIDToTypeID;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
        r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
        var sel = executeActionGet(r).getList(p);

        // Loop forwards over top level layer sets
        for (var i = 0; i < activeDocument.layerSets.length; i++) {
          // Loop backwards over top level layer sets
          // for (var i = activeDocument.layerSets.length - 1; i >= 0; i--) {

          // Set the for loop variable as the active layer
          activeDocument.activeLayer = activeDocument.layerSets[i];

          // Conditional (redundant) check that the active layer is a layer set
          if (activeDocument.activeLayer.typename === "LayerSet") {

            // Set the remaining naming variables
            var A = activeDocument.activeLayer.name.replace(/(^.+?)(_.+)/, "$1");
            var C = activeDocument.activeLayer.layers[0].name;
            var D = ".jpg";

            // Rename the layer set
            activeDocument.activeLayer.name = A + "_" + B + "_" + C + D;
          }
        }

        /* activeDocument.activeLayer = currentLayer; */
        // Restore the original layer/s selection
        // by jazz-y
        // restore selection
        if (sel.count) {
          r = new ActionReference();
          for (var i = 0; i < sel.count; i++) {
            r.putIdentifier(s2t('layer'), sel.getReference(i).getIdentifier())
          }
          (d = new ActionDescriptor()).putReference(s2t('target'), r);
          executeAction(s2t('select'), d, DialogModes.NO);
        } else {
          (r = new ActionReference()).putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
          (d = new ActionDescriptor()).putReference(s2t('target'), r);
          executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
        }
      }

    } else {
      alert('A document must be open to use this script!');
    }

    // Single history step
    activeDocument.suspendHistory("Rename Artboards", "main()");

  }());

 

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
Guide ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

* an interesting fact (which I came across in one of the previous threads) - frame layers are also a group 🙂 Sometimes this can prevent the script from working correctly.

2023-01-19_01-03-17.png

alert (activeDocument.layerSets.length + '\n' + (activeDocument.activeLayer.typename === "LayerSet"))

 

2023-01-19_01-05-40.png

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 ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@jazz-y – Ah, "interesting" (as in an unexpected and unwanted wrinkle)!

 

Hopefully all is good if there are no frames used as top-level layers. Something to try to remember though. Is there another property that can be used to differentiate all of these layerSets?

 

Group = layerSet

Artboard = layerSet

Frame = layerSet

 

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
Guide ,
Jan 19, 2023 Jan 19, 2023

Copy link to clipboard

Copied

This is easy enough to do through AM:

var s2t = stringIDToTypeID,
    t2s = typeIDToStringID;
(r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
var len = executeActionGet(r).getInteger(p),
    result = [];
for (var i = 1; i <= len; i++) {
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
    r.putIndex(s2t('layer'), i);
    if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerKind'));
    r.putIndex(s2t('layer'), i);
    if (executeActionGet(r).getInteger(p) == 7) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('name'));
        r.putIndex(s2t('layer'), i);
        var title = executeActionGet(r).getString(p);
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
        r.putIndex(s2t('layer'), i);
        var id = executeActionGet(r).getInteger(p);
        var kind = '';
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('artboardEnabled'));
        r.putIndex(s2t('layer'), i);
        if (executeActionGet(r).hasKey(p) && executeActionGet(r).getBoolean(p)) kind = 'artboard';
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('framedGroup'));
        r.putIndex(s2t('layer'), i);
        if (executeActionGet(r).hasKey(p)) kind = 'frame layer'
        if (kind=='') kind = 'layer section'
        result.push('Layer "' + title + '" with id ' + id + ' is ' + kind)
    }
}
alert(result.join('\n'))

 

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

Copy link to clipboard

Copied

UPDATE - 23rd February 2023 (added for loop option):

UPDATE - 26th March 2024 (added a conditional check to account for the frame or frame content being active)

 

@jazz-y 

 

Your code was too complex for me to repurpose into the conditional checks that I wanted, however, I was able to extract key parts and plug them into other script code that suited my purpose.

 

I am open to suggestions for improving the code.

 

/* 
As Groups, Artboards & Frames are all considered as "layerSets" in DOM code, it takes AM code to truly determine the actual layerSet variant... 
Modified from a script by greless with hints from jazz-y!
v1.0, 11th February 2023, Stephen Marsh
*/

#target photoshop

if (activeDocument.activeLayer.typename === "LayerSet" && isGroup() === true) {
    alert("The layer is a Group!");
    // Do stuff
} else {
    alert("The layer isn't a Group...");
    // Do other stuff
}

function isGroup() {
    // modified from a script by greless with hints from jazz-y!
    // returns true or false
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
        var options = executeActionGet(r);
        return options.hasKey(stringIDToTypeID('layerSection')) && !options.hasKey(stringIDToTypeID('framedGroup')) && !options.hasKey(stringIDToTypeID('artboard')); // test for the required key
    } catch (e) {
        //alert(e);
    }
}

/*

// Loop over top level layers...

for (var i = 0; i < activeDocument.layers.length; i++) {
    try {
        activeDocument.activeLayer = activeDocument.layers[i];
        if (activeDocument.activeLayer.typename === "LayerSet" && isGroup() === true) {
            alert("The layer is a Group!");
            // Do stuff
        } else {
            alert("The layer isn't a Group...");
            // Do other stuff
        }
    } catch (e) {
        alert("Error!" + "\r" + e + ' ' + e.line);
    }

    function isGroup() {
        // modified from a script by greless with hints from jazz-y!
        // returns true or false
        try {
            var d = new ActionDescriptor();
            var r = new ActionReference();
            r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
            var options = executeActionGet(r);
            return options.hasKey(stringIDToTypeID('layerSection')) && !options.hasKey(stringIDToTypeID('framedGroup')) && !options.hasKey(stringIDToTypeID('artboard')); // test for the required key
        } catch (e) {
            //alert(e);
        }
    }
}

*/

 

 

 

/* 
As Groups, Artboards & Frames are all considered as "layerSets" in DOM code, it takes AM code to truly determine the actual layerSet variant... 
Modified from a script by greless with hints from jazz-y!
v1.0, 11th February 2023, Stephen Marsh
*/

#target photoshop

if (activeDocument.activeLayer.typename === "LayerSet" && isArtboard() === true) {
    alert("The layer is an Artboard!");
    // Do stuff
} else {
    alert("The layer isn't an Artboard...");
    // Do other stuff
}

function isArtboard() {
    // modified from a script by greless with hints from jazz-y!
    // returns true or false
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
        var options = executeActionGet(r);
        return options.hasKey(stringIDToTypeID('artboard')); // test for the required key
    } catch (e) {
        //alert(e);
    }
}

/*

// Loop over top level layers...

for (var i = 0; i < activeDocument.layers.length; i++) {
    try {
        activeDocument.activeLayer = activeDocument.layers[i];
        if (activeDocument.activeLayer.typename === "LayerSet" && isArtboard() === true) {
            alert("The layer is an Artboard!");
            // Do stuff
        } else {
            alert("The layer isn't an Artboard...");
            // Do other stuff
        }
    } catch (e) {
        alert("Error!" + "\r" + e + ' ' + e.line);
    }

    function isArtboard() {
        // modified from a script by greless with hints from jazz-y!
        // returns true or false
        try {
            var d = new ActionDescriptor();
            var r = new ActionReference();
            r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
            var options = executeActionGet(r);
            return options.hasKey(stringIDToTypeID('artboard')); // test for the required key
        } catch (e) {
            //alert(e);
        }
    }
}

*/

 

 

 

/* 
As Groups, Artboards & Frames are all considered as "layerSets" in DOM code, it takes AM code to truly determine the actual layerSet variant... 
Modified from a script by greless with hints from jazz-y!
v1.0, 11th February 2023, Stephen Marsh
v1.1, 26th March 2024 - Added a conditional check to account for the frame content being selected
https://community.adobe.com/t5/photoshop-ecosystem-discussions/custom-script-for-renaming-artboards-with-multiple-elements/m-p/13498536
*/

#target photoshop

if (app.activeDocument.activeLayer.parent.name != app.activeDocument.name) {
    app.activeDocument.activeLayer = app.activeDocument.activeLayer.parent;
    if (app.activeDocument.activeLayer.typename === "LayerSet" && isFrame() === true) {
        alert(app.activeDocument.activeLayer.name + "\r" + "The layer is a Frame!");
        // Do stuff
    }
} else if (app.activeDocument.activeLayer.typename === "LayerSet" && isFrame() === true) {
    alert(app.activeDocument.activeLayer.name + "\r" + "The layer is a Frame!");
    // Do stuff {
} else {
    alert(activeDocument.activeLayer.name + "\r" + "The layer isn't a Frame...");
    // Do other stuff
}

function isFrame() {
    // modified from a script by greless with hints from jazz-y!
    // returns true or false
    try {
        var d = new ActionDescriptor();
        var r = new ActionReference();
        r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
        var options = executeActionGet(r);
        return options.hasKey(stringIDToTypeID('framedGroup')); // test for the required key
    } catch (e) {
        //alert(e);
    }
}

/*

// Loop over top level layers...

for (var i = 0; i < activeDocument.layers.length; i++) {
    try {
        activeDocument.activeLayer = activeDocument.layers[i];
        if (activeDocument.activeLayer.typename === "LayerSet" && isFrame() === true) {
            alert(activeDocument.activeLayer.name + "\r" + "The layer is a Frame!");
            // Do stuff
        } else {
            alert(activeDocument.activeLayer.name + "\r" + "The layer isn't a Frame...");
            // Do other stuff
        }
    } catch (e) {
        alert("Error!" + "\r" + e + ' ' + e.line);
    }

    function isFrame() {
        // modified from a script by greless with hints from jazz-y!
        // returns true or false
        try {
            var d = new ActionDescriptor();
            var r = new ActionReference();
            r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
            var options = executeActionGet(r);
            return options.hasKey(stringIDToTypeID('framedGroup')); // test for the required key
        } catch (e) {
            alert("Error!" + "\r" + e + ' ' + e.line);
        }
    }
}

*/

/*

// Loop over top level layers...

for (var i = 0; i < activeDocument.layers.length; i++) {
    try {
        activeDocument.activeLayer = activeDocument.layers[i];
        if (activeDocument.activeLayer.typename === "LayerSet" && isFrame() === true) {
            alert(activeDocument.activeLayer.name + "\r" + "The layer is a Frame!");
            // Do stuff
        } else {
            alert(activeDocument.activeLayer.name + "\r" + "The layer isn't a Frame...");
            // Do other stuff
        }
    } catch (e) {
        alert("Error!" + "\r" + e + ' ' + e.line);
    }

    function isFrame() {
        // modified from a script by greless with hints from jazz-y!
        // returns true or false
        try {
            var d = new ActionDescriptor();
            var r = new ActionReference();
            r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
            var options = executeActionGet(r);
            return options.hasKey(stringIDToTypeID('framedGroup')); // test for the required key
        } catch (e) {
            alert("Error!" + "\r" + e + ' ' + e.line);
        }
    }
}

*/​

 

 

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

Copy link to clipboard

Copied

@jazz-y 

 

My initial tests with the three scripts posted above worked as expected with a check for a single active layerSet.

 

However, when used in a for loop, they didn't work.

 

It would be good to know if it is possible to use the check in a for loop over layers.

 

Update: 23rd February 2023, I have fixed the issue with the for loop!

 

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 ,
Jan 18, 2023 Jan 18, 2023

Copy link to clipboard

Copied

@RRowe – Try this updated 1.2 version:

 

* Extension for use with Generator/Image Assets is extracted from the original artboard name (not thoroughly tested)

 

* The back/last layer name of the layer within the parent artboard is now used rather than the first layer name

 

/*
Rename Artboards Using A Specific Text Pattern.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/custom-script-for-renaming-artboards-with-multiple-elements/td-p/13498536
v1.2, 20th January 2023, Stephen Marsh
*/

#target photoshop

  (function () {

    // Check for open doc
    if (app.documents.length > 0) {

      // Set the Keyword_Size_SKU naming variable
      var B = prompt("Enter the Keyword_Size_SKU info:", "Keyword_Size_SKU");
      // Test if cancel returns null, then terminate the script
      if (B === null) {
        //alert('Script cancelled!');
        return;
      }

      // Main script function for single history step
      function main() {

        // Set the initial layer visibility
        var currentLayersState = getLayersVisiblity();

        // Loop forwards over top level layer sets
        for (var i = 0; i < activeDocument.layerSets.length; i++) {
          // Loop backwards over top level layer sets
          // for (var i = activeDocument.layerSets.length - 1; i >= 0; i--) {

          // Set the for loop variable as the active layer
          activeDocument.activeLayer = activeDocument.layerSets[i];

          // Conditional (redundant) check that the active layer is a layer set
          if (activeDocument.activeLayer.typename === "LayerSet") {

            // Set the remaining naming variables
            var A = activeDocument.activeLayer.name.replace(/(^.+?)(_.+)/, "$1");
            if (activeDocument.activeLayer.typename === "LayerSet") {
              activeDocument.activeLayer = activeDocument.activeLayer.layers[activeDocument.activeLayer.layers.length - 1];
              var backLayerName = activeDocument.activeLayer.name;
              activeDocument.activeLayer = activeDocument.activeLayer.parent;
            }
            var C = backLayerName;
            var D = activeDocument.activeLayer.name.replace(/(^.+?)(\.[^\.]+$)/, "$2");

            // Rename the layer set
            activeDocument.activeLayer.name = A + "_" + B + "_" + C + D;
          }
        }

        // Restore the initial layer visibility
        setLayersVisiblity(currentLayersState);


        // Functions

        function getLayersVisiblity() {
          // by jazz-y
          var s2t = stringIDToTypeID,
            t2s = typeIDToStringID;
          (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
          r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
          var targetLayers = executeActionGet(r).getList(p),
            seletion = [],
            visiblity = {};
          for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
          (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
          r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
          var len = executeActionGet(r).getInteger(p);
          for (var i = 1; i <= len; i++) {
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
            r.putIndex(s2t('layer'), i);
            if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
            r.putIndex(s2t('layer'), i);
            var id = executeActionGet(r).getInteger(p);
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
            r.putIndex(s2t('layer'), i);
            var visible = executeActionGet(r).getBoolean(p);
            visiblity[id] = visible;
          }
          return {
            selection: seletion,
            visiblity: visiblity
          }
        }

        function setLayersVisiblity(layersStateObject) {
          // by jazz-y
          var s2t = stringIDToTypeID;
          for (var a in layersStateObject.visiblity) {
            makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
            (r = new ActionReference()).putIdentifier(s2t('layer'), a);
            (d = new ActionDescriptor()).putReference(s2t('target'), r);
            executeAction(s2t(makeVisible), d, DialogModes.NO);
          }
          if (layersStateObject.selection.length) {
            var r = new ActionReference()
            for (var i = 0; i < layersStateObject.selection.length; i++)
              r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
            (d = new ActionDescriptor()).putReference(s2t("target"), r);
            d.putBoolean(s2t("makeVisible"), false);
            executeAction(s2t("select"), d, DialogModes.NO);
          } else {
            (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
            (d = new ActionDescriptor()).putReference(s2t('target'), r);
            executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
          }
        }

      }

    } else {
      alert('A document must be open to use this script!');
    }

    // Single history step
    activeDocument.suspendHistory("Rename Layer Groups", "main()");

  }());

 

Note to other scripters:

 

I am not happy that I have to select the (variable length) back layer within the active layer set in order to set its name as a variable. As the child layers length is variable (2 or 20 child layers in the set), I can't get the last/back layer via an explicit absolute [index number]. Is there any AM code for this, or a way to do this via DOM, to get the relative name without actually selecting the layer?

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
Explorer ,
Jan 19, 2023 Jan 19, 2023

Copy link to clipboard

Copied

@Stephen_A_Marsh I have tested this code several ways, and it seems to be working great and as expected! I can rename if needed, it's pulling the name from the lowest layer as needed. It's great! There is an error that pops up at the end of the script running, but doesn't seem to be affecting anything. All processes run correctly and complete, but then the attached error. Considering everything is completed, the error shouldn't be an issue. It might as well just say "Script done and all is well!"

Stephen, I can't thank you enough for this! I am always so surprised and greatful for people's willingness to help withing communities like this.

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 ,
Jan 19, 2023 Jan 19, 2023

Copy link to clipboard

Copied

quote

All processes run correctly and complete, but then the attached error. 


By @RRowe


I have updated the code to a 1.2 version which should remove this error message.

 

quote

Stephen, I can't thank you enough for this! I am always so surprised and greatful for people's willingness to help withing communities like this.

 

You're welcome!

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
Guide ,
Jan 19, 2023 Jan 19, 2023

Copy link to clipboard

Copied


@Stephen_A_Marsh wrote:

I am not happy that I have to select the (variable length) back layer within the active layer set in order to set its name as a variable. As the child layers length is variable (2 or 20 child layers in the set), I can't get the last/back layer via an explicit absolute [index number]. Is there any AM code for this, or a way to do this via DOM, to get the relative name without actually selecting the layer?


 

not very elegant, but you can do it like this:

 

[].slice.call(activeDocument.activeLayer.layers).reverse()[0]

 

When I need to know the location of layers relative to groups, I usually use my getLayersCollection() AM function. It returns a DOM-like object with the document structure and the properties I specified. Further, this object can be easily and quickly parsed using a recursive function. Since indexing in the AM code is the opposite of DOM indexing, the first nested layer in each object will be the bottom one:

2023-01-19_16-26-51.png

2023-01-19_16-26-07.png

 

/**Get the full structure of document layers (including nested groups)
 * as an array of objects. Parameters that you need to specify yourself
 * (in the example, the script gets the name, id, type, visibility, three types of layer borders)
*/
#target photoshop
var o = getLayersCollection()

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 = {};
            {   /** get AM proprties here */
                properties.name = lr.getProperty('name', i, true)
                properties.artboard = lr.hasProperty('artboardEnabled', i, true) ? lr.getProperty('artboardEnabled', i, true) : false;
            }
            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.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
        return executeActionGet(r).hasKey(property)
    }
    this.descToObject = function (d) {
        var o = {}
        for (var i = 0; i < d.count; i++) {
            var k = d.getKey(i)
            o[t2s(k)] = getDescValue(d, k)
        }
        return o
    }
    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;
        };
    }
}

 

 

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

Copy link to clipboard

Copied

An updated 1.3 version using the code from @jazz-y  to reverse the parent layerSet child layers array.

 

/*
Rename Artboards Using A Specific Text Pattern.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/custom-script-for-renaming-artboards-with-multiple-elements/td-p/13498536
v1.3, 22nd January 2023, Stephen Marsh
*/

#target photoshop

  (function () {

    // Check for open doc
    if (app.documents.length > 0) {

      // Set the Keyword_Size_SKU naming variable
      var B = prompt("Enter the Keyword_Size_SKU info:", "Keyword_Size_SKU");
      // Test if cancel returns null, then terminate the script
      if (B === null) {
        //alert('Script cancelled!');
        return;
      }

      // Main script function for single history step
      function main() {

        // Set the initial layer visibility
        var currentLayersState = getLayersVisiblity();

        // Loop forwards over top level layer sets
        for (var i = 0; i < activeDocument.layerSets.length; i++) {
          // Loop backwards over top level layer sets
          // for (var i = activeDocument.layerSets.length - 1; i >= 0; i--) {

          // Set the for loop variable as the active layer
          activeDocument.activeLayer = activeDocument.layerSets[i];

          // Conditional (redundant) check that the active layer is a layer set
          if (activeDocument.activeLayer.typename === "LayerSet") {

            // Set the remaining naming variables
            var A = activeDocument.activeLayer.name.replace(/(^.+?)(_.+)/, "$1");
            var C = [].slice.call(activeDocument.activeLayer.layers).reverse()[0].toString().replace(/(^\[.+ )(.+)(\]$)/, "$2");
            var D = activeDocument.activeLayer.name.replace(/(^.+?)(\.[^\.]+$)/, "$2");

            // Rename the layer set
            activeDocument.activeLayer.name = A + "_" + B + "_" + C + D;
          }
        }

        // Restore the initial layer visibility
        setLayersVisiblity(currentLayersState);


        // Functions

        function getLayersVisiblity() {
          // by jazz-y
          var s2t = stringIDToTypeID,
            t2s = typeIDToStringID;
          (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
          r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
          var targetLayers = executeActionGet(r).getList(p),
            seletion = [],
            visiblity = {};
          for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
          (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
          r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
          var len = executeActionGet(r).getInteger(p);
          for (var i = 1; i <= len; i++) {
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
            r.putIndex(s2t('layer'), i);
            if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
            r.putIndex(s2t('layer'), i);
            var id = executeActionGet(r).getInteger(p);
            (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
            r.putIndex(s2t('layer'), i);
            var visible = executeActionGet(r).getBoolean(p);
            visiblity[id] = visible;
          }
          return {
            selection: seletion,
            visiblity: visiblity
          }
        }

        function setLayersVisiblity(layersStateObject) {
          // by jazz-y
          var s2t = stringIDToTypeID;
          for (var a in layersStateObject.visiblity) {
            makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
            (r = new ActionReference()).putIdentifier(s2t('layer'), a);
            (d = new ActionDescriptor()).putReference(s2t('target'), r);
            executeAction(s2t(makeVisible), d, DialogModes.NO);
          }
          if (layersStateObject.selection.length) {
            var r = new ActionReference()
            for (var i = 0; i < layersStateObject.selection.length; i++)
              r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
            (d = new ActionDescriptor()).putReference(s2t("target"), r);
            d.putBoolean(s2t("makeVisible"), false);
            executeAction(s2t("select"), d, DialogModes.NO);
          } else {
            (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
            (d = new ActionDescriptor()).putReference(s2t('target'), r);
            executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
          }
        }

      }

    } else {
      alert('A document must be open to use this script!');
    }

    // Single history step
    activeDocument.suspendHistory("Rename Layer Groups", "main()");

  }());

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
Explorer ,
Jan 24, 2023 Jan 24, 2023

Copy link to clipboard

Copied

Stephen,

I just got back into town and ran this new script. It's great! I really appreciate the help with getting this locked in. It's already blown my office away with time this is saving us.

Thank you again.

Reed

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 ,
Sep 14, 2023 Sep 14, 2023

Copy link to clipboard

Copied

Hi Stephen,

I'm looking for a similar script that can do find/replace on artboard names. Is this possible? Even better would be if there could be a dialogue box open when you run the script to enter the find replace fields so we don't have to adjust the code each time. I've tried mashing together different bits of code, but I don't know how to code so obviously nothing's worked so far!

Cheers,

Dave

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 ,
Sep 14, 2023 Sep 14, 2023

Copy link to clipboard

Copied

You could try the following:

 

https://github.com/Paul-Riggott/PS-Scripts/blob/master/Layer%20Name%20Edit.jsx

 

You can change the dialog colour from:

 

var myBrush = g.newBrush(g.BrushType.SOLID_COLOR, [0.99, 0.99, 0.99, 1]);

 

To:

 

var myBrush = g.newBrush(g.BrushType.THEME_COLOR, "appDialogBackground");

 

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 ,
Sep 14, 2023 Sep 14, 2023

Copy link to clipboard

Copied

LATEST

Amazing! Thank you so much.

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