Script Time Exceeded in Google App Script - google-apps-script

This is the first time I am programming using Google Script and I cannot figure out how to add a function to circumvent Google's error message of exceeding processing time. Could you please help?
The program gets the number of bars and pints ordered and references them into a different sheet which has a calculator to calculate costs and outputs the value. Would really appreciate the help
/**
*
*
*/
function STBIBOL()
{
var r = 6
var destclm = 11
var pintsclm = 105
var barsclm = 101
var spreadsheet_url = 'https://docs.google.com/spreadsheets/d/1cqgdo_pgJ4n0xhXqMah24g6jjv7sfl2o92k1pwXNUuo/edit#gid=532254312';
var sheet_name = 'BOLs Entered for Fulfillment';
var sheet_name1 = 'STBI Calculator';
var ss = SpreadsheetApp.openByUrl(spreadsheet_url);
var sheet = ss.getSheetByName(sheet_name);
var sheet1 = ss.getSheetByName(sheet_name1);
var lastRow = sheet.getLastRow();
for(i =1; i< 20; i++)
{
var rangeD = sheet.getRange(r,destclm)
var dest = rangeD.getValue()
var rangeS = sheet.getRange(r,pintsclm)
var pints = rangeS.getValue()
var rangeB = sheet.getRange(r, barsclm)
var bars = rangeB.getValue()
var range = sheet1.getRange(14,3)
range.setValue(dest)
var range2 = sheet1.getRange(11, 3)
range2.setValue(pints)
var range3 = sheet1.getRange(12, 3)
range3.setValue(bars)
var rangev = sheet1.getRange(8,3)
var value = rangev.getValue()
var range4 = sheet.getRange(r,110)
range4.setValue(value)
r = r + 1
}
}

Instead of making multiple calls to GAS services on each run of the loop, which causes the execution to fail, you could simply get the entire range in one call like this:
var range1 = sheet1.getRange(startRow, startColumn, numberOfRows, numberOfColumns);
If the range in the 2nd sheet has the same dimensions (same number of rows and columns) as the 1st sheet, you could simply 1) get the values from the original sheet as a 2d array
var values1 = range.getValues();
2) Write values to the 2nd sheet
var range2 = sheet2.getRange(startRow, startColumn, numberOfRows, numberOfColumns);
range2.setValues(values1);

Related

Missing Headers row and Leaving space

