0

This script here renames the sheetnames with the value in A1. I manage a school database with over 150 sheets. The script is throwing a maximum time execution timeout error. I have read on the forums here that you can reduce service calls. This here Google app script timeout ~ 5 minutes? looks like a solution but I can't in the life of me wrap my head around what's going on.

I should probably mention that I am a complete noob and your help will be of immense help.

function onEdit() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();

// Array holding the names of the sheets to exclude from the execution
var exclude ="Sheet1","Sheet2","Sheet3","Article","Frontpage","Logos","Sheet4","Sheet5","Sheet6","Sheet10"];

for(var s=10;s<allsheets.length;s++) {
var sheet = allsheets[s];
var oldName = sheet.getName();
var newName = sheet.getRange(1,1).getValue();
if (newName.toString().length>0 && newName !== oldName) {
sheet.setName(newName);

// Stop iteration execution if the condition is meet.
if(exclude.indexOf(sheet.getName())==-1) continue;
}

} // end of loop

} // end of function

Kindly help me reduce the number of service calls the script is making or a faster way to avoid the timeout error.

//Updated Script

//Sample code below generating error missing ) after condition

function testArray() {
    var arr = ["Sh1","Sh2","Sh3","Sh4","Sh5","Sh6","Sh7","Sh8","Sh9","Sh10"];  //etc etc
    var res = [];

    arr.forEach(function (element,index) {
        if(index>9) {
            var sheet = allsheets[s];
            var oldName = sheet.getName();
            var newName = sheet.getRange(1,1).getValue(); 

            if (newName.toString().length>0 && newName !== oldName) {
                sheet.setName(newName); // Stop iteration execution if the condition is meet. 
                if(exclude.indexOf(sheet.getName())==-1}) continue; //iterable code goes here; 
            }
        // }
     }); 
}
Rubén
  • 34,714
  • 9
  • 70
  • 166
  • Could you please include your execution transcript so that we can see what's taking the most time? This can be viewed by running the script then going to `View > Execution transcript`. – ross May 28 '19 at 13:51
  • Hi, `[19-05-28 08:12:42:455 PDT] Range.getValue() [2.157 seconds]` there are many of this so I didn't want to post the entire log here because this only is repeating. –  May 28 '19 at 15:17

1 Answers1

1

First of all, get rid of unnecessary calls - did you consider the splice() part of my answer to your previous question?

allsheets.splice(0,10); //0-based start and end indexes;

If excluded sheet names can be encountered anywhere, keep your exclude Array and if statement (btw, there seems to be a typo in your sample - the Array declaration misses an opening bracket).

Regardless of how you exclude your first 10 sheets, the call to stop iteration becomes overkill as you invoke getName() method allsheets.length times (thus, 150 unnecessary method calls) - reference the newName variable instead.

You can further reduce calls by checking for the condition before calling the setName() method (assuming you do not want to do anything is new name is in exclude Array).

Then, use the for loop to do the same manipulations (note that in case the Array is filtered using splice(), index s should be 0):

for(var s=10; s<allsheets.length; s++) {
  var sheet = allsheets[s];
  var oldName = sheet.getName();
  var newName = sheet.getRange(1,1).getValue();

  //this reduces setName() calls if you don't need to set reserved names;
  if(exclude.indexOf(newName)!==-1) { continue; }

  if (newName.toString().length>0 && newName !== oldName) {
    sheet.setName(newName);
  }
}

Alternatively, you can use a forEach to make manipulations you want. This is how the whole function will look like using splice() and forEach():

