Anyway to speed up the following code in google sheets script? - google-apps-script

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.

Related

How to assign a tag to an event that would allow for 3d conflict detection on a google calendar?

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.

Issue matching argument in google script

I am new to scripting, and have been trying to get a script to place a date in an adjacent cell when a checkbox is checked. This is a minor part of the whole script I am trying to get working. I am trying to write a script to build a new sheet from another sheets values, including naming the sheet.
I can get the script to work when I type the sheet name into the if statement, but when I try and use an argument by calling the sheet name and calling string, I can not get them to return a true value.
When I log the sheet name and the string they match. If I copy and paste ether value from the log into the sheet name it will then return true. It will also return true when I type the name of the sheet.
I have tried to change the type using: toString() but this has not worked.
I have tried to use the length and typeof to find the solution, from this page:
How to debug identical strings that do not equal in google app script?
But they where the same type and length. I have tried to get the every function on this page to work but have been unsuccessful in getting it to run.
I have used it like this:
[td].every((char,i) => char === nac[i] || console.info(`Unequal character at ${i}`))
and get this error:
10:55:03 AM Error
TypeError: Cannot read property 'every' of undefined
onEdit # Time Stamp test day.gs:33
Code:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ac = ss.getActiveSheet();
var as = ss.getActiveSheet().getSheetName();
var d = new Date();
var month = new Array(12);
month[0] = "Jan";
month[1] = "Feb";
month[2] = "Mar";
month[3] = "Apl";
month[4] = "May";
month[5] = "Jun";
month[6] = "Jul";
month[7] = "Aug";
month[8] = "Sep";
month[9] = "Oct";
month[10] = "Nov";
month[11] = "Dec";
var year = d.getFullYear();
var date = d.getDate();
var today = month[d.getMonth()] + " " + date +", " + year
var td = "Test " + today
var nac = ac.getSheetName()
Logger.log(td)
Logger.log(nac)
Logger.log(nac == td)
if(nac == td) {
var cell = ac.getActiveCell()
var col = cell.getColumn()
if(col == 9 && cell.getValue() == true){
Logger.log(123456)
var date = new Date()
var dateCell = cell.offset(0,1)
dateCell.setValue(date)
}//close if
} // Close if
} // Close function
Log
11:26:46 PM Notice Execution started
11:26:47 PM Info Test Dec 27, 2020
11:26:47 PM Info Test Dec 27, 2020
11:26:47 PM Info false
11:26:47 PM Notice Execution completed

Trouble deploying sheets addon

