How to get an updated cell value in google sheets - javascript

i want to send an email to myself if my script in python does not run anymore.
I have implemented in python an uptime function. Cell E5 gets updated with the new uptime every 15 seconds. If the uptime does not change my script does not run anymore and i want to get notified via email. For this reason i compare the cell value after 5 minutes.
But uptime_zahl and uptime_new_zahl are always equal the value when i start my apps script function.
How can I get the updated cell value??
function uptimeCheck() {
var ss = SpreadsheetApp.openById("XXX");
var sheet = ss.getSheetByName('Tabellenblatt1');
var uptime_string = sheet.getRange("E5").getValue().toString();
var uptime_zahl = Number(uptime_string.replace(',', "."));
Utilities.sleep(300000);//wait for 5 minutes
var uptime_new_string = sheet.getRange("E5").getValue().toString();
var uptime_new_zahl = Number(uptime_new_string.replace(',', "."));
if (uptime_zahl == uptime_new_zahl)
{
var emailAddress = 'XXX';
var subject = 'The bot does not run';
var message = 'old time: '+uptime_zahl+'new time: '+uptime_new_zahl;
MailApp.sendEmail(emailAddress, subject,message);
}
}

You can store uptime_zahl in Script properties and run your automatically script on a time-driven trigger (e.g. every 5 minutes).
The following sample
sets during the first run the script property 'uptime_zahl' to the actual value in "E5" and the sent status to 0
compares the current value in "E5" against the one stored during the last script run
sends an email if the value is still the same and an email has not been sent yet
sets the script property to the current value and sent to 1, if an email for the current value has been sent already
function uptimeCheck() {
var ss = SpreadsheetApp.openById('XXX');
var sheet = ss.getSheetByName('Tabellenblatt1');
var uptime_string = sheet.getRange("E5").getValue().toString();
var uptime_new_zahl = Number(uptime_string.replace(',', "."));
if(PropertiesService.getScriptProperties().getKeys().length==0){ // first time you run the script
PropertiesService.getScriptProperties().setProperty('uptime_zahl',uptime_new_zahl);
PropertiesService.getScriptProperties().setProperty('sent',0);
}
var sent=parseInt(PropertiesService.getScriptProperties().getProperty('sent'));
var uptime_zahl = PropertiesService.getScriptProperties().getProperty('uptime_zahl');
if (uptime_zahl == uptime_new_zahl&&sent==0)
{
Logger.log('still the same, email sent: '+uptime_zahl);
var emailAddress = 'XXX';
var subject = 'The bot does not run';
var message = 'old time: '+uptime_zahl+'new time: '+uptime_new_zahl;
MailApp.sendEmail(emailAddress, subject,message);
sent=1;
}else if(uptime_zahl != uptime_new_zahl){
sent=0;
Logger.log('value changed');
}else{
Logger.log('value did not change, but email has been sent already');
}
PropertiesService.getScriptProperties().setProperty('uptime_zahl',uptime_new_zahl);
PropertiesService.getScriptProperties().setProperty('sent',sent);
}
To set up a time-driven trigger:

Related

Google AppScripts Send Email to on cell value or button click only

I've just started with Javascript in AppScripts and I'm trying to piece together a system that will send emails based on the type of resident we have (owner, renter, renewal). Right now, this code is sending the same email to everyone on the spreadsheet when I run the script or click the assigned "sendEmails" button. I want co-workers to be able to send the emails to the appropriate resident type after they have made an appointment for them, individually. I have a data validation drop down column with the different types. Is there a way that upon clicking the resident type in the drop-down that the appropriate email will go out according to resident type? Any assistance is appreciated! Complete novice here, but this would really help our workflow immensely.
function sendEmail() {
//Email for New Tenant Only
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Schedule Residents");
var lr = ss.getLastRow();
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1,1).getValue();
for (var i = 2;i<=lr;i++){
var currentEmail = ss.getRange(i, 11).getValue();
var currentDate = ss.getRange(i, 1).getValue();
var currentName = ss.getRange(i, 3).getValue();
var messageBody = templateText.replace("{name}",currentName).replace("{date}",currentDate);
var subjectLine = "Reminder: " + currentDate + " Upcoming Appointment";
MailApp.sendEmail(currentEmail, subjectLine, messageBody);
}
}
You can use the onEdit that allows you to send an email when an edit is taking place in the sheet
Triiger allow you to use event objects that are tied to the event causing the trigger to fires
That is you can query which range has been edited, what is the new value etc.
You can implement that an email is automatically sent when a resident type is set and retrieve dynamically the correct template
For sending limits you cannot use the simple onEdit trigger due to limitations
Instead, bind to your function manually an installable onEdit trigger
Mind that functions containg event objects (e) will error if you try to run them manually - they run automatically on trigger event
Sample function to be bound to a trigger:
function sendOnEdit(e) {
//Email for New Tenant Only
var ss = e.range.getSheet();
var typeColumn = 4;
if (sheet.getName() == "Schedule Residents" && e.range.getColumn() == typeColumn){
var row = e.range.getRow();
var value = e.value;
var templates = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Template").getRange(1,1,3,1).getValues();
var templateText;
switch (value){
case "Email New Owner":
templateText = templates[1][0];
break;
case "Email New Tenant":
templateText = templates[0][0];
break;
case "Email Renewal":
templateText = templates[2][0];
break;
}
var currentEmail = "ziganotschka1#egs-sbt015.eu"//ss.getRange(row, 11).getValue();
var currentDate = ss.getRange(row, 1).getValue();
var currentName = ss.getRange(row, 3).getValue();
var messageBody = templateText.replace("{name}",currentName).replace("{date}",currentDate);
var subjectLine = "Reminder: " + currentDate + " Upcoming Appointment";
MailApp.sendEmail(currentEmail, subjectLine, messageBody);
}
}

