cell reference out of range on Email Notifications - google-apps-script

I have the below code for sending a email notification when a cell changes, but it is always returning Cell reference out of range(line 5, file "Missing Cuts Report"). Can anyone advise if i need to change the code or if there is a way of getting it to stop failing and still send the email notification through. The trigger i use is OnChange because when it was on OnEdit it came back with error service invoked too many times on line 17 MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body }). Any help would really be appreciated.
function sendEnailNotification(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var cellvalue = ss.getActiveCell().getValue().toString();
if(SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getName() == "Missing Cuts Report") {
if(cell.indexOf('B')!=-1){
if(cellvalue > "") {
//Define Notification Details
var recipients = "email#email.co.uk;
var subject = "New Missing Cut Added";
var body = 'A new line has been added on the Missing Cuts Report on line <b>' + cell + '</b> - click here to view the update';
var msgPlain = body.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body });
}
}
}
}

Hi this is a not a very good way of achieving the result you want. Not really to sure what you are after. I have however made some adjustments to your code with notes after the closing braces. This is not an answer to your original problem. Just some hints.
function sendEmailNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var cellvalue = ss.getActiveCell().getValue().toString();
if(sheet.getName() === "Missing Cuts Report") {
//if(cell.indexOf('B')!== -1){
if(cellvalue !== "") {
//Define Notification Details
var recipients = "email#address.org";
var subject = "New Missing Cut Added";
var body = 'A new line has been added on the Missing Cuts Report on line <b>' + cell + '</b> - click here to view the update';
var msgPlain = body.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
MailApp.sendEmail(recipients, subject, msgPlain, { htmlBody: body });
} // "<" and ">" are not for comparing string values. (At least not in this case.)
//} //IndexOf will always result in -1 if you are looking for just "B" as your result will always be "B1/B2/B3/ect."
} // Already have the sheet object, no need to call again.
}

Related

Weird behaviour of Mailapp.sendEmail in Google apps script

I have been sending emails successfully through Google apps script triggered through submission in a Google sheet. Lately (about a week back), the email sender starts behaving very weird.
If I use the following format, my emails get bounced
MailApp.sendEmail(email1, subject, message,{cc:email2,attachments:[file.next()]});
If I use the following form, the email does NOT get delivered neither does it get bounced
MailApp.sendEmail(email, subject, message);
If I use the following format, the recipient gets the message as shown
MailApp.sendEmail(email,subject,{htmlBody: message});
Revecied message
[object Object]
and the rest of the stuff blank!
I'm at my wits' end as to how to go about. Any help or a pointer will be of immense help. Regards
Madhurjya
Following is the app script, which is attached to the Google sheet. Once I run the function sendPasswd() from sheet, it gets some vital parameters from the sheet data and then send the message to the person (through the variable email2)
function sendPasswd() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var dataRange = sheet.getDataRange()
var data = dataRange.getValues();
var subject = "Example Subject";
var message = "";
var i;
var file = DriveApp.getFilesByName("some_file.pdf");
for (i in data) {
var row = data[i];
if (i == 0) continue; // Skip the first row
if (row[4] == "Sent") continue;
var first = row[0]; var last = row[1]; var email = row[2];
var passwd = row[3]; var email2 = row[7];
if (row[15] == "some condition") {
message = "Dear <b>"+first+" "+last+"</b>,<br><br>"+
"This is to inform you that your .... ";
MailApp.sendEmail(email2, subject, message);
//MailApp.sendEmail(email2,subject,{htmlBody: "message"});
//MailApp.sendEmail(email2, subject, message,{cc:"some_email#example.com",attachments:[file.next()]});
}
}
}
The surprising fact is that from the same account similar emails are being sent and are NOT affected!
Madhurjya
This might be happening because you're using htmlbody which is part of options as third argument whereas in sendEmail(recipient, subject, body, options) of class MailApp, body should be third argument, that's is the reason of getting [object Object].
Try following modification:-
MailApp.sendEmail(email2,subject,"",{htmlBody: message});
Reference:
sendEmail
You could also use this way (its really more practical):
const email 'yourEmail#outlook.com'
const cc ='copyEmail#hotmail.com'
const bcc = 'blindCarbonCopy#gmail.com'
MailApp.sendEmail({
to:email,
cc: cc,
bcc: bcc,
subject: 'Whatever you want, even template strings' ,
htmlBody: `
You could just create your HTML IN HERE (using template strings)
Or create before and add here as variable as well.
`
})

How to add an existing chart in sheets while sending an email

