I am sending emails from a spreadsheet. I want the value of B2 to be the body of the email. This way I can type into cell B2 what I want to say in the message. I have the script set to send the charts and data contained in the sheet, and that works. But when I tried to set the body of the email as the value of cell B2, it simply sends a message that says "Range" and then adds the charts.
My code looks like this thus far
function emailParentsUpdates(sheet,emails,emailSubject){
var targetspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = targetspreadsheet.getActiveSheet();
var emailSubject = 'Grades Update';
var charts = sheet.getCharts();
var startRow = 1; // First row of data to process
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 1)
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var teacherEmail = "efazekas#dcsdk12.org"
if(charts.length==0){
MailApp.sendEmail({
to: teacherEmail,
subject: "ERROR:"+emailSubject,
htmlBody: "No charts in the spreadsheet"});
return;
}
var chartBlobs=new Array(charts.length);
//this is where the issue is. I need the email body to be the value, the actual words, of cell B2
var emailBody = sheet.getRange('B2');
var emailImages={};
for(var i=0;i<charts.length;i++){
var builder = charts[i].modify();
builder.setOption('vAxis.format', '#');
var newchart = builder.build();
chartBlobs[i]= newchart.getAs('image/png');
emailBody= emailBody + "<p align='center'><img src='cid:chart"+i+"'></p>";
emailImages["chart"+i]= chartBlobs[i];
}
MailApp.sendEmail({
to: emailAddress,
subject: emailSubject,
htmlBody: emailBody,
inlineImages:emailImages
});
}
}
I know it's rough and maybe not very succinct or elegant, but it does what I need except for the whole email body issue.
function getB2Value(){
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('B2');
return range.getValue();
}
getRange() returns a range, you need to call getValue() to get a reference to the value of the cell. I.e:
var emailBody = sheet.getRange('B2').getValue();
Related
I wrote a google script code (to send specific emails) and it'd been working for a while. But then I stopped it for about a month ago, and now I need it again. The problem is that code is executed, but it doesn't send any message. Could you please tell me what's wrong with my code.
function sendEmailL() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Lb'); //Sheet name
var startRow = 2; // First row of data to process
var numRows = 30; // Number of rows to process
// Fetch the range of cells U:V
var dataRange = sheet.getRange(startRow, 1, numRows, 30)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = row[20]; // First column
var message = row[21]; // Second column
var subject = 'Новое поступление от рекламодателя';
MailApp.sendEmail(emailAddress, subject, message);
}
}
If your not getting the right data in the dialog you need to learn how to use developer tools to figure out what's wrong.
function sendEmailL() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Lb'); //Sheet name
var startRow = 2; // First row of data to process
var numRows = 30; // Number of rows to process
// Fetch the range of cells U:V
var dataRange = sheet.getRange(startRow, 1, numRows, 30)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
let html='Test Data:<br />';
for (var i;i<data.length;i++) {
var row = data[i];
var emailAddress = row[20]; // First column
var message = row[21]; // Second column
var subject = 'Новое поступление от рекламодателя';
//MailApp.sendEmail(emailAddress, subject, message);
html+=Utilities.formatString('<br />Row:%s-emal: %s subject: %s message: %s',i+startRow,emailAddress,subject,message)
}
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html),'Testing');
}
And you probably should be checking getRemainingDailyQuota() to make sure you haven't exceeded the daily quota
I want the script to send an email to those mail addresses where unchecked boxes are in the row - This works fine. But I want the value of the checkbox to be set “True” after the mails were sent.
My Problem is that I need the last for-loop to stop after all checkboxes are checked. In other words: The last loop has to stop when an empty cell appears.
First of all I manually trigger the script - later I will start it with the help of a button in the menu (function onOpen...)
Appreciate any help – thanks a lot!
Check out the sheet and the code below:
function sendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
var response = ui.alert("mail was send to ", ui.ButtonSet.OK);
}
for (k=1; k < 20; k++) { //loop which has to stop
s.getRange(k, 3).setValue("True");
}
}
A couple of major changes in your script.
The condition for the loop is wrong. Change to:
for(var i=v.length-1;i>0;i--)
The UI response is missing the recipient name. Change to:
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
var UserData = range.getValues(); is declared twice: delete one row
Immediately after the UI alert (and still within the IF loop), add a line to update the checkbox: UserData[i][2] = true;
Simplify the updating of checkboxes.
Delete the existing lines:
for (k=1; k < 20; k++) {
s.getRange(k, 3).setValue("True");
}
Substitute:
range.setValues(UserData)
Revised Script
function sosendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
// MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
Logger.log("mail sent")
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
UserData[i][2] = true;
}
range.setValues(UserData)
}
Alternative Script
The following script is offered as an alternative. It avoids multiple getRange()/getValue statements and uses a more conventional top-down loop.
function sosendmail01() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
// get the number of rows (Alast)
var Avals = ss.getRange("A2:A").getValues();
var AlastRow = Avals.filter(String).length;
// Logger.log("DEBUG: number of rows = "+AlastRow)
// get the data range
var r = s.getRange(2, 1, AlastRow, 3);// get all the data
// Logger.log("DEBUG: the data range = "+r.getA1Notation())
var v = r.getValues(); // get the data
// loop through the rows of data
for (var i = 0;i<AlastRow;i++){
if (v[i][2] != false) {
// the checkbox is ticked Don't sent an email
// Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" - the checkbox is ticked");
} else{
// the checkbox IS NOT ticked - send an email
//Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" checkbox = "+v[i][2]+" - the checkbox is NOT ticked");
var name = v[i][0];
var email = v[i][1];
//MailApp.sendEmail(email, "Test", "Hello " + name + ", This is an email");
Logger.log("DEBUG: mail sent to "+name+" at "+email)
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
v[i][2] = true;
}
}
r.setValues(v);
}
Cant work out how to count the number of rows that have an email address in them, to populate the number of rows to process. I have a spreadsheet with a list of emails, the number of emailable rows changes regularly, so I'd like to count emailable rows, and instead of manually typing "28" or whatever, I'd like it to automatically find that number :)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 28; // Number of rows to process
// Fetch the range of cells
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 emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = "membership number"
MailApp.sendEmail(emailAddress, subject, message);
}
}
Returns the current number of rows in the sheet, regardless of content.
var emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
var noOfRows = sheet.getMaxRows();
var dataRange = sheet.getRange(startRow, 1, noOfRows , 4)
var data = dataRange.getValues();
data.foreach((row)=>{
if(emailRegex.test(row[0])){
var emailAddress = row[0];
var message = row[1];
var subject = "membership number"
MailApp.sendEmail(emailAddress, subject, message);
}
});
https://developers.google.com/apps-script/reference/spreadsheet/sheet#getLastRow%28%29
for counting email addresses in a range you can use simply:
=COUNTIF(A:C, "*#*")
or the proper way:
=ARRAYFORMULA(COUNTIF(ISEMAIL(A:C), TRUE))
I am trying to get a script working that hooks into a google sheet, pulls information that is taken of the phone, and sends it via email once marked. So far I have this, from sources on the internet and a bit of customising.
function sendApprovalEmail() {
var sheetNameToWatch = "SHEETNAMEGOESHEREUSUALLY";
var columnNumberToWatch = 12; // column A = 1, B = 2, etc.
var valueToWatch = "SENT";
var date = 5;
var name = 9;
var number = 10;
var message = 11;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch && range.getValue() == valueToWatch) {
var emailAddress = "MYEMAILGOESHEREUSUALLY";
var subject = "Missed Call Notifcation";
var email = "Hello! "+date+" "+name+" "+number+" "+message+"";
MailApp.sendEmail(emailAddress, subject, email);
}
}
The above works, triggers, and sends properly. The only thing it doesn't do is suck in the Date, Name, Number and Message.
These need to be unique for each email, based on the line that was just marked as SENT. Usually, there are only a couple a day, never at the same time.
So if Row 23 is marked as SENT, it needs A23, B23, and C23.
If row 66 is marked as SENT, it needs A66, B66, and C66.
How do I get the script to look up values in column 5, 9, 10 and 11 OF THE ROW that it has detected 'SENT' in?
The code is using var range = sheet.getActiveCell() the get the active cell. Then you could use range.getRow() to get the row number, then you could use something like sheet.getRange(range.getRow(), columnNumber) to get the desired cells where columnNumber could be 5, 9, 10 and/or 11. In other words, instead of
var date = 5;
use
var date = sheet.getRange(range.getRow(), 5).getValue();
but put the above line after
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getActiveCell();
Do the same for the name, number and message variables.
Note: There are other more efficient ways like using sheet.getDataRange().getValues() which will return an array of arrays having all the sheet values, the use
var date = data[range.getRow()][5];
and so on.
This is probably close to what your looking for:
First you have to settle on a format for your spreadsheet so that all operators will record the information in a standard format. I used the following format for each of my sheets.
All of the sheets used for recording information start with the prefix of 'ph:'. I get the entire array of sheets and I loop through them looking for the sheets that begin in 'ph:' name.slice(0,3). Once found I get the range of A1:B6 and collect all of the data into one array and then loop through the array putting all of the information into an associative array using the following algorithm dObj[value in column1]=value in column2. So in my example you can get the name with dObj.Name and the message is obtained by using dObj.Message and so on. So this associates the key in column one with the value in column2.
Now here is the code:
function sendApprovalEmails(){
var ss=SpreadsheetApp.getActive();
var shts=ss.getSheets();
for(var i=0;i<shts.length;i++){
var sh=shts[i];
var name=sh.getName();
if(name.slice(0,3)=='ph:'){//finds the operator log sheets
var dObj={};
var rg=sh.getRange('A1:B6');//Use a fixed range so you can use the rest of the sheet for whatever
var vA=rg.getValues();
for(var j=0;j<vA.length;j++){
dObj[vA[j][0]]=vA[j][1];//Builds the associative array
}
if(dObj.Approval=='Yes'){
Logger.log('Send Email:\nDate: %s\nNumber: %s\nName: %s\nMessage: %s,To: %s',Utilities.formatDate(new Date(dObj.Date),Session.getScriptTimeZone(),"E MMM dd, yyyy"),dObj.Number,dObj.Name,dObj.Message,dObj.Email);
var recipient=dObj.email;
var subject="Missed Call Notification";
var body = Utilities.formatString('Hello! %s %s %s %s',Utilities.formatDate(new Date(dObj.Date),Session.getScriptTimeZone(),"E MMM dd, yyyy"),dObj.Name,dObj.Number,dObj.Message);
//MailApp.sendEmail(recipient, subject, body);
}
}
}
}
In my example B1 has a data validation of either Yes or No.
Of course this is probably just a starting point. You can create the code to copy a master sheet and open it up with each phone call. I don't know if there is a limit to the number of sheets but there is a a limit to the number of cells in one Spreadsheet.
Documentation Reference:
By the way this version of your code works.
function sendApprovalEmail() {
var sheetNameToWatch = "test";
var columnNumberToWatch = 1;
var valueToWatch = "SENT";
var date = 5;
var name = 9;
var number = 10;
var message = 11;
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var range = sheet.getActiveCell();
if (sheet.getName()==sheetNameToWatch && range.getColumn()==columnNumberToWatch && range.getValue() == valueToWatch) {
var emailAddress = "foundit#found.com";
var subject = "Missed Call Notifcation";
var email = Utilities.formatString('Hello! %s %s %s %s',date,name,number,message);
//MailApp.sendEmail(emailAddress, subject, email);
Logger.log('\nemailAddress: %s\nsubject: %s\nemail: %s',emailAddress,subject,email);
}
}
I don't like to send out a lot of useless emails while debugging so I just use the Logger to record the email information.
I've been searching online all morning, and haven't been able to find what I want to do. I found a similar post on here, but couldn't figure out how to adapt it to my needs.
I'm a teacher, and I was thinking about how I could use Google Sheets to automatically email parents when their child's grade falls below a C in my class. I was able to quickly find the script to have Sheets send an email, and was wondering if it's possible to edit that script to have the email sent ONLY if the value in a specific cell is below 70.
Here's the script I found. I edited the subject line to read "Math Grade" (that was easy to figure out), but I'd like to edit it so that the email only gets sent if the value in cell D2 (or D3, D4, D5, etc) is below 70. (Column A has email, Column B has the message, Column C would have the student's name, and Column D would have their numerical grade.) I feel like it should be obvious, but my scripting knowledge is non-existent. Can anybody help?
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 2)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = "Math Grade";
MailApp.sendEmail(emailAddress, subject, message);
}
}
The code was only getting 2 columns of data, and it needs to get 4.
getRange(row, column, numRows, numColumns)
I added a line of code that gets how many columns are in the sheet. Then the for loop got an extra line of code to get the grade, and finally, an if conditional check was added.
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var numOfColumns = sheet.getLastColumn();
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, numOfColumns);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var grade = "";
var i = 0;
for (i=0;i<data.length;i++) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
grade = row[3];
if (grade < 70) {
var subject = "Math Grade";
MailApp.sendEmail(emailAddress, subject, message);
};
};
};