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.
Related
I am completely new to Google Scripts. I experimented with the script found here (as written by Snipe and edited by Govoni in the first comment).
What I am trying to do is combine both scripts, to get an email on form submit that would:
only show answered questions (it works)
format questions in bold (it works)
populate the subject line (I can't get it to work)
The code below works.
function newResponse()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formName = ss.getSheetByName('Form Responses 1');
var lastRow = formName.getLastRow();
var lastColumn = formName.getLastColumn();
var email = "sample#myemail.com";
var name = "My Email";
var subject = 'New form response: ';
var body = '';
var cell = '';
for (var i = 1; i <= lastColumn ; i++)
{
var title = formName.getRange(1,i).getDisplayValue();
var cell = formName.getRange(lastRow, i).getDisplayValue();
if (cell != '' && cell != 0)
{
body = body + '<b>'+ title + '</b>: ' + cell + '<br>';
};
};
MailApp.sendEmail({
to: email,
name: name,
subject: subject,
htmlBody: body
});
}
So, to try and add variable entries to the subject line I changed 'function newResponse()' to 'function newResponse(e)' and added this line before MailApp:sendEmail:
// The email subject line should look like this: "New form response: Item (Company, Country)"
// Item, Company and Country are the 2nd, 3rd and 4th columns from my form
subject += e.namedValues[title[1]].toString() + " (" + e.namedValues[title[2]].toString()+ ", "
+ e.namedValues[title[3]].toString()+ ")";
But when I do this, it doesn't send an email at all. If I change e.namedValues and instead put something like [title[0]], it then returns the first letter of the last question answered.
I am not quite sure what to try next?
From your code snippet, I suppose title variable holds a string, so title[0] is the first character of the string. e.namedValues[title[1]] will be undefined if no questions are single-character. undefined.toString() will throw an error, crashing the entire script.
You'll need to save an array of titles of all columns in the sheet.
var titles = [];
for (var i = 1; i <= lastColumn ; i++) {
var title = formName.getRange(1,i).getDisplayValue();
titles.push(title);
var cell = formName.getRange(lastRow, i).getDisplayValue();
...
}
Afterwards, you'll be able to use e.namedValues[titles[1]]. Note that I use titles, the array.
Subject is not a member of the advanced parameters object its just a mailapp.senEdmail parameter.
Try:
sendEmail(email, subject, '', {name: name, htmlBody: body});
I have an emailer script that I would like to run for specified tabs and also make sure it skips any rows with blank values as it currently seems to break down as soon as it hits a blank row.
I have successfully built the script to work for one tab, but it seems to break down as soon as I try and get it to work for multiple tabs.
function reminders() {
var ss = SpreadsheetApp.openById("SHEET-ID");
var sheet = SpreadsheetApp.setActiveSheet(ss.getSheetByName(("sheet_1","sheet_2","sheet_3")));
var editedCell = sheet.getActiveRange().getColumnIndex();
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var text1 = 'Insert body of email here';
for (var i = 1; i < data.length; i++)
(function(val) {
var row = data[i];
var recipient = row[4];
var name = row[2];
var replyto = 'reply_to#email.com';
var body = 'Dear' + ' ' + name + ',' + '\n\n' + text1;
var subject = 'Hello World';
GmailApp.sendEmail(recipient, subject, body, {from:'reply_to#email.com', replyto:'reply_to#email.com'});
})(i);
}
This currently works for sheet_1 but does not work for sheet_2 or sheet_3.
Does anyone have any suggestions for how I can improve this script to send to multiple sheets and also skip blank rows?
You want to send emails using the values of column "C" and "E" from the Spreadsheet.
You want to run your script for the sheet names of "sheet_1", "sheet_2" and "sheet_3".
You want to skip the rows which have no values of the column "C" and/or "E".
If my understanding is correct, how about this modification?
Modification points:
It seems that when var sheet = SpreadsheetApp.setActiveSheet(ss.getSheetByName(("sheet_1","sheet_2","sheet_3"))); is run, only "sheet_3" is retrieved.
In your case, I think that setActiveSheet() might not be required to be used.
Number of arguments of getSheetByName(("sheet_1","sheet_2","sheet_3")) is one.
When you want to use multiple sheets, please use each sheet name in the loop.
var editedCell = sheet.getActiveRange().getColumnIndex(); is not used in your script.
val of (function(val) { is not used in your script.
When you want to skip the empty rows, please put the if statement before GmailApp.sendEmail(). By this, the error is removed at GmailApp.sendEmail().
When above points are reflected to your script, it becomes as follows. Please think of this as just one of several answers.
Modified script:
Please copy and paste the following modified script to the script editor.
function reminders() {
var sheets = ["sheet_1","sheet_2","sheet_3"]; // Please set the sheet names here.
var ss = SpreadsheetApp.openById("SHEET-ID");
for (var s = 0; s < sheets.length; s++) {
var sheet = ss.getSheetByName(sheets[s]);
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var text1 = 'Insert body of email here';
for (var i = 1; i < data.length; i++) {
var row = data[i];
var recipient = row[4];
var name = row[2];
if (!recipient || !name) continue; // Here, the empty rows are skipped.
var replyto = 'reply_to#email.com';
var body = 'Dear' + ' ' + name + ',' + '\n\n' + text1;
var subject = 'Hello World';
GmailApp.sendEmail(recipient, subject, body, {from:'reply_to#email.com', replyto:'reply_to#email.com'});
}
}
}
Note:
In this modified script, when "recipient" or "name" are not existing, the row is skipped.
When you send a lot of emails, please be careful the quotas of "Email read/write". You can see it at here.
References:
getSheetByName(name)
Quotas for Google Services
If I misunderstood your question and this was not the result you want, I apologize.
I am using a google spreadsheet which looks like:
A B C D
1 Name e-mail Identifer Status
2 Alex ax#gmail.com ERT ER A
3 Micke miike477#gmail.com Ejyu er w
4 John john7788#tri.com Arb Ed C
I have a drop down list in column D (let say A,B & C for example), now i want that whenever the value changes (Initially the column D would be blank) in column D against a particular Name than an automatic e-mail trigger to e-mail id mentioned in column B by below mentioned sender id and content.
The email should be trigger whenever value changes in column D except for the blank, and if there were previously value was "B" and now it change to "C" than mail should be trigger.
Sender-example#gmail.com
CC-test1#gmail.com,test2#gmail.com
E-mail Body:
Hi Alex (Should be picked from column A depending against which name e-mail trigger)
some sentence here.
some sentence here with your ERT ER (Should be pick from column C) has status A (should be pick from column D).
Regards,
example
123456789
I am trying using below mentioned script:
function onEdit(event){
if(event.range.getColumn() == 4){ //A -> 1, B -> 2, etc
function sendMyEmail(line){
var sendTo = spreadsheet.getRange(row, 2).getValue();
var cc = 'test1#gmail.com'+","+'test2#gmail.com';
var subject = "What is the: "+ spreadsheet.getRange(row, 3).getValue();
var content = "Hi "+spreadsheet.getRange(row, 1).getValue();+","
+"what is the vlaue "+spreadsheet.getRange(row, 3).getValue();+ "with the status"+spreadsheet.getRange(row, 4).getValue();+ "."
MailApp.sendEmail(sendTo,
cc,
subject,
content);
}
}
}
You have two major issues.
Simple triggers cannot access services that require authorization (such as MailApp).
Your usage of MailApp.sendEmail() is incorrect as you're passing cc to where should be passed either the subject or the replyTo address (docs). Argument order is important.
To address the issue of simple triggers, all you need to do is install a trigger manually that calls your function on edit.
All other issues are addressed in the code below.
function sendEmailToUser(event){
var eventRange = event.range;
var sheet = eventRange.getSheet();
var sheetName = sheet.getName();
var column = eventRange.getColumn();
if (sheetName == "Sheet1" && column == 4){ // Make sure the edited column is in the correct sheet, otherwise editing Column D in Sheet3 might trigger this
var row = eventRange.getRow(); // You need to know which row so you can send the email to the correct person
var rowValues = sheet.getRange(row, 1, 1, 4).getValues();
var name = rowValues[0][0];
var sendTo = rowValues[0][1];
var identifier = rowValues[0][2];
var status = rowValues[0][3];
if (status != "") { // Don't send the email if the status is blank
var cc = "test1#example.com, test2#example.com";
var subject = "What is the: " + identifier;
var content = "Hi " + name + "\nWhat is the value " + identifier + " with the status " + status + "?";
MailApp.sendEmail(sendTo, subject, content, {
cc: cc
});
}
}
}
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).
I have a Spreadsheet in Google Drive, which has two sheet in it "Production" and "Germination"
For the Production sheet, I to an email notification if a change has been made to the columns from A - F. Also if there is a row added or delete from the sheet.
The following code does the trick to some extent:
function onEdit( e ){
//To get email notification if any changes to the perticular cells
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("production");
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var recipients = "zeeshanrang#gmail.com";
var message = '';
if(cell.indexOf('C')!=-1){
message = sheet.getRange('D'+ sheet.getActiveCell().getRowIndex()).getValue()
}
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + ss.getUrl() + ' to view the changes on row: «' + row + '». New comment: «' + cellvalue + '». For message: «' + message + '»';
Logger.log(body);
//MailApp.sendEmail(recipients, subject, body);
};
But it sends me a mail on every edit, which is not required. It's required to send mail once every hour (if there is a change). Also right now it is only checking for changes on only Column C and not the rest of them.
Also, I was unable to understand if(cell.indexOf('C')!=-1) . Can someone explain me what does this statement means.
TIA
It means the following:
if(cell.indexOf('C')!=-1) // means that if you edit column C
....... //the following will happen
}
So to explain in more detail:
cell.indexOf('C')-> search for 'C'
!= -> Does not equal
-1 -> not there/ not found
if(cell.indexOf('C')!=-1) -> if indexOf('C') does not equal '-1' (i.e. if 'C' is there, do the 'if' statement