Copy link to clipboard
Copied
Hello,
I am trying to sort some layers within my document alphabetically. I have some scripts that work but they sort ALL layers and I would like to be able to sort only selected layers. Here is one of the scripts I have that work. Do you have a better code or do you know what I can add to this code to make it only work on selected layers?
#target photoshop
/**
* @copyright Copyright (c) 2020 Matthew Kimber. All rights reserved.
* @author Matthew Kimber <matthew.kimber@gmail.com>
* @version 1.1
* @license Apache Software License 2.0
*/
(function(app) {
if (isDocumentOpen()) {
main();
} else {
alert("Please open a document to run this script.");
}
/**
* @Desc Program entry point. Retrieves the active document, determines if layers exist, and then sorts all ArtLayer and LayerSet objects.
*/
function main() {
var activeDoc = app.activeDocument;
if (activeDoc.layers.length > 0) {
sortLayers(activeDoc.layers);
}
}
/**
* @Desc Sorts the layers in the current LayerSet.
* @Param {Layers} layers Collection of ArtLayer and LayerSet objects in the current scope.
*/
function sortLayers(layers) {
var layerBuffer = new Array(),
index = 0;
for (index = 0; index < layers.length; index++) {
if (!layers[index].isBackgroundLayer) {
layerBuffer.push(layers[index]);
// Check to see if we need to sort groups in the current layer set.
if (typeof layers[index].layers !== "undefined" && layers[index].layers.length > 0) {
sortLayers(layers[index].layers);
}
}
}
// Sort the buffer array using built-in natural sort comparer.
layerBuffer.sort(compareWithNumbers);
// Move each layer accordingly.
for (index = 0; index < layerBuffer.length; index++) {
layerBuffer[index].move(layers[index], ElementPlacement.PLACEBEFORE);
}
}
/**
* @Desc Checks to see if there is a document open.
* @Returns {Boolean}
*/
function isDocumentOpen() {
return app.documents.length > 0;
}
}(app));
Thank you for your help!
Alright, it took me awhile, but here's a script that I hope works to sort just the selected layers. As you mentioned, the layers will be all together, so if the selected layers aren't contiguous, the script will just move all the other layer after where ever the first selected layer is located.
#target photoshop
var doc = activeDocument;
var bkgn = hasBackground ();
var topLayerID//To hold top selected layer ID
var lyrSelIDX = (getSelectedLayersIdx ())//indexes of selected layers
var orgLay
...
Copy link to clipboard
Copied
Just a question, for now: if your selected layers are not contiguous, do you want the sorted layers to keep the same arrangement with non selected layers between them?
Copy link to clipboard
Copied
Hey, I've only needed this feature for layers that are grouped together so I don't see that ever being important for me.
Copy link to clipboard
Copied
Slowly working on a solution, unless someone else comes up with one first. I have some old code about selecting multiple layers, just have to adapt it to this situation.
Copy link to clipboard
Copied
Could you please post screenshots with the pertinent Panels (Toolbar, Layers, Options Bar, …) visible for the state you start with and the result you want to get?
Hey, I've only needed this feature for layers that are grouped together so I don't see that ever being important for me.
It makes a difference for a Script so please make a meaningful and unequivocal decision.
Should all the selected Layers be arranged at the Layer Stack-position the topmost selected one, the lowermost selected one, …?
Copy link to clipboard
Copied
Here is an example of what I would need.
Could you please post screenshots with the pertinent Panels (Toolbar, Layers, Options Bar, …) visible for the state you start with and the result you want to get?
Hey, I've only needed this feature for layers that are grouped together so I don't see that ever being important for me.It makes a difference for a Script so please make a meaningful and unequivocal decision.
Should all the selected Layers be arranged at the Layer Stack-position the topmost selected one, the lowermost selected one, …?
By @c.pfaffenbichler
I am sorry I thought it was clear - No I do not need the script to take other layers into account. My layers will all be grouped.
Thank you for your help!
Copy link to clipboard
Copied
I should have added this to the OP for more context.
There is this old thread that has code that is supposed to work, but I receive an error that I mentioned in the comments and I havent heard back:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/sort-order-selected-layers-alphabetic...
I get some numerical value expected error. Again, more detail in the comment section on that thread. Another person commented about the same error.
Copy link to clipboard
Copied
I should have added this to the OP for more context.
There is this old thread that has code that is supposed to work, but I receive an error that I mentioned in the comments and I havent heard back:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/sort-order-selected-layers-alphabetic...
I get some numerical value expected error. Again, more detail in the comment section on that thread. Another person commented about the same error.
By @happyplant1111
When Adobe changed the forum software, many scripts were broken as the new forum software removed critical bits such as references to variables in square brackets, such as [i] etc.
Copy link to clipboard
Copied
Alright, it took me awhile, but here's a script that I hope works to sort just the selected layers. As you mentioned, the layers will be all together, so if the selected layers aren't contiguous, the script will just move all the other layer after where ever the first selected layer is located.
#target photoshop
var doc = activeDocument;
var bkgn = hasBackground ();
var topLayerID//To hold top selected layer ID
var lyrSelIDX = (getSelectedLayersIdx ())//indexes of selected layers
var orgLayA = getLayerSetsData(lyrSelIDX)//array of selected layer names and IDs
multiSelectByIDs (topLayerID);
var topLayer = doc.activeLayer;//top selected layer
moveUpLayer ();
var upLayer = doc.activeLayer
var upLayerIDX = getSelectedLayersIdx ()
multiSelectByIDs (orgLayA[0][1])
var firstLayer = doc.activeLayer
if(upLayerIDX<lyrSelIDX[lyrSelIDX.length-1])
{firstLayer.move (doc.layers[0], ElementPlacement.PLACEBEFORE)}
else
{firstLayer.move (topLayer, ElementPlacement.PLACEBEFORE) }
var lastLayer = doc.activeLayer
for(var i=1;i<orgLayA.length;i++){
multiSelectByIDs (orgLayA[i][1]);
nextLayer = doc.activeLayer;
nextLayer.move (lastLayer, ElementPlacement.PLACEAFTER)
lastLayer = doc.activeLayer
}
function hasBackground(){// function to check if there is a background layer
var res = undefined;
try{
var ref = new ActionReference();
ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID("Nm "));
ref.putIndex( charIDToTypeID("Lyr "), 0 );
executeActionGet(ref).getString(charIDToTypeID("Nm ") );
res = true;
}catch(e){ res = false}
return res;
}
//used in getSelectedLayersIds()
function getSelectedLayersIdx(){// get the selected layers index( positon in layer editor)
var selectedLayers = new Array;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
var desc = executeActionGet(ref);
var add = 1;
if(hasBackground()){add = 0}
if( desc.hasKey( stringIDToTypeID( 'targetLayers' ) ) ){
desc = desc.getList( stringIDToTypeID( 'targetLayers' ));
var c = desc.count
var selectedLayers = new Array();
for(var i=0;i<c;i++){
selectedLayers.push( (desc.getReference( i ).getIndex()) + add);
}
}else{
var ref = new ActionReference();
ref.putProperty( charIDToTypeID('Prpr') , charIDToTypeID( 'ItmI' ));
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
srs = hasBackground()?executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ))-1:executeActionGet(ref).getInteger(charIDToTypeID( 'ItmI' ));
selectedLayers.push( srs);
}
return selectedLayers;
}
function getLayerSetsData(layA)
{
var lyrSetsList = []
var lyrSets = [];
for(i=0;i<layA.length;i++){
var layerSets = layA[i]
//var layerSets = 4
ref = new ActionReference();
ref.putIndex(charIDToTypeID('Lyr '), layerSets);
var d1 = executeActionGet(ref)
var c2t = function (s){return app.charIDToTypeID(s);};
var s2t = function (s){return app.stringIDToTypeID(s);};
var lyrSet = {};
lyrSet.name = d1.getString(c2t("Nm "));
lyrSet.id = d1.getInteger(s2t("layerID"));
lyrSetsList.push ([lyrSet.name,lyrSet.id])
}
topLayerID = lyrSetsList[lyrSetsList.length -1][1]
lyrSetsList.sort ()
return lyrSetsList
};
//=========
function makeLayerActiveByLayerID(id){//is this needed?
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID( "Lyr " ), id );
desc.putReference( charIDToTypeID( "null" ), ref );
desc.putBoolean( charIDToTypeID( "MkVs" ), false );
executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
};
//used in multiSelectByIDs(ids)
function doesIdExists( id ){// function to check if the id exists
var res = true;
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID('Lyr '), id);
try{var desc = executeActionGet(ref)}catch(err){res = false};
return res;
}
//uses doesIdExists(id)
function multiSelectByIDs(ids) {
if( ids.constructor != Array ) ids = [ ids ];
var layers = new Array();
var id54 = charIDToTypeID( "slct" );
var desc12 = new ActionDescriptor();
var id55 = charIDToTypeID( "null" );
var ref9 = new ActionReference();
for (var i = 0; i < ids.length; i++) {
if(doesIdExists(ids[i]) == true){// a check to see if the id stil exists
layers[i] = charIDToTypeID( "Lyr " );
ref9.putIdentifier(layers[i], ids[i]);
}
}
desc12.putReference( id55, ref9 );
var id58 = charIDToTypeID( "MkVs" );
desc12.putBoolean( id58, false );
executeAction( id54, desc12, DialogModes.NO );
}
//=======================
function moveUpLayer(){
var idslct = charIDToTypeID( "slct" );
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idFrwr = charIDToTypeID( "Frwr" );
ref1.putEnumerated( idLyr, idOrdn, idFrwr );
desc3.putReference( idnull, ref1 );
var idMkVs = charIDToTypeID( "MkVs" );
desc3.putBoolean( idMkVs, false );
var idLyrI = charIDToTypeID( "LyrI" );
var list1 = new ActionList();
list1.putInteger( 3 );
desc3.putList( idLyrI, list1 );
executeAction( idslct, desc3, DialogModes.NO );
}
Copy link to clipboard
Copied
You rock Chuck! I'll give it a try tomorrow and post back. Thanks!
Copy link to clipboard
Copied
Just wanted to say this script works perfectly, thank you so much!!
I was just trying to use the ones from the older thread mentioned earlier and was getting the same error as OP (on PS 23.3.1), since that thread was so old I wasn't sure if it would be possible to find one that worked. This made my day!!
Copy link to clipboard
Copied
Glad it's working for you, as well.
Copy link to clipboard
Copied
works flawlessly, thanks!
Copy link to clipboard
Copied
Thanks! Glad it worked for you.
Copy link to clipboard
Copied
Hey! I don't know if anybody is looking for help in 2024 lol, but I've managed to get a working script for selected layers, ordering A-Z or Z-A depending on which option you choose from the dialog box that pops up.
// Sort selected layers alphabetically by name with a sorting order dialog
function sortSelectedLayersByName() {
var doc = activeDocument;
var selectedLayers = getSelectedLayers();
// Show a dialog box to choose sorting order
var sortingOrder = showSortingDialog();
if (sortingOrder === null) return; // Exit if the dialog was canceled
// Sort the selected layers by name based on the chosen order
selectedLayers.sort(function (a, b) {
var comparison = a.name.toLowerCase().localeCompare(b.name.toLowerCase());
return sortingOrder === "A-Z" ? comparison : -comparison;
});
// Move each layer to its new position
for (var i = 0; i < selectedLayers.length; i++) {
selectedLayers[i].move(doc, ElementPlacement.PLACEATEND);
}
// Function to get selected layers
function getSelectedLayers() {
var selLayers = [];
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var desc = executeActionGet(ref);
if (desc.hasKey(stringIDToTypeID("targetLayers"))) {
var list = desc.getList(stringIDToTypeID("targetLayers"));
for (var i = 0; i < list.count; i++) {
var layerIndex = list.getReference(i).getIndex();
activeDocument.activeLayer = activeDocument.layers[layerIndex];
selLayers.push(activeDocument.activeLayer);
}
} else {
selLayers.push(activeDocument.activeLayer);
}
return selLayers;
}
// Function to show sorting order dialog
function showSortingDialog() {
var dialog = new Window("dialog", "Sort Layers");
dialog.orientation = "column";
dialog.alignChildren = "left";
dialog.add("statictext", undefined, "Select sorting order:");
var dropdown = dialog.add("dropdownlist", undefined, ["A-Z", "Z-A"]);
dropdown.selection = 0; // Default to "A-Z"
var buttonGroup = dialog.add("group");
buttonGroup.alignment = "right";
var okButton = buttonGroup.add("button", undefined, "OK");
var cancelButton = buttonGroup.add("button", undefined, "Cancel");
okButton.onClick = function () {
dialog.close(1);
};
cancelButton.onClick = function () {
dialog.close(0);
};
if (dialog.show() == 1) {
return dropdown.selection.text;
} else {
return null; // Dialog was canceled
}
}
}
sortSelectedLayersByName();
Cheers!