function testArray() { 

  var ss = SpreadsheetApp.getActive();
  var arr = ss.getSheets();

  arr.splice(0,10); //removes first 10 Sheets from Array;

  var exclude = []; //fill with unchangeable names;

  arr.forEach(function (sheet,index) { //iterates over Array of Sheets;

      var oldName = sheet.getName(); 
      var newName = sheet.getRange(1,1).getValue(); 

      if(newName.toString().length>0 && newName!==oldName) { 

        //Move to next iteration if new name should be excluded;
        if(exclude.indexOf(newName)===-1) {
          sheet.setName(newName); //set name otherwise;
        }

      }

  }); // end of loop 

} // end of function
  • This answer assumes that you want to exclude first ten sheet name, not the *ten sheet names from the Array provided* - judging from your answer, I might be wrong here, please, let me know if this is the case, I will update the answer accordingly – Oleg Valter is with Ukraine May 28 '19 at 14:06
  • Just in case, updated the answer to be solution-independed, will keep looking if it can be optimized further. – Oleg Valter is with Ukraine May 28 '19 at 14:36
  • About the missing bracket that's a typo. I was testing the two options for excluding the first 10 sheets. They are the same ones I listed there so I should remove the list and let the script check for the first 10 and exclude them. –  May 28 '19 at 15:14
  • Hi Oleg, getting this error when i run the script above `ReferenceError: "allsheets" is not defined. (line 1, file "Code")` –  May 28 '19 at 15:21
  • Hi! You should call this method (if we are talking about `splice()` here) only after you got your sheets written into a `allsheets` variable - judging from the error, you tried to invoke it globally on the first line, whereas you should call it in-function after calling `ss.getSheets()` – Oleg Valter is with Ukraine May 28 '19 at 15:24
  • I have tried but each time I get an error - `Continue must be inside loop. (line 48, file "Code")` Looks like this is beyond my reach. Here is what I did, I listed all sheets in an array then added the iteration code after the `if(index>9) { res.push(element); //push to test Array` Any pointers or a simplified example. Sorry that I have to ask again. –  May 28 '19 at 19:56
  • @DanstanOngubo, please, update your question with all the code that you currently have, looks like there is a closure problem (the error message states that continue is outside the loop, which means that most likely you accidentally closed the loop before invoking the `if` statement. No worries! – Oleg Valter is with Ukraine May 28 '19 at 20:01
  • `function testArray() { var arr = ["Sh1","Sh2","Sh3","Sh4","Sh5","Sh6","Sh7","Sh8","Sh9","Sh10"];//etc etc var res = []; arr.forEach(function (element,index) { if(index>9) { var sheet = allsheets[s]; var oldName = sheet.getName(); var newName = sheet.getRange(1,1).getValue(); if (newName.toString().length>0 && newName !== oldName) { sheet.setName(newName); // Stop iteration execution if the condition is meet. if(exclude.indexOf(sheet.getName())==-1) continue; //iterable code goes here; } }); }` –  May 28 '19 at 21:33
  • Thanks! Yep, there is a missing `}` right before the `)` - there should be three of curly brackets to properly close one of the `if` statements. – Oleg Valter is with Ukraine May 28 '19 at 21:41
  • `//...truncating for character count var res = []; arr.forEach(function (element,index) { if(index>9) { var sheet = allsheets[s]; var oldName = sheet.getName(); var newName = sheet.getRange(1,1).getValue(); if (newName.toString().length>0 && newName !== oldName) { sheet.setName(newName); // Stop iteration execution if the condition is met. if(exclude.indexOf(sheet.getName())==-1}) continue; } } // end of loop } // end of function` Sorry, Missing ) after condition. I have tried adding the bracket after but it won't work. What I'm I doing wrong? –  May 28 '19 at 22:06
  • Please, simply update your question with this code (for example, after the sample code) - posting it in comments makes it hard to parse and read (you can edit your posts as much as you want to) – Oleg Valter is with Ukraine May 28 '19 at 22:23
  • Also, I noticed that you are trying to use continue inside a forEach loop, this should not be used here (as forEach uses a callback function, not a proper loop) - I updated my answer with an example of the test function you are trying to build - please, do not forget to actually fetch sheets at the start – Oleg Valter is with Ukraine May 28 '19 at 22:49
  • Your final test script worked! I thank you from the bottom of my heart! Good luck buddy. –  May 28 '19 at 23:56
  • My pleasure! Take a look at the MDN [documentation on Array class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) when you have time (and their JS doc in gerenal - it greatly helped me when I started). And to you! – Oleg Valter is with Ukraine May 29 '19 at 00:15