I was working with a combine sheets app script which is working fine at the spot by mereging A bunch of 36 sheetsinto one masterenter code here
the only flaw of the script is that it is not showing a common header row in the top and also leaving a space after data end from first sheets and so on >>>
here the code can anyone help a bit here
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var s1= sApp.getSheetByName("A1");
var s2= sApp.getSheetByName("A2");
var s3= sApp.getSheetByName("A3");
var s4= sApp.getSheetByName("A4");
var s5= sApp.getSheetByName("A5");
var s6= sApp.getSheetByName("A6");
var s7= sApp.getSheetByName("A7");
var s8= sApp.getSheetByName("A8");
var s9= sApp.getSheetByName("A9");
var s10= sApp.getSheetByName("A10");
var s11= sApp.getSheetByName("A11");
var s12= sApp.getSheetByName("A12");
var s13= sApp.getSheetByName("A13");
var s14= sApp.getSheetByName("A14");
var s15= sApp.getSheetByName("A15");
var s16= sApp.getSheetByName("A16");
var s17= sApp.getSheetByName("A17");
var s18= sApp.getSheetByName("A18");
var s19= sApp.getSheetByName("A19");
var s20= sApp.getSheetByName("A20");
var s21= sApp.getSheetByName("A21");
var s22= sApp.getSheetByName("A22");
var s23= sApp.getSheetByName("A23");
var s24= sApp.getSheetByName("A24");
var s25= sApp.getSheetByName("A25");
var s26= sApp.getSheetByName("A26");
var s27= sApp.getSheetByName("A27");
var s28= sApp.getSheetByName("A28");
var s29= sApp.getSheetByName("A29");
var s30= sApp.getSheetByName("A30");
var s31= sApp.getSheetByName("A31");
var s32= sApp.getSheetByName("A32");
var s33= sApp.getSheetByName("A33");
var s34= sApp.getSheetByName("A34");
var s35= sApp.getSheetByName("A35");
var s36= sApp.getSheetByName("A36");
var s37= sApp.getSheetByName("Master");
// If Master doesn't exist you'll need to create it here.
var s1values = s1.getRange(2,1,s1.getLastRow(),27).getValues();
var s2values = s2.getRange(2,1,s2.getLastRow(),27).getValues();
var s3values = s3.getRange(2,1,s3.getLastRow(),27).getValues();
var s4values = s4.getRange(2,1,s4.getLastRow(),27).getValues();
var s5values = s5.getRange(2,1,s5.getLastRow(),27).getValues();
var s6values = s6.getRange(2,1,s6.getLastRow(),27).getValues();
var s7values = s7.getRange(2,1,s7.getLastRow(),27).getValues();
var s8values = s8.getRange(2,1,s8.getLastRow(),27).getValues();
var s9values = s9.getRange(2,1,s9.getLastRow(),27).getValues();
var s10values = s10.getRange(2,1,s10.getLastRow(),27).getValues();
var s11values = s11.getRange(2,1,s11.getLastRow(),27).getValues();
var s12values = s12.getRange(2,1,s12.getLastRow(),27).getValues();
var s13values = s13.getRange(2,1,s13.getLastRow(),27).getValues();
var s14values = s14.getRange(2,1,s14.getLastRow(),27).getValues();
var s15values = s15.getRange(2,1,s15.getLastRow(),27).getValues();
var s16values = s16.getRange(2,1,s16.getLastRow(),27).getValues();
var s17values = s17.getRange(2,1,s17.getLastRow(),27).getValues();
var s18values = s18.getRange(2,1,s18.getLastRow(),27).getValues();
var s19values = s19.getRange(2,1,s19.getLastRow(),27).getValues();
var s20values = s20.getRange(2,1,s20.getLastRow(),27).getValues();
var s21values = s21.getRange(2,1,s21.getLastRow(),27).getValues();
var s22values = s22.getRange(2,1,s22.getLastRow(),27).getValues();
var s23values = s23.getRange(2,1,s23.getLastRow(),27).getValues();
var s24values = s24.getRange(2,1,s24.getLastRow(),27).getValues();
var s25values = s25.getRange(2,1,s25.getLastRow(),27).getValues();
var s26values = s26.getRange(2,1,s26.getLastRow(),27).getValues();
var s27values = s27.getRange(2,1,s27.getLastRow(),27).getValues();
var s28values = s28.getRange(2,1,s28.getLastRow(),27).getValues();
var s29values = s29.getRange(2,1,s29.getLastRow(),27).getValues();
var s30values = s30.getRange(2,1,s30.getLastRow(),27).getValues();
var s31values = s31.getRange(2,1,s31.getLastRow(),27).getValues();
var s32values = s32.getRange(2,1,s32.getLastRow(),27).getValues();
var s33values = s33.getRange(2,1,s33.getLastRow(),27).getValues();
var s34values = s34.getRange(2,1,s34.getLastRow(),27).getValues();
var s35values = s35.getRange(2,1,s35.getLastRow(),27).getValues();
var s36values = s36.getRange(2,1,s36.getLastRow(),27).getValues();
// Now, we can put out all together and stuff it in Master
var s37values = [];
s37values = s1values.concat(s2values,s3values,s4values,s5values,s6values,s7values,s8values,s9values,s10values,s11values,s12values,s13values,s14values,s15values,s16values,s17values,s18values,s19values,s20values,s21values,s22values,s23values,s24values,s25values,s26values,s27values,s28values,s29values,s30values,s31values,s32values,s33values,s34values,s35values,s36values);
s37.getRange(1,1,s37values.length,27).setValues(s37values);
}
Modification points:
About not showing a common header row in the top, in your script, all values are retrieved from the 2nd row. I thought that this might be the reason for your issue. From a common header row, in this modification, the header row is retrieved from the 1st sheet.
About also leaving a space after data end from first sheets and so on, I thought that the reason of your issue is due to getRange(2,1,s1.getLastRow(),27). In this case, the values are retrieved from 2nd row to the last row + 1 rows. In this case, it required to be getRange(2,1,s1.getLastRow() - 1,27).
In your script, I thought that the sheet names from "A1" to "A36" can be created using a script.
When these points are reflected in your script, it becomes as follows.
Modified script:
function combineSheets() {
var sApp = SpreadsheetApp.getActiveSpreadsheet();
var values = [...Array(36)].map((_, i) => `A${i + 1}`).flatMap((s, i) => {
var sheet = sApp.getSheetByName(s);
var lastRow = sheet.getLastRow();
if (i == 0) {
return sheet.getRange(1, 1, lastRow, 27).getValues();
}
return lastRow > 1 ? sheet.getRange(2, 1, lastRow - 1, 27).getValues() : [];
});
sApp.getSheetByName("Master").getRange(1, 1, values.length, 27).setValues(values);
}
The headr row is retrieved from the 1st sheet.
Note:
In this modification, it supposes that the sheet names of "A1" to "A36" and "Master" are existing in your Spreadsheet. Please be careful about this.
From a common header row in the top, this script supposes that your all sheets have the same header row. Please be careful about this.
About Exception: The number of rows in the range must be at least 1. AT HERE................var values = [...Array(36)].map((_, i) => A${i + 1}).flatMap((s, i) => { var sheet = sApp.getSheetByName(s); return sheet.getRange(i == 0 ? 1 : 2, 1, sheet.getLastRow() - (i == 0 ? 0 : 1), 27).getValues(); , from your question, I had thought that your all sheets have the values. But from your reply, it seems that my understanding was not correct. So, I updated my proposed script. Could you please confirm it?
References:
getRange(row, column, numRows, numColumns)
map()

How to transfer a row to another tab in order to archive it in googlesheet

Quite new to JS, I'm willing to do some repetitive task within google sheet script editor.
The idea is to check all rows of tab1. For each row, if date in column D is older than 5 days prior to today, it transfers the full row to tab2 first empty row and make sure the row doesn't exist anymore in tab1. The idea is to archive data older than 5 days.
I could do this with VBA but I am very new to google sheet script and need the help of the community (I'm afraid I really don't have the basis of JS).
I will then add a time trigger (I know how to do this !) for this script.
EDIT:
from this script deleting :
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Foglio1");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][2];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < oneweekago) { sheet.deleteRow(i); } } }
And this script moving data :
function moveCols() {
var ss = SpreadsheetApp.getActive();
var sourceSheet = ss.getSheetByName('Sheet1');
var destSheet = ss.getSheetByName('Sheet2');
sourceSheet.getRange('A:A').moveTo(destSheet.getRange('G1'))
sourceSheet.getRange('B:B').moveTo(destSheet.getRange('I1'))
sourceSheet.getRange('C:C').moveTo(destSheet.getRange('L1')) }
I was able to do the below :
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("input");
var destSheet = ss.getSheetByName("input archive");
var datarange = sheet.getDataRange();
var lastrow = datarange.getLastRow();
var values = datarange.getValues();// get all data in a 2D array
var currentDate = new Date();
var oneweekago = new Date();
oneweekago.setDate(currentDate.getDate() - 7);
for (i=lastrow;i>=2;i--) {
var tempdate = values[i-1][2];// arrays are 0 indexed so row1 = values[0] and col3 = [2]
if(tempdate < oneweekago) {
sourceSheet.getRange('i:i').moveTo(destSheet.getRange('LASTAVAILABLEROW'));
} } }
But I have no idea how to paste to last row. Maybe this will work ?
var Avals = destSheet.getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
Haven't got time to write a full answer but hope this gives you some guidance
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("data");
var sheet2 = ss.getSheetByName("archive");
var data = sheet1.getRange("I1:I"+sheet.getLastRow()).getValues();
sheet2.getRange("A" + (sheet2.getLastRow()+1) + ":A" +sheet.getLastRow()).setValues(data);

Method is heavily used by the script

I am very new on using Google Apps Script and has a shallow knowledge on programming. What I am trying to do is copy the values of specific columns to a different Spreadsheet. Here's my code:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var x=2, y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
for (j=0; j<maxRows; j++){
var eventID = selectedSheets[i].getRange(y,2).getValue();
var employeeName = selectedSheets[i].getRange(y,3).getValue();
var productionDate = selectedSheets[i].getRange(y,4).getValue();
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,1).setValue(eventID);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,2).setValue(employeeName);
var consolidatedSheetCell = consolidatedSheet.getRange(lastRow,3).setValue(productionDate);
y++;
lastRow++;
}
}
}
However, I am experiencing this notification on the Execution hints (light bulb icon):
screenshot of the message. I am thinking that my code can be simplified. I am just not sure how to do it. Thank you in advance.
Every line with .getRange().getValue() and getRange.setValue() is a call to the file. Since you have these inside a for(){} loop, they are being called many times. Your goal is to limit these to as few as possible. Since you can read and write a range, you could do something similar to this:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var responses = ss.getSheetByName("Responses ID");//Where ID's of the spreadsheets are listed.
var consolidatedSheet = ss.getSheetByName("Consolidated");//Where the data should be pasted.
var responseColValues = responses.getRange(2,2, responses.getMaxRows() -1).getValues();
var responsesIds = [i for each (i in responseColValues)if (isNaN(i))];
var ssSelected = SpreadsheetApp.openById(responsesIds[0]);
var selectedSheets = ssSelected.getSheets();
for (i=0; i<3; i++){
var maxRows = selectedSheets[i].getLastRow()-1;
var y=2;
var lastRow = consolidatedSheet.getLastRow()+1;
var copyValues = selectedSheets[i].getRange(y,2, maxRows, 4).getValues();
consolidatedSheet.getRange(lastRow,1, maxRows, 4).setValues(copyValues);
}
}

