Automating Google Spreadsheets – Email Reminders - google-apps-script

I have a Google Spreadsheet and have modified the code below as indicated to send an email alert 7 days before the date condition is due. This works perfectly, however it only looks at the first sheet and the spreadsheet contains 23 sheets in total. I think I need to include an array and loop the code but cannot work this out so would appreciate some help! Thanks in advance.
function checkReminder() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// set the first sheet as active
SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
// fetch this sheet
var sheet = spreadsheet.getActiveSheet();
// figure out what the last row is
var lastRow = sheet.getLastRow();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 7;
// grab column 14 (the 'days left' column)
var range = sheet.getRange(7, 14, lastRow - startRow + 1, 1);
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Now, grab the reminder name column
range = sheet.getRange(7, 15, lastRow - startRow + 1, 1);
var reminder_info_values = range.getValues();
// Now, grab the deceased name column
range = sheet.getRange(3, 1);
var name_of_sheet = range.getValue();
var warning_count = 0;
var msg = "";
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if (days_left == 7) {
// if it's exactly 7, do something with the data.
var reminder_name = reminder_info_values[i][0];
msg = msg + "Reminder: " + name_of_sheet + " inscription work is due in " + days_left + " days.\n";
warning_count++;
}
}
if(warning_count) {
MailApp.sendEmail("my#email.com",
"Reminder Inscription Schedule Message", msg);
}
};

Related

Sending email when a date count down is triggered

I am trying to set up a sheet with varying email address and
dates. when a date (due) counts down to 20 say, I'd like to send the
owner of the issue an automatic email. All info in in the same row
just varying columns. I post my semi-functional script here, I can get the correct line item to pull based on date, I just cant get the script to pull the associated email with the date. Or I get a ton of emails that i dont want. Sheet
Any help would be much appreciated!!
function checkReminder() {
// get the spreadsheet object
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// set the first sheet as active
SpreadsheetApp.setActiveSheet(spreadsheet.getSheets()[0]);
// fetch this sheet
var sheet = spreadsheet.getActiveSheet();
// Number of rows to process
var numRows = sheet.getLastRow()-1;
// figure out what the last row is
var lastRow = sheet.getLastRow();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 2;
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 2 ,lastRow,
sheet.getLastColumn());
// Fetch values for each row in the Range.
var data = dataRange.getValues();
//Logger.log(data)
// grab column 20 (the 'days left' column) changed numrow to last r
row
get last row change
var range = sheet.getRange(startRow,20,lastRow-startRow+1,1 );
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Now, grab the reminder name column
range = sheet.getRange(2, 16, lastRow-startRow+1, 1);
var reminder_name_values = range.getValues();
var warning_count = 0;
var msg = "";
//msg = msg + "Trial Reminder Trial: "+reminder_name+" is due in
"+days_left+" days.\n"
//for (i in data) {
// var row = data[i];
// First column
// var emailAddress = row[13];
// Recipe column (Priority HIGH)
// var message = row[14];
// var subject = "Reminder CAPA ";
//subject = subject + reminder_name;
// Loop over the days left values
for (var k = 0; k <= numRows-1; k++) {
var days_left = days_left_values[k][0];
if(days_left == 20) {
// if it's exactly 20, do something with the data.
var reminder_name = reminder_name_values[k][0];
msg = msg + "Reminder CAPA: "+reminder_name+" is due in
"+days_left+" days.\n";
warning_count++;
}
if(warning_count) {
//MailApp.sendEmail(emailAddress, subject, message);
Logger.log(msg);
}
}}

Confirm that a value is in a spreadsheet column using Google Apps Script