I want a Line chart from my spreadsheet to appear in the email.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Agent Report - Monthly")
var startRow = 3; // First row of data to process since there is a header row
var emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Agent Report - Monthly").getRange("D3");
var emailAddress = emailRange.getValues();
var chartImg = Charts.newLineChart.setRange(12, 8) //This Throws an error
var subject = "Agent Report - Monthly"; // This is the subject of the email
var greeting_text = 'Hey Please find the below Report '+'</b><br><br>';
var text = greeting_text;
text+=SheetConverter.convertRange2html(sheet.getRange(startRow, 3 ,10,8));
text+='<br>';
var options = {
htmlBody: text,
noReply:true
};
MailApp.sendEmail({
to: "xxx#der.com",
subject: subject,
htmlBody: options,
inlineImages: {
chartImg: chartImage,
}
});
}
When I try to add the chart to the variable ChartImg in line 7, it throws an exception.
If I understand correctly, you already have the chart created without issue in the spreadsheet, and you only want to get it as an image. To do this you need a reference to the chart in the sheet, and then use the getAs() method on the chart's blob, it would look something like this for you:
var chart = sheet.getCharts()[0]; // assuming you only have that chart, this is just to get the chart's reference.
var options = {
htmlBody: "<img src='cid:chart' style='width:24px; height:16px;'/>",
noReply:true
};
var chartImg = chart.getBlob().getAs('image/png').setName("areaBlob");
// Then you would add it in the body of the email as an attachment
MailApp.sendEmail({
to: "xxx#der.com",
subject: subject,
htmlBody: options,
inlineImages: {
chart: chartImg,
}
});
In the following link you can find a more in depth explanation and example: Chart image in email from Google spreadsheet with google-apps-script returns white image

Modifying the Google Spreadsheet script for sending values by email

This is an offshoot of a similar post here. A good answer was provided by Rivero but his code sends the values on the Google Spreadsheet's response sheet. I was wondering if instead the script would return values of the same row and column range specified by the code BUT from other sheet in the same spreadsheet. I'm really new to this and can't seem to find the right combination of codes to do so. Here is Rivero's code, I hope someone can help me accomplish this. Thanks in advance!
/* Send Confirmation Email with Google Forms */
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for (var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SendConfirmationMail")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
function SendConfirmationMail(e) {
try {
var ss, cc, sendername, subject, columns;
var header, message, value, textbody, sender, itemID, url;
// This is your email address and you will be in the CC
cc = "name#email.com";
// This will show up as the sender's name
sendername = "name to be displayed as sender";
// Optional but change the following variable
// to have a custom subject for Google Docs emails
subject = "Choose an approppiate subject";
// This is the body of the auto-reply
message = "";
ss = SpreadsheetApp.getActiveSheet();
columns = ss.getRange(1, 1, 1, ss.getLastColumn()).getValues()[0];
// This is the submitter's email address
sender = e.namedValues["Username"].toString();
// Only include form values that are not blank
for ( var keys in columns ) {
var key = columns[keys];
//Use this to look for a particular named key
if ( e.namedValues[key] ) {
if ( key == "Username" ) {
header = "The user " + e.namedValues[key] + " has submitted the form, please review the following information.<br />";
} else {
message += key + ' ::<br /> '+ e.namedValues[key] + "<br />";
}
}
}
}
textbody = header + message;
textbody = textbody.replace("<br>", "\n");
Logger.log("Sending email");
GmailApp.sendEmail(cc, subject, textbody,
{cc: cc, name: sendername, htmlBody: textbody});
} catch (e) {
Logger.log(e.toString());
}
}
It would better if you can name your sheet and use it instead of using active spreadsheet.
var sheet = SpreadsheetApp.openById('spreadsheetId').getSheetByName('name');
OR you can also use the sheet number to access it.
var sheet = SpreadsheetApp.openById('spreadsheetId').getSheets()[0];
After you have reference to the sheet, get the range for the column followed by data array:
var columnRange = sheet.getRange('a1Notation');
var dataArray = columnRange.getValues();
then iterating the data as per your convenience
for(var i=1; i<=dataArray.length; i++)
{
}

Delete Columns from a spreadsheet that has blanks or 0's

