I'm looking for a way to trigger an automatic email notification to myself when any value within a column of data ("Column H") drops below a certain threshold. Ideally, the notification would include the name associated with the value, which is stored in a separate column of the spreadsheet ("Column A").
My best guess so far is that I need to use an onEdit function, which has a condition that checks the values within the specific column and then sends a email when a value meets that condition.
Here's what I have so far, but I'm having issues with completing this.
function onEdit(e){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange("H1:H200").getValues();
var newValue = e.value;
}
if (newValue < "10"){
MailApp.sendEmail("test#test.com","TEST", "TEST");
}
Any help would be appreciated. Thanks!
Update: Here's what I currently have, following the creation of an installable trigger. I'm getting a 'value' undefined error at the moment and think that possibly syntax/formatting are to blame.
function createSpreadsheetEditTrigger(){
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger(StationeryEdited)
.forSpreadsheet(ss)
.onEdit()
.create();
}
function StationeryEdited(e){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange(2, 8, 200, 1).getValues();
var newValue = e.value;
if (newValue < "10"){
MailApp.sendEmail("justin#bond.co", "TEST", "TEST");
}
}
Does this feature doesnt help you?
Tools >> Notification Rules
Related
I am a newbie and have been using a simple App Script to send out emails with triggers onEdit and onChange. However, my Worksheet has over ten sheets and any edits/changes (done by me or by computations) in any of the sheets sends out an email, causing unintended spam! To avoid this, if I could use some code that sends the email based only on ANY CHANGE to a specific cell's value, in a specific sheet, my problem would be solved. My outgoing email message is short and the whole message is in just ONE cell (C2). If I can add a line of code which monitors for ANY change in that cell C2, and sends out an email if there is a change, that's it! I'd be done. My Script is as follows:
function sendEmail(){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet1=ss.getSheetByName('Email');
var emailAddress = sheet1.getRange(2,1).getValue();
var subject = sheet1.getRange(2,2).getValue();
var message = sheet1.getRange(2,3).getValue();
MailApp.sendEmail(emailAddress, subject, message);
}
Answer:
You can do this with an onEdit() and a conditional.
Code Example:
function onEdit(e) {
const specificSheet = "Email" // for example
const specificCell = "C2" // for example
let sheetCheck = (e.range.getSheet().getName() == specificSheet)
let cellCheck = (e.range.getA1Notation() == specificCell)
if (!(sheetCheck && cellCheck)) {
return
}
else {
sendEmail()
}
}
Rundown of this function:
Defines the sheet and A1 notation of the specific cell to check
Gets the Sheet and the A1 notation of the cell which was just edited
Returns if either the Sheet or the Cell are not the defined specific cell (using De Morgan's law)
Runs sendEmail() if the cell and Sheet are correct
References:
Event Objects | Apps Script | Google Developers
Simple Triggers | Apps Script | Google Developers
De Morgan's laws - Wikipedia
Working from the answer, this is how it ended up for me since I had several ranges to check:
function onEdit(e){
if(wasEdited(e, range1)){ // e.g. range1 = "Sheet1!A5"
// handle range1 change
}
if(wasEdited(e, range2)){ // e.g. range2 = "Sheet1!A7"
// handle range2 change
}
}
function wasEdited(e, range){
let tab = getTabFromA1Range(range)
let cell = getRangeFromA1Range(range)
return e.range.getSheet().getName() == tab && e.range.getA1Notation() == cell
}
function getTabFromA1Range(a1Range){
return a1Range.substring(0, a1Range.indexOf("!"))
}
function getRangeFromA1Range(a1Range){
return a1Range.substring(a1Range.indexOf("!")+1)
}
On further research, the following solution seems to work the best:
function sendEmail(){
Utilities.sleep(30000);
var ss=SpreadsheetApp.getActiveSpreadsheet();
var data=ss.getActiveSheet().getActiveCell().getA1Notation();
var sheetname = ss.getActiveSheet().getName();
var sheet1=ss.getSheetByName('Email');
var emailAddress = sheet1.getRange(2,1).getValue();
var subject = sheet1.getRange(2,2).getValue();
var message = sheet1.getRange(2,3).getValue();
if(data.indexOf('A:C')!=-1.23456789) {
MailApp.sendEmail(emailAddress, subject, message);
}
};
The key seems to be the "if statement" on line 10. Please note the time delay of half a minute I added to the script. This is because without it, on the trigger activating, the previous email was going out instead of the current one. Obviously my app has a slight delay in syncing and the trigger fired before all the current data got populated in the relevant cell!
I have a sheet where when I change a specific cell to "YES", I need a template sheet to be copied to a new version and named as per the value of a cell on the current row.
I'm having trouble working out how to get the value of the first cell in the row selected. This is what I have so far (I know this is wrong):
function onEdit() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var currentCell = sheet.getCurrentCell();
if (currentCell = "YES")
{
SpreadsheetApp.getActiveSpreadsheet().toast("New change control sheet added to workbook.","Change Control",15);
var sourceRow = ss.getActiveRange().getRowIndex();
var tabName = ss.getRange(cell,1).getValues();
ss.getSheetByName("CCTemplate").showSheet()
.activate();
ss.setActiveSheet(ss.getSheetByName('CCTemplate'), true);
ss.duplicateActiveSheet();
ss.setActiveSheet(ss.getSheetByName('CCTemplate'), true);
ss.getActiveSheet().hideSheet();
ss.setActiveSheet(ss.getSheetByName('Copy of CCTemplate'), true);
ss.getActiveSheet().setName("CC" & tabName);
}
}
Any ideas?
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()=='Your Sheet Name' && e.value=="YES") {
e.source.toast="New change control sheet added to workbook.","Change Control",15);
var tabName=sh.getRange(e.range.rowStart,1).getValue();
var tsh=e.source.getSheetByName('CCTemplate');
var csh=tsh.copyTo(e.source);
csh.setName('CC'+tabName);
}
}
You should avoid using activate in your scripts especially in simple triggers where you have to finish in 30 seconds. I think this code does the same thing that you intended for your code. One significant difference is that I use the information that comes in the event object that comes with the trigger. You should add the code Logger.log(JSON.stringify(e)) and then look at the logs you will see that there is a lot of information available to you which removes the need to run extra functions to get things like a spreadsheet.
Use event objects
onEdit offers among others the event objects range and value which are helpful to retrieve the range that has been edited and its value.
Also
When you want to a cell and compare it against a value, like in if (currentCell = "YES") - you need to retrive its value (either currentCell.getValue() or just event.value) and you need to use == instead of = for comparison.
Be careful with getValues() vs getValue(). The former gives you a 2D array and is not necessary if you want to retrieve the value of a single cell.
There is no need to set your sheet to active in order to change its name.
You can rewrite your code as following:
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var currentCell = event.range;
var value = event.value;
if (value == "YES")
{
...
var sourceRow = range.getRowIndex();
var tabName = ss.getRange(sourceRow, 1).getValue();
...
ss.getSheetByName('Copy of CCTemplate').setName("CC" + tabName);
}
}
I'm quite new to google sheet script and looking for some assistance. I am trying to make a google script that will erase cells in a response sheet after a user has submitted it. As this could be a form edit url, it may not necessarily be the last row.
So everytime a form is submitted / edited, columns AN:AQ are cleared.
Any help greatly appreciated
I'm adding the working script to OP's question for anyone who comes across this.
function onFormSubmit11(e) {
var range = e.range;
var ss = range.getSheet();
var row = range.getRowIndex();
ss.getRange("AN"+row).clear();
ss.getRange("AO"+row).clear();
ss.getRange("AP"+row).clear()
ss.getRange("AQ"+row).clear()
}
The Spreadsheet trigger invoked by the Google Form contains the Range object. You can retrieve the sheet linked to the range as well the index of the row linked to the current form submission.
function formTrigger(e) {
var range = e.range;
var sheet = range.getSheet();
var rowIndex = row.getRowIndex();
sheet.getRange(rowIndex + 1, 1).setValue("Hello");
}
You could try something as simple as an onFormSubmit running the script through your linked spreadsheet. The script below will clear AN:AQ every time a form is submitted which is 'alf of what I think you're asking for.
As for on edit, that's something I'm trying to figure out myself in my own question!
function onFormSubmit() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sh = ss.getActiveSheet()
sh.getRange('AN1:AQ').clear();
}
Hi Again,
Try this below. As before, make sure your trigger is set on OnFormSubmit and it should work flawlessly. I've tested it myself, it only cleared the range between AN:AQ on row (wherever the form edits). If you want to delete different sections just replace the AN:AQ for whatever column(s) you wish to clear.
function onFormSubmit(e) {
var range = e.range;
var ss = range.getSheet();
var row = range.getRowIndex();
ss.getRange("AN:AQ"+row).clear();
}
I'm trying to create a script in Google Sheets that will send me an automated email every time that a value within a given column ("Column H") drops below a certain threshold. I've currently got the following script written, which includes an installable onEdit trigger. However, the script is not running when the spreadsheet is edited:
function StationeryEdited(e){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange(2, 8, 200, 1).getValues();
var newValue = e.value;
if (newValue < "10"){
MailApp.sendEmail("test#test.co", "TEST", "TEST");
}
function createSpreadsheetEditTrigger(){
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger(StationeryEdited)
.forSpreadsheet(ss)
.onEdit()
.create();
}
}
Have you tried putting function name in quotation marks like this?
ScriptApp.newTrigger('StationeryEdited')
Also, you can simply go to Edit -> Current project triggers and configure the trigger for your function manually select the following options for the 'StationeryEdited' function
Try this and set the installable trigger through the script editor:
function onEdit(e) {
var editColumn=e.range.getSheet().getActiveCell().getColumn()
if(editColumn==8 && e.value>10){
MailApp.sendEmail("test#test.co", "TEST", "TEST");
}}
I just wondered why clearContent() function does not work very well in new google spreadsheet!
function onEdit(event) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A:L");
var cell = ss.getActiveSelection();
var row = cell.getRow();
var column = cell.getColumn();
var range2 = sheet.getRange(row,column);
var response = Browser.msgBox('Did you confirm it?', Browser.Buttons.YES_NO);
if(response == 'yes'){Browser.msgBox('Thank you!', Browser.Buttons.OK)}
else{range2.clearContent()}
}
When I used old google spreadsheet, it worked.
But I'm using new google spreadsheet. It doesn't work.
getRange('A1:A2').clearContent(); is works.
But getRange(1,2).clearContent(); not work, even though it did work in old google spreadsheet!
Please do not tell me use old google spreadsheet.
Tell me how!!
I don't even see a .getActiveSelection() method in the ss class.
Don't see what you're doing with var range either.
We can just use the passed ss object e to get the range, then clear it when needed.
function onEdit(e) {
var range = e.range;
var response = Browser.msgBox('Did you confirm it?', Browser.Buttons.YES_NO);
if ( response == 'yes' ) {
Browser.msgBox('Thank you!', Browser.Buttons.OK);
}
else {
range.clearContent();
}
}
Thank you for your kind answer.
But I found what the problem is.
In the new google spreadsheet function clearContent() doesn't wotk because of 'data validation'!
So I set remove data validation function and clearcontent, finally, set same data validation in active cell.
It works!
Remove data validation.
Clearcontent.
Set data validation.
If anyone has same problem, try it.