Looping over row and copy them on the next sheet

I've a list of rows automatically updated and I would like to copy and save them on daily basis.
I've wrote the following script :
function saveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var rowcount = sheet.getRange("A1:A").getValues();
var sheetdef = ss.getSheets()[1];
for(var i = 0; i < rowcount.length; i++){
var weeknum = sheet.getRange('Feed!A1').getValue();
var year = sheet.getRange('Feed!B1').getValue();
var date = sheet.getRange('Feed!C1').getValue();
var sessions = sheet.getRange('Feed!D1').getValue();
sheetdef.appendRow([weeknum,year,date,sessions]);
}}
but as you will see it never stop running, plus it only copy the data from the first row. if I'm able to identify my issue I don't really know how to solve it.
I assume that my rowcount line if wrong since it also count blank row. I also need to update sheet.getRange formula so they take dynamic argument.
thanks !
Untested but should work:
function saveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
//var rowcount = sheet.getRange("A1:A").getValues();
var Avals = ss.getRange("A1:A").getValues();
var rowcount = Avals.filter(String).length; //This will take the last non blank cell from A column
var sheetdef = ss.getSheets()[1];
//I suggest you define Feed sheet as well
var feedsheet = ss.getSheetsByName("Feed")
for(var i = 0; i < rowcount.length; i++){
var weeknum = feedsheet(i,1).getValue(); //<- ith row and first/second column
var year = feedsheet.getRange(i,2).getValue();
var date = feedsheet.getRange(i,3).getValue();
var sessions = feedsheet.getRange(i,4).getValue();
sheetdef.appendRow([weeknum,year,date,sessions]);
}}
With the help of Vasim, I've come up with this:
// function to save data Tendance sessions
function saveData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var sheetdef = ss.getSheets()[1];
lastRow = sheet.getLastRow();
for (i = lastRow; i > 0; i--){
var weeknum = sheet.getRange(i,1).getValue();
var year = sheet.getRange(i,2).getValue();
var date = sheet.getRange(i,3).getValue();
var sessions = sheet.getRange(i,4).getValue();
sheetdef.appendRow([weeknum,year,date,sessions]);
}}