Our website spits out CSV files that we use as event rosters, but they include way too much data. There's no feasible way to change what's included in the export, so an admin assistant must edit & format for print. It's repetitive and time consuming, so I figured it's the perfect time to learn Google Apps Script.
Thanks to the incredible knowledge shared here on stack overflow, a total noob like me can cobble together a script that does what I need! Just by using snippets from other answers, I was able to automate:
Delete unwanted & empty columns
Rename & auto-resize columns
Sort by the last name column
Generate print-ready PDF that saves in the same Drive directory.
But now I'm having trouble testing and deploying the script as an addon so my co-workers can use it. When I run a "test as addon" the sheet opens, but nothing happens. I've tried all the variables for installation config and searched for others having the same trouble, but can't find anything so I think the problem is prbly somewhere on my end - script or user error.
Once I get it to test correctly, I'm not entirely sure about how to correctly deploy the addon to our domain and get all the permissions, etc setup correctly. I've read up and now I feel more confused than ever! So two questions:
What's wrong w/ my testing?
Once it tests successfully, what's the easiest way I can let all of our domain's apps users utilize the script?
Here's the script:
function expCalc() {
DeleteColumns();
RemoveEmptyColumns();
RenameColumns();
ResizeColumns();
Sort();
SavePDF();
}
//delete unwanted columns
function DeleteColumns() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var dataRange = sheet.getRange("A1:AH200");
var data = sheet.getRange("A1:AH200");
var values = data.getValues();
var numRows = values.length;
var numCols = values[0].length;
for (var col = numCols - 1; col > 0; col--) {
for (var row = 0; row < numRows; row++) {
switch (values[row][col]) {
case "Group":
case "ID":
case "Reg ID":
case "Reg Date":
case "Type of Payment":
case "Transaction ID":
case "Coupon Code":
case "# Attendees":
case "Date Paid":
case "Price Option":
case "Event Date":
case "Event Time":
case "Website Check-in":
case "Tickets Scanned":
case "Check-in Date":
case "Seat Tag":
case "BLS Add-on items (received at class):":
case "Company Name":
case "Address":
case "Address 2":
case "City":
case "State":
case "Zip":
sheet.deleteColumn(col + 1); // delete column in sheet (1-based)
continue; // continue with next column
break; // can't get here, but good practice
}
}
}
}
//Remove Empty Columns
function RemoveEmptyColumns() {
var sh = SpreadsheetApp.getActiveSheet();
var maxColumns = sh.getMaxColumns();
var lastColumn = sh.getLastColumn();
sh.deleteColumns(lastColumn + 1, maxColumns - lastColumn);
}
//Rename Columns
function RenameColumns() {
SpreadsheetApp.getActiveSheet().getRange('A1').setValue('Type');
SpreadsheetApp.getActiveSheet().getRange('B1').setValue('Paid');
SpreadsheetApp.getActiveSheet().getRange('C1').setValue('Price');
SpreadsheetApp.getActiveSheet().getRange('D1').setValue('Amt');
SpreadsheetApp.getActiveSheet().getRange('E1').setValue('Class');
SpreadsheetApp.getActiveSheet().getRange('F1').setValue('First Name');
SpreadsheetApp.getActiveSheet().getRange('G1').setValue('Last Name');
SpreadsheetApp.getActiveSheet().getRange('H1').setValue('Email');
SpreadsheetApp.getActiveSheet().getRange('I1').setValue('Phone');
}
//Auto-Resize Columns
function ResizeColumns() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
sheet.autoResizeColumn(1);
sheet.autoResizeColumn(2);
sheet.autoResizeColumn(3);
sheet.autoResizeColumn(4);
sheet.autoResizeColumn(5);
sheet.autoResizeColumn(6);
sheet.autoResizeColumn(7);
sheet.autoResizeColumn(8);
sheet.autoResizeColumn(9);
}
//Sort by last name
function Sort() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
sheet.sort(7);
}
//Save PDF
function SavePDF(optSSId, optSheetId) {
// If a sheet ID was provided, open that sheet, otherwise assume script is
// sheet-bound, and open the active spreadsheet.
var ss = (optSSId) ? SpreadsheetApp.openById(optSSId) : SpreadsheetApp.getActiveSpreadsheet();
// Get URL of spreadsheet, and remove the trailing 'edit'
var url = ss.getUrl().replace(/edit$/, '');
// Get folder containing spreadsheet, for later export
var parents = DriveApp.getFileById(ss.getId()).getParents();
if (parents.hasNext()) {
var folder = parents.next();
} else {
folder = DriveApp.getRootFolder();
}
// Get array of all sheets in spreadsheet
var sheets = ss.getSheets();
// Loop through all sheets, generating PDF files.
for (var i = 0; i < sheets.length; i++) {
var sheet = sheets[i];
// If provided a optSheetId, only save it.
if (optSheetId && optSheetId !== sheet.getSheetId()) continue;
//additional parameters for exporting the sheet as a pdf
var url_ext = 'export?exportFormat=pdf&format=pdf' //export as pdf
+
'&gid=' + sheet.getSheetId() //the sheet's Id
// following parameters are optional...
+
'&size=letter' // paper size
+
'&portrait=false' // orientation, false for landscape
+
'&fitw=true' // fit to width, false for actual size
+
'&sheetnames=false&printtitle=false&pagenumbers=false' // hide optional headers and footers
+
'&gridlines=true' // hide/show gridlines
+
'&fzr=false'; // do not repeat row headers (frozen rows) on each page
var options = {
headers: {
'Authorization': 'Bearer ' + ScriptApp.getOAuthToken()
}
}
var response = UrlFetchApp.fetch(url + url_ext, options);
var blob = response.getBlob().setName(ss.getName() + ' - ' + sheet.getName() + '.pdf');
folder.createFile(blob);
}
}
/**
* Dummy function for API authorization only.
* From: https://stackoverflow.com/a/37172203/1677912
*/
function forAuth_() {
DriveApp.getFileById("Just for authorization"); // https://code.google.com/p/google-apps-script-issues/issues/detail?id=3579#c36
}
Great use for an add-on. In order to make it work as an add-on you need to create an onOpen() trigger so that the users can interact with your code.
Refer to the onOpen() docs here: https://developers.google.com/apps-script/guides/triggers/#onopen
See an example here: https://developers.google.com/apps-script/add-ons/#user_interfaces

google apps script very very slow

I am using a google spreadsheet as a simple database of members and I want to create a user interface for searching through them (The primary users for this are not very technically adept and there is quite allot of data associated with each member so viewing it as a spreadsheet can be a bit tedius)
I have written the folowing script which worked last night but appears to run so slowly it times out today and I have no idea why.
function findMember() {
// set spreadsheet variable
var SS = SpreadsheetApp.getActiveSpreadsheet();
// set sheet variables
var memberSearchSheet = SS.getActiveSheet();
var memberDataSheet = SS.getSheetByName("Member Data");
// get the search variables
var searchFirstName = memberSearchSheet.getRange('C2').getValue();
var searchLastName = memberSearchSheet.getRange('C3').getValue();
// get last row of data
var lastRow = memberDataSheet.getLastRow();
for (var i = 2;lastRow;i=i+1){
if (searchFirstName == memberDataSheet.getRange('R'+i+'C2').getValue() && searchLastName == memberDataSheet.getRange('R'+i+'C3').getValue()){
memberSearchSheet.getRange('C5').setValue(memberDataSheet.getRange('R'+i+'C5').getValue());
//throw new Error("ouch")
}
}
// small pop up notification in bottom right corner .toast(message, title, display time)
//var message = "Your search for " + searchFirstName + " " + searchLastName + " is complete.";
//SS.toast(message,"Search Complete",15);
};
You can probably trying getting all the data inside an array in one step and then quickly compare your value with those in the array. Something like this:
var sheet = SpreadsheetApp.getActive().getSheetByName("Member Data");
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][0] == firstName && data[i][1] == secondName) {
throw("Found");
}
}

Setting Script Property using it in "if" in Google

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") {