Copy link to clipboard
Copied
Hi, I'm trying to write a script to search and merge layers and groups by matching sequence numbers, then merge the groups and set the group name
played with chatgpt, but since I have little knowledge in javascript, nothing works =((
given:
layers and groups named:
"step_n_n"
"mask_n_n"
"back_n_n"
n = sequence number
task:
group layers and groups with similar serial numbers and name the group "[slot] step-n-n"
 
That's what chatgpt suggested 😃
function findSimilarStepNums() {
var stepLayers = app.activeDocument.layers;
varstepNums = [];
// Search for all layers with a name containing "step"
for (var i = 0; i < stepLayers.length; i++) {
if (stepLayers[i].name.indexOf("step") !== -1) {
// Extract the number from the layer name and add it to the array
var num = parseInt(stepLayers[i].name.match(/\d+/)[0]);
stepNums.push(num);
}
}
// Search for duplicate numbers
var similarNums = [];
for (var j = 0; j < stepNums.length; j++) {
for (var k = j + 1; k < stepNums.length; k++) {
if (stepNums[j] === stepNums[k]) {
similarNums.push(stepNums[j]);
break;
}
}
}
// Output found duplicate numbers
if (similarNums.length > 0) {
alert("Found similar sequence numbers for layers named 'step': " + similarNums.join(", "));
} else {
alert("Similar sequence numbers were not found for layers named 'step'.");
}
// Combining layers into a group and setting a name
var slotGroup = app.activeDocument.layerSets.add();
slotGroup.name = "[slot] step-" + (stepNums.length + 1);
for (var l = 0; l < stepLayers.length; l++) {
if (stepLayers[l].name.indexOf("step") !== -1) {
stepLayers[l].move(slotGroup, ElementPlacement.INSIDE);
}
}
}
Quite frankly I think you may want to work on your manners.
// select selected layers the name of which ends in "_xx_xx" and group them in groups ending in the same numbers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectSelectedLayersByNames([/_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], fa
...
Copy link to clipboard
Copied
Copy link to clipboard
Copied
something goes wrong, throws an error
// Create a function to compare sequence numbers
function compareNumbers(a, b) {
// Extract serial numbers from layer names
var aNum = parseInt(a.name.match(/_(\d+)_(\d+)/)[2]);
var bNum = parseInt(b.name.match(/_(\d+)_(\d+)/)[2]);
// Compare numbers and return the result
return aNum - bNum;
}
// Create an array from all layers in the document
var layers = doc.layers;
// Filter layers by given patterns and create new arrays
var stepLayers = layers.filter(function(layer) {
return layer.name.match(/^step_\d+_\d+$/);
});
var maskLayers = layers.filter(function(layer) {
return layer.name.match(/^mask_\d+_\d+$/);
});
var backLayers = layers.filter(function(layer) {
return layer.name.match(/^back_\d+_\d+$/);
});
// Sort arrays by serial numbers
stepLayers.sort(compareNumbers);
maskLayers.sort(compareNumbers);
backLayers.sort(compareNumbers);
// Create groups for layers
var stepGroup = doc.layerSets.add();
stepGroup.name = "[slot] step-" + stepLayers[0].name.match(/_(\d+)_(\d+)/)[1];
// Move the layers to their respective groups
for (var i = 0; i < stepLayers.length; i++) {
stepLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < maskLayers.length; i++) {
maskLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < backLayers.length; i++) {
backLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
Copy link to clipboard
Copied
If you don’t define the variable »doc« then referring to it to define an Array of Layers cannot work.
Copy link to clipboard
Copied
error appeared elsewhere
// Create a function to compare sequence numbers
function compareNumbers(a, b) {
// Extract serial numbers from layer names
var aNum = parseInt(a.name.match(/_(\d+)_(\d+)/)[2]);
var bNum = parseInt(b.name.match(/_(\d+)_(\d+)/)[2]);
// Compare numbers and return the result
return aNum - bNum;
}
// Create an array from all layers in the document
var doc = app.activeDocument;
var layers = doc.layers;
// Filter layers by given patterns and create new arrays
var stepLayers = layers.filter(function(layer) {
return layer.name.match(/^step_\d+_\d+$/);
});
var maskLayers = layers.filter(function(layer) {
return layer.name.match(/^mask_\d+_\d+$/);
});
var backLayers = layers.filter(function(layer) {
return layer.name.match(/^back_\d+_\d+$/);
});
// Sort arrays by serial numbers
stepLayers.sort(compareNumbers);
maskLayers.sort(compareNumbers);
backLayers.sort(compareNumbers);
// Create groups for layers
var stepGroup = doc.layerSets.add();
stepGroup.name = "[slot] step-" + stepLayers[0].name.match(/-(\d+)-(\d+)/)[1];
// Move the layers to their respective groups
for (var i = 0; i < stepLayers.length; i++) {
stepLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < maskLayers.length; i++) {
maskLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < backLayers.length; i++) {
backLayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
Copy link to clipboard
Copied
JavaScript/ExtendScript is case sensitive:
steplayers
vs
stepLayers
Copy link to clipboard
Copied
changed L to lowercase, the error did not go away =(
// Create a function to compare sequence numbers
function compareNumbers(a, b) {
// Extract serial numbers from layer names
var aNum = parseInt(a.name.match(/_(\d+)_(\d+)/)[2]);
var bNum = parseInt(b.name.match(/_(\d+)_(\d+)/)[2]);
// Compare numbers and return the result
return aNum - bNum;
}
// Create an array from all layers in the document
var doc = app.activeDocument;
var layers = doc.layers;
// Filter layers by given patterns and create new arrays
var steplayers = layers.filter(function(layer) {
});
var steplayers = layers.filter(function(layer) {
return layer.name.match(/^step_\d+_\d+$/);
});
var masklayers = layers.filter(function(layer) {
return layer.name.match(/^mask_\d+_\d+$/);
});
var backlayers = layers.filter(function(layer) {
return layer.name.match(/^back_\d+_\d+$/);
});
// Sort arrays by serial numbers
steplayers.sort(compareNumbers);
masklayers.sort(compareNumbers);
backlayers.sort(compareNumbers);
// Create groups for layers
var stepGroup = doc.layerSets.add();
stepGroup.name = "[slot] step-" + stepLayers[0].name.match(/-(\d+)-(\d+)/)[1];
// Move the layers to their respective groups
for (var i = 0; i < steplayers.length; i++) {
steplayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < masklayers.length; i++) {
masklayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
for (var i = 0; i < backlayers.length; i++) {
backlayers[i].move(stepGroup, ElementPlacement.PLACEATEND);
}
Copy link to clipboard
Copied
Again: Two opening brackets with only one closing bracket cannot work.
Copy link to clipboard
Copied
sorry, can't find that bracket
Copy link to clipboard
Copied
sorry, can't find that bracket
By @Max_red_cat
The alert tells you which line the missing bracket is in, doesn’t it?
Edit: opening bracket: (
closing bracket: )
square brackets: []
curly brackets: {}
Copy link to clipboard
Copied
Two opening brackets and one closing one cannot work.
Is that more worthless ChatGPT-code?
Copy link to clipboard
Copied
Sorry, mistake on my part.
Copy link to clipboard
Copied
You can try this.
// select layers the name of which ends in "_xx_xx";
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectLayersByNames([/_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers ("stuff_"+String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// collect layers and/or groups with certain name, 0 layers, 1 groups, 2 both //////
function collectLayersByNames (theNames, layersOrGroups) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
var theCheck = false;
switch (Number(layersOrGroups)) {
case 0:
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart") {theCheck = true}
break;
case 1:
if (layerSet == "layerSectionStart") {theCheck = true}
break;
default:
if (layerSet != "layerSectionEnd") {theCheck = true}
break;
};
if (theCheck == true && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < theLayers.length; y++) {
if (theNumbers == String(theLayers[y][0][0].match(theNames[x]))) {
theLayers[y].push([theName, theIndex, theID]);
theCheck = true;
};
};
if (theCheck == false) {
theLayers.push([[theName, theIndex, theID]])
}
}
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
oh cool!
I slightly corrected the search filter by adding (mask|back|step), so I got rid of the accidental hit of other layers with numbering
but I don't know how to fix the following problem.
now each layer is placed in its own group, but all 3 (mask, back, step) should have a group and the numbering of the new group is now "_", but you need "-"
I am attaching the screenshot and the corrected code, I hope it helps)
// select layers the name of which ends in "_xx_xx";
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectLayersByNames([/(mask|back|step)_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers ("step"+String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// collect layers and/or groups with certain name, 0 layers, 1 groups, 2 both //////
function collectLayersByNames (theNames, layersOrGroups) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
var theCheck = false;
switch (Number(layersOrGroups)) {
case 0:
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart") {theCheck = true}
break;
case 1:
if (layerSet == "layerSectionStart") {theCheck = true}
break;
default:
if (layerSet != "layerSectionEnd") {theCheck = true}
break;
};
if (theCheck == true && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < theLayers.length; y++) {
if (theNumbers == String(theLayers[y][0][0].match(theNames[x]))) {
theLayers[y].push([theName, theIndex, theID]);
theCheck = true;
};
};
if (theCheck == false) {
theLayers.push([[theName, theIndex, theID]])
}
}
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
The Script I posted collected the Layers of the same »end-numbers« (»_xx_xx«) in Arrays in the returned Array.
You changed that so that the other name parts (»step« etc.) are included in the match and therefore the Array does not collect the Layers of corresponding numbers anymore.
I would recommend to
• either change the regExp for the collect-function back to the previous state and include a check for the other name parts in the for-clause
for (var d = 0; d < theLayers.length; d++) {
• or change the collect-function to do two separate matches based on two distinct arguments (the words and the numbering).
Maybe someone else can provide a more efficient approach, though.
Copy link to clipboard
Copied
@Stephen Marsh can you help me figure this out?
Copy link to clipboard
Copied
@Stephen Marsh can you help me figure this out?
By @Max_red_cat
This is a little advanced for me, I'm glad that @c.pfaffenbichler could solve the issue!
Copy link to clipboard
Copied
You may have used anbother approach but I trust you could have achieved the intended result anyway.
Copy link to clipboard
Copied
Found a way to replace the "_" sign with "-":
"groupSelectedLayers("[slot] step" + String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)).replace(/_/g, "-"));"
But with the rest it is more difficult, I see 2 ways to solve it:
1. if you remove from sorting (mask|back|step), then you need the script to apply only to selected layers and groups
2. how to fix the method (mask|back|step), but I don't know how))
// select layers the name of which ends in "_xx_xx";
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectLayersByNames([/_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers("[slot] step" + String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)).replace(/_/g, "-"));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// collect layers and/or groups with certain name, 0 layers, 1 groups, 2 both //////
function collectLayersByNames (theNames, layersOrGroups) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
var theCheck = false;
switch (Number(layersOrGroups)) {
case 0:
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart") {theCheck = true}
break;
case 1:
if (layerSet == "layerSectionStart") {theCheck = true}
break;
default:
if (layerSet != "layerSectionEnd") {theCheck = true}
break;
};
if (theCheck == true && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < theLayers.length; y++) {
if (theNumbers == String(theLayers[y][0][0].match(theNames[x]))) {
theLayers[y].push([theName, theIndex, theID]);
theCheck = true;
};
};
if (theCheck == false) {
theLayers.push([[theName, theIndex, theID]])
}
}
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
// select layers the name of which ends in "_xx_xx", start with some other words and group them in groups eending in the same numbers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectLayersByNames([/_\d{1,2}_\d{1,2}$/], /^(mask|back|step)/, 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers ("step"+String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// collect layers and/or groups with certain name, 0 layers, 1 groups, 2 both //////
function collectLayersByNames (theNames, theNames2, layersOrGroups) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
var theCheck = false;
switch (Number(layersOrGroups)) {
case 0:
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart") {theCheck = true}
break;
case 1:
if (layerSet == "layerSectionStart") {theCheck = true}
break;
default:
if (layerSet != "layerSectionEnd") {theCheck = true}
break;
};
if (theCheck == true && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// check name;
var theName2 = theName.match(theNames2);
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null && theName2 != null) {
var theCheck = false;
for (var y = 0; y < theLayers.length; y++) {
if (theNumbers == String(theLayers[y][0][0].match(theNames[x]))) {
theLayers[y].push([theName, theIndex, theID]);
theCheck = true;
};
};
if (theCheck == false) {
theLayers.push([[theName, theIndex, theID]])
}
}
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
cool, but I forgot about some nuances, sorry
Can you change this script so that it does not apply the action to the entire document, but only to the selected layers?...I think this will be the perfect way for the project 😃
// select layers the name of which ends in "_xx_xx";
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectLayersByNames([/_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers("[slot] step" + String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)).replace(/_/g, "-"));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// collect layers and/or groups with certain name, 0 layers, 1 groups, 2 both //////
function collectLayersByNames (theNames, layersOrGroups) {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
var theCheck = false;
switch (Number(layersOrGroups)) {
case 0:
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart") {theCheck = true}
break;
case 1:
if (layerSet == "layerSectionStart") {theCheck = true}
break;
default:
if (layerSet != "layerSectionEnd") {theCheck = true}
break;
};
if (theCheck == true && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < theLayers.length; y++) {
if (theNumbers == String(theLayers[y][0][0].match(theNames[x]))) {
theLayers[y].push([theName, theIndex, theID]);
theCheck = true;
};
};
if (theCheck == false) {
theLayers.push([[theName, theIndex, theID]])
}
}
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
Quite frankly I think you may want to work on your manners.
// select selected layers the name of which ends in "_xx_xx" and group them in groups ending in the same numbers;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
// search layers with regexp;
var theLayers = collectSelectedLayersByNames([/_\d{1,2}_\d{1,2}$/], 2);
// process layers;
if (theLayers.length > 0) {
for (var d = 0; d < theLayers.length; d++) {
selectLayerByID(theLayers[d][0][2], false);
for (var e = 1; e < theLayers[d].length; e++) {
selectLayerByID(theLayers[d][e][2], true)
};
// group the active layer;
groupSelectedLayers("[slot] step" + String(theLayers[d][0][0].match(/_\d{1,2}_\d{1,2}$/)).replace(/_/g, "-"));
};
} else {alert ("no such layer")}
};
////////////////////////////////////
////// based on code by mike hale and paul riggott //////
function selectLayerByID(theID,add){
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), theID);
var desc = new ActionDescriptor();
desc.putReference(charIDToTypeID("null"), ref );
if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
try{
executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
////// collect selected layers matching names //////
function collectSelectedLayersByNames (theNames) {
// get selected layers;
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var desc = executeActionGet(ref);
if (desc.getBoolean(stringIDToTypeID("hasBackgroundLayer")) == true) {var theAdd =0}
else {var theAdd = 1};
if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
var c = desc.count;
var selectedLayers = new Array();
// run through selected layers;
for(var i=0;i<c;i++){
var theIndex = desc.getReference( i ).getIndex()+theAdd;
// get id for layers;
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID("Lyr "), theIndex );
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
var thisIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theIdentifier = layerDesc.getInteger(stringIDToTypeID ("layerID"));
////////////////////////////////////
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < selectedLayers.length; y++) {
if (theNumbers == String(selectedLayers[y][0][0].match(theNames[x]))) {
selectedLayers[y].push([theName, thisIndex, theIdentifier]);
theCheck = true;
};
};
if (theCheck == false) {
selectedLayers.push([[theName, thisIndex, theIdentifier]])
}
}
};
////////////////////////////////////
} catch (e) {};
};
// if only one:
}else{
alert ("only one layer selected");
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var layerDesc = executeActionGet(ref);
try {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var thisIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theIdentifier = layerDesc.getInteger(stringIDToTypeID ("layerID"));
////////////////////////////////////
// check name;
for (var x = 0; x < theNames.length; x++) {
var theNumbers = theName.match(theNames[x]);
if (theNumbers != null) {
var theCheck = false;
for (var y = 0; y < selectedLayers.length; y++) {
if (theNumbers == String(selectedLayers[y][0][0].match(theNames[x]))) {
selectedLayers[y].push([theName, thisIndex, theIdentifier]);
theCheck = true;
};
};
if (theCheck == false) {
selectedLayers = [[[theName, thisIndex, theIdentifier]]]
}
}
};
////////////////////////////////////
} catch (e) {};
};
return selectedLayers;
};
Copy link to clipboard
Copied
Thank you very much, you are the best! everything works perfect!
I'm sorry if I said something wrong, translation difficulties, English is not my native language
Copy link to clipboard
Copied
No sweat, I am being nitpicky, I guess.
Glad it is sorted now.
If you should decide to delve deeper into Scripting I expect the code could still be improved for efficiency and brevity.