This function sends email reminders based on a few conditions. One of the things I need to check for is that the Visit ID (which is in column 11 in the "email log" sheet) exists in a separate sheet ("DATA", stored in the enrollmentData variable). How do I search this array and return the ID to match in the IF statement below?
function sendReminders() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var sheet = ss.getSheetByName("Email Log");
var rows = sheet.getLastRow()-1;
var startRow = 2; // First row of data to process
var numRows = rows; // Number of rows to process
var now = new Date();
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, 22)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var today = Utilities.formatDate(new Date(), "GMT-5", "m/d/yyyy")
var reminderSent = "Reminder Sent";
//get email body and subject
var bodyTem = ss.getSheetByName("Email Templates").getRange('b8').getValues();
var subject = ss.getSheetByName("Email Templates").getRange('d13').getValues();
//get enrollments data to search for visit ID
var enrollmentData = ss.getSheetByName("DATA").getRange('H:H').getValues();
for (var i = 0; i < data.length; i++) {
var row = data[i];
//set conditions
var sendReminder = row[18];
var reminderDate = row[19];
var reminderStatus = row[20];
var visitID = row[11]
//need condition to look for visit ID to not include already cancelled. Search enrollmentData for visitID and return as foundID for conditional below
if (sendReminder == "Yes" && reminderStatus != reminderSent && reminderDate >= today && visitID == foundID) {
//assemble email
var studentEmail = row[13];
var firstName = row[12];
var instructor = row[0];
var body1 = bodyTem.replace(/*name*/gi,firstName);
var body2 = body1.replace(/*instructorFull*/gi,instructor);
MailApp.sendEmail(studentEmail, subject, body2);
//need to write in that the reminder email was sent.
sheet.getRange(startRow + i, 20).setValue(reminderSent);
sheet.getRange(startRow + i, 21).setValue(now);
};
};
};
You want to search the array
var enrollmentData = ss.getSheetByName("DATA").getRange('H:H').getValues();
The method getValues always returns a double array: in this case, it's of the form [[1], [2], [3],..] since each row has one element. I usually flatten this:
var enrollmentDataFlat = enrollmentData.map(function(row) {return row[0];});
Now enrollmentDataFlat is like [1, 2, 3, ..] so indexOf will work as usual:
if (enrollmentDataFlat.indexOf(visitID) != -1) {
// it's there
}
else {
// it's not there
}

Email Reminder for multiple Column

