15 Replies Latest reply on Sep 21, 2015 4:02 PM by Qwertyfly...

    Need help cleaning up a recursive loop, please.

    williamadowling Level 4

      Hello again,

       

      I'm on yet another quest to write a completely idiot proof function to do a very specific task in Illustrator. The task is to create a new artboard in the target document (determined by a small script ui prompt) that is a certain distance from the existing artboard with the highest index (so i'm always putting the new artboard at the end). After I've created the artboard, I want to activate the source document and duplicate all artwork and layers (some layers are blank but will be used later) into the target doc and place them on the newly created artboard.

       

      With the help and guidance of Silly-V I wrote a recursive loop to handle the nested layer situation. That brings me to part one of my question. Please take a look at the recursion and let me know if there's anything I can do to clean it up and streamline it as much as possible. (I know it looks really messy. I was learning how to do it on the fly and i changed a lot of variables and loops after the fact, just trying to make it work). I'm also hoping that finding a slightly more efficient way to work this will help improve stability as well. As it stands, I can only run this script 3 or 4 times (if i'm lucky) before i get persistent MRAP errors on trivial things such as: layers.getByName("Information").visible = false; At that point, the only remedy is to quit illustrator and reopen the files. Then i'm usually good for a few more runs..

       

      Part 2 of my question is this. Is there a way to duplicate artwork from one document to another and have it placed onto the new artboard rather than artboard[0]? Currently, the art is duplicating from artboard[0] of the source doc to artboard[0] of the target doc and then i'm manually manipulating the placement by setting: this.left = this.left + (artboards.length * 2100). First of all, this is just adding WAY too many steps to the script and slowing things down i'm sure. The second problem with this is that after 4 artboards, i need to move down to another row (to keep from spilling off the pasteboard). That adds another layer of complexity and a lot more if statements to determine how far to move it and in what direction.

       

      Here's the script in it's entirety. Please feel free to tear it apart and ask me WTH i was thinking. In the words of carloscanto, script.elegant is definitely false.

       

      var copyToMaster = function(){
        var docRef = app.activeDocument;
        var layers = docRef.layers;
        var masterFile = getTargetDoc();
        if(masterFile == null){
        return;
        }
        var master = app.documents.getByName(masterFile);
        var sourceDoc = app.activeDocument;
        var move;
        var myLayer;
        var targetLayer;
        var innerTargetLayer;
        var outerTargetLayer;
      
      
        //Logic Container//
      
        function outerRecursive(layer){
        var name = layer.name;
        try{
        outerTargetLayer = targetLayer.layers.getByName(layer.name);
        }
        catch(e){
        outerTargetLayer = targetLayer.layers.add(ElementPlacement.PLACEATBEGINNING);
        outerTargetLayer.name = name;
        }
        if(layer.pageItems.length>0){
        for(var b=layer.pageItems.length-1;b>-1;b--){
        var curItem = layer.pageItems[b];
        var copyCurItem = curItem.duplicate(outerTargetLayer,ElementPlacement.PLACEATBEGINNING);
        copyCurItem.left = curItem.left+move;
        }
        }
        if(layer.layers.length>0){
        for(var e=layer.layers.length-1;e>-1;e--){
        var subSubLayer = layer.layers[e];
        innerRecursive(subSubLayer);
        }
        }
        }
      
        function innerRecursive(subLayer){
        try{
        innerTargetLayer = outerTargetLayer.layers.getByName(subLayer.name);
        }
        catch(e){
        innerTargetLayer = outerTargetLayer.layers.add();
        innerTargetLayer.name = subLayer.name;
        }
        if(subLayer.pageItems.length>0){
        for(var g=subLayer.pageItems.length-1;g>-1;g--){
        var curItem = subLayer.pageItems[g];
        var copyCurItem = curItem.duplicate(innerTargetLayer,ElementPlacement.PLACEATBEGINNING);
        copyCurItem.left = copyCurItem.left + move;
        }
        }
        if(subLayer.layers.length>0){
        for(var h=subLayer.layers.length-1;h>-1;h--){
        innerRecursive(subLayer.layers[h]);
        }
        if(name == "Information"){
        layer.locked = true;
        layer.visible = true;
        }
        else if(name == "Prepress"){
        layer.locked = false;
        layer.visible = false;
        }
        }
        if(subLayer.name == "Information"){
        subLayer.locked = true;
        subLayer.visible = true;
        }
        else if(subLayer.name == "Prepress"){
        subLayer.locked = false;
        subLayer.visible = false;
        }
        }
      
        function getTargetDoc(){
      
        var docs = [];
      
      
        for(var a=0;a<app.documents.length;a++){
        docs.push(app.documents[a].name);
        }
      
      
        var targetIndex = new Window("dialog", "Which is Master");
        var newTextGroup = targetIndex.add("group");
        newTextGroup.text = targetIndex.add("statictext",undefined,"Which file do you want to merge to?");
        newTextGroup.align = "center";
        var radioGroup = targetIndex.add("group");
        radioGroup.alignChildren = "left";
        radioGroup.orientation = "column";
        for(var a=0;a<docs.length;a++){
        radioGroup.add("radiobutton",undefined,docs[a]);
        }
        radioGroup.children[0].value = true;
      
        var buttonGroup = targetIndex.add("group");
        var ok = buttonGroup.add("button", undefined, "OK");
        var can = buttonGroup.add("button", undefined, "Cancel");
      
      
        function selected(which){
        for(var c=0;c<which.children.length;c++){
        if(which.children[c].value == true){
        return which.children[c].text;
        }
        }
        }
      
      
        if(targetIndex.show() == 1){
        return (selected(radioGroup));
        }
        else{
        return;
        }
      
      
        targetIndex.show();
        }
      
        function createNewArtboard(){
        master.activate();
        move = ((master.artboards.length) * 2100)
        var aBcount = master.artboards.length;
        var lastAB = master.artboards[master.artboards.length-1];
        var aB = lastAB.artboardRect;
        var left = aB[0];
        var top = aB[1];
        var right = aB[2];
        var bot = aB[3];
        var moveRight = 2100;
        var moveDown = 2100;
        if(aBcount != 5 && aBcount != 10){
        var newLeft = left + moveRight;
        var newRight = right + moveRight;
        var rect = [newLeft,top,newRight,bot];
        var newAb = master.artboards.add(rect);
        }
        else{
        var originAb = master.artboards[0].artboardRect;
        var oLeft = originAb[0];
        var oTop = originAb[1];
        var oRight = originAb[2];
        var oBot = originAb[3];
        oTop = oTop - moveDown;
        oBot = oBot - moveDown;
        var rect = [oLeft,oTop,oRight,oBot];
        var newAb = master.artboards.add(rect);
        }
        sourceDoc.activate();
        }
      
        //Function Calls
      
        createNewArtboard();
      
        for(var a=0;a<layers.length;a++){
        layers[a].locked = false;
        layers[a].visible = true;
        }
        for(var a=0;a<master.layers.length;a++){
        master.layers[a].locked = false;
        master.layers[a].visible = true;
        }
      
        for(var a=layers.length-1;a>-1;a--){
        var curLayer = layers[a];
        try{
        targetLayer = master.layers.getByName(curLayer.name);
        }
        catch(e){
        targetLayer = master.layers.add();
        targetLayer.name = curLayer.name;
        }
        if(curLayer.pageItems.length>0){
        for(var k=curLayer.pageItems.length-1;k>-1;k--){
        var curItem = curLayer.pageItems[k];
        var copyCurItem = curItem.duplicate(targetLayer,ElementPlacement.PLACEATBEGINNING);
        copyCurItem.left = copyCurItem.left + move;
        }
      
      
        }
        if(curLayer.layers.length>0){
        for(var f=curLayer.layers.length-1;f>-1;f--){
        var curSubLayer = curLayer.layers[f];
        outerRecursive(curSubLayer);
        }
        }
        }
      
        //re-lock/hide layers;
      
        for(var a=0;a<master.layers.length;a++){
        if(master.layers[a].name == "Guides" || master.layers[a].name == "BKGRD, do not unlock"){
        master.layers[a].locked = true;
        }
        else{
        for(var b=0;b<master.layers[a].layers.length;b++){
        var level2 = master.layers[a].layers[b];
        if(level2.name == "Prepress"){
        level2.locked = false;
        level2.visible = false;
        }
        else if(level2.name == "Information"){
        level2.locked = true;
        level2.visible = true;
        }
        }
        }
        }
      
      
      
      
      
      
      
      
      }
      copyToMaster();
      copyToMaster = null;
      
        • 1. Re: Need help cleaning up a recursive loop, please.
          williamadowling Level 4

          Well I rebuilt the script as lean as I could make sense of it. I removed the lines that move the artwork after it's duplicated because i'm positive there's got to be a better way to do that... Unfortunately, my suspicion that setting the activeArtboardIndex() to the newly created artboard doesn't do anything. Illustrator shows the correct artboard is active. But the duplication is still happening relative to the coordinates of the source document. Any thoughts on that???

           

          Here's the updated code. Still copies all the artwork and layers as it should (and in the correct order as well) but still places duplicated artwork directly on top of artboard[0] in the target document. I'll also note that this version does run a little faster than the old one, but I'm sure that's solely due to the lack of position adjustments. Basically i just cleaned up the variable names and used more variables as function arguments rather than global variables.

           

          And back to the MRAP "Illustrator Error Occurred" issue, is this script just really poorly written? Or is CC just screwing me with it's abysmal memory management? I can deal with the script taking some time to execute. But the necessity of quitting and relaunching illustrator just seems unbelievably unacceptable..

           

          function copyToMaster(){
            var docRef = app.activeDocument;
            var layers = docRef.layers;
            var masterFile = getTargetDoc();
            if(masterFile == null){return;}
            var master = app.documents.getByName(masterFile);
          
            ///////////////////////
            ////Logic Container////
            ///////////////////////
          
            function outer(target,source){
            if(source.pageItems.length>0){
            for(var c=source.pageItems.length-1;c>-1;c--){
            var curItem = source.pageItems[c];
            var curItem2 = curItem.duplicate(target);
            }
            }
            if(source.layers.length>0){
            for(var c=source.layers.length-1;c>-1;c--){
            var subSubLayer = source.layers[c];
            try{
            var innerTarget = target.layers.getByName(subSubLayer.name);
            }
            catch (e){
            var innerTarget = target.layers.add();
            innerTarget.name = subSubLayer.name;
            }
            inner(innerTarget,subSubLayer);
            }
            if(innerTarget.name == "Prepress"){
            innerTarget.visible = false;
            }
            else if(innerTarget.name == "Information"){
            innerTarget.locked = true;
            }
            }
          
          
            }
          
            function inner(inTarget, inSource){
            if(inSource.pageItems.length>0){
            for(var d=inSource.pageItems.length-1;d>-1;d--){
            var curItem = inSource.pageItems[d];
            var curItem2 = curItem.duplicate(inTarget);
            }
            }
            if(inSource.layers.length>0){
          
          
            for(var d=inSource.layers.length-1;d>-1;d--){
            try{
            var newInTarget = inTarget.layers.getByName(inSourceLayers.layers[d].name);
            }
            catch(e){
            var newInTarget = inTarget.layers.add();
            newInTarget.name = inSourceLayers.layers[d].name;
            }
            var newInSource = inSource.layers[d];
            inner(newInTarget,newInSource);
            }
            if(newInTarget.name == "Prepress"){
            newInTarget.visible = true;
            }
            else if(newInTarget.name == "Information"){
            newInTarget.locked = true;
            }
            }
            }
          
            function getTargetDoc(){
          
            var docs = [];
          
          
            for(var a=0;a<app.documents.length;a++){
            docs.push(app.documents[a].name);
            }
          
          
            var targetIndex = new Window("dialog", "Which is Master");
            var newTextGroup = targetIndex.add("group");
            newTextGroup.text = targetIndex.add("statictext",undefined,"Which file do you want to merge to?");
            newTextGroup.align = "center";
            var radioGroup = targetIndex.add("group");
            radioGroup.alignChildren = "left";
            radioGroup.orientation = "column";
            for(var a=0;a<docs.length;a++){
            radioGroup.add("radiobutton",undefined,docs[a]);
            }
            radioGroup.children[0].value = true;
          
            var buttonGroup = targetIndex.add("group");
            var ok = buttonGroup.add("button", undefined, "OK");
            var can = buttonGroup.add("button", undefined, "Cancel");
          
          
            function selected(which){
            for(var c=0;c<which.children.length;c++){
            if(which.children[c].value == true){
            return which.children[c].text;
            }
            }
            }
          
          
            if(targetIndex.show() == 1){
            return (selected(radioGroup));
            }
            else{
            return;
            }
          
          
            targetIndex.show();
            }
          
            function createNewArtboard(){
            master.activate();
            var aBcount = master.artboards.length;
            var lastAB = master.artboards[master.artboards.length-1];
            var aB = lastAB.artboardRect;
            var left = aB[0];
            var top = aB[1];
            var right = aB[2];
            var bot = aB[3];
            var moveRight = 2100;
            var moveDown = 2100;
            if(aBcount != 5 && aBcount != 10){
            var newLeft = left + moveRight;
            var newRight = right + moveRight;
            var rect = [newLeft,top,newRight,bot];
            var newAb = master.artboards.add(rect);
            }
            else{
            var originAb = master.artboards[0].artboardRect;
            var oLeft = originAb[0];
            var oTop = originAb[1];
            var oRight = originAb[2];
            var oBot = originAb[3];
            oTop = oTop - moveDown;
            oBot = oBot - moveDown;
            var rect = [oLeft,oTop,oRight,oBot];
            var newAb = master.artboards.add(rect);
            }
            master.artboards.setActiveArtboardIndex(master.artboards.length-1);
            docRef.activate();
            }
          
            ///////////////////////
            ////Logic Container////
            ///////////////////////
          ////////////////////////////////////////////////////////////////////////////////
            //////////////////////
            ////Function Calls////
            //////////////////////
          
            createNewArtboard();
          
            for(var a=layers.length-1;a>-1;a--){
            var topLayer = layers[a];
            try{
            var targetLayer = master.layers.getByName(topLayer.name);
          
          
            }
            catch(e){
            var targetLayer = master.layers.add();
            targetLayer.name = topLayer.name;
            }
            targetLayer.locked = false;
            targetLayer.visible = true;
            if(topLayer.pageItems.length>0){
            for(var b=topLayer.pageItems.length-1;b>-1;b--){
            var curItem = topLayer.pageItems[b];
            var curItem2 = curItem.duplicate(targetLayer);
            }
            }
            if(topLayer.layers.length>0){
            for(var b=topLayer.layers.length-1;b>-1;b--){
            var subLayer = topLayer.layers[b];
            try{
            var outerTarget = targetLayer.layers.getByName(subLayer.name);
            }
            catch(e){
            var outerTarget = targetLayer.layers.add();
            outerTarget.name = subLayer.name;
            }
            outerTarget.locked = false;
            outerTarget.visible = true;
            outer(outerTarget,subLayer);
            }
            if(outerTarget.name == "Information" || outerTarget.name == "Guides" || outerTarget.name == "BKGRD, do not unlock"){
            outerTarget.locked = true;
            }
            }
            }
          
          
          
            //////////////////////
            ////Function Calls////
            //////////////////////
          }
          copyToMaster();
          copyToMaster = null;
          
          • 2. Re: Need help cleaning up a recursive loop, please.
            williamadowling Level 4

            So my next thought was to switch the app.CoordinateSystem to ARTBOARDCOORDINATESYSTEM and then set the activeArtboardIndex() to the newly created artboard, but that doesn't seem to make a difference???

             

            Does anyone have any insight on how app.CoordinateSystem works? The documentation is abysmal...

            • 3. Re: Need help cleaning up a recursive loop, please.
              Qwertyfly... Level 4

              I did the positioning for this by adding 2 lines and changing 1 other.

              it should not slow things down much.

               

              at the end of the createNewArtboard function add a return to hand back the rect array.

              docRef.activate();
                return rect;
                }
              

               

              then just below that function you have a call to it.

              add a variable to catch the rect array that it returns.

              var newABpos = createNewArtboard();
              

               

              then directly under the line that does the Duplication and the translate to put item in correct position

              var curItem2 = curItem.duplicate(targetLayer); 
                curItem2.translate(newABpos[0],newABpos[1]);
                }
              

              without digging too deep I think the translate is also needed in the inner or outer functions.

              if so this is repeated code and may be worth its own function?

               

              as for the error I did not get it.

              I did find that my 5th page was hanging off the drawing area.

              same with the 10th page.

              then it places the pages ontop of the last row.

              ie. page 6 is under page 11.

               

              the code could do with some indenting so it can be read easily.

               

              there are a few things I can see that may help speed.

              ie.

              your loop to push doc names to an array. is not needed.

              this can just be done when building the list of radio buttons.

              not a big deal as I guess it will never loop through alot of documents but 1 less loop is 1 less loop. and 1 less array of info the engine needs to assign memory for.

              • 4. Re: Need help cleaning up a recursive loop, please.
                Qwertyfly... Level 4

                I was having a play with this and came up with this.

                 

                the only seen improvement will be that the activeDocument won't show in the list to choose master.

                may also be a speed increase but no promises.

                 

                I do still get the errors on occasion. and as I get them in much simpler code and can't work out why I'm not sure what to do about it.

                 

                I have not touched you function for adding the art board, this needs work as I stated in the last post.

                I left a log function in that people will laugh at. I use this a lot as I find i can then write to the console very quickly when testing. i just find it faster to type "log(..." then "$.writeln(..."

                 

                the main thing I did was to clean up the recursive loop.

                could be more elegant but I think this is not too bad.

                I also added some indenting...

                function copyToMaster(){ 
                    //-------FUNCTIONS-------------------------
                    function miner(target,source,depth){  
                         depth++;
                        if(source.pageItems.length>0){  
                            for(var c=source.pageItems.length-1;c>-1;c--){  
                                var curItem = source.pageItems[c];  
                                var curItem2 = curItem.duplicate(target);
                                  curItem2.translate(newABpos[0],newABpos[1]);
                            }
                         }
                         if(source.layers.length>0){
                            for(var d=source.layers.length-1;d>-1;d--){  
                                  var targetLayer = getLayer(source.layers[d].name,target);
                                targetLayer.locked = false;  
                                targetLayer.visible = true;  
                                miner(targetLayer,source.layers[d],depth);  
                                  if(targetLayer.name == "Prepress" ){  
                                      targetLayer.visible = (depth > 2)?true:false;  
                                  } else if(targetLayer.name == "Information"){  
                                      targetLayer.locked = true;  
                                  }
                              }
                         }  
                    }  
                    
                    function getLayer(layName,parent){
                        try{
                            return parent.layers.getByName(layName);
                        }catch (e){
                            log(e + " - " + layName);
                            var mylay = parent.layers.add();
                            mylay.name = layName;
                            return mylay;
                        }
                    }
                
                
                    function getTargetDoc(){
                        var w = new Window("dialog", "Which is Master");  
                        w.newTextGroup = w.add("group");  
                        w.newTextGroup.text = w.add("statictext",undefined,"Which file do you want to merge to?");  
                        w.newTextGroup.align = "center";  
                        w.radioGroup = w.add("group");  
                        w.radioGroup.alignChildren = "left";  
                        w.radioGroup.orientation = "column";  
                        for(var a=0;a<app.documents.length;a++){  
                              if(app.documents[a] != app.activeDocument){
                                  w.radioGroup.add("radiobutton",undefined,app.documents[a].name);
                              }
                        }  
                        w.radioGroup.children[0].value = true;  
                        w.buttonGroup = w.add("group");  
                        w.buttonGroup.ok = w.buttonGroup.add("button", undefined, "OK");  
                        w.buttonGroup.can = w.buttonGroup.add("button", undefined, "Cancel");  
                         // function to get selected radio button  --  I like this method, quite neat...
                        function selected(which){  
                            for(var c=0;c<which.children.length;c++){  
                                if(which.children[c].value == true){  
                                    return which.children[c].text;  
                                }  
                            }  
                        }  
                        if(w.show() == 1){  
                            return (selected(w.radioGroup));  
                        } else{  
                            return;  
                        }  
                        w.show();  
                    }  
                
                
                    function createNewArtboard(){  
                        master.activate();  
                        var aBcount = master.artboards.length;  
                        var lastAB = master.artboards[master.artboards.length-1];  
                        var aB = lastAB.artboardRect;  
                        var left = aB[0];  
                        var top = aB[1];  
                        var right = aB[2];  
                        var bot = aB[3];  
                        var moveRight = 2100;  
                        var moveDown = 2100;  
                        if(aBcount != 5 && aBcount != 10){  
                            var newLeft = left + moveRight;  
                            var newRight = right + moveRight;  
                            var rect = [newLeft,top,newRight,bot];  
                            var newAb = master.artboards.add(rect);  
                        } else{  
                            var originAb = master.artboards[0].artboardRect;  
                            var oLeft = originAb[0];  
                            var oTop = originAb[1];  
                            var oRight = originAb[2];  
                            var oBot = originAb[3];  
                            oTop = oTop - moveDown;  
                            oBot = oBot - moveDown;  
                            var rect = [oLeft,oTop,oRight,oBot];  
                            var newAb = master.artboards.add(rect);  
                        }  
                        master.artboards.setActiveArtboardIndex(master.artboards.length-1);  
                        doc.activate(); 
                        return rect;
                    } 
                    function log(msg){$.writeln(msg);}
                    //---------MAINCODE----------------------
                    var doc = app.activeDocument;  
                    var layers = doc.layers;  
                    var masterFile = getTargetDoc();
                    if(masterFile == null){return;}  
                    var master = app.documents.getByName(masterFile);  
                    var newABpos = createNewArtboard();  
                    for(var a=layers.length-1;a>-1;a--){  
                         var targetLayer = getLayer(layers[a].name,master);
                        targetLayer.locked = false;  
                        targetLayer.visible = true; 
                         var depth = 0;
                         miner(targetLayer,layers[a],depth);
                        if(targetLayer.name == "Guides" || targetLayer.name == "BKGRD, do not unlock"){  
                            targetLayer.locked = true;  
                        }    
                    }  
                }  
                copyToMaster();  
                copyToMaster = null;
                

                 

                edit:

                HA HA.

                I indented with a different program. it must have used tabs not spaces.

                the above does not look as intended.

                edit2:

                Ok now it looks better...

                • 6. Re: Need help cleaning up a recursive loop, please.
                  williamadowling Level 4

                  Thanks a lot for your help Qwerty,

                   

                  I also noticed the issue with the 5th and 10th artboards being placed off the drawing area. I have fixed that issue as well so the artboards only go 4 wide. I thought i had that in the revised version i posted, but i guess not. I made a lot of changes at a lot of different times to try to get this working.

                   

                  I also do have my code nicely indented, but it always gets flattened when i put it into the forum.. i use tabs instead of spaces, so i'm sure that's the problem.. sorry i should have done something about that to make it easier for you to read.

                   

                  I see what you did with the transform function, unfortunately it doesn't do what I was hoping it'd do. It's still duplicating the item in place and then moving it. this leads to 2 steps instead of 1, which effectively doubles the time it takes to execute the script. It appears that both duplicate() and transform() carry an implied app.redraw();. That means that if something went wrong, you can't just undo and try again. Because you have to undo every step of the script (there can be thousands of pageItems that were duplicated and each one requires 2 undos.

                   

                  I poked around in your code and a lot of it makes sense. i can see where some of my errors were slowing stuff down. But on the other side of that coin, with your code, i'm getting MRAP errors much more frequently than i did with mine... Is this the type of errors you were talking about? I got these errors too frequently in my code as well, but usually i could run the script 5-7 times before I'd get any errors. With yours I get the error after 2 or 3 executions..

                   

                  I included a screenshot of the data browser. We can see that the error is simply due to Illustrator/ESTK not being able to read the typename of a layer. This is the type of error i get on the regular. The more complicated the script, the more frequently it happens. In some of my more simple scripts we use every day, i get errors just like this in attempting to read a swatch, or even sometimes, i get an error attempting to set the variable: docRef = app.activeDocument. Because ESTK can't read the activeDocument!!!?

                   

                  Getting really sick of CC very quickly.. But unfortunately, there's nothing I can do about it. We've created 10s of thousands of files with CC that are not backwards compatible with CS6 without manual backsaving..

                   

                  I really appreciate your help on this. But due to the stability issues i mentioned, I'm going to hang onto the script I currently have because it seems to be working satisfactorily. But I will for sure be studying your trimmed down recursion. I need to step through a few times to really see what's happening in there. As it stands I don't understand how it moves up a level after digging all the way down..

                  • 7. Re: Need help cleaning up a recursive loop, please.
                    Qwertyfly... Level 4

                    I don't expect you to use my code, I did it as much for the exercise as anything else.

                    though I was hoping to eliminate the errors. and yes I am getting the same errors, I get PARM as im on a pc while you get the MRAP telling me you are on a Mac.

                    I was getting them quite a bit as I was going, but once I was happy with the script I ran it over a dozen times with out issue.

                    I also found I was only getting the errors regularly when the script need to create a layer, top or sub, and it always bugged out on the "mylay.name = layName;"

                    was thinking it may have something to do with the try catch statement, but I can't see why.

                     

                    The PARM, MRAP errors are so common now its killing me.

                    I have been Playing with an extension built with HTML and CEP and these issues then cause whole program crashes.

                    it's driving me bonkers.

                     

                    as far as the move/translate is concerned. I just had a thought, but I just tested it and it does not make a lick of difference.

                    this is what my thought was.

                    var curItem2 = curItem.duplicate(target).translate(newABpos[0],newABpos[1]);

                     

                    maybe if you cycled through all items in a layer setting each to selected then did a app.copy() - app.paste() - then did the move to the selection it may be quicker?

                    if I have time I'll give it a go.

                    • 8. Re: Need help cleaning up a recursive loop, please.
                      Qwertyfly... Level 4

                      I'll need to remember this one, thanks Carlos.

                      • 9. Re: Need help cleaning up a recursive loop, please.
                        Qwertyfly... Level 4

                        on my above thought.

                        if you do not "NEED" empty layers.

                        could you set your master to paste remembers layers.

                        then do a selectall

                        copy

                        paste

                        move

                        • 10. Re: Need help cleaning up a recursive loop, please.
                          williamadowling Level 4

                          Thanks Qwerty. I had considered that as well as it was obviously much easier than writing the script to do it. However, I do need those empty layers (the files i'm copying are blank template files that will be used for mockup creation, and another script i wrote relies on artwork being placed on named layers). I also had some of the artists testing out "Paste Remembers Layers" for a couple days and all of them had nothing but complaints. I've always found that feature frustrating as well, because more often than not, it ends up creating a new layer where i didn't want one. There are also concerns I have with locked layers/sublayers. someone could forget that a sublayer was locked or hidden, and when they paste the artwork in, anything that was supposed to be on that layer would be missing. And if they got too far before they realized it, it could be a big waste of time for them to notice the problem and fix the problem.

                           

                          thanks again. =)

                          • 11. Re: Need help cleaning up a recursive loop, please.
                            Qwertyfly... Level 4

                            I was still thinking of a script.

                            you can do something like:

                             

                            executeMenuCommand('copy');

                            master.activate();

                            executeMenuCommand('pasteInPlace');

                            master.selection.translate(newABpos[0],newABpos[1]);


                            this was typed from memory so don't hold me to it being correct


                            even if you just did this per layer you reduce the number of steps greatly reducing the run time.

                            if you have 20 objects on a layer an have to duplicate and translate each one thats 40 steps.


                            if you could do something like:

                            app.activeDocument.layers.getByName('Layer 2').hasSelectedArtwork = true;

                            followed by the above code you are reducing the 40 steps to 5.


                            that last line of code will select items in subLayers though so it needs more thought.



                            • 12. Re: Need help cleaning up a recursive loop, please.
                              williamadowling Level 4

                              i do like that idea. However it looks like "Paste Remembers Layers" is not accessible through the script.. I can only read whether it's true : false. I would like to be able to avoid having the artists toggling that setting manually because other than this exact process.. it breaks almost every other process we have in some way or another..

                               

                              But that did get me thinking.. what if I selected al artwork in the source document via "artboard[0].hasSelectedArtwork = true", translated the artwork all together in the source document and then duplicated the artwork with the loop i already have.. that would at least cut those 40 steps down to 21..

                               

                              or. an even better solution would be for adobe to support a layer.duplicate function....

                              • 13. Re: Need help cleaning up a recursive loop, please.
                                Qwertyfly... Level 4

                                How's this?

                                 

                                function duplicateToMaster(){
                                    function pasteInMaster(){
                                        if(app.pasteRemembersLayers === false){
                                            app.pasteRemembersLayers = true;
                                            app.executeMenuCommand('pasteInPlace'); 
                                            app.pasteRemembersLayers = false;
                                        }else{
                                            app.executeMenuCommand('pasteInPlace'); 
                                        }
                                    }
                                
                                
                                var aDoc = app.activeDocument;
                                app.executeMenuCommand('selectall');  
                                app.executeMenuCommand('copy'); 
                                var bDoc = app.documents[1];
                                bDoc.activate(); 
                                pasteInMaster();
                                }
                                duplicateToMaster();
                                
                                • 14. Re: Need help cleaning up a recursive loop, please.
                                  williamadowling Level 4

                                  brilliant! this works perfectly and it works a hundred times faster than the initial loops i made. And it has the HUUUUGEE added benefit of performing all of the translations in one step, rather than doing each one separately (resulting in hundreds of undos if necessary). This works in the blink of an eye and has increased stability in the program by a ton! Thanks a lot Qwerty!

                                   

                                  Here's the final code i ended up with just for fun. Hope it can help someone else who's lurking around the forums.

                                   

                                  //Merge Template Rebuild
                                  //Author: William Dowling
                                  //Date: 9/17/15
                                  
                                  
                                  
                                  
                                  function mergeDocuments(){
                                  
                                  
                                      function getTargetDoc(){
                                          if(app.documents.length>1){
                                              var targetIndex = new Window("dialog", "Which is Master");
                                                  var newTextGroup = targetIndex.add("group");
                                                      newTextGroup.text = targetIndex.add("statictext",undefined,"Which file do you want to merge to?");
                                                      newTextGroup.align = "center";
                                                  var radioGroup = targetIndex.add("group");
                                                      radioGroup.alignChildren = "left";
                                                      radioGroup.orientation = "column";
                                                      for(var a=0;a<app.documents.length;a++){
                                                          if(app.documents[a] != app.activeDocument){
                                                              radioGroup.add("radiobutton",undefined,app.documents[a].name);
                                                          }
                                                      }
                                                      radioGroup.children[0].value = true;
                                                  var buttonGroup = targetIndex.add("group");
                                                      var ok = buttonGroup.add("button", undefined, "OK");
                                                      var can = buttonGroup.add("button", undefined, "Cancel");
                                              function selected(which){
                                                  for(var c=0;c<which.children.length;c++){
                                                      if(which.children[c].value == true){
                                                          return which.children[c].text;
                                                      }
                                                  }
                                              }
                                  
                                  
                                              if(targetIndex.show() == 1){
                                                  return (selected(radioGroup));
                                              }
                                              else{
                                                  return;
                                              }
                                  
                                  
                                              targetIndex.show();
                                          }
                                          else{
                                              alert("You need to have more than 1 document open!");
                                              valid = false;
                                              return;
                                          }
                                      }
                                      
                                      function createNewArtboard(){
                                          master.activate();
                                          var aBcount = master.artboards.length;
                                          var lastAB = master.artboards[master.artboards.length-1];
                                          var aB = lastAB.artboardRect;
                                          var left = aB[0];
                                          var top = aB[1];
                                          var right = aB[2];
                                          var bot = aB[3];
                                          var moveRight = 2100;
                                          var moveDown = 2100;
                                          if(aBcount != 4 && aBcount != 8){
                                              var newLeft = left + moveRight;
                                              var newRight = right + moveRight;
                                              var rect = [newLeft,top,newRight,bot];
                                              var newAb = master.artboards.add(rect);
                                          }
                                          else{
                                              var originAb = master.artboards[0].artboardRect;
                                              var oLeft = originAb[0];
                                              var oTop = originAb[1];
                                              var oRight = originAb[2];
                                              var oBot = originAb[3];
                                              oTop = oTop - moveDown;
                                              oBot = oBot - moveDown;
                                              var rect = [oLeft,oTop,oRight,oBot];
                                              var newAb = master.artboards.add(rect);
                                          }
                                          
                                          //determine how far in which direction the duplicates should move
                                          if(aBcount < 4){
                                              move = [(aBcount)*2100, 0]
                                          }
                                          else if(aBcount == 4){
                                              move = [0,2100];
                                          }
                                          else if(aBcount>4 && aBcount<8){
                                              move = [(aBcount)*2100, 2100];
                                          }
                                          else if(aBcount == 8){
                                              move = [0,4200];
                                          }
                                          else if(aBcount > 8 && aBcount<12){
                                              move = [(aBcount)*2100, 4200];
                                          }
                                          else{
                                              alert("Sorry. No more than 12 mockups are allowed in the same file.");
                                              valid = false;
                                              return;
                                          }
                                      }
                                      
                                      function copyArt(){
                                          docRef.activate();
                                          app.executeMenuCommand('selectall');
                                          translateArt(docRef.selection,move[0],move[1]);
                                          app.executeMenuCommand('copy');
                                      }
                                      
                                      function pasteArt(){
                                          master.activate();
                                          if(app.pasteRemembersLayers == false){
                                              app.pasteRemembersLayers = true;
                                              app.executeMenuCommand('pasteInPlace');
                                              app.pasteRemembersLayers = false;
                                          }
                                          else{
                                              app.executeMenuCommand('pasteInPlace');
                                          }
                                      }
                                      
                                      function translateArt(sel,right,down){
                                          for(var a=0;a<sel.length;a++){
                                              var cur = sel[a];
                                              sel.left = sel.left + right;
                                              sel.top = sel.top - down;
                                          }
                                      }
                                          
                                      function lockUnlock(doc,lock, vis){
                                          try{
                                              doc.layers.getByName("Guides").locked = lock;
                                              doc.layers.getByName("BKGRD, do not unlock").locked = lock;
                                              doc.layers[0].layers.getByName("Information").locked = lock;
                                              doc.layers[0].layers.getByName("Prepress").visible = vis;
                                          }
                                          catch(e){
                                              alert("Couldn't properly set layer properties.");
                                              valid = false;
                                              return;
                                          }
                                      }
                                      
                                      /////////////////
                                      ///Script Main///
                                      /////////////////
                                      
                                      /////////////////////////////
                                      ///Script Global Variables///
                                      /////////////////////////////
                                      
                                      var docRef = app.activeDocument;
                                      var layers = docRef.layers;
                                      var masterFile = getTargetDoc();
                                      if(masterFile == null){return;}
                                      var master = app.documents.getByName(masterFile);
                                      var valid = true;
                                      var move = [];
                                      
                                      ///////////////////////
                                      ///Function Callouts///
                                      ///////////////////////
                                      
                                      
                                      createNewArtboard();
                                      if(valid){
                                          lockUnlock(docRef,false,true);
                                          lockUnlock(master,false,true);
                                      }
                                      if(valid){
                                          copyArt();
                                          pasteArt();
                                      }
                                      lockUnlock(master,true,false);
                                      
                                      
                                      
                                  }
                                  mergeDocuments();
                                  
                                  • 15. Re: Need help cleaning up a recursive loop, please.
                                    Qwertyfly... Level 4

                                    Glad we could get it work well for you.

                                    thanks for posting your final code.

                                    these forums a great database of info that the Adobe documentation just does not touch on.

                                    I hope it does help others down the track.

                                     

                                    in all likelihood it will be me at some point