I am trying to have this script loop per column. If a date in the column is the same as today's date, the script will send an email using the persons name and email address detailed in the same row.
Table of Expiry Dates
function myFunction()
{
var spreadSheet = SpreadsheetApp.getActiveSheet();
var dataRange = spreadSheet.getDataRange();
var data = dataRange.getValues();
var date = Utilities.formatDate(new Date(), "GMT", "dd/MM/yyyy")
var engcheck1 = dataRange.getColumn[2];
for (var i = 1; i < data.length; i++)
if (engcheck1 == date)
{
var row = data[i];
var emailAddress = row[7]; //position of email header — 1
var name = row[1]; // position of name header — 1
var subject = "Your Currency for Engineering is now expired";
var text = "Please note that your currency has expired today (" + date +"). You are now unauthorised to carry out any engineering tasks until you have been signed off by a member of the engineering team.";
var message = "Dear " + name + "," + "\n\n" + text + "\n\n" + "Please get back in currency at your earliest convenience." + "\n\n" + "Many thanks," + "\n" + "Dominic Paul"
MailApp.sendEmail(emailAddress, subject, message);
}(i);
}
Without the 'If' statement, the script will loop through each row and sending out an email address. When I include the 'If' statement, nothing is sent to the email addresses. Either I am using the if statement incorrectly or I am not targeting the column accurately. I tried creating a variable engcheck1 for column 2 ONLY but no email is sent despite today being one of the dates in column 2 (C).
I did not understand, what is var engcheck1 = dataRange.getColumn[2];.
If you need to send and email if date is the same as the value in C column, provided column C has type Plain text, this is the answer:
function myFunction() {
var spreadSheet = SpreadsheetApp.getActiveSheet();
var dataRange = spreadSheet.getDataRange();
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getDataRange().getNumRows();
var dateData = spreadSheet.getRange("C1:C" + lastRow).getDisplayValues().flat();
var data = dataRange.getValues();
var date = Utilities.formatDate(new Date(), "GMT", "dd/MM/yyyy")
for (var i = 1; i < data.length; i++) {
var rowDate = dateData[i];
var row = data[i];
// if the date in row is the same as date variable
if (rowDate === date) {
var emailAddress = row[7]; //position of email header — 1
var name = row[1]; // position of name header — 1
var subject = "Your Currency for Engineering is now expired";
var text = "Please ...";
var message = "Dear ...";
MailApp.sendEmail(emailAddress, subject, message);
};
}
}
Try this:
function myFunction() {
const ss = SpreadsheetApp.getActive();
var sh = ss.getActiveSheet();
var rg = sh.getDataRange();
var vs = rg.getValues();
const dt = new Date();
var dtv = new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()).valueOf();
vs.forEach((r,i) => {
let d = new Date(r[2]);
let dv = new Date(d.getFullYear(),d.getMonth(),d.getDate()).valueOf();
if(dv == dtv ) {
//send you email
}
})
}
Related
Reference to the previous question to Filter Gmail body and paste in Spreadsheet
I had created below a google app script and set a trigger for after every 5 minutes:
function GetEmailsData(){
// SKIP TO OUT OF OFFICE HOURS AND DAYS
var nowH=new Date().getHours();
var nowD=new Date().getDay();
if (nowH>19||nowH<8||nowD==0) { return }
// START OPERATION
var Gmail = GmailApp;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var MasterSheet = ss.getSheetByName("Master");
var index = 2;
var aa = 0; // count already update entries
var na = 0; // count not update entries
var lasttime = MasterSheet.getRange("Z1").getValue(); // in spreadsheet i record the last time of email scanned, so next trigger will search after that
Logger.log(lasttime);
var cdate = new Date();
var ctime = cdate.getTime();
var qDate = MasterSheet.getRange("Z1").getValue();
Logger.log("QDATE IS " + qDate);
//problem # 1: from filter is not working.
// SEARCH EMAIL
var query = 'from: email id, subject: email subject, after:' + Math.floor((qDate.getTime()) /1000);
var threadsNew = Gmail.search(query);
Logger.log(threadsNew.length);
//loop all emails
for(var n in threadsNew){
var thdNew = threadsNew[n];
var msgsNew = thdNew.getMessages();
var msgNew = msgsNew[msgsNew.length-1];
// GET ATTACHMENT
//var bodyNew = msgNew.getBody();
var plainbody = msgNew.getPlainBody();
var subject = msgNew.getSubject();
var Etime = msgNew.getDate();
//var attachments = msgNew.getAttachments();
//var attachment = attachments[0];
Logger.log(Etime);
Logger.log(subject);
//Logger.log(plainbody);
var tdata = plainbody.trim();
var data = parseEmail001(tdata);
//Logger.log(data);
// First Check Email Date
var newdate = new Date();
var dd = newdate.getDate();
var mm = newdate.getMonth() + 1;
var yyyy = newdate.getFullYear();
var cd = dd + "-" + mm + "-" + yyyy
//Logger.log(new Date());
//Logger.log(cd);
if (Etime.getDate() != dd) {return}
// first check current sheet exist or not
// DATE DECLARATION IS ABOVE
var itt = ss.getSheetByName(cd);
if (!itt) {
ss.insertSheet(cd);
var itt = ss.getSheetByName(cd);
var ms = ss.getSheetByName("Master");
var hlc = ms.getLastColumn();
var headings = ms.getRange(1,1,1,hlc).getValues();
itt.getRange(1,1,1,hlc).setValues(headings);
}
var MasterSheet = ss.getSheetByName(cd);
var mlr = MasterSheet.getLastRow();
var mlc = MasterSheet.getLastColumn();
//check data already updated or not
var NewDepositSlipNumber = Number(data[2]).toFixed(0);
//Logger.log(Number(data[2]).toFixed(0));
var olddata = MasterSheet.getDataRange().getValues();
//Logger.log(olddata[1][2]);
for(var i = 0; i<olddata.length;i++){
if(olddata[i][2] == NewDepositSlipNumber){
//Logger.log(i + 1);
var status = 'Already Update'
Logger.log(status);
break;
}
else{
var status = 'Not Update'
//Logger.log(status);
}
}
// count how many updated and how many not.
if(status == 'Not Update'){
na = na + 1;
}
else{
aa = aa + 1;
}
if(status == 'Not Update'){
MasterSheet.appendRow(data);
Logger.log("Data Updated");
}
}
//problem # 2: if conversation length are long, it is not reaching there
var lastscantime = threadsNew[0].getLastMessageDate();
var master = ss.getSheetByName("Master");
master.getRange("Z1").setValue(lastscantime);
Logger.log(lastscantime);
master.getRange("Z2").setValue(new Date());
Logger.log(new Date());
Logger.log("Total " + threadsNew.length + " found, out of which " + aa + " are already updated, while " + na + " are updated.");
}
function parseEmail001(message) {
var replaces = [
'Branch Code',
'Branch Name',
'Slip No',
'BL Number',
'Type Of Payment',
'Customer Name',
'Payer Bank',
'Payer Bank Branch',
'Transaction Type',
'Amount',
'Posting Date',
'Value Date'
];
return message.split('\n').slice(0, replaces.length)
.map((c,i) => c.replace(replaces[i], '').trim());
}
This script is working fine but I have two problems:
I placed three filters in query 1) from 2) subject 3) after
but sometimes it gives me emails that are from the same ID but different subject.
as per my observation, and I verified it by using debug mode if the conversation length is long I guess more than 30 it will not reach the end part of the script. it skipping my last step as I also marked it in the above script. and if conversation length is less it works smoothly.
explanation: in other words, from morning to evening it's working fine after every five minutes, but the next day it gets the problem, then I manually update my spreadsheet master sheet Z1 value as of today's date and time, then it works fine till tonight.
You might be reaching a script limitation. Possibly the custom function runtime.But it can be any, you should see an error if it didn't finish.
I'm having an issue where I want to be able to send an email with CC's based off cell values. i.e. both the main recipient email and CC email are in the spreadsheet in the same row. The code should cycle through each row and send an email to the recipient and attaches the CC to that email.
My code is as follows:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // Start at second row because the first row contains the data labels
var numRows = 10; // Put in here the number of rows you want to process
// Fetch the range of cells A2:B4
// Column A = Email Address, Column B = First Name
var dataRange = sheet.getRange("A2:C")
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var name = row[0];
var emailAddress = row[1];
var daysAbsent = row[2];
var CC = row[3];
var message = "Hi " + name + ",\n. We see that you have been absent for " + daysAbsent + " days.";
var subject = "Attendance Notification";
MailApp.sendEmail(emailAddress, subject, message,{
cc: CC
});
}
}
I have a Google Sheet where the Email & Name columns are auto-fill based on user submitted form. Also, I have 2 more columns where one column contain the list of giveaway code and another column is to act as an approval to send the email.
So for now I manage to create a button where when click it will send all emails with the giveaway code.
Now,
How can I only send the email to the user that only has a value "y" in the Status column?
Also, after sending the emails, the value "y" will changed to "d"? So that later, if I use the function again, it will only sending to the new users.
This is the sheet example https://docs.google.com/spreadsheets/d/1KkShktBnJoW9TmIzNsAuAJb6XslBrMwJGEJu7xeF1fk/edit?usp=sharing
This is the code
function sendArticleCountEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Test1"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:E1000");
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var emailAddress = rowData[1];
var timeStamp = rowData[0];
var recipient = rowData[2];
var code = rowData[3];
var status = rowData[4];
var message = 'Dear ' + recipient + ',\n\n' + 'The giveaway code is ' + code;
var subject = 'Here is your giveaway code!';
MailApp.sendEmail(emailAddress, subject, message);
}
}
/**
* The event handler triggered when opening the spreadsheet.
* #param {Event} e The onOpen event.
*/
function onOpen(e) {
var spreadsheet = SpreadsheetApp.getActive();
var menuItems = [
{name: 'Send Emails', functionName: 'sendArticleCountEmails'}
];
spreadsheet.addMenu('Send Emails', menuItems);
}
Just add an if statement like this:
function sendArticleCountEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Test1"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:E1000");
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var emailAddress = rowData[1];
var timeStamp = rowData[0];
var recipient = rowData[2];
var code = rowData[3];
var status = rowData[4];
var message = 'Dear ' + recipient + ',\n\n' + 'The giveaway code is ' + code;
var subject = 'Here is your giveaway code!';
if (status == "y") {
MailApp.sendEmail(emailAddress, subject, message);
var actualRow = parseInt(i)+2;
sheet.getRange(actualRow,5).setValue("d");
}
}
}
This script works, except it sends multiple emails, This script check Column F for any value above 0 then sends an email.Column F is where i manually enter data. Trying to get it to only send one email and put a "Email Sent" in column H. Then check if column H has a "Email Sent" if so don't send email again.
Here Is what my sheet looks like
https://docs.google.com/spreadsheets/d/1o5jKMDECIFozrwAQx6EDvPL1NkoMQ1nbpkd6AdS9ULk/edit?usp=sharing
function sendEmails() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses"); //get the sheet "Form Responses"
var data = sSheet.getRange(2, 1, sSheet.getLastRow(),sSheet.getLastColumn()).getValues(); //get the values of your table, without the header
var lastRow = sSheet.getLastRow();//gets the last row of entered data
var yourColumn = "H";//set your column
var yourFunction = ("Email Sent");//whatever function or formula or data you want,just don't forget to use lastRow do do the row number
sSheet.getRange(yourColumn+lastRow).setValue(yourFunction);
for (var i = 0; i < data.length; i++) { // For each element of your tab
var row = data[i];
if(row[5] > 0) { // If the person have got at least 1 report outstanding (column E)
var body = "Good day "+ row[0] + " you have " + row[5] + " Internal Audit reports outstanding.";
GmailApp.sendEmail(row[1],"Outstanding Internal Audit Reports", body); // Sending a mail to alert
}
}
}
Try This:
function sendEmailsToTechs() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("Form Responses");
//var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var data=rg.getValues();
var hRange=sh.getRange(2,8,sh.getLastRow(),1);
var hValues=hRange.getValues();
for (var i=1;i<data.length;i++){
var row = data[i];
if(row[5] && row[7]!='Email Sent') {
var body = "Good day "+ row[0] + " you have " + row[5] + " Internal Audit reports outstanding.";
GmailApp.sendEmail(row[1],"Outstanding Internal Audit Reports", body);
//Logger.log(body);
hValues[i-1][0]='Email Sent';
}
}
hRange.setValues(hValues);//Puts the values into the spreadsheet all at one time.
}
I am looking to get a few values from a previously submitted row from a google form response and then send these values, along with the title of the form, along to an end user.
however, I think I may be going about it the wrong way, I can pull up the spreadsheet and sheet and use this to edit a field, but i can not see how to pull the values back out from here, it just comes back as "range". what is the right syntax to get a values from a range?
is there any way to pull the title of the linked form? or the spreadsheet if that is not possible, as that is just "formName" +(responses).
here is the code i have so far, it is probably just missing something simple here (the e value that it accepts is a formatted URL):
function doGet(e){
var params = JSON.stringify(e);
var message = "thank you, your Decision has been sent.";
var id = '10kf5QDeBc-vr6XJnkFxQh-ch_poQhqBQWQbgJ';
var ss = SpreadsheetApp.openById(id);
// var ss = SpreadsheetApp.getActiveSpreadsheet();
// var sheet = ss.getActiveSheet();
var sheet = ss.getSheets()[0];
var column = 20;
var datecolumn = 5;
var row = e.parameter.row;
//var title = sheet.getTitle();
var sheetname = ss.getSheetName();
var sheetnamesheet = sheet.getName();
var eventDaterange = sheet.getRange(row, datecolumn);
var eventDate = eventDaterange.getvalues();
var approval_cell = sheet.getRange(row, column);
//set default to declined
approval_cell.setValue("declined");
var approvedMessage = "<HTML><body>"+
"<h2>your request has been Approved </h2><br />"
+"<P>" + title +" " + sheet
+"<p>" + " for this date: "+ eventDate;
var deniedMessage = "<HTML><body>"+
"<h2>your request has been denied </h2><br />"
+"<P>" + ss +" " + sheet
+"<p>" + " for this date: "+ eventDate;
var aprovalResponce = (e.parameter.approval == 'true') ? approvedMessage : deniedMessage;
//var msg = "Your manager said this: " + aprovalResponce;
var msg = aprovalResponce
var replyEmail = e.parameter.reply;
if (e.parameter.approval == 'true') {
approval_cell.setValue("APPROVED");
} else {
approval_cell.setValue("DECLINED");
}
//send the actual email out
//MailApp.sendEmail(replyEmail, "Approval Request", msg);
MailApp.sendEmail(replyEmail, "Approval Request", {htmlBody: msg});
return HtmlService.createHtmlOutput(message);
}
To get values from a range, you use var values = range.getValues(); This will return a result in an 2D array of values, which is like a grid representing the range, i.e. values[row][column]. So, if our range is, say, "A1:C3", and we want the values in A1 and C3, we could do this:
var range = sheet.getRange("A1:C3");
var values = range.getValues();
var valueOne = values[0][0];
var valueTwo = values[2][2];
var msg = '"Form name" + valueOne + ValueTwo'
I don't know how to get the form name though, perhaps something as simple as e.source.title? If not, if you are using multiple forms, you may have to do this by getting the form Id from the form being submitted, and then using a switch statement to match that ID to a list of form names within your script.