I want to send email reminder if the date columns is 7 or 1 days away from today. I have already made the script and what i want to add is it should consider others columns too, not only 1 with one script, for sending reminder for respective columns.
For eg:
It should remind for Plan Date, Plan Date 1, Plan Date 2 and Plan Date 3.
Please see the Sample Attached.
Script:
function checkReminder() {
// get the spreadsheet object
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// fetch this sheet
var sheet = spreadsheet.getSheets()[0];
// figure out what the last row is
var lastRow = sheet.getLastRow();
// figure out what the last column is
var lastCol = sheet.getLastColumn();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 2;
// the columns are indexed starting at 2, and the first column
// is the headers, so start with column 2
var startCol = 2;
// grab column 3 (the 'days left' column)
var range = sheet.getRange(2,3,lastRow-startRow+1,1 );
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Now, grab the reminder name column
range = sheet.getRange(2, 1, lastRow-startRow+1, 1);
var reminder_info_values = range.getValues();
// Now, grab the first row
range = sheet.getRange(1, 2, lastCol-startCol+1, 1);
var column_info_values = range.getValues();
var warning_count = 0;
var msg = "";
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if(days_left == 1) {
// if it's exactly 1, do something with the data.
var reminder_name = reminder_info_values[i][0];
var column_name = column_info_values[0][0];
msg = msg + "Reminder: "+reminder_name+" - "+column_name+" is due in "+days_left+" day.\n";
warning_count++;
}
}
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if(days_left == 7) {
// if it's exactly 7, do something with the data.
var reminder_name = reminder_info_values[i][0];
var column_name = column_info_values[0][0];
msg = msg + "Reminder: "+reminder_name+" - "+column_name+" is due in "+days_left+" days.\n";
warning_count++;
}
}
if(warning_count) {
MailApp.sendEmail("myidsample#gmail.com",
"Reminder Spreadsheet Message", msg);
}
};
You're currently fetching only single column and processing that only.
In order to make this script run over other columns too, you'll need to loop through them, fetch data and then process them one by one.
Here you're fetching data from 3rd column :
// grab column 3 (the 'days left' column)
var range = sheet.getRange(2,3,lastRow-startRow+1,1 );
var numRows = range.getNumRows();
var days_left_values = range.getValues();
Like wise you can run a loop till last column and fetch data from 3rd, 5th, 7th .. columns and keep processing them.
So the code goes like this
function checkReminder() {
// get the spreadsheet object
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// fetch this sheet
var sheet = spreadsheet.getSheets()[0];
// figure out what the last row is
var lastRow = sheet.getLastRow();
// figure out what the last column is
var lastCol = sheet.getLastColumn();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 2;
// the columns are indexed starting at 2, and the first column
// is the headers, so start with column 2
var startCol = 2;
// Now, grab the reminder name column
range = sheet.getRange(2, 1, lastRow - startRow + 1, 1);
var reminder_info_values = range.getValues();
// Now, grab the first row
range = sheet.getRange(1, 2, lastCol - startCol + 1, 1);
var column_info_values = range.getValues();
var warning_count = 0;
var msg = "";
for (var u = 3; u <= lastCol; u += 2) {
// grab the day's left column
var range = sheet.getRange(2, u, lastRow - startRow + 1, 1);
var numRows = range.getNumRows();
var days_left_values = range.getValues();
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if (days_left == 1) {
// if it's exactly 1, do something with the data.
var reminder_name = reminder_info_values[i][0];
var column_name = column_info_values[0][0];
msg = msg + "Reminder: " + reminder_name + " - " + column_name + " is due in " + days_left + " day.\n";
warning_count++;
}
}
for (var i = 0; i <= numRows - 1; i++) {
var days_left = days_left_values[i][0];
if (days_left == 7) {
// if it's exactly 7, do something with the data.
var reminder_name = reminder_info_values[i][0];
var column_name = column_info_values[0][0];
msg = msg + "Reminder: " + reminder_name + " - " + column_name + " is due in " + days_left + " days.\n";
warning_count++;
}
}
if (warning_count) {
MailApp.sendEmail("myidsample#gmail.com",
"Reminder Spreadsheet Message", msg);
}
}
}
This is un-tested code, let me know if any issue arises. I'll be happy to help you.
Thank you!

Google Spreadsheet Script - Analyze table for value (1) and post several rows with this value in another

i want to analyze a sheet (name: 1) for a value (e.g. 1) and post some values from these rows with this value in another sheet (name: 2).
"search for all cells in column F which got the value (e.g. 1). copy columns A, E and G (if F is 1) and post it at the end of sheet 2.
My Script just post one result actually. Could you please help me? I think i just dont get any kind of loop?
function checkWS() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName("1"));
var sheet = spreadsheet.getActiveSheet();
// figure out what the last row is
var lastRow = sheet.getLastRow();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 2;
// grab column 5 (the 'month left' column)
var range = sheet.getRange(2, 6, lastRow - startRow + 1, 1);
var numRows = range.getNumRows();
var soll_values = range.getValues();
// Now, grab the reminder name column
range = sheet.getRange(2, 1, lastRow - startRow + 1, 1);
var branch_values = range.getValues();
// and the count column
range = sheet.getRange(2, 7, lastRow - startRow + 1, 1);
var count_values = range.getValues();
var warning_count = 0;
var msg = "";
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var soll = soll_values[i][0];
if (soll == 1) {
// if it's exactly 1, do something with the data.
var name = branch_values[i][0];
var count = count_values[i][0];
warning_count++;
}
}
if (warning_count) {
var ss = SpreadsheetApp.openById("1vn4xTwdNk7E1Av4VNugtW6KWgZns2LzKS1lN1F6CTPw");
var Tab = ss.getSheetByName('2');
var lastRow = Tab.getLastRow();
Tab.getRange(lastRow + 1, 1).setValue(name);
Tab.getRange(lastRow + 1, 5).setValue(count);
Tab.getRange(lastRow + 1, 10).setValue(new Date());
SpreadsheetApp.flush();
}
}
now it's done. I just worked with a little helping-coloumn:
function checkWS() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(spreadsheet.getSheetByName("NAME"));
var sheet = spreadsheet.getActiveSheet();
// figure out what the last row is
var lastRow = sheet.getLastRow();
// the rows are indexed starting at 1, and the first row
// is the headers, so start with row 2
var startRow = 6;
// grab date (the 'month left' column)
var range = sheet.getRange(6, 54, lastRow - startRow + 1, 1);
var numRows = range.getNumRows();
var soll_values = range.getValues();
// Now, grab the branch column
range = sheet.getRange(6, 11, lastRow - startRow + 1, 1);
var branch_values = range.getValues();
// and the count column
range = sheet.getRange(6, 49, lastRow - startRow + 1, 1);
var count_values = range.getValues();
var warning_count = 0;
var msg = "";
// Loop over the days left values
for (var i = 0; i <= numRows - 1; i++) {
var soll = soll_values[i][0];
if (soll == 1) {
// if it's exactly 1, do something with the data.
var name = branch_values[i][0];
var count = count_values[i][0];
warning_count++;
// if (warning_count) { -> not needed
var ss = SpreadsheetApp.openById("ID");
var Tab = ss.getSheetByName('NAME_other_ss');
var lastRow = Tab.getLastRow();
Tab.getRange(lastRow + 1, 10).setValue(name);
Tab.getRange(lastRow + 1, 14).setValue(count);
Tab.getRange(lastRow + 1, 20).setValue(new Date());
SpreadsheetApp.flush();
// }
}
}
}

