Method is heavily used by the script - google-apps-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);
}
}

Related

Script not finishing and error deletes the ranges that already ran

For some reason this script will run through exactly how I want it to. Then it will continue to load, then delete half the ranges that I have put into the cells and come up with the error:
"TypeError: Cannot read properties of undefined (reading 'getRange')
newSheet
# New sheet.gs:11"
Why would this happen if the script runs perfectly? The getRange is reading in line 11 or it wouldn't run the script correctly at first. I tried putting this into a new script window to see if it is just a fluke but that did not help.
function newSheet() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
const templateSheet = ss.getSheetByName("Template");
var sheetName = templateSheet.getRange("G1").getValue();
templateSheet.copyTo(ss).setName("F"+sheetName);
var ods = ss.getSheetByName("F"+sheetName);
var ds = SpreadsheetApp.openById("1meEEfjXuOKQ3jCZi2wwmvz7CH83crsPzgnhOEC0rDhI");
var sheet = ds.getSheets();
for (var i=0;i<=sheet.length;i++){
var sheets = sheet[i]
var range = sheets.getRange("A1").getValue();//this is the spot that is getting the error
var label = templateSheet.getRange("A1").getValue();
var values1 = sheets.getRange("A9:B14").getValues();
var values2 = sheets.getRange("G8").getValues();
var values3 = sheets.getRange("A17:A22").getValues();
var values4 = sheets.getRange("A25:A32").getValues();
var values5 = sheets.getRange("A34:G44").getValues();
var values6 = sheets.getRange("A45:A49").getValues();
var values7 = sheets.getRange("A52:A58").getValues();
var values8 = sheets.getRange("A62:A67").getValues();
var values9 = sheets.getRange("E69:E74").getValues();
var values10 = sheets.getRange("E100:E103").getValues();
var values11 = sheets.getRange("H100:H101").getValues();
if(range==label){
ods.getRange("A9:B14").setValues(values1);
ods.getRange("G8").setValues(values2);
ods.getRange("A17:A22").setValues(values3);
ods.getRange("A25:A32").setValues(values4);
ods.getRange("A34:G44").setValues(values5);
ods.getRange("A45:A49").setValues(values6);
ods.getRange("A52:A58").setValues(values7);
ods.getRange("A62:A67").setValues(values8);
ods.getRange("E69:E74").setValues(values9);
ods.getRange("E100:E103").setValues(values10);
ods.getRange("H100:H101").setValues(values11);
}
}
}

Copying Data from One Spreadsheet to Several Others with Array and For Loop - Repost as suggested did not solve

The following appears to work, however the code times out. A portion of the data is transferred to the 1st sheet of the loop and then the following error occurs: "Exception: Service Spreadsheets failed while accessing document with id "Y". CopyCmpstrs # Code.gs:33" For the purpose of the post, I removed the actual spreadsheetIDs.
The following has been suggested as a solution, however this only deals with data within the same spreadsheet and is a separate issue. The issue that I am having, I think, is that the dataset is large and the 2nd sheet being pasted to is freezing: Is possible to copy a data range from one spreadsheet to another?
Is possible to copy a data range from one spreadsheet to another?
function CopyCmpstrs() {
var DashboardSSID = "X";
var PaymentSSID = "Y";
var SalesSSID = "Z";
var FormsSSID = "A";
var ProductSSID = "B";
var InvoiceSSID = "C";
var TargetSSID = [PaymentSSID,SalesSSID,FormsSSID,ProductSSID,InvoiceSSID];
var ssSource = SpreadsheetApp.openById(DashboardSSID);
var CmpstrsSheet = ssSource.getSheetByName("Cmpstrs");
var CmpstrsSheetName = CmpstrsSheet.getName();
var RowCountSource = CmpstrsSheet.getRange(1, 2).getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var CustomerData = CmpstrsSheet.getSheetValues(1,1,RowCountSource,176);
var ArraySize = TargetSSID.length;
for (var i=0; i<= ArraySize; i++){
var TargetSS = SpreadsheetApp.openById(TargetSSID[i]);
var TargetSheet = TargetSS.getSheetByName(CmpstrsSheetName);
var MaxRow = TargetSheet.getMaxRows();
var MaxCol = TargetSheet.getMaxColumns();
var TargetFullRange = TargetSheet.getRange(1,1,MaxRow,MaxCol);
TargetFullRange.clearContent();
var TargetRange = TargetSheet.getRange(1,1,RowCountSource,176);
TargetRange.setValues(CustomerData);
}
}

