I have two scripts working on the same sheet, one works fine, the other fails every time. The catch? they're duplicates of each other, just pointing at different sheets.
The debuggers announce that the 'message' variable doesn't exist, but again, the first copy here works great, the second just never runs.
Posting below
Functioning:
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var email = 'fakeemail#fake.com';
var updater = Session.getActiveUser();
var subject = 'Tracker Updated by ' + updater;
var text = sheet.getDataRange().getValues();
if(cell.indexOf('I')!=-1){
message = sheet.getRange('A'+ sheet.getActiveCell().getRowIndex()).getValue()
}
var body = 'Page Updated for ' + message + ' by; ' + updater;
GmailApp.sendEmail(email, subject, body);
}
;
and the failing one
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var email = 'fakeemail#fake.com';
var updater = Session.getActiveUser();
var subject = 'Tracker Now Updated by ' + updater;
var text = sheet.getDataRange().getValues();
if(cell.indexOf('Votes!L')!=-1){
message = sheet.getRange('Votes!A'+ sheet.getActiveCell().getRowIndex()).getValue()
}
var body = 'Page Updated for ' + message + ' by; ' + updater;
GmailApp.sendEmail(email, subject, body);
}
;
So what gives?
Related
I am getting an error ReferenceError: options is not defined at myfunctionFDI(OverallScript.gs:39:48)at onEdit(OverallScript.gs:3:1), when I am trying to run multiple myfunctions within onEdit, what am I doing wrong, it appears to run the first myfunction correctly. Help would be appreciated script is here
function onEdit(e) {
myfunctionMCR(e);
myfunctionFDI(e);
}
function myfunctionMCR(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var recipients = "joebloggs#blogs.com";
var message = '';
if(cellvalue === 'MCR Approved'){
message = 'Cell ' + cell + ' in Sheet MAN ' + sheetName + ' was changed to MCR Approved and is ready for your Review & Approval.';
var subject = 'Cell Changed to MCR Approved';
var body = message + ' Visit ' + ss.getUrl() + ' to view the change and approve';
var options = {
cc: "fredblogs#blogs.com,bobblogs#blogs.com"
}
MailApp.sendEmail(recipients, subject, body, options);
}
}
function myfunctionFDI(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var recipients = "fredblogs#blogs.com";
var message = '';
if(cellvalue === 'FDI'){
message = 'Cell ' + cell + ' in Sheet MAN ' + sheetName + ' was changed to FDI and is ready for your review.';
var subject = 'Cell Changed to FDI Review';
var body = message + ' Visit ' + ss.getUrl() + ' FDI to Review';
MailApp.sendEmail(recipients, subject, body, options);
};
}
I've developed the below script (with the help of existing scripts in stackoverflow) and it does what it is intended to do. There are 2 things I want to change in the script but not sure how.
1- Instead of reading the value in a cell where I do a count of values, I want to count the values in the script
2- In the email I send out, I want to display a hyperlink text instead of the url.
Any help would be highly appreciated.
function sendEmails() {
//enter the sheet name
var sheetname = 'CFS Open Cases Report'
var counter_sheet = 'count of recipients'
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetname);
//A1 is the cell that counts the number of rows in Column A. Try counting values in A2:A in the script instead
var row_counter = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(counter_sheet).getRange("A2");
var row_count = row_counter.getValue();
var startRow = 2; // First row of data to process
var numRows = row_count; // Number of rows to process
//find a way to display the url as a hyperlink in the email body
var report_url = "https://google.com";
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var first_name = row[0]; // First column
var emailAddress = row[3]; // Fourth column
//html message text
var msgHtml = 'message and' + report_url
;
//today's date to be used as report date
var report_date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy");
var report_desc = "Report Name"
var subject = report_date +' - '+ report_desc;
//send the email
MailApp.sendEmail(emailAddress, subject, msgHtml);
}
}
Here's the modified script:
function sendEmails() {
var sheetname = 'Sheet1' // enter the sheet name where the recipient details are listed
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetname);
var row_count = sheet.getRange("A2:A" + sheet.getLastRow()).getValues().flat().filter(String).length; // counts the rows in the A2:A range
var startRow = 2; // first row of data to process
var numRows = row_count; // number of rows to process
var report_url = "www.google.com";
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var first_name = row[0]; // First column
var emailAddress = row[3]; // Fourth column
//html message text
var msgHtml = 'Hi ' + first_name +','
+ '<br/><br/>message here.'
+ '<br/><br/>more message here.'
+ '<br/><br/>and more: '+ 'Go to Google'
+ '<br/><br/>Kind Regards,'
+ '<br/><br/>my name'
;
//today's date to be used as report date
var report_date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy");
var report_desc = "CFS Open Cases Report"
var subject = report_date +' - '+ report_desc;
// clear html tags and convert br to new lines for plain mail
var msgPlain = msgHtml.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
//send the email
MailApp.sendEmail(emailAddress, subject, msgPlain);
}
}
Here's where I'm stuck with. I need to get rid of the html tags but keep the line breaks before I send the emails out:
var msgHtml = 'Hi ' + first_name +','
+ '<br/><br/>second line.'
+ '<br/><br/>third line.'
+ '<br/><br/>fourth line ' + `Go to Google`
+ '<br/><br/>fifth line,'
+ '<br/><br/>sixth line'
;
//today's date to be used as report date
var report_date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy");
var report_desc = "CFS Open Cases Report"
var subject = report_date +' - '+ report_desc;
// clear html tags and convert br to new lines for plain mail
var msgPlain = msgHtml.replace(/\<br\/\>/gi, '\n').replace(/(<([^>]+)>)/ig, "");
//send the email
MailApp.sendEmail(emailAddress, subject, msgHtml);
}
Finally understood what was wrong:
MailApp.sendEmail(emailAddress, subject, msgHtml);
Changed the above to and it works now:
MailApp.sendEmail({to: emailAddress, subject: subject, htmlBody: msgHtml});
Modification points:
About Instead of reading the value in a cell where I do a count of values, I want to count the values in the script, in order to covert counta(A2:A) to Google Apps Script, I thought that var row_count = counter_sheet_obj.getRange("A2:A" + counter_sheet_obj.getLastRow()).getValues().flat().filter(String).length; might be useful.
About In the email I send out, I want to display a hyperlink text instead of the url., in order to send an email including the hyperlink of report_url, I thought that htmlBody can be used. For this, I modified var msgHtml = 'message and' + report_url to var msgHtml = 'message and ' + ${report_url};.
When these points are reflected in your script, it becomes as follows.
Modified script:
function sendEmails() {
var sheetname = 'CFS Open Cases Report'
var counter_sheet = 'count of recipients'
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetname);
var counter_sheet_obj = ss.getSheetByName(counter_sheet);
var row_count = counter_sheet_obj.getRange("A2:A" + counter_sheet_obj.getLastRow()).getValues().flat().filter(String).length;
var startRow = 2;
var numRows = row_count;
var report_url = "https://google.com";
var dataRange = sheet.getRange(startRow, 1, numRows, 4)
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var first_name = row[0]; // This is not used in your script.
var emailAddress = row[3];
var msgHtml = 'message and ' + `${report_url}`;
var report_date = Utilities.formatDate(new Date(), "GMT+1", "dd/MM/yyyy");
var report_desc = "Report Name"
var subject = report_date + ' - ' + report_desc;
MailApp.sendEmail({to: emailAddress, subject: subject, htmlBody: msgHtml});
}
}
Reference:
sendEmail(message) of Class MailApp
Added:
When I saw your current script, I think that you don't correctly reflect my proposed script. Please modify your current script as follows.
From:
+ '<br/><br/>and more: '+ 'Go to Google'
To:
+ '<br/><br/>and more: '+ `Go to Google`
Please use ` instead of '.
Reference:
Template literals
I am creating a google script that when a person changes a column to "Approved" it sends an email out that grabs the cell that was changed. However, I am not a expert scripter at all and am having a hard time in figuring out how to get the script to call the information from the actual row into the email either.
Here is my script:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var rowData = sheet.getActiveRange().getRow();getValue();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var recipients = "test#sendemail.com";
var message = '';
if(cellvalue === 'Approved'){
message = 'Cell ' + cell + ' ' + ' ' + rowData + ' was changed to Approved.';
var subject = 'Cell Changed to Approved in Interns List';
var body = message;
MailApp.sendEmail(recipients, subject, body);
}
}
I couldnt find any solution thats been done already that would include the entire row that was triggered.
Try this:
function onMyEdit(e) {
const sh=e.range.getSheet();
var rowData = sh.getRange(e.range.rowStart,1,1,sh.getLastColumn()).getValues()[0].join(',');
var recipients = "test#sendemail.com";
var message = '';
if(e.value == 'Approved'){
message = 'Cell ' + e.range.getA1Notation() + ' ' + ' ' + rowData + ' was changed to Approved.';
var subject = 'Cell Changed to Approved in Interns List';
MailApp.sendEmail(recipients, subject, message);
}
}
In the new Google Spreadsheet I have a large script that clears the contents from many cells throughout 8 different sheets.
The formulas that total up the sheet is the only section that is protected, but I keep getting the error on the .clearContent(); method when the script isn't touching any of the protected cells.
Any thoughts? This is the identical script used (working perfect) on the old spreadsheets.
function masterCloseWeek() {
var hideLiqOrder = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LIQUOR ORDER');
hideLiqOrder.hideSheet();
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var costReport = spreadsheet.getSheetByName('COST REPORT').activate();//Moves sheet to position 1
spreadsheet.moveActiveSheet(1);
var invoiceLog = spreadsheet.getSheetByName('INVOICE LOG').activate();//Moves sheet to position 2
spreadsheet.moveActiveSheet(2);
var dailyInventory = spreadsheet.getSheetByName('DAILY INVENTORY').activate();//Moves sheet to position 3
spreadsheet.moveActiveSheet(3);
SpreadsheetApp.flush();
var spreadsheetId = 'xxxxxxxxxxxx'; //ID
var file = Drive.Files.get(spreadsheetId);
var url = file.exportLinks['application/pdf'];
var token = ScriptApp.getOAuthToken();
var response = UrlFetchApp.fetch(url, {
headers: {
'Authorization': 'Bearer ' + token
}
});
//var pdf = response.getBlob();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getName();
var pdf = response.getBlob().setName(ss.getName() + '.pdf');
var CopyDate = Utilities.formatDate(new Date(), "GMT-3", "MM/dd/yyyy HH:mm"); // Funtion Date + Format
DocsList.createFile(pdf);
MailApp.sendEmail({
to:"myEmail#test.com",
subject: "Blank (v2.0) Weekly File Attached" + "_" + "Sent on " + CopyDate,
body:"(This is an automated email.).....Attached is a copy of the weekly file sent on" + " "+CopyDate,
attachments: [pdf]
})
var hideLiqOrder = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('LIQUOR ORDER');
hideLiqOrder.showSheet();
var liquorInventory = SpreadsheetApp.getActive().getSheetByName('LIQUOR INVENTORY');
liquorInventory.getRange('J6:J588').copyTo(liquorInventory.getRange('M6:M588'),{contentsOnly:true});
var foodInventory = SpreadsheetApp.getActive().getSheetByName('FOOD INVENTORY');
foodInventory.getRange('G5:G622').copyTo(foodInventory.getRange('I5:I622'),{contentsOnly:true});
//Finished closing week
//Starting a new week
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var costReport = activeSheet.getSheetByName('COST REPORT');
var FraminghamSnapShot = activeSheet.getSheetByName('FraminghamSnapShot');
costReport.getRange('E12:E16').copyTo(FraminghamSnapShot.getRange('B23:B27'),{contentsOnly:true});
This is the first error, when it tries to clear invoiceLog.getRange('A3:L52').clearContent();
var invoiceLog = SpreadsheetApp.getActive().getSheetByName('INVOICE LOG');
invoiceLog.getRange('A3:L52').clearContent();
var dailyInventory = SpreadsheetApp.getActive().getSheetByName('DAILY INVENTORY');
dailyInventory.getRange('C5:C9').clearContent();
dailyInventory.getRange('D6:I9').clearContent();
dailyInventory.getRange('C13:C17').clearContent();
dailyInventory.getRange('D14:I17').clearContent();
dailyInventory.getRange('C21:C25').clearContent();
dailyInventory.getRange('D22:I25').clearContent();
dailyInventory.getRange('C29:C33').clearContent();
dailyInventory.getRange('D30:I33').clearContent();
dailyInventory.getRange('C37:C41').clearContent();
dailyInventory.getRange('D38:I41').clearContent();
dailyInventory.getRange('C45:C49').clearContent();
dailyInventory.getRange('D46:I49').clearContent();
dailyInventory.getRange('C55:C59').clearContent();
dailyInventory.getRange('D56:I59').clearContent();
dailyInventory.getRange('C63:C67').clearContent();
dailyInventory.getRange('D64:I67').clearContent();
dailyInventory.getRange('C71:C75').clearContent();
dailyInventory.getRange('D72:I75').clearContent();
dailyInventory.getRange('C79:C83').clearContent();
dailyInventory.getRange('D80:I83').clearContent();
dailyInventory.getRange('C87:C91').clearContent();
dailyInventory.getRange('D88:I91').clearContent();
dailyInventory.getRange('C95:C99').clearContent();
dailyInventory.getRange('D96:I99').clearContent();
dailyInventory.getRange('C105:C109').clearContent();
dailyInventory.getRange('D106:I109').clearContent();
dailyInventory.getRange('C113:C117').clearContent();
dailyInventory.getRange('D114:I117').clearContent();
dailyInventory.getRange('C121:C125').clearContent();
dailyInventory.getRange('D122:I125').clearContent();
dailyInventory.getRange('C129:C133').clearContent();
dailyInventory.getRange('D130:I133').clearContent();
dailyInventory.getRange('C137:C141').clearContent();
dailyInventory.getRange('D138:I141').clearContent();
dailyInventory.getRange('C145:C149').clearContent();
dailyInventory.getRange('D146:I149').clearContent();
var foodInventory = SpreadsheetApp.getActive().getSheetByName('FOOD INVENTORY');
foodInventory.getRange('D5:F622').clearContent();
var liquorInventory = SpreadsheetApp.getActive().getSheetByName('LIQUOR INVENTORY');
liquorInventory.getRange('E6:I371').clearContent(); //Vodka thru Wines
liquorInventory.getRange('G375:I433').clearContent(); //Draft Beer
liquorInventory.getRange('G437:I535').clearContent(); //Bottle Beer
liquorInventory.getRange('E539:I588').clearContent(); //Non Alcoholic
var dailySalesSheet = SpreadsheetApp.getActive().getSheetByName('DAILY SALES SHEET');
dailySalesSheet.getRange('B4:H11').clearContent(); //Sales Categories
var costReport = SpreadsheetApp.getActive().getSheetByName('COST REPORT');
costReport.getRange('F12:F16').clearContent(); //Theoreticals
costReport.getRange('D20:D20').clearContent(); //Week Ending Date
var safeAudit = SpreadsheetApp.getActive().getSheetByName('SAFE AUDIT');
safeAudit.getRange('C3:P11').clearContent();
safeAudit.getRange('C14:P18').clearContent();
safeAudit.getRange('C22:P22').clearContent();
var destination = SpreadsheetApp.getActiveSpreadsheet();
Browser.msgBox('Closed Successfully','Your week has been successfully closed\\n and emailed.', Browser.Buttons.OK);
var name = Browser.inputBox('Enter Week Ending Date ONLY', 'Example: 11-5-14 \\n\\n', Browser.Buttons.OK);
destination.rename("BlankWE" + name);
costReport.getRange('D20').setValue(name);
}
Is there a better more efficient way to clear cells? Would that help solve the issue?
Sean.
Well, I don't find anything wrong in your invoiceLog.getRange('A3:L52').clearContent();, it works perfectly for me.
How do I tell cell C2 to set the date when cells A2 or B2 have been updated?
Further, how do I trigger the sending of my email function when A2 or B2 have been updated?
My issue is that onEdit fires anytime the document is edited at all, but I only want an action if a specific range is edited.
For the sending of emails, I've found and edited a script that almost works, but it sends me email notifications whenever any cell in the document is changed rather than just when column G is changed. Any suggestions?
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var recipients = "me#email.com";
var message = 'Cell value has been changed';
if(cell.indexOf('G')!=-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 + '»';
MailApp.sendEmail(recipients, subject, body);
};
Does this have to do with my onEdit() function being off?
For anyone that needs the final scripts
I ended up splitting this up in two separate functions. Here are the finished scripts.
The first one is the email notifications
/* This function send an email when a specified range is edited
* The spreadsheets triggers must be set to onEdit for the function
*/
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Define Notification Details
var recipients = ENTEREMAILHERE;
var subject = "Update to "+ss.getName();
var body = ss.getName() + "has been updated. Visit " + ss.getUrl() + " to view the changes.";
//Check to see if column is A or B to trigger
if (cellcol == EDITMECOLUMN)
{
//check for row to trigger
if (cellrow == EDITMEROW)
{
//Send the Email
MailApp.sendEmail(recipients, subject, body);
}
//End sendNotification
}
}
And here is the one for time stamps
/* This function saves the date in a cell
* every time a specific row or column is edited
* The spreadsheets triggers must be set to onEdit for the function
*/
function setDate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Check to see if column is A or B to trigger
if (cellcol == EDITMECOLUMN)
{
//check for row to trigger
if (cellrow == EDITMEROW)
{
//Find cell and set date in a defined cell
var celldate = sheet.getRange(EDITMEROW, EDITMECOLUMN);
celldate.setValue(new Date());
//end set date
}
}
}
This should work or at least give you the idea as I do something very similar. I usually set the trigger for this to be onEdit()
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Check to see if column is A or B to trigger email
if (cellcol == 1 || cellcol ==2)
{
//check for row to trigger email
if (cellrow ==2)
{
//Find cell and set date
var celldate = sheet.getRange(2, 3);
celldate.setValue(new Date());
//end set date
var cellvalue = mycell.getValue().toString();
var recipients = "me#email.com";
var message = 'Cell value has been changed';
if(cell.indexOf('G')!=-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 + '»';
MailApp.sendEmail(recipients, subject, body);
}
}
}
Your onEdit(event) needs to check the event.range and make decisions based on that.
See Understanding Events.
Here's an answer to a similar question.