I've seen several scripts listed on how to delete rows that contain blanks or 0's however I have a form and once submitted the responses are entered into the last row. The form has required fields but also has fields that don't need to be answered. For the columns that don't have a response I would like to not have the headers show up on the email on once the form is submitted. If I use the scripts that deal with rows all the information is deleted.
My current script is:
function sendFormByEmail(e)
{
var email = "anyone#anywhere.com";
var subject = "Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers)
message += headers[i] + ' = '+ e.namedValues[headers[i]].toString() + "\n\n";
MailApp.sendEmail(email, subject, message);
}
Right now if the person filling out the form doesn't provide a response I get the following:
Cell Number =
I would like to get only headers on responses and eliminate any blanks or "0's".
You simply need to validate your conditions before adding a response value to the message.
Since a blank response can sometimes contain spaces (and thus be 'non-blank'), first use the .replace() method to strip any padding before testing the string.
You can adjust the if statement here to suit your needs:
function sendFormByEmail(e)
{
var email = "anyone#anywhere.com";
var subject = "Form Submitted";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers) {
var value = e.namedValues[headers[i]]
.toString()
.replace(/(^\s+|\s+$)/g, ''); // Remove padding
// Only report form responses that aren't blank or 0.
if (value.length > 0 && value != '0') {
message += headers[i] + ' = '+ value + "\n\n";
}
}
MailApp.sendEmail(email, subject, message);
}

Email Google Form Results not working

I am using a script to have form results e-mailed to me every time the form is submitted. Entire code is posted in Google Groups here:
http://groups.google.com/a/googleproductforums.com/d/topic/apps-script/1rObNfuez6k/discussion
Here's the current code:
function contactUsMailer2(e) {
// var ss = SpreadsheetApp.getActive();
// SpreadsheetApp.setActiveSpreadsheet(ss);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data'); //default sheets - change if you
var setup = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Setup'); //rename the sheets
var width = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data').getLastColumn(); //get "width" of sheet, used to enumrate fields
var myEmailAddress = setup.getRange('B3').getValue(); //get email recipient(s) from "Setup" (default)
var myEmailSubject = setup.getRange('B4').getValue(); //get a subject line from "Setup" (default)
//from row 1 of "Data"
var sheetURL = SpreadsheetApp.getActiveSpreadsheet().getUrl(); //get sheet url to include in email
var formURL = SpreadsheetApp.getActiveSpreadsheet().getFormUrl(); //get form url to include in email
var column = 'A';
var message = '';
var htmlBody = '<html><body><table>'; //generated email will have both an HTML table and a plain-text part
//to be RFC compliant. beginning of html and table.
for (var c=1; c<=width; ++c) {
var data = sheet.getRange(1, c, 1, 1).getValue(); //this gets the "filed" names from the 1st row of "Sheet1"
try {
//retrieve field data and build the HTML and plain-text emails
var message = message + data + ': ' + e.namedValues[data].toString() + '\r\n'; //plain-text
var htmlBody = htmlBody + '<tr><td><b>' + data + ': </b></td><td>' + e.namedValues[data].toString() + '</td></tr>'; //HTML
}
catch (a) {
var message = message + data + ': n/a\r\n';
var htmlBody = htmlBody + '<tr><td><b>' + data + ': </b></td><td>n/a</td></tr>';
}
var column = String.fromCharCode(column.charCodeAt() + 1); //increment column letter
}
var htmlBody = htmlBody + '</table>'; //close table
var message = message + '\r\n\r\nData from form located at ' + formURL + '\r\n'; //put form url in text email
var message = message + 'Data posted to spreadsheet at ' + sheetURL; //put sheet url in text email
var htmlBody = htmlBody + '<br><br>Data from form located here<br>'; //put form url in HTML email
var htmlBody = htmlBody + 'Data posted to spreadsheet here<br>'; //put sheet url in HTML email
var htmlBody = htmlBody + '</body></html>'; //close html
MailApp.sendEmail(myEmailAddress, myEmailSubject, message, {htmlBody: htmlBody}) ; //send the email
}
function showid() {
Browser.msgBox("The sheet ID is:\r\n\r\n" + SpreadsheetApp.getActiveSpreadsheet().getId());
}
Script now works fine with the original spreadsheet, but when I try to use it with a new form and spreadsheet it fails to send the e-mail. The form fill in the spreadsheet just fine and we get the usual e-mail stating that the spreadsheet has been updated, but the script e-mail doesn't come through.
Funny thing is when I debug the script it does send the e-mail, just null entries in all fields (which is what I would expect). Debug doesn't report any errors in the script itself. What am I missing?
Have you authorized the script in your new form ? Since your script is required to send out an email it requires explicit authorization.
Try removing the quote around
for (var c=1; c<=width; ++c) {
var data = sheet.getRange(column + '1').getValue(); //this gets the "filed" names from the 1st row of "Sheet1"
I do something similar in a script and the following works for me.
var rangeval = "B"+(i+1);
var nameFld = filesheet.getRange(i+1,1).getValue();
Joe
Make sure trigger is set to "On Submit". Mine was set to "On Open".