9 Replies Latest reply on Jul 26, 2018 11:54 AM by Kukurykus

    Sort / Order Selected Layers (Alphabetically)?

    Tom_01 Level 1

      Hi,

       

      I'm looking for a script to order selected layers alphabetically. I'm familiar with  Adobe Photoshop Scripts | Trevor Morris Photographics, but am looking for constraint to selection. I've tried using this script: get array of selected layers in photoshop via extendscript · GitHub in combination, however, I've hit a wall.

       

      Thanks,

      Tom

        • 1. Re: Sort / Order Selected Layers (Alphabetically)?
          r-bin Level 5

          Try this code )

           

          while (1)
              {
              var list = get_selected_layers();
          
              if (!list) { alert("No selected layers"); break; }
          
              var list2 = new Array();
              for (var i in list) list2.push(list[i]);
          
              function cmp(a, b) 
                  {
                  var x = expand_numbers(a[0]);
                  var y = expand_numbers(b[0]);
          
                  if (x > y) return -1;
                  if (x < y) return 1;
                  return 0;
                  }
          
              list.sort(cmp);
          
              var cont = false;
          
              for (var i = 0; i < list.length; i++)
                  {
                  if (list2[i][1] != list[i][1]) 
                      {
                      set_layers_index(list2[i][1], list[i][1]);
                      cont = true;
                      break;
                      }
                  }
          
              if (!cont) break;
              }
          
          alert("Done!");
          
          //////////////////////////////////////////////////////////////////
          function set_layers_index(cur_idx, new_idx)
              {
              try {
                  var d = new ActionDescriptor();
          
                  var r1 = new ActionReference();
                  r1.putIndex( charIDToTypeID( "Lyr " ), cur_idx);
          
                  var r2 = new ActionReference();
                  r2.putIndex( charIDToTypeID( "Lyr " ), new_idx );
          
                  d.putReference( charIDToTypeID( "null" ), r1 );
                  d.putReference( charIDToTypeID( "T   " ), r2 );
          
                  executeAction( charIDToTypeID( "move" ), d, DialogModes.NO );
                  }
              catch (e) { alert(e);  }
              }
          
          //////////////////////////////////////////////////////////////////
          function get_selected_layers()
              {
              try {
                  var r = new ActionReference();    
                  r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));   
                  r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
          
                  var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers"));
          
                  var n = 0;
                  try { activeDocument.backgroundLayer } catch (e) { n = 1; }
          
                  var len = list.count;
              
                  var selected_layers = new Array();
              
                  for (var i = 0; i < len; i++)
                      {
                      try 
                          {
                          var idx = list.getReference(i).getIndex() + n;
          
                          var r = new ActionReference();
                          r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("name"));   
                          r.putIndex( charIDToTypeID( "Lyr " ), idx);
          
                          var ret = executeActionGet(r).getString(stringIDToTypeID("name"));
          
                          selected_layers.push([executeActionGet(r).getString(stringIDToTypeID("name")), idx]);
                          }
          
                      catch (e) { alert(e); return null; }
                      }
              
                  return selected_layers;
                  }
          
              catch (e) { return null; }
              }
          
          ////////////////////////////////////////////////////////////////////////////////////////////
          function expand_numbers(s, max_digit)
              {
              if (max_digit == undefined) max_digit = 10;    
          
              var digit_cnt;
          
              s = s.toString();
              
              var len = s.length;
          
              var s1 = "";
          
              for (var i = len-1; i >= 0; i--) 
                  {
                  var c = s.charAt(i);
          
                  if (c >= "0" && c <="9")
                      {
                      if (digit_cnt == undefined)     
                          digit_cnt = 1;
                      else                        
                          ++digit_cnt;
          
                      s1 += c;
                      }
                  else if (digit_cnt != undefined) 
                      {
                      if (digit_cnt < max_digit) for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";
          
                      s1 += c;
                      digit_cnt = undefined;
                      }
                  else
                      {
                      s1 += c;
                      }
                  }
          
              if (digit_cnt != undefined && digit_cnt < max_digit)
                  for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";
          
              len = s1.length;
          
              var ret = "";
          
              for (var i = len-1; i >= 0; i--) ret += s1.charAt(i);
          
              ret = ret.toUpperCase();
          
              return ret;
              }
          
          
          • 2. Re: Sort / Order Selected Layers (Alphabetically)?
            Tom_01 Level 1

            Thanks!

            I ran the script and all but one of the selected layers got grouped into the group above them. I undid that and placed the group below all of the selected layers and ran again. Got a script alert: Error: General Photoshop error occurred. This functionality may not be available in this version of Photoshop.

            - The command "Move" is not currently available.

             

            I click OK or the x button and a new script alert appears (saying the same thing). I cannot exit Script Alerts...

            • 3. Re: Sort / Order Selected Layers (Alphabetically)?
              r-bin Level 5

              Please post the screenshot of your layers structures and their selection. What version of Photoshop are you running?

               

               

              upd. change

              catch (e) { alert(e);  }

              to

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

              • 4. Re: Sort / Order Selected Layers (Alphabetically)?
                r-bin Level 5

                I reproduced the error ).

                This should work

                 

                var idx_shift = 0;  
                try { activeDocument.backgroundLayer } catch (e) { idx_shift = 1; }  
                
                while (1)  
                    {  
                    var list = get_selected_layers();  
                  
                    if (!list) { alert("No selected layers"); break; }  
                  
                    var list2 = new Array();  
                    for (var i in list) list2.push(list[i]);  
                  
                    function cmp(a, b)   
                        {  
                        var x = expand_numbers(a[0]);  
                        var y = expand_numbers(b[0]);  
                  
                        if (x > y) return -1;  
                        if (x < y) return 1;  
                        return 0;  
                        }  
                  
                    list.sort(cmp);  
                
                    var cont = false;  
                  
                    for (var i = 0; i < list.length; i++)  
                        {  
                        if (list2[i][1] != list[i][1])   
                            {  
                            set_layers_index(list2[i][1], list[i][1]);  
                            cont = true;  
                            break;  
                            }  
                        }  
                  
                    if (!cont) break;  
                    }  
                  
                alert("Done!");  
                  
                //////////////////////////////////////////////////////////////////  
                function set_layers_index(cur_idx, new_idx)  
                    {  
                    try {  
                        var d = new ActionDescriptor();  
                  
                        var r1 = new ActionReference();  
                        r1.putIndex( charIDToTypeID( "Lyr " ), cur_idx);  
                  
                        var r2 = new ActionReference();  
                        r2.putIndex( charIDToTypeID( "Lyr " ), new_idx-idx_shift );  
                  
                        d.putReference( charIDToTypeID( "null" ), r1 );  
                        d.putReference( charIDToTypeID( "T   " ), r2 );  
                  
                        executeAction( charIDToTypeID( "move" ), d, DialogModes.NO );  
                        }  
                    catch (e) { alert(e); throw(e); }  
                    }  
                  
                //////////////////////////////////////////////////////////////////  
                function get_selected_layers()  
                    {  
                    try {  
                        var r = new ActionReference();      
                        r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));     
                        r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));  
                  
                        var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers"));  
                  
                        var len = list.count;  
                      
                        var selected_layers = new Array();  
                      
                        for (var i = 0; i < len; i++)  
                            {  
                            try   
                                {  
                                var idx = list.getReference(i).getIndex() + idx_shift;  
                  
                                var r = new ActionReference();  
                                r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("name"));     
                                r.putIndex( charIDToTypeID( "Lyr " ), idx);  
                  
                                var ret = executeActionGet(r).getString(stringIDToTypeID("name"));  
                  
                                selected_layers.push([executeActionGet(r).getString(stringIDToTypeID("name")), idx]);  
                                }  
                  
                            catch (e) { alert(e); return null; }  
                            }  
                      
                        return selected_layers;  
                        }  
                  
                    catch (e) { return null; }  
                    }  
                  
                ////////////////////////////////////////////////////////////////////////////////////////////  
                function expand_numbers(s, max_digit)  
                    {  
                    if (max_digit == undefined) max_digit = 10;      
                  
                    var digit_cnt;  
                  
                    s = s.toString();  
                      
                    var len = s.length;  
                  
                    var s1 = "";  
                  
                    for (var i = len-1; i >= 0; i--)   
                        {  
                        var c = s.charAt(i);  
                  
                        if (c >= "0" && c <="9")  
                            {  
                            if (digit_cnt == undefined)       
                                digit_cnt = 1;  
                            else                          
                                ++digit_cnt;  
                  
                            s1 += c;  
                            }  
                        else if (digit_cnt != undefined)   
                            {  
                            if (digit_cnt < max_digit) for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";  
                  
                            s1 += c;  
                            digit_cnt = undefined;  
                            }  
                        else  
                            {  
                            s1 += c;  
                            }  
                        }  
                  
                    if (digit_cnt != undefined && digit_cnt < max_digit)  
                        for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";  
                  
                    len = s1.length;  
                  
                    var ret = "";  
                  
                    for (var i = len-1; i >= 0; i--) ret += s1.charAt(i);  
                  
                    ret = ret.toUpperCase();  
                  
                    return ret;  
                    }  
                
                1 person found this helpful
                • 5. Re: Sort / Order Selected Layers (Alphabetically)?
                  Tom_01 Level 1

                  Amazing! Thank you very much--I really appreciate it.

                  • 6. Re: Sort / Order Selected Layers (Alphabetically)?
                    Kukurykus Adobe Community Professional

                    Before you run script go to 'Layers' panel, select 'Panel Oprions' from dropdown menu (you open clicking icon in right upper corner of panel), make 'Add "copy" to copied Layers and Groups' box empty. Script will be working if that won't be done, but all layer(Set)s get 'copy' word in their names. It is possible to remove it by script, but I did not do it as because of Photoshop bug there is need to select each single layer before renaming what increases time of performance. If you want script worked extremaly fast, press 'tab' key to toggle off your panels (it's scriptable but I let user decide of it). Script works for background and all kind of layers (those nasted in all levels groups as well). If any group will be selected before running script it is going to be unselected. Sorting is based on modified order of ASCII characters, so generally it is the same for digits and non letter characters. Difference is that order for letters is like: AaBbCc(...)Zz. Script distinguishes letters case and numbers in names - not as single digits but row of them - so there will be for ex. this order applied: 0, 1, 2, 3, 10, 99, 100 and so on. I didn't sort for any possible case there can happen but probably noone uses so complex layers names it ever was needed to cover unusual namings. It works also for layers having same content and length, while for example 'A' named layer will be sorted before 'a' named layer. I did not play with (disabled) linked layers, however those selected keep their links to each other while lose to those they were unselected and disabled ones gets enabled. These properties are possible to retrieve but as far there is no need to do it I didn't spend time for it. Visibility, effects and transparency stay untouched. It took 7,5 second with toggled off panels for 299 layer with background, so it gives 1 second for 40 layers! If you get some errors let me know so I'll make fixes.

                     

                    gT = new Date().getTime(), $.level = 0; function sTT(v) {return stringIDToTypeID(v)}
                    
                    function arr(v) {
                         (ref1 = new ActionReference()).putProperty(sTT('property'), tL = sTT('targetLayers'))
                         ref1.putEnumerated(sTT('document'), sTT('ordinal'), sTT('targetEnum'))
                    
                         if ((dsc1 = executeActionGet(ref1)).hasKey(tL)) {for(lst = dsc1.getList(tL), i = 0; i < lst.count;) {
                              (ref2 = new ActionReference()).putIndex(sTT('layer'), lst.getReference(i++).getIndex() + bG), s = 'Start'
                              if (typeIDToStringID((dsc = executeActionGet(ref2)).getEnumerationValue(sTT(lS = 'layerSection'))) == lS + s)
                                   {ref2.putIdentifier(sTT('layer'), dsc.getInteger(sTT('layerID'))), dsc1.putReference(sTT('null'), ref2)
                                   dsc1.putEnumerated(sTT(sM = 'selectionModifier'), sTT(sM + 'Type'), sTT('removeFromSelection'))
                                   dsc1.putBoolean(sTT('makeVisible'), false), executeAction(sTT('select'), dsc1, DialogModes.NO)}
                              else v.unshift([dsc.getString(sTT('name')), dsc.getInteger(sTT('layerID'))])}
                         }
                         return v
                    }
                    
                    (ref = new ActionReference()).putIdentifier(sTT('layer'), 1)
                    try{bG = !(dsc = executeActionGet(ref)).getBoolean
                    (sTT('background'))} catch (err) {bG = 1}
                    
                    if ((sL = arr([])).length > 1) {
                         (srt = Array().slice.call(sL)).sort(function(v1, v2) {
                              function l(v) {return v.length}; if ((v1 = v1[0]) != v2 = v2[0]) {
                                   for(g = 0; g < l(v1); g++) {
                                        if ((v1g = v1[g]) != v2g = v2[g]) {
                                             function dig(v) {return !isNaN(v)}
                                             if (dig(v1g) && dig(v2g)) {
                                                  function slc(v) {
                                                       return +String(v).slice(g).match(/\d+/)
                                                  }
                                                  return slc(v1) - slc(v2)
                                             }
                                             function cCA(v) {
                                                  return v.charCodeAt() -
                                                  (/[a-z]/.test(v) ? 31.5 : 0)
                                             }
                                             if (v1g && v2g) return cCA(v1g) - cCA(v2g)
                                        }
                                        if (!v1g || !v2g) return l(v1) - l(v2)
                                   }
                              }
                         });
                    
                         (ref1 = new ActionReference()).putEnumerated(sTT('layer'), sTT('ordinal'),
                         sTT('targetEnum')); (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1)
                         dsc1.putInteger(sTT('version'), 5), executeAction(sTT('duplicate'), dsc1, DialogModes.NO);
                    
                         dL = arr([]);
                    
                         (ref1 = new ActionReference()).putClass(sTT('layerSection'));
                         (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1);
                         (ref2 = new ActionReference()).putEnumerated(sTT('layer'),
                         sTT('ordinal'), sTT('targetEnum')), dsc1.putReference(sTT
                         ('from'), ref2), executeAction(sTT('make'), dsc1, DialogModes.NO)
                         grp = executeActionGet(ref2).getInteger(sTT('layerID' ))
                    
                         function del(v1, v2) {
                              eval("(ref1 = new ActionReference()).put" + v1 + "(sTT('layer'), v2)");
                              (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1)
                              executeAction(sTT('delete'), dsc1, DialogModes.NO)
                         }
                    
                         for(i = 0; i < sL.length; i++) {
                              for(j = 0; j < srt.length; j++) {
                                   if (sL[i][1] == srt[j][1]) {
                                        (ref1 = new ActionReference()).putIdentifier(sTT('layer'), dL.shift()[1]);
                                        (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1);
                                        (ref1 = new ActionReference()).putIdentifier(sTT('layer'), sL[j][1])
                                        t = executeActionGet(ref1).getInteger(sTT('itemIndex'));
                                        (ref2 = new ActionReference()).putIndex(sTT('layer'), t)
                                        dsc1.putReference(sTT('to'), ref2), executeAction
                                        (sTT('move'), dsc1, DialogModes.NO);
                    
                                        del('Index', t - (bG ? 0 : 1))
                    
                                        if (!bG && t == 1) {
                                             (ref1 = new ActionReference()).putClass(sTT('backgroundLayer'));
                                             (dsc1 = new ActionDescriptor()).putReference(sTT('null'), ref1);
                                             (ref2 = new ActionReference()).putIndex(sTT('layer'), t);
                                             dsc1.putReference(sTT('using'), ref2), executeAction
                                             (sTT('make'), dsc1, DialogModes.NO)
                                        }
                                        break
                                   }
                              }
                         }
                    
                         del('Identifier', grp), new Date().getTime() - gT
                    }
                    
                    • 7. Re: Sort / Order Selected Layers (Alphabetically)?
                      Kukurykus Adobe Community Professional

                      I compared performance of our scripts and found the more selected layers the longer time your script needs to sort all of them. Only up to 10 selected layers yours is a little faster - here is comparision in seconds (layers number / yours / mine):

                       

                      10     /     0.12     /     0.17

                      20     /     2.20     /     0.38

                      30     /     8.00     /     0.55

                      40     /     25.4     /     0.80

                      50     /     57.5     /     1.00

                       

                      It also does not handle layers with same name like '1' and '1', 'Layer 0' and 'Layer 0' or 'a' and 'A'. It's looping endlessly itself...

                      • 8. Re: Sort / Order Selected Layers (Alphabetically)?
                        r-bin Level 5

                        Here is new version whithout "while" cycle )

                         

                        var idx_shift = 0;    
                        try { activeDocument.backgroundLayer } catch (e) { idx_shift = 1; }    
                        
                        var list = get_selected_layers();    
                        
                        if (list) 
                            {
                            var orig_idx = new Array();    
                            for (var i in list) orig_idx.push(list[i][1]);    
                        
                            function cmp(a, b)     
                                {    
                                var x = expand_numbers(a[0]);    
                                var y = expand_numbers(b[0]);    
                        
                                if (x > y) return -1;    
                                if (x < y) return 1;    
                                return 0;    
                                }    
                        
                            list.sort(cmp);    
                        
                            for (var i = list.length-1; i >= 0; i--) set_layers_index(list[i][2], orig_idx[i]);    
                            }
                        
                        alert("Done!");    
                            
                        //////////////////////////////////////////////////////////////////    
                        function set_layers_index(id, idx)    
                            {    
                            try {    
                                var d = new ActionDescriptor();    
                            
                                var r1 = new ActionReference();    
                                r1.putIdentifier( charIDToTypeID( "Lyr " ), id);    
                            
                                var r2 = new ActionReference();    
                                r2.putIndex( charIDToTypeID( "Lyr " ), idx-idx_shift );    
                            
                                d.putReference( charIDToTypeID( "null" ), r1 );    
                                d.putReference( charIDToTypeID( "T   " ), r2 );    
                            
                                executeAction( charIDToTypeID( "move" ), d, DialogModes.NO );    
                                }    
                            catch (e) { alert(e); throw(e); }    
                            }    
                            
                        //////////////////////////////////////////////////////////////////    
                        function get_selected_layers()    
                            {    
                            try {    
                                var r = new ActionReference();        
                                r.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("targetLayers"));       
                                r.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));    
                            
                                var list = executeActionGet(r).getList(stringIDToTypeID("targetLayers"));    
                            
                                var len = list.count;    
                                
                                var selected_layers = new Array();    
                                
                                for (var i = 0; i < len; i++)    
                                    {    
                                    try     
                                        {    
                                        var idx = list.getReference(i).getIndex() + idx_shift;    
                            
                                        var r = new ActionReference();    
                                        r.putIndex( charIDToTypeID( "Lyr " ), idx);    
                        
                                        var ret = executeActionGet(r);
                            
                                        selected_layers.push([ret.getString(stringIDToTypeID("name")), idx, ret.getString(stringIDToTypeID("layerID"))]);    
                                        }    
                            
                                    catch (e) { alert(e); return null; }    
                                    }    
                                
                                return selected_layers;    
                                }    
                            
                            catch (e) { return null; }    
                            }    
                            
                        ////////////////////////////////////////////////////////////////////////////////////////////    
                        function expand_numbers(s, max_digit)    
                            {    
                            if (max_digit == undefined) max_digit = 10;        
                            
                            var digit_cnt;    
                            
                            s = s.toString();    
                                
                            var len = s.length;    
                            
                            var s1 = "";    
                            
                            for (var i = len-1; i >= 0; i--)     
                                {    
                                var c = s.charAt(i);    
                            
                                if (c >= "0" && c <="9")    
                                    {    
                                    if (digit_cnt == undefined)         
                                        digit_cnt = 1;    
                                    else                            
                                        ++digit_cnt;    
                            
                                    s1 += c;    
                                    }    
                                else if (digit_cnt != undefined)     
                                    {    
                                    if (digit_cnt < max_digit) for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";    
                            
                                    s1 += c;    
                                    digit_cnt = undefined;    
                                    }    
                                else    
                                    {    
                                    s1 += c;    
                                    }    
                                }    
                            
                            if (digit_cnt != undefined && digit_cnt < max_digit)    
                                for (var n = 0; n < max_digit-digit_cnt; n++) s1 += "0";    
                            
                            len = s1.length;    
                            
                            var ret = "";    
                            
                            for (var i = len-1; i >= 0; i--) ret += s1.charAt(i);    
                            
                            ret = ret.toUpperCase();    
                            
                            return ret;    
                            }    
                        
                        • 9. Re: Sort / Order Selected Layers (Alphabetically)?
                          Kukurykus Adobe Community Professional

                          btw now your script is twice faster than mine. Both are exremaly fast though, but yours does not regroup layers - it s why