Google Apps Script Error "Exception: Invalid argument: options. Should be of type: Map"

I'm trying to make a quick script to copy information from a series of spreadsheets into a single spreadsheet. I'm getting an error
"Exception: Invalid argument: options. Should be of type: Map".
I know very little about maps, and this error makes no sense to me.
function make_new_contact_lists() {
DriveApp.getFileById("1IZBpDno4MOBeiGJeIKd2ykHpCr2359jhcV_SJpSuQ94");
var ss = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = ss.getSheetByName("Sheet2")
ss.setActiveSheet(sheet);
var lr = sheet.getLastRow();
var range = sheet.getRange("A2:B" + lr).getValues();
var list = [];
list.push([range]);
for (i = 0; i < list.length; i++) {
var entry = list[i];
var name = entry[0];
var fileID = entry[1];
var newsheet =
SpreadsheetApp.openById("1IZBpDno4MOBeiGJeIKd2ykHpCr2359jhcV_SJpSuQ94");
SpreadsheetApp.setActiveSpreadsheet(newsheet);
/**-->This is where the error gets flagged**/
newsheet.insertSheet(name);
var newsheet2 = newsheet.setActiveSheet(name);
var file = SpreadsheetApp.getFileById(fileID);
var spreadsheet = file.setActiveSpreadsheet();
var current = spreadsheet.getSheetByName("Current Contacts");
spreadsheet.setActiveSheet(current);
var range2 = current.getRange("A1:G3").getValues();
current.setValues
}
}
Thank you for any help you can provide
Issue:
var range = sheet.getRange("A2:B"+lr).getValues();//[[a2,b2],..]
var list = [];
list.push([range]); //[[[[a2,b2],[a3,b3],..]]]
for (i=0; i < list.length; i++){
var entry = list[i];//[[[a2,b2],[a3,b3],..]]
var name = entry[0];//[[a2,b2],[a3,b3],..]
list is a 4D array and name is a 2D array. newsheet.insertSheet(name) expects name to be a string or object, whereas the script is providing a 2D array.
Solution:
Directly access range as a 2D array, which makes name a string
Snippet:
const range = sheet.getRange("A2:B"+lr).getValues();//[[a2,b2],..]
for (const i=0; i < range.length; i++){
var entry = range[i];//[a2,b2]
var name = entry[0];//"a2"
Some of your code simply does not make sense. You might be better of to start again with this:
function make_new_contact_lists() {
DriveApp.getFileById("1IZBpDno4MOBeiGJeIKd2ykHpCr2359jhcV_SJpSuQ94");
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet2")
const lr = sh.getLastRow();
const vs = sh.getRange("A2:B" + lr).getValues();
const ss1 = SpreadsheetApp.openById("1IZBpDno4MOBeiGJeIKd2ykHpCr2359jhcV_SJpSuQ94");
for (i = 0; i < vs.length; i++) {
let entry = vs[i];
let name = entry[0];
let fileID = entry[1];
let nsh = ss1.insertSheet(name);
let ss2 = SpreadsheetApp.openById(fileID);
let csh = ss2.getSheetByName("Current Contacts");
let vs2 = csh.getRange("A1:G3").getValues();
//the rest of the code makes no sense
csh.setValues
}
}
And don't just make up methods go read the documentation about them paying attention to parameters and return values.

Double the variables in move script (Google)

For my work I am trying to automatically move a marked line to a 'Historie' sheet. I have currently managed to follow an example and use 1 variable (see copy).
Now I want 2 variables. Instead of just column K -> Completed, I also want to add that column J needs to be True!
function onEdit(event){
var url = "https://docs.google.com/spreadsheets/d/1per7L2wPkMKrzVgv5npQ-2RQ8fkWzslo09Ntlzy4qAs/edit?ts=6034e66e#gid=0";
var source_sheet_name = "Werklijst";
var target_sheet_name = "Historie";
var columnLetter = "J";
var ss= SpreadsheetApp.openByUrl(url);
var source_sheet = ss.getSheetByName(source_sheet_name);
var target_sheet = ss.getSheetByName(target_sheet_name);
var source_range = source_sheet.getRange(columnLetter+":"+columnLetter).getValues();
for(var i = source_range.length-1; i >= 0;i--){
if(source_range[i]=="COMPLETE"){
var targetRange = target_sheet.getRange(target_sheet.getLastRow() + 1, 1);
source_sheet.getRange((i+1), 1, 1, source_sheet.getLastColumn()).moveTo(targetRange);
source_sheet.deleteRow((i+1));
}
}
}
Here is the link to a copy of said sheet (it is in Dutch).
The obvious solution would be to do something like that:
var columnLetter1 = "K";
var columnLetter2 = "J";
var source_range1 = source_sheet.getRange(columnLetter1+":"+columnLetter1).getValues();
var source_range2 = source_sheet.getRange(columnLetter2+":"+columnLetter2).getValues();
and then change the if statement to:
if(source_range1[i]=="COMPLETE" && source_range2[i]==true)
Full snippet of the user's code with the modification points:
function onEdit(event){
var url = "https://docs.google.com/spreadsheets/d/1per7L2wPkMKrzVgv5npQ-2RQ8fkWzslo09Ntlzy4qAs/edit?ts=6034e66e#gid=0";
var source_sheet_name = "Werklijst";
var target_sheet_name = "Historie";
var columnLetter1 = "K";
var columnLetter2 = "J";
var ss= SpreadsheetApp.openByUrl(url);
var source_sheet = ss.getSheetByName(source_sheet_name);
var target_sheet = ss.getSheetByName(target_sheet_name);
var source_range1 = source_sheet.getRange(columnLetter1+":"+columnLetter1).getValues();
var source_range2 = source_sheet.getRange(columnLetter2+":"+columnLetter2).getValues();
for(var i = source_range.length-1; i >= 0;i--){
if(source_range1[i]=="COMPLETE" && source_range2[i]==true){
var targetRange = target_sheet.getRange(target_sheet.getLastRow() + 1, 1);
source_sheet.getRange((i+1), 1, 1, source_sheet.getLastColumn()).moveTo(targetRange);
source_sheet.deleteRow((i+1));
}
}
}
Keep in mind that the current code is not very optimal since you don't use the event object anywhere in your code. The latter will help you get info regarding the edits.
For example, right now your whole code will be executed upon every edit in any cell in the entire spreadsheet file. If you use the event object you can execute some code upon edits on a particular sheet (e.g. Werklijst) and on particular cells (e.g. cells in column K or J). In this way your code will be way faster and more efficient.

We're sorry, a server error occurred. Please wait a bit and try again. (line 63, file "Code")

Thank you in advance for helping.
I am trying to convert the most recent submitted data from Google Form/Google sheets to a "template" Google doc. Basically, when a user submit a form, it will convert the data from Google Sheet and create a new Google Doc.
Side note: Im not really a coder.. I found the base script online and tried to modified it accordingly. I would greatly appreciate a step by step if possible?
AGAIN, THANK YOU SO MUCH
function createDocument() {
var headers = Sheets.Spreadsheets.Values.get('SHEET-ID', 'A1:AU1');
var tactics = Sheets.Spreadsheets.Values.get('SHEET-ID', 'A2:AU2');
var templateId = 'DOCTEMPLATE-ID';
for(var i = 0; i < tactics.values.length; i++){
var Fclient = tactics.values[i][0];
var Lclient = tactics.values[i][1];
var birthday = tactics.values[i][2];
var profession = tactics.values[i][3];
var email = tactics.values[i][4];
var phone = tactics.values[i][5];
var whatsapp = tactics.values[i][6];
var preferredcontact = tactics.values[i][7];
var UScitizen = tactics.values[i][8];
var Ocitizen = tactics.values[i][9];
var Tsapre = tactics.values[i][10];
var Pairplane = tactics.values[i][11];
var Photelamen = tactics.values[i][12];
var FFlyer = tactics.values[i][13];
var hotelloy = tactics.values[i][14];
var vistedcountries = tactics.values[i][15];
var smoke = tactics.values[i][16];
var allergies = tactics.values[i][17];
var Othermed = tactics.values[i][18];
var addANOTHER = tactics.values[i][19];
var emergencyname = tactics.values[i][20];
var emergencyphone = tactics.values[i][21];
var emergencyrelation = tactics.values[i][22];
var emergencyname2 = tactics.values[i][23];
var emergencyphone2 = tactics.values[i][24];
var emergencyrelation2 = tactics.values[i][25];
var comptravelmag = tactics.values[i][26];
var secondaryFname = tactics.values[i][27];
var secondaryLname = tactics.values[i][28];
var secondarybirthday = tactics.values[i][29];
var secondaryprofession = tactics.values[i][30];
var secondaryemail = tactics.values[i][31];
var secondaryphone = tactics.values[i][32];
var secondarywhatsapp = tactics.values[i][33];
var secondarypreferredcontact = tactics.values[i][34];
var secondaryUScitizen = tactics.values[i][35];
var secondaryOcitizen = tactics.values[i][36];
var secondaryTsapre = tactics.values[i][37];
var secondaryPairplane = tactics.values[i][38];
var secondaryPhotelamen = tactics.values[i][39];
var secondaryFFlyer = tactics.values[i][40];
var secondaryhotelloy = tactics.values[i][41];
var secondaryvistedcountries = tactics.values[i][42];
var secondarysmoke = tactics.values[i][43];
var secondaryallergies = tactics.values[i][44];
var secondaryOthermed = tactics.values[i][45];
var timestamp = tactics.values[i][46];
//Make a copy of the template file
var documentId = DriveApp.getFileById(templateId).makeCopy().getId();
//Rename the copied file
DriveApp.getFileById(documentId).setName('Basic Information: ' + Lclient + 'test');
//Get the document body as a variable.
var body = DocumentApp.openById(documentId).getBody(); **ERROR HERE**
//Insert the supplier name
body.replaceText('{{Fcilent}}', Fclient);
body.replaceText('{{Lcilent}}', Lclient);
body.replaceText('{{birthday}}', birthday);
body.replaceText('{{profession}}', profession);
body.replaceText('{{email}}', email);
body.replaceText('{{phone}}', phone);
body.replaceText('{{whatsapp}}', whatsapp);
body.replaceText('{{preferredcontact}}', preferredcontact);
body.replaceText('{{UScitizen}}', UScitizen);
body.replaceText('{{Ocitizen}}', Ocitizen);
body.replaceText('{{Tsapre}}', Tsapre);
body.replaceText('{{Pairplane}}', Pairplane);
body.replaceText('{{Photelamen}}', Photelamen);
body.replaceText('{{FFlyer}}', FFlyer);
body.replaceText('{{hotelloy}}', hotelloy);
body.replaceText('{{vistedcountries}}', vistedcountries);
body.replaceText('{{smoke}}', smoke);
body.replaceText('{{allergies}}', allergies);
body.replaceText('{{Othermed}}', Othermed);
body.replaceText('{{addANOTHER}}', addANOTHER);
body.replaceText('{{emergencyname}}', emergencyname);
body.replaceText('{{emergencyphone}}', emergencyphone);
body.replaceText('{{emergencyrelation}}', emergencyrelation);
body.replaceText('{{emergencyname2}}', emergencyname2);
body.replaceText('{{emergencyphone2}}', emergencyphone2);
body.replaceText('{{emergencyrelation2}}', emergencyrelation2);
body.replaceText('{{comptravelmag}}', comptravelmag);
body.replaceText('{{secondaryFname}}', secondaryFname);
body.replaceText('{{secondaryLname}}', secondaryLname);
body.replaceText('{{secondarybirthday}}', secondarybirthday);
body.replaceText('{{secondaryprofession}}', secondaryprofession);
body.replaceText('{{secondaryemail}}', secondaryemail);
body.replaceText('{{secondaryphone}}', secondaryphone);
body.replaceText('{{secondarywhatsapp}}', secondarywhatsapp);
body.replaceText('{{secondarypreferredcontact}}', secondarypreferredcontact);
body.replaceText('{{secondaryUScitizen}}', secondaryUScitizen);
body.replaceText('{{secondaryOcitizen}}', secondaryOcitizen);
body.replaceText('{{secondaryTsapre}}', secondaryTsapre);
body.replaceText('{{secondaryPairplane}}', secondaryPairplane);
body.replaceText('{{secondaryPhotelamen}}', secondaryPhotelamen);
body.replaceText('{{secondaryFFlyer}}', secondaryFFlyer);
body.replaceText('{{secondaryhotelloy}}', secondaryhotelloy);
body.replaceText('{{secondaryvistedcountries}}', secondaryvistedcountries);
body.replaceText('{{secondarysmoke}}', secondarysmoke);
body.replaceText('{{secondaryallergies}}', secondaryallergies);
body.replaceText('{{secondaryOthermed}}', secondaryOthermed);
body.replaceText('{{timestamp}}', timestamp);
//Append tactics
parseTactics(headers.values[0], tactics.values[i], body);
}
}
function parseTactics(headers, tactics, body){
for(var i = 1; i < tactics.length; i++){
{tactics[i] != '' &&
body.appendListItem(headers[i] + ' | ' + tactics[i] + ' OTHER').setGlyphType(DocumentApp.GlyphType.BULLET);
}
}
}
Error: "We're sorry, a server error occurred. Please wait a bit and try again. (line 63, file "Code")"
I expected the script to generate a new google doc from the data sheet as it is being submitted on google form.
I think your pretty close. Here's an example I did.
First, I created a function to generate some data for myself.
function testData() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.clearContents();
var rg=sh.getRange(1,1,10,10);
var vA=rg.getValues();
for(var i=0;i<vA.length;i++) {
for(var j=0;j<vA[i].length;j++) {
vA[i][j]=Utilities.formatString('row: %s - col: %s',i+1,j+1);
}
}
rg.setValues(vA);
}
The above function creates a sheet that looks like this:
The Template File Looks like this:
And after running this code:
function createDoc(){
var spreadsheetId='spreadsheet Id';
var templateId='template Id';
var data=Sheets.Spreadsheets.Values.get(spreadsheetId,'Sheet177!A1:J2');//range include sheet name
var docId=DriveApp.getFileById(templateId).makeCopy('Test').getId();
var body=DocumentApp.openById(docId).getBody();
for(var i=0;i<data.values.length;i++) {
for(var j=0;j<data.values[i].length;j++) {
var s=Utilities.formatString('{{col%s-%s}}',i+1,j+1);
body.replaceText(s,data.values[i][j]);
}
}
}
There appears in the same folder another file named test that looks like this:
I must say that sure is a simple way to get data.
I'm kind of wondering if perhaps you simply didn't authenticate the program in the script editor.