Google Script cell value email notification by current date

I would like to send automated email notifications from my google spreadsheet if the value in column E is higher than 0. The spreadsheet looks like this. The problem is I cant figure out how to check only values for current days date and then post by email. My code looks like this
var failedOperationRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("notif").getRange("E2");
var failedOperation = failedOperationRange.getValue();
var ui = SpreadsheetApp.getUi();
// Check totals sales
if (failedOperation > 0){
// ui.alert('Failed operation occured!');
// Send Alert Email.
var message = failedOperation;
var subject = 'Your Google Spreadsheet Alert';
for(var i in TO) {
MailApp.sendEmail(TO[i], subject, message);
}
Get the value for the corresponding row in column 'H' and compare it with a javascript Date object.
If you need the current date in a string format you can use this:
var today = new Date();
today.toLocaleDateString(); // 3/26/2020
Then you send the email if the two conditions (failed operations > 0 and date = today) are satisfied.

Failed redundancy measures on google script for sending emails via google sheets

I'm trying to send a reminder for a weekly webinar with emails that live on a Google Sheet using Google's script editor/codelab. The link for the tutorial it's based off of is here: https://developers.google.com/apps-script/articles/sending_emails
In their second section of code they post, it is an improved version because after the email is sent it populates a column with "EMAIL_SENT" and should prevent a duplicate email being sent out because "EMAIL_SENT" occupies that space (as I understand it).
My problem is that after I run the script, I'm able to get the emails to send off (I used three email accounts and each one received it), but I also get an error that reads:
Failed to send email: no recipient (line 24, file "macros").
Macros is the name of the file. The other issue I'm having is that if I run the script again after EMAIL_SENT has populated, it still sends an additional email even though it's not supposed to.
I've tried making the object in the first portion of the code different numbers to try and capture the right data. After I got the right data in there I don't understand why the other portions won't work.
`// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails_w_verification() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 116; // First row of data to process
var numColumns = 8;
var startColumn = 1;
// Fetch the range of cells as object
var dataRange = sheet.getRange(startRow, startColumn,
sheet.getLastRow(), numColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = "Thank you for registering for the webinar"; // Second
column
var emailSent = row[8]; // ninth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = 'AFWERX Webinar Reminder';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 9).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is
interrupted
SpreadsheetApp.flush();
}
}
}
Expected duplicates not to send and no error message of "Failed to send email: no recipient (line 24, file "macros")" when the email sent.
Your first no recipient error seems to be caused by how you're starting your for loop, if you switch it to i++ instead, the script runs fine. This is because by using ++i you're picking up an extra row which doesn't have any email address in it, causing it to throw the "no recipient" error you're getting.
The second issue with the script not being able to check against column 9 is because the range you defined is only 8 columns wide, not 9. I found this by using a simple Logger.log(emailSent) which came back as undefined, which is what you'd expect to see if the value isn't even being defined in the range at all.
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails_w_verification() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 1; // First row of data to process
var numColumns = 9;
var startColumn = 1;
// Fetch the range of cells as object
var dataRange = sheet.getRange(startRow, startColumn, sheet.getLastRow(), numColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = "Thank you for registering for the webinar"; // Second column
var emailSent = row[8]; // ninth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = 'AFWERX Webinar Reminder';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 9).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I've changed the for statement to use i++ rather than ++i which fixes the "no recipient" error message.
for (var i = 0; i < data.length; i++) {
Then changed your var numColumns to 9 rather than 8 so that it can see the column you're trying to check with your if statement.
var numColumns = 9;

getValue not working on sheets

I'm trying to set up an email alert system based on a project tracking sheet my team uses at work. I need it to send an email when a task's status is changed to "Done" in column K. I got the code to work on a test sheet, but when I copy it to the live sheet the getValue() code stops working? Since the email is sent based on if() statements, the script runs, but doesn't actually work. I'm not sure if it's a permissions issue since I am not the owner of the live sheet?
I hope that is descriptive enough -- I have taught myself javascript in order to get this working and it seems so close, but I am stuck!!
Here is a screenshot of what the project tracking sheet looks like.
function emailUpdate(e) {
var emailInfoRange = sheet.getRange("B:O");
var edit = e.range.getA1Notation(); // Gets edited cell location
var editColumn = edit.substring(0,1) // Gets column of edited cell
var editRow = edit.substring(1,3) // Gets row of edited cell
if(editColumn == "K") { // gets all relevent information needed for email
var taskTypeCell = emailInfoRange.getCell(editRow,1);
var taskType = taskTypeCell.getValue();
var requestedByCell = emailInfoRange.getCell(editRow,3);
var requestedBy = requestedByCell.getValue();
var emailRequestCell = emailInfoRange.getCell(editRow,4);
var emailRequest = emailRequestCell.getValue();
var projectIdCell = emailInfoRange.getCell(editRow,5);
var projectID = projectIdCell.getValue();
var taskDescriptionCell = emailInfoRange.getCell(editRow,6);
var taskDescription = taskDescriptionCell.getValue();
var claimedByCell = emailInfoRange.getCell(editRow,9);
var claimedBy = claimedByCell.getValue();
var taskStatusCell = emailInfoRange.getCell(editRow,10);
var taskStatus = taskStatusCell.getValue();
if(taskStatus == "Done") {
if(emailRequest == "Yes" || emailRequest == "yes") { // Determines if status is "Done", and email notification is "Yes" or "yes"
var emailAddress;
var getEmailAddress = function(personelArray) { // Defines function to search email address arrays for the one that belongs to requestedBy
for (var i = 0; i < personelArray.length; i++) {
if(requestedBy === personelArray[i]) {
emailAddress = personelArray[i+1];
} } }
// Searches through all email arrays to find the one belonging to requester
getEmailAddress(specialistsAndEmails)
getEmailAddress(coordinatorsAndEmails)
getEmailAddress(managersAndEmails)
// Sends email
MailApp.sendEmail(emailAddress,
"AUTOGEN: " + taskType + " for " + projectID + " " + taskDescription + " completed by " + claimedBy + ".", "This email has been automatically generated by an edit to the work available sheet. \n"
+ "PLEASE DO NOT REPLY");
} else (Logger.log("No email requested"))
} else (Logger.log("Status not changed to done"))
} else (Logger.log("Update not to status cell"))
}
I would make the following changes to help prevent issues with string manipulations. Which could be the cause for your issues with getValues().
function emailUpdate(e) {
var emailInfoRange = sheet.getRange("B:O");
var edit = e.range // Gets edited cell location
var editColumn = edit.getColumn() // Gets column of edited cell
var editRow = edit.getRow() // Gets row of edited cell
if(editColumn == 11) // Column K should correspond to column number 11, if i can count correctly.
{
/// Remainder of the code should be the same as above
}
}
So instead of converting the range to A1 notation, you should get column number and row number using getColumn and getRow() on the range object. This will prevent issues with text to number manipulation and could be the cause of your problems.

If/Else Statement not working to send different emails

I am trying to write a script in google sheets that will send one of two different emails based on the response to a multiple choice question. I can get my if/else statement to send either one or the other of the emails but it will not recognize the text of the multiple choice answer and send the correct email.
Here is the full script:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1;
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 8)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var title = row[1]; // First column
var startDate = row[3]; // Second column
var endDate = row[4];
var description = row[2];
var location = row[6];
var eventImport = row[5];
var emailAddress = row[7];
var multchoice = row[8];
if (multchoice == "Part Time") {
var subject = "New Hire Part Time Email - " + startDate;
var emailBody = "Congradulations"
var htmlBody = "Congradulations! Part time person"
MailApp.sendEmail (emailAddress, subject, emailBody);
} else {
var subject = "New Hire Appointment - " + startDate;
var emailBody = "Congratulations! We are excited"
var htmlBody = "Congratulation! </i><br/> <br/> We are excited"
MailApp.sendEmail(emailAddress, subject, emailBody);
}
}
}
I believe the problem is here:
if (multchoice == "Part Time")
Any help is greatly appreciated! I am a novice
It looks like you are assigning your variables starting with '1' I stead of '0'. Start assigning them with 0 and counting up.
Without an example sheet to use, I won't be able to do a whole lot of debugging for you.
However, Apps Script comes with it's own debugger. Select the function you wish you debug and click the Little bug icon beside the play button.
Click on the sidebar where you want to set a breakpoint, where the code will stop executing.
Once it hits that breakpoint you can see all the variables currently within your scope. So the array, value, and i variables are visible to you.
Use this to your advantage and debug your code to find out where the issue is. Alternatively, you can use Logger.log() to log values at certain points within your code and then read back through the logs to try and determine where the problem lies.
The problem is not with your if/else statement. The problem is with how you are assigning your variables from your row[] array. While you use regular numbers in the getRange() function, the range that is returned is an array of those cells. Arrays always start with an index of [0]. Change var multchoice = row[8] to var multchoice = row[7] and your if/else statement will work (you'll want to change all of your other references, too).

Categories