Copy rows from one sheet to another

I need to create a master sheet for our managers that only include activity happening in their areas (I have a script for this that does what I need). These sheets are populated from my master sheet (and are not in the same workbook).
I need to have rows copy to the applicable sheet when there is a new submission. My code below dumps them all to one sheet and I'm not sure why. I'm assuming I don't have the right condition but how do you say "move rows to this sheet when it's this manager"? I thought calling the sheet ID by row would be enough, but I guess not.
Would I then have to do an if else statement for every manager? That will get tedious since I have about 80 managers.
Below is my current code. Any help or advice is appreciated!
function moveRows(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName("Form Responses 1");
var data = sh.getDataRange().getValues();
// Grab the Headers
var headers = sh.getRange(1,1,1,sh.getLastColumn()).getValues();
var nameCol = headers[0].indexOf('Enter Your Name');
var candCol = headers[0].indexOf('Choose Candidate');
var typeCol = headers[0].indexOf('Merged Experience');
var docCol = headers[0].indexOf('Document Link');
var timeCol = headers[0].indexOf('Timestamp');
var subjectCol = headers[0].indexOf('Choose the Content Area');
var ratingsCol = headers[0].indexOf('Ratings Summary');
var accessCol = headers[0].indexOf('Access');
var activityCol = headers[0].indexOf('Copied to Activity Sheet');
var masterCol = headers[0].indexOf('Master Activity Sheet');
var target = [];
// Loop over the values line by line
for (var i = 0; i < data.length; i++) {
var row = data[i];
var name = row[nameCol];
var activity = row[activityCol];
var master = row[masterCol];
var candidate = row[candCol];
var type = row[typeCol];
var subject = row[subjectCol];
var ratings = row[ratingsCol];
var access = row[accessCol];
var guide = row[docCol];
var time = row[timeCol];
if (activity == "") { // if condition is true copy the whole row to target
target.push([time,name,candidate,subject,type,guide,ratings]);
Logger.log(target);
var ss2 = SpreadsheetApp.openById(master);
var sh2 = ss2.getSheetByName("Sheet1");
sh2.getDataRange().offset(sh2.getLastRow(), 0, target.length, target[0].length).setValues(target);
}
}
}
Note: I have a bunch of different scripts that move rows from one tab to another, but I couldn't find anything where I move it across multiple workbooks.
What you can do is to have an array with for each manager the sheet where to copy the data.
var managerSheet = {
"manager1":"SheetAzerty",
"manager2":"SheetQwerty"
};
to select the sheet just do :
var manager = "manager1"; //This is the value you retrieve
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(managerSheet[manager]);
Stéphane