Copy only active row from one spreadsheet to another

I want to create a script to copy the active row of a sheet(TIME MACHINE) to another Google spreadsheet's sheet(Database). I also want to send "1" to the 13 row of the copied row. It would be great if anyone can guide me. The code given below only works to copy within the same spreadsheet.
function endTime() {
transfer("1E3CWWohirN4DD_f_23WWBElYrhqnAs_27crrxowFjFA", "TIME MACHINE", "TIME MACHINE2")
}
function transfer(targetId, sourceSheetName, targetSheetName) {
var d = new Date();
var offset = -d.getTimezoneOffset()/60;
var h = d.getHours();
var h = h >= 13? h - 12: h;
h = h == 0? 12: h;
var m = m < 10? "0" + d.getMinutes(): d.getMinutes();
var s = d.getSeconds();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName(sourceSheetName);
var last = sourceSheet.getActiveRange().getRow();
var data = sourceSheet.getRange(last, 1, 1, 14).getValues();
var time1 = h + ":" + m + ":" + s;
sourceSheet.getRange(last, 28).setValue(time1);
var tamma = sourceSheet.getRange(last, 11).getValue();
// copy data
var ss2 = SpreadsheetApp.openById(targetId);
var targetSheet = ss2.getSheetByName(targetSheetName);
//get last row
var lastRow = targetSheet.getLastRow();
//write data
targetSheet.getRange(lastRow + 1, 1, data.length, data[0].length).setValues(data);
//write "1" into column 13
targetSheet.getRange(lastRow + 1, 13, data.length, 1).setValue("1");
targetSheet.getRange(lastRow + 1, 11, data.length, 1).setValue(tamma);
}
your code just needs a little reorganization and you need to get the right data from the source-sheet.
this should work:
function main() {
transfer("1mEluY-_K9oBvbxzASKn25YZ8BgF_naLl0XNitb4zIA8", "Sheet1", "Sheet1");
}
function transfer(targetId, sourceSheetName, targetSheetName) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName(sourceSheetName);
var last = sourceSheet.getActiveRange().getRow();
var data = sourceSheet.getRange(last, 1, 1, 14).getValues();
// copy data
var ss2 = SpreadsheetApp.openById(targetId);
var targetSheet = ss2.getSheetByName(targetSheetName);
//get last row
var lastRow = targetSheet.getLastRow();
//write data
targetSheet.getRange(lastRow + 1, 1, data.length, data[0].length)
.setValues(data);
//write "1" into column 13
targetSheet.getRange(lastRow + 1, 13, data.length, 1)
.setValue("1")
}