I have a script that is supposed to mail a chart URL when a metric falls out of X range and Only if someone has entered a new metric. It's mailing everytime I run the script so I know the setProperty is not working and the "if" statement isn't working because it's only supposed to mail if X is TRUE.
The sheet... https://docs.google.com/spreadsheet/ccc?key=0Ai_2YLvaQba0dHN1dWFpY0ZSbGpudWF4cTJYNlFwNHc&usp=sharing
My code...
function myAverages() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("EmailServices").getRange("P2").getValue().toString();
var outside = ss.getSheetByName("EmailServices").getRange("S2").getValue().toString;
var mailed = ss.getSheetByName("EmailServices").getRange("T2").getValue().toString();
var stemiAverage = ss.getSheetByName("EmailServices").getRange("R2").getValue().toString();
var stemiChart = ss.getSheetByName("EmailServices").getRange("U2").getValue().toString();
var last = ScriptProperties.getProperty('last');
//if "value" is not equal to ScriptProperty "last" AND "outside" is TRUE, then mail
if(value =! last, outside = "TRUE")
{
MailApp.sendEmail("dave#mydomain.com", "Metric Warning",
"Yearly STEMI Average has fallen below 65%, it is now: " + stemiAverage + "%" +
"\n\nTo see the current trending chart " + stemiChart + "\n\n The sheet that calculated this is here " + ss.getUrl());
ScriptProperties.setProperty('last','value');
}
}
Thanks for any help you can lend. I'm teaching myself this stuff and feel very much like a newby. I've tried a hundred or more combinations to the script before posting here.
As a complement to Phil's answer and following your comment, there is another error in your script :
ScriptProperties.setProperty("last","value");
should be
ScriptProperties.setProperty({'last':value},true);
The true parameter is optional, see documentation on ScriptProperties, it gives you the possibility to delete all other keys.
So you're complete function with corrections would be :
function myAverages(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("EmailServices").getRange("P2").getValue().toString();
Logger.log('value = '+value)
var outside = ss.getSheetByName("EmailServices").getRange("S2").getValue().toString();
Logger.log('outside='+outside)
var mailed = ss.getSheetByName("EmailServices").getRange("T2").getValue().toString();
Logger.log('mailed = '+mailed)
var stemiAverage = ss.getSheetByName("EmailServices").getRange("R2").getValue().toString();
var stemiChart = ss.getSheetByName("EmailServices").getRange("U2").getValue().toString();
var last = ScriptProperties.getProperty('last');
Logger.log('last='+last)
if(value != last && outside == "true"){
MailApp.sendEmail("me#mydomain.com", "Metric Warning",
"Yearly STEMI Average has fallen below 65%, it is now: " + stemiAverage + "%" +
"\n\nTo see the current trending chart " + stemiChart + "\n\n The sheet that calculated this is here " + ss.getUrl());
ScriptProperties.setProperty({'last':value});
Logger.log('mail sent')
}
}
You need to use the AND operator: &&.
And also, checking for equality requires 2 equals signs: ==.
So be sure you try this:
if (value!=last && outside=="TRUE") {
Related
I'm trying to write a piece of code that whenever someone on our rosters is terminated it will capture their data, put them into a "termed associates" sheet and delete them from the roster.
The code I wrote works fine for single instances of the change (though it is a bit slow), but the main problem is if I change multiple people to "TERM" in quick succession, it breaks and sometimes will delete rows that aren't the row meant to be deleted.
Here's my code:
const ss = SpreadsheetApp.getActiveSpreadsheet();
const termSheet = ss.getSheetByName('Term Tracker');
const check = SpreadsheetApp.getActiveSheet().getActiveCell().getValue();
function deleteTerm() {
if(check == 'TERM'){
//grabs the cell that has just been edited, finds the index of the row
let sheet = ss.getActiveSheet();
let cell = ss.getActiveCell();
let index = cell.getRowIndex();
//grabs data and posts to new sheet
//grabs values to inset into email
let read = sheet.getRange(index,1,1,55).getValues();
let name = sheet.getRange(index, 4).getValue();
let shift = sheet.getRange(index,1).getValue();
termSheet.insertRowBefore(2);
termSheet.getRange(2,1,1,55).setValues(read);
//deletes the index row
sheet.deleteRow(index)
//mails me a notification someone was termed
MailApp.sendEmail({
to: "{myemail}",
subject: "New Term, " + name ,
body: "There is a new term of " + name + ", please confirm the term reason and term date.
They are on the " + shift + " roster"
});
}}
Any ideas on exactly what I'm doing wrong? I'm still very new to coding, so I'm sure that the code isn't very great. Any feedback would be lovely as well. :)
This should work faster
But any expectation of consistently fast response for an onEdit function is a hopeless wish that is not going to be fulfilled. You must be patient and give it time to operate.
function onEdit(e) {
const sh = e.range.getSheet();
const tsh = e.source.getSheetByName('Term Tracker');
if (e.value == 'TERM') {
let vs = sh.getRange(e.range.rowStart, 1, 1, 55).getValues();
let name = vs[0][3];
let shift = vs[0][0];
tsh.insertRowBefore(2);
tsh.getRange(2, 1, 1, 55).setValues(vs);
sh.deleteRow(e.range.rowStart);
MailApp.sendEmail({to: "{myemail}",subject: "New Term, " + name,body: "There is a new term of " + name + ", please confirm the term reason and term date. They are on the " + shift + " roster"});
}
}
I'm attempting to create a resource management system that would allow members of my office to reserve a room through forms, creating a calendar event on a public calendar.
The issue I am facing in the creation process revolves around conflict checking complications, due to the fact that I would like to have all the calendar events located on one calendar per office. The result is multiple resources on one calendar, and the need for my conflict checking script to not only check for conflicting events but also evaluate the room in which the events are.
Ideally, I would need the script to check first if there are any conflicts, and if there are, it would then check the room name of the conflict event. If the events are in different rooms, it will approve the event creation. If otherwise, it would be denied, and the form respondent would receive an email. I've scoured through the documentation, but with my limited knowledge of the language and coding in general I haven't been able to find a good solution.
At first, I thought I would be able to compare event descriptions, which I would set as the room name based on input from the form submissions. When I called all of the conflicts within the start and end time I would then evaluate their descsriptions with the description of the event to be created and check from there. Unfortunately, from what I tested, it is not possible to do with multiple conflicting events.
I then have what I have listed here where I have an array of the rooms submitted in the past, from the spreadsheet attached to the form, and it checks through them. The issue here is that it doesn't account for start and end times only room names.
My principal question in all of this would be, is there a way to assign a tag of some sort to my event on creation that I would then be able to call back in the conflict checking portion of my script. Ideally, this tag would be something I can assign myself and then evaluate with the new form submission data. I think the best way would be through inviting a room resource to the event, but I have been unable to figure out how to do that as well.
function getConflicts(request){
var conflicts = request.calendar.getEvents(request.dateTime, request.edateTime);
//var description = conflicts.getDescription();
if(conflicts.length >= 1){
Logger.log(conflicts.length);
for (var i=0; i<conflicts.length; i++) {
if (request.room != request.slroom[i]) {
request.status = "Approve";
} else if (request.room == request.slroom[i]) {
request.status = "Conflict";
}
}}
else request.status = "Approve";
}
Full Script:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var calendarb = CalendarApp.getCalendarById("link");
function Submission(){
var row = lastRow;
var slrow = (lastRow-1);
this.timestamp = sheet.getRange(row, 1).getValue();
this.name = sheet.getRange(row , 3).getValue() + ": " + sheet.getRange(row, 5).getValue();
this.email = sheet.getRange(row, 2).getValue();
this.dateTime = sheet.getRange(row, 6).getValue();
this.edateTime = sheet.getRange(row,7).getValue();
this.room = sheet.getRange(row, 5).getValue();
this.slroom = sheet.getRange(2, 5, (lastRow-1)).getValues();
this.roomstart =sheet.getRange(2, 6, (lastRow-1)).getValues();
this.roomend = sheet.getRange(2, 7, (lastRow-1)).getValues();
//this.roomInt = this.room.replace(/\D+/g, '');
//this.status;
this.calendar = calendarb;
return this;
var event;
}
function getConflicts(request){
var conflicts = request.calendar.getEvents(request.dateTime, request.edateTime);
//var description = conflicts.getDescription();
if(conflicts.length >= 1){
Logger.log(conflicts.length);
for (var i=0; i<conflicts.length; i++) {
if (request.room != request.slroom[i]) {
request.status = "Approve";
} else if (request.room == request.slroom[i]) {
request.status = "Conflict";
}
}}
else request.status = "Approve";
}
function draftEmail(request){
request.buttonLink = "link";
request.buttonText = "New Request";
switch (request.status) {
case "Approve":
request.subject = "Confirmation: " + request.room + " Reservation for " + request.dateTime + "-" + request.edateTime;
request.header = "Confirmation";
request.message = "Your room reservation has been scheduled.";
break;
case "Conflict":
request.subject = "Conflict with " + request.room + " Reservation for " + request.dateTime + "-" + request.edateTime;
request.header = "Conflict";
request.message = "There is a scheduling conflict. Please pick another room or time."
request.buttonText = "Reschedule";
break;
}
}
function updateCalendar(request){
var event = {
summary: request.name,
location: 'Location',
description: request.room,
start: {
dateTime: request.dateTime.toISOString()
},
end: {
dateTime: request.edateTime.toISOString()
},
attendees: [
{email: request.email}
],
tag: request.room
};
event = Calendar.Events.insert(event, "Calandar ID");
// request.calendar.addSmsReminder(10);
Logger.log('Event Tag: ' + event.description);
Logger.log('Event ID: ' + event.id);
}
function sendEmail(request){
MailApp.sendEmail({
to: request.email,
subject: request.header,
htmlBody: makeEmail(request)
})
sheet.getRange(lastRow, 8).setValue("Sent: " + request.status);
}
function main(){
var request = new Submission();
getConflicts(request);
draftEmail(request);
if (request.status == "Approve") updateCalendar(request);
sendEmail(request);
}
My spreadsheet is set up in this order
A: Timestamp
B: Email Adress
C: Name
D: Location
E: Room
F: Start Date & Time
G: End Date & Time
Sample Sheet
Based on your code, you store your room details in your event's description. Why not use the descriptions of the conflicted events to check if the room is still available? In this manner, we don't need to tag our events.
I also modified some lines as to improve the efficiency of your whole script. Kindly see changes below.
Code:
function Submission() {
// get values by bulk
var rowValues = sheet.getRange(lastRow, 1, 1, 7).getValues().flat();
// avoid using this as that contains another values you don't need
// create a request variable instead
var request = {};
request.timestamp = rowValues[0];
request.name = rowValues[2] + ": " + rowValues[4];
request.email = rowValues[1];
request.dateTime = rowValues[5];
request.edateTime = rowValues[6];
request.room = rowValues[4];
request.calendar = calendarb;
// No need to store previous lists of rooms and their time.
// See getConflicts for clarification
return request;
}
function getConflicts(request) {
var conflicts = request.calendar.getEvents(request.dateTime, request.edateTime);
// Since you stored the room into the description
// Filter the conflicts by comparing conflicts' descriptions to the room
if(conflicts.filter(conflict => conflict.getDescription() == request.room).length > 0)
request.status = "Conflict";
else
request.status = "Approve";
}
Changes:
Get the row values by bulk.
Create request variable instead of using this. The latter contains other values you don't need.
Removed getting past room and date time values for other events.
Makes use of the descriptions of the conflicts and filter them by comparing that to your room.
So I have this script pulling from a response sheet and running an if statement on each response to check what type of response it is at the current moment I have to types it checks for one being "Register a new Fox" and "Submit a Transaction" I'm pretty new to googlescripts with a decent knowledge of other languages. I'm looking for a solution for why my loop is stopping and how it can be fixed rather, any examples will help a lot. Thanks in advance.
function SetCellData() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var debugSheet = ss.getSheetByName("Debug")
var famTree = ss.getSheetByName("Family")
var transaction = ss.getSheetByName("Transactions")
var sheetMaster = ss.getSheetByName("Form Responses")
debugSheet.getRange("Debug!A1").setValue(sheetMaster.getRange("Form Responses!C2").getValue());
debugSheet.getRange("Debug!A2").setValue(sheetMaster.getRange("Form Responses!C:C").getLastRow());
var mainRange = sheetMaster.getRange("Form Responses!B2:B");
var registeredFoxes = 0
var transactionsMade = 0
for (i=2; i <= sheetMaster.getRange("Form Responses!C:C").getLastRow();i++){
// Checks to see if they are trying to add a new fox.
if (sheetMaster.getRange("Form Responses!C" + i.toString()).getValue() == "Register a New Fox"){
famTree.getRange("Family!B"+(6+registeredFoxes)).setValue(sheetMaster.getRange("Form Responses!D" + i.toString()).getValue());
famTree.getRange("Family!C"+(6+registeredFoxes)).setValue(sheetMaster.getRange("Form Responses!E" + i.toString()).getValue());
famTree.getRange("Family!D"+(6+registeredFoxes)).setValue(sheetMaster.getRange("Form Responses!F" + i.toString()).getValue());
famTree.getRange("Family!E"+(6+registeredFoxes)).setValue(sheetMaster.getRange("Form Responses!G" + i.toString()).getValue());
famTree.getRange("Family!H"+(6+registeredFoxes)).setValue(sheetMaster.getRange("Form Responses!H" + i.toString()).getValue());
registeredFoxes = registeredFoxes + 1;
// Checks to see if they are submiting a transaction.
}else if (sheetMaster.getRange("Form Responses!C" + i.toString()).getValue() == "Submit a Transaction"){
transaction.getRange("Transactions!E"+(8+transactionsMade)).setValue(sheetMaster.getRange("Form Responses!I" + i.toString()).getValue());
transaction.getRange("Transactions!F"+(8+transactionsMade)).setValue(sheetMaster.getRange("Form Responses!L" + i.toString()).getValue());
if (sheetMaster.getRange("Form Responses!J" + i.toString()).getValue() == "Profit"){
transaction.getRange("Transactions!C"+(8+transactionsMade)).setValue("+");
transaction.getRange("Transactions!D"+(8+transactionsMade)).setValue(sheetMaster.getRange("Form Responses!K" + i.toString()).getValue());
}else{
transaction.getRange("Transactions!C"+(8+transactionsMade)).setValue("-");
transaction.getRange("Transactions!D"+(8+transactionsMade)).setValue("-"+ sheetMaster.getRange("Form Responses!K" + i.toString()).getValue());
}
transaction.getRange("Transactions!B"+(8+transactionsMade)).setValue(sheetMaster.getRange("Form Responses!M" + i.toString()).getValue());
transactionsMade = transactionsMade + 1
}else{
debugSheet.getRange("Debug!A3").setValue(registeredFoxes);
}
}
famTree.getRange("Family!B2").setValue("Fox Family Members:\n" + registeredFoxes)
transaction.getRange("Transactions!B4").setValue("Transactions Made:\n" + transactionsMade)
}
The only way that you can speed things up is to get all the data out of all 3 sheet tabs, manipulate the data in the 2D arrays, and then set the new values all at once. Currently you are getting and setting values on every iteration of the loop, so there are read and write operations happening constantly which takes time. You need to read all the data once, and write all the data once.
The loop might be terminating for some reason. And the only reason it might be doing that is if the count hits the last row number, or there is an error in your code:
I would change:
for (i=2; i <= sheetMaster.getRange("Form Responses!C:C").getLastRow();i++){
To:
var L = sheetMaster.getRange("Form Responses!C:C").getLastRow();
Logger.log("L: " + L)
for (i=2; i<=L;i++){
This seems to work but it's not orthodox any adjustments that could be made let me know
Pretty much it was taking to much effort and memory to find the fields that I keep calling so I got all of them at once and then ran statements off that.
function SetCellData() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var debugSheet = ss.getSheetByName("Debug")
var family = ss.getSheetByName("Family")
var transaction = ss.getSheetByName("Transactions")
var sheetMaster = ss.getSheetByName("Form Responses")
// Starts from Row 2 Column C
var vA=sheetMaster.getRange(2, 3,(sheetMaster.getLastRow()-1),(sheetMaster.getLastColumn()-2)).getValues();
var lastColumn = sheetMaster.getLastColumn()
var registeredFoxes = 0
var transactionsMade = 0
var slotsScanned = 0
var L = sheetMaster.getRange("Form Responses!C:C").getLastRow();
Logger.log("L: " + L)
for (i=2; i<=L;i++){
// Checks to see if they are trying to add a new fox.
if (vA[i-2][0] == "Register a New Fox"){
for (j=1;j<=5;j++){
if (j==5){
family.getRange(registeredFoxes+6,j+3).setValue(vA[i-2][j]);
}else{
family.getRange(registeredFoxes+6,j+1).setValue(vA[i-2][j]);
}
}
registeredFoxes ++
// Checks to see if they are submiting a transaction.
}else if (vA[i-2][0] == "Submit a Transaction"){
for (j=7; j<=11;j++){
transaction.getRange(transactionsMade+8,j-5).setValue(vA[i-2][j-1]);
if (vA[i-2][j-1] == "Profit"){
transaction.getRange(transactionsMade+8,j-5).setValue("+");
}else if (vA[i-2][j-1] == "Loss"){
transaction.getRange(transactionsMade+8,j-5).setValue("-");
}else if (j == 9 && vA[i-2][7] == "Loss"){
transaction.getRange(transactionsMade+8,j-5).setValue("-" + vA[i-2][j-1]);
}
}
transactionsMade ++
}else{
Logger.log("Tried to read something...")
}
}
family.getRange(2,2).setValue("Fox Family Members:\n" + registeredFoxes);
transaction.getRange(4,2).setValue("Transactions Made:\n" + transactionsMade);
}
i am fairly new to coding in google scripts so the you will probably look at the code below and shake your head with its current inefficiency haha. in short this code is checking the value of cells A5 to D5 and seeing if its in the master list with the same values of E5 and F5. if its not it then copies A5-D5 to two different lists on another workbook. the code works at the moment but i was wondering if there is anyway to speed it up? its going to be mainly triggered by the IOS sheets app on an Ipad.(hence why i had to use onEdit instead of a button to trigger). when its checking to see if its already on the list, its on a local sheet in the same workbook that updates via a formula from the external workbook. Any help you could provide would be greatly appreciated. like i said though I'm new to coding i managed to piece this one together from the help of google when i ran into an issue.
function onEdit(e) {
var sheet1 = SpreadsheetApp.getActive().getSheetByName("sheet1")
var SiteName = sheet1.getRange("A5").getValue()
var Type = sheet1.getRange("B5").getValue()
var Fleet = sheet1.getRange("C5").getValue()
var Rego = sheet1.getRange("D5").getValue()
var Inside = sheet1.getRange("E5").getValue()
var Outside = sheet1.getRange("F5").getValue()
var User = sheet1.getRange("A3").getValue()
var master = SpreadsheetApp.getActive().getSheetByName("Master Wash List");
var True = true
var False = false
var mastermaster = SpreadsheetApp.openById("links to external workbook2").getSheetByName("master")
var mastertolocal = SpreadsheetApp.openById("links to external workbook2").getSheetByName("MasterToLocal")
var sheet = SpreadsheetApp.getActive().getSheetByName("Master Wash List");
var lastrow = sheet.getLastRow()
var SubmitButton = SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("G5").getValue()
if(Inside == True) {
for(var x = 1; x < lastrow+1;x++) {
var cell = master.getRange(x,3).getValue()
var masterinside = master.getRange(x, 4).getValue()
var masteruser = master.getRange(x,6).getValue()
if(Fleet == cell && masterinside != "N/A"){
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue([cell + " has already been Internally washed on " + masterinside + " by " + masteruser])
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("G5").setValue("false")
}
}
}
if(Outside == True) {
for(var y = 2; y < lastrow+1;y++) {
var cell = master.getRange(y,3).getValue()
var masteroutside = master.getRange(y, 5).getValue()
var User1 = master.getRange(y, 6).getValue()
if(Fleet == cell && masteroutside != "N/A"){
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue([cell + " has already been externally washed on " + masteroutside + " by " + User1])
SpreadsheetApp.getActive().getSheetByName("sheet1").deleteRows(17,2)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("F5").setValue("false")}
}
}
if(SubmitButton == True){
if(Inside == True && Outside == True && Fleet != "" ) {
mastermaster.appendRow([SiteName, Type, Fleet, Rego, new Date(), new Date(), User,])
mastertolocal.appendRow([SiteName, Type, Fleet, Rego, "N/A", new Date(), User])
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("E5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("F5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("G5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("A5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("B5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("C5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("D5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue([Fleet + " has successfully been Washed Internally & Externally."])
SpreadsheetApp.getActive().getSheetByName("sheet1").deleteRows(17, 2)}
else if(Outside == True && Fleet != "" ) {
mastermaster.appendRow([SiteName, Type, Fleet, Rego,"N/A", new Date(), User])
mastertolocal.appendRow([SiteName, Type, Fleet, Rego, "N/A", new Date(), User])
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("F5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("G5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("A5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("B5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("C5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("D5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue([Fleet + " has successfully been Washed Externally."])
SpreadsheetApp.getActive().getSheetByName("sheet1").deleteRows(17, 2) }
else if(Inside == True && Fleet != "") {
mastermaster.appendRow([SiteName, Type, Fleet, Rego, new Date(), "N/A", User])
mastertolocal.appendRow([SiteName, Type, Fleet, Rego, new Date(), "N/A", User])
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("E5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("G5").setValue("false")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("A5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("B5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("C5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("D5").setValue("")
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue([Fleet + " has successfully been Washed Internally."])
SpreadsheetApp.getActive().getSheetByName("sheet1").deleteRows(17, 2)}
else if(Inside != True && Outside != True && Fleet != "") {
SpreadsheetApp.getActive().getSheetByName("sheet1").insertRowAfter(6)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange(7,1).setValue(["Please select if " + Fleet + " Has been washed Internally, Externally or Both"])
SpreadsheetApp.getActive().getSheetByName("sheet1").deleteRows(17, 2)
SpreadsheetApp.getActive().getSheetByName("sheet1").getRange("F5").setValue("false")}
}
}
Google has provided a Best Practices resource that you should definitely review. From there, the most relevant section is about using batch operations. Not specific to Google Apps Script, but a good practice, is to reduce some of the repetition in your code (see DRY principle). Here are some specific notes that you can apply to your entire script:
Reduce the number of times you call SpreadsheetApp.getActive() or SpreadsheeApp.openById() by placing the returned value into a variable.
var ss = SpreadsheetApp.getActive();
var externalSS = SpreadsheetApp.openById("links to external workbook2");
Reduce the number of times you call SpreadsheetApp.getActive().getSheetByName("sheet1") by using the variable that you already created sheet1. You can use find & replace-all to fix this.
Reduce the number of times you call getValue() by using getValues() instead and accessing the array values.
var row5 = sheet1.getRange(1, 1, 1, 7).getValues(); // A5:G5
var SiteName = row5[0][0]; // A5
var Type = row5[0][1]; // B5
var Fleet = row5[0][2]; // C5
var Rego = row5[0][3]; // D5
var Inside = row5[0][4]; // E5
var Outside = row5[0][5]; // F5
true and false are constants in javascript, so no need to place them into variables True & False.
Reduce the number of times you call new Date() by placing it in a variable;
var now = new Date();
Similary to point 3, reduce the number of times you call setValue() by instead using setValues().
row5.setValues([ // row5 previously defined A5:G5
[""], // A5
[""], // B5
[""], // C5
[""], // D5
[false], // E5
[false], // F5
[false] //G5
]);
The examples I wrote above are just examples, but they are based on your code. You'll need to go through your entire script and figure out exactly how to apply these principles without breaking the functionality of your script.
I am new to google scripting and am running into something I can't figure out. I am trying to name a range with the hope of eventually putting it into an array and populating another sheet with the data.
I am running into problems naming the range. I want to eventually be able to iterate through and name many ranges, so I'd like to be able to use variables for the row numbers.
If I try this:
var rngProject = "A8:Y21";
var RngName = "project1";
Then everything works and I have the data in an array. But, as mentioned, I want to use variables for the row numbers, as well as the range name, as shown below.
If I try this:
var rngProject = "A" + strtRow + ":Y" + totRows + strtRow - 1;
var RngName = "project" + toString(i);
On this line:
var rng_to_name = active_spreadsheet.getSheetByName(sheet_name).getRange(address);
I am getting the error: "Argument must be a range." In the debugger the address value shows as NaN, so I think this is not right. But I've also tried using strRange (commented out below) and I get the same error on the same line.
Is there a way I can take this value and cast it to a range type, or is there something else I am doing wrong?
function namePrjRange () {
var i = 1
var strtRow = 8;
var shtName = "USER INPUT by week: TEST";
var totRows = 14;
//var strRange = "A" + toString(strtRow) + ":Y" + toString(totRows + strtRow - 1);
var rngProject = "A" + strtRow + ":Y" + totRows + strtRow - 1;
var RngName = "project" + toString(i);
//Logger.log(strRange);
Logger.log(rngProject);
Logger.log(RngName);
nameRange(shtName, rngProject, RngName);
}
// Given a sheet name (assumed to be in the active spreadsheet, an address using "A1" notation,
// and a name string, assign that name to the range address in the given sheet.
function nameRange(sheet_name, address, rng_name) {
// Create an spreadsheet object.
Logger.log("Entered nameRange function")
var active_spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// Get a range object by firstly getting a sheet object from the spreadsheet object and then pass the
// "address" argument to the sheet "getRange()" method.
var rng_to_name = active_spreadsheet.getSheetByName(sheet_name).getRange(address);
// Use the spreadsheet object method "setNamedRange()" to assign a range name to a range object.
Logger.log("About to set Named Range");
Logger.log(rng_name);
Logger.log(rng_to_name);
active_spreadsheet.setNamedRange(rng_name, rng_to_name);
}
Use:
var rngProject = "A" + strtRow + ":Y" + (totRows + strtRow - 1);
As you are performing string concatenation here, the parser would be attempting to concatenate everything together (ie not actually adding totRows to strtRow), and ultimately drop it's bundle when it arrives at the minus sign, which isn't a valid string operator. So you just need to put parentheses around the arithmetic part.
https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Expressions_and_Operators#String_operators