Set age group based on DOB - function

I would like to create a Google Sheet function that if supplied with a date of birth, looks up the below table and gives the appropriate age group. I will be using this table to group 200 kids for surf lifesaving.
for example...date of Birth is 11 Oct 2011, then the age group will be U7. I have use the query function to get this data but I would like to contain it in a function and store the table as a array and compare the date to the array table.
- U 5 01 Oct 2013 30 Sep 2017
- U 6 01 Oct 2012 30 Sep 2013
- U 7 01 Oct 2011 30 Sep 2012
- U 8 01 Oct 2010 30 Sep 2011
- U 9 01 Oct 2009 30 Sep 2010
- U 10 01 Oct 2008 30 Sep 2009
- U 11 01 Oct 2007 30 Sep 2008
- U 12 01 Oct 2006 30 Sep 2007
- U 13 01 Oct 2005 30 Sep 2006
- U 14 01 Oct 2004 30 Sep 2005

Dates can be a little tricky. See This question to get a better idea. But this script can at least get you started.
This Google Sheet demonstrates a custom formula (AGEGROUP) to compare the input date to a "age-groups" sheet.
Note: Only add to "age-groups" sheet if needed.
The last row with a value is used to consider if someone is too old.
The first row of the sheet is used to see if someone is too young.
AGEGROUP() will accept a cell reference to look up
Example AGEGROUP(B2)would check cell B2, assuming it contains a date, and return a group assignment (U 5, U 6, U7...).
Looking up dates manually (instead of referencing another cell) can be accomplished by nesting DATE inside of AGEGROUP. You must follow the right arguments for DATE (year, month, day).
Example AGEGROUP(DATE(2010,1,21))
I'm new to custom functions and did not look into the options for supporting function details like #param or #return and so on.
Apps Script
/**
* Finds age group of the input value (date).
*
* #param {date} Input the date to compare to date ranges.
* #return Returns age groupd based on provided date.
* #customfunction
*/
function AGEGROUP(date) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var ages = ss.getSheetByName("age-groups");
var range = ages.getDataRange();
var values = range.getValues();
var i = 0;
var ranges = values.length;
var lastRow = ranges -1;
// loop through dateRanges
for(i; i < ranges; i++) {
// if date in AGEGROUP()
if(date >= values[i][1] && date <= values[i][2]) {
// return age group
return values[i][0];
}
// if child is too old
if(date > values[0][2]) {
return "Child is too young.";
}
// if child is too young
if(date < values[lastRow][1]) {
return "Child is too old.";
}
}
}

Related

Google Apps Script; how to solve TypeError: Cannot read properties of undefined (reading '0')?

I have a Google sheet which I follow stock prices Daily; every day I get the stock prices online and write them to the sheet via apps script. Now I want to check monthly P/L for each stock and create a sheet that shows monthly P/L for each stock.
I am trying to get the prices with dates for each stock in an array and then push the first and last entries for every month in "monthly" array. And then I am trying to write this monthly values in "Aylık P/L" sheet.
The code works fine till I added "for" statement to write the monthly datas to the sheet; it throws: "Error in Monthly: TypeError: Cannot read properties of undefined (reading '0')":
Here goes the code:
function aylikRapor() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Fiyat Çek');
var sheet2 = ss.getSheetByName('Günlük Fon Takip');
var sheet3 = ss.getSheetByName('Haftalık Fon Takip');
var sheet4 = ss.getSheetByName('Aylık Fon Takip');
var sheet5 = ss.getSheetByName('Funds Main');
var sheet6 = ss.getSheetByName('Aylık');
var sheet7 = ss.getSheetByName('Aylık P/L');
var pfs = sheet5.getRange(1,1).getValue(); // pfs = PortföydekiFonSayısı
var i = 1;
var f = 1;
var a;
var b;
try {
for(i=1; i<=pfs; i++) {
var colH = sheet2.getRange(1,3*i,1,1);
var harf = colH.getA1Notation().match(/([A-Z]+)/)[0];
var column = sheet2.getRange(harf+":"+harf);
// get lastFilledRow
var value = ''
const max = sheet2.getMaxRows()
var values = column.getValues()
values = [].concat.apply([], values)
for (row = max - 1; row > 0; row--) {
value = values[row]
if (value != '') { break }
}
lastRowD = row + 1;
Logger.log(lastRowD);
let veriler = sheet2.getRange(14,3*i-1,lastRowD-12,2).getValues();
let month = veriler[0][0].getMonth();
let monthly = [[veriler[0][0],veriler[0][1]]];
veriler.forEach( (row,index) => {
let test = new Date(row[0]).getMonth();
if( test !== month ) {
monthly.push([veriler[index-1][0],veriler[index-1][1]]);
monthly.push([row[0],row[1]]);
month = test;
}
}
)
Logger.log(monthly);
for (f=1, a=0, b=1; f <=monthly.length-1; f++, a+=2, b+=2){
sheet7.getRange(3+f,5*i-2).setValue(monthly[a][0]);
sheet7.getRange(3+f,5*i-1).setValue(monthly[a][1]);
sheet7.getRange(3+f,5*i).setValue(monthly[b][0]);
sheet7.getRange(3+f,5*i+1).setValue(monthly[b][1]);
}
}
}
catch(err) {
Logger.log("Error in Monthly: "+err);
}
}
I think there is a null value in "monthly" array; but I could not figure out how I can solve it!
Execution Log:
Yürütme günlüğü
09:49:37 Bildirim Yürütme işlemi başlatıldı
09:49:49 Bilgi 119.0
09:49:50 Bilgi [[Wed Aug 17 00:00:00 GMT+03:00 2022, 0.080777], [Wed Aug 31 00:00:00 GMT+03:00 2022, 0.082585], [Thu Sep 01 00:00:00 GMT+03:00 2022, 0.0831], [Fri Sep 30 00:00:00 GMT+03:00 2022, 0.08431], [Mon Oct 03 00:00:00 GMT+03:00 2022, 0.085019], [Mon Oct 31 00:00:00 GMT+03:00 2022, 0.096867], [Tue Nov 01 00:00:00 GMT+03:00 2022, 0.098144], [Wed Nov 30 00:00:00 GMT+03:00 2022, 0.115665], [Thu Dec 01 00:00:00 GMT+03:00 2022, 0.117343], [Fri Dec 30 00:00:00 GMT+03:00 2022, 0.126554], [Mon Jan 02 00:00:00 GMT+03:00 2023, 0.127234], [Thu Jan 12 00:00:00 GMT+03:00 2023, 0.111894], [, ]]
09:49:50 Bilgi Error in Monthly: TypeError: Cannot read properties of undefined (reading '0')
09:49:38 Bildirim Yürütme işlemi tamamlandı
I have fixed the problem:
As you can see from the execution log; for i=1 the first monthly array length is 12; during the for (f=1, a=0, b=1; f <=monthly.length-1; f++, a+=2, b+=2)
the max f should be 6; so after 6 there would be no values in the array.
I fixed the problem by the following amendment:
(f=1, a=0, b=1; f <=monthly.length/2; f++, a+=2, b+=2)
I hope the others could get some help in case problems like this.

How do I enter multiple timestamps for multiple columns as they are modified?

I was able to modify if in any column within column 1 through 9 was modified the time stamp was entered on column 10 and last modified on column 11.
I know need to get granular and timestamp when each column is first modified, while maintaining the existing timestamp setting.
I believe this is as simple as an "if" statement but I can't seem to figure it out.
Here is what I have so far. This gives me the date and time any cell, between column 1 and 9 is first modified, on that row and returns date and time on column 10, then last modified date and time on column 11 if any changes are done.
Now i want to keep record of when column 1-9 are first modified as well, and enter them on the same sheet starting at column 12
function addTimestamp (e){
//variables
var startRow = 2;
var ws = "Daily Log"
var currentDate = 1
//get modified row and column
var row = e.range.getRow();
var col = e.range.getColumn();
if(([1,2,3,4,5,6,7,8,9].includes(col))&& row >= startRow
&&e.source.getActiveSheet().getName() ==ws){
var currentDate = new Date();
e.source.getActiveSheet().getRange(row, 11).setValue(currentDate);
if(e.source.getActiveSheet().getRange(row, 10).getValue()== ""){
e.source.getActiveSheet().getRange(row,10).setValue(currentDate);
} // END IF check if date created exists
} // END IF column, row, worksheet
}
Special thanks to #raygun who helped me in creating uniq driver IDs.
Explanation:
Your goal is:
Keep the datetime for which any cell in columns 1-9 is modified for the first time in column 10.
For every cell modified in columns 1-9 add a last modified stamp in columns 12-20 respectively. For example if column 1 is modified, update timestamp in column 12, if column 2 is modified update column 13 etc.
For performance reasons, it is always a good practice to store the code you are using often, in variables:
For example e.source.getActiveSheet() is used 4 times in your code and every time it is called, it consumes resources. You can instead store it in a variable and use that variable instead.
Solution:
function addTimestamp (e){
//variables
const startRow = 2;
const ws = "Daily Log"
//get modified row and column
const rng = e.range;
const as = rng.getSheet();
const row = rng.getRow();
const col = rng.getColumn();
if(col>=1 && col<=9&& row >= startRow && as.getName() ==ws){
const currentDate = new Date();
const rng_all = as.getRange(row, col+11);
const rng_ten = as.getRange(row, 10);
as.getRange(row,11).setValue(currentDate);
if(rng_all.getValue()== ""){
rng_all.setValue(currentDate)
}
if(rng_ten.getValue()== ""){
rng_ten.setValue(currentDate);
}
}
}
Side Note:
You don't need an installable trigger for this particular task. You can replace addTimestamp(e) with onEdit(e) (simple trigger) and it would also work. But it is up to you what you prefer, but it would be a good idea to read the differences (in the hyperlinks I provided).
Here's a function for logging all of your changes into a file:
function onMyEdit(e) {
e.source.toast('entry');
let sh = e.range.getSheet();
if (e.range.columnStart < 10) {
let f = DriveApp.getFileById('file id');
let c = f.getBlob().getDataAsString();
let ts = Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "E MMM dd yyyy HH:mm:ss");
let o = c + ts + ',' + sh.getName() + ',' + e.range.rowStart + ',' + e.range.columnStart + ',' + e.oldValue + ',' + e.value + ',' + e.user.getEmail() + '\r\n';
f.setContent(o);
Logger.log(o);
}
}
Requires Installable Trigger
Data Table:
timestamp
sheetname
row
col
oldvalue
value
useremail
Sat Feb 13 2021 08:53:53 GMT-0700 (Mountain Standard Time)
Sheet1
5
4
30
55
Redacted
Sat Feb 13 2021 08:54:58 GMT-0700 (Mountain Standard Time)
Sheet1
9
4
32
55
Redacted
Sat Feb 13 2021 08:56:05 GMT-0700 (Mountain Standard Time)
Sheet1
14
7
62
new value
Redacted
Sat Feb 13 2021 08:56:45 GMT-0700 (Mountain Standard Time)
Sheet1
1
2
10
45
Redacted
Sat Feb 13 2021 08:56:52 GMT-0700 (Mountain Standard Time)
Sheet1
3
2
11
77
Redacted
Sat Feb 13 2021 09:10:16 GMT-0700 (Mountain Standard Time)
Sheet2
5
2
4
77
Redacted
Sat Feb 13 2021 09:16:08 GMT-0700 (Mountain Standard Time)
Sheet5
8
4
undefined
666
Redacted
Sat Feb 13 2021 09:18:04 GMT-0700 (Mountain Standard Time)
Sheet5
13
7
undefined
66
Redacted
Sat Feb 13 2021 09:19:44 GMT-0700 (Mountain Standard Time)
Sheet5
9
3
undefined
66
Redacted
Sat Feb 13 2021 09:20:29 GMT-0700 (Mountain Standard Time)
Sheet5
11
7
undefined
kk
Redacted
Sat Feb 13 2021 09:22:21 GMT-0700 (Mountain Standard Time)
Sheet1
1
1
undefined
undefined
Redacted
Here's a utility for loading a simple csv into a spreadsheet:
function loadCSVintoSpreadsheet() {
const ss = SpreadsheetApp.getActive();
const ui = SpreadsheetApp.getUi();
const resp1 = ui.prompt('Select Sheet Name', 'Enter destination sheet name', ui.ButtonSet.OK_CANCEL);
if (resp1.getSelectedButton() == ui.Button.OK && resp1.getResponseText().length > 0) {
const sh = ss.getSheetByName('Sheet1');
sh.clearContents();
const resp2 = ui.prompt('CSV FileId', 'Enter file id of csv', ui.ButtonSet.OK_CANCEL);
if (resp2.getSelectedButton() == ui.Button.OK && resp2.getResponseText().length > 0) {
const file = DriveApp.getFileById(resp2.getResponseText());
const csv = file.getBlob().getDataAsString();
let csvA = Utilities.parseCsv(csv)
sh.getRange(1, 1, csvA.length, csvA[0].length).setValues(csvA);
}
}
}

Find and match a date in array

I'm trying to make a function in order to find & match the date of day in a array.
But for a weird reason, if two dates are matching, my function never find the match.
So..., if I change my date by an other string (ex : "foo" match with "foo"), it's work.
Here my code, and then the log return. Have you an idea why my script can't match two equal dates ?
Thank you !
function hideBeforeToday(values, value)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = SpreadsheetApp.setActiveSheet(ss.getSheetByName(roadmapSS))
var range = sheet.getRange(4, 11, 1, sheet.getLastColumn())
var values = range.getValues();
Logger.log(values);
var value = moment().set({hour:0,minute:0,second:0,millisecond:0}).utc().toDate();
Logger.log("date", value);
for(var i = 0; i < values.length; i++) {
if(values[i].indexOf(value) > -1) {
Logger.log("data found");
}
}
}
[18-01-11 13:49:33:065 CET] Logger.log([arrayValues, [[[Wed Jan 10 00:00:00 GMT+01:00 2018, Thu Jan 11 00:00:00 GMT+01:00 2018]]]]) [0 secondes]
[18-01-11 13:49:33:067 CET] Logger.log([dateOfDay, [Thu Jan 11 00:00:00 GMT+01:00 2018]]) [0 secondes]
[18-01-11 13:49:33:070 CET] Script exécuté [durée totale d'exécution : 0,535 secondes]
Look at this example:
var date1 = new Date("Thu Jan 11 00:00:00 GMT+01:00 2018");
var dates = [date1];
console.log(date1); // prints 2018-01-10T23:00:00.000Z
console.log(dates.indexOf(date1)); // prints 0
While this:
var date1 = new Date("Thu Jan 11 00:00:00 GMT+01:00 2018");
var dates = [new Date("Thu Jan 11 00:00:00 GMT+01:00 2018")];
console.log(date1); // prints 2018-01-10T23:00:00.000Z
console.log(dates.indexOf(date1)); // prints -1
I don't know what data you have in the spreadsheet, if it is a string or a Date object, but try converting both to the same type before comparing. Check their types and perhaps use the toISOString() function?

To get values from 2D array

I have used this query to retrieve the dates for one particular user's approved leaves -
LeaveRequest.where(user_id: 6).where(status: 1).pluck(:from_date, :to_date)
and I'm getting this array as result -
[[Mon, 12 Sep 2016, Fri, 16 Sep 2016], [Tue, 06 Sep 2016, Tue, 06 Sep 2016], [Thu, 01 Sep 2016, Fri, 02 Sep 2016], [Tue, 30 Aug 2016, Wed, 31 Aug 2016]]
what I want is to fetch all the dates as well as the dates between 12 Sep 2016 and 16 Sep, 2016 (13th 14th and 15th).
I am assuming you mean something like this
require 'date'
#This is to simulate your current Array
current_array = 5.times.map {|n [Date.new(2016,n+1,1).<<(1),Date.new(2016,n+1,1)]}
#map the 2 dates to a Range
new_array = current_array.map{|start_date,end_date| (start_date..end_date)}
new_array.first.class
#=> Range
Calling to_a on the Range will blow it out into all the dates between start_date and end_date
With a rails you could do something like
class LeaveRequest
def self.user_requested_ranges(user_id, status_id)
scoped.
where(user_id: user_id, status: status_id).
pluck(:from_date, :to_date).
map do |from_date, to_date|
#optionally to output the full Array in each Range you could use
#(from_date..to_date).to_a
(from_date..to_date)
end
end
end
Then call as
LeaveRequest.user_requested_ranges(6,1)

Dealing with empty cells in Google Apps Script

Why doesn't this work?
function sendDuesReminder() {
var paid = 3;
var name = 1;
var submitted = 0;
var allowance = 9;
var ms = 86400000; // Number of milliseconds in a day
var today = new Date();
var reminder = 72;
var data = SpreadsheetApp.openById('___').getSheetByName('Master').getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][paid] != 'Yes' &&
data[i][paid] != 'yes' &&
data[i][reminder] == '' &&
((((today.valueOf()) - (data[i][submitted].valueOf()))/ms) > allowance)) {
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
if (data[i][paid] != 'Yes' &&
data[i][paid] != 'yes' &&
data[i][reminder] != null &&
((((today.valueOf()) - (data[i][reminder].valueOf()))/ms) > allowance)) {
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
}
Browser.msgBox("OK. Reminder e-mails have been sent. !")
}
What I really want to do is say send the e-mail if column BT is empty OR if the date in column BT is older than 9 days. But I didn't know how to include an or statement within the if statement. So I just set up two separate if statements.
When I use '', though, for the second if statement, I get an error saying that it can't get the value of something that's undefined.
When I use null or undefined, it doesn't work.
Anybody have any thoughts?
Are you sure you have 72 columns in your spreadsheet ? when you use data[i][reminder] == '' the error returned concerns the first term of the equal, not the second... so I guess data doesn't have 72 secondary index and this is returning an error.
(EDIT : to be more clear : you cannot get the value of an undefined item using .valueOf and divide it by something, that's why you get "an error saying that it can't get the value of something that's undefined ".)
If you want to learn about how to implement OR statement you can have a look at w3school, 'Comparison Operators'
Note that you can compare date object directly, you don't need to convert them to milliseconds explicitely, javascript does it internally.
here is an example of how you could write this shortly
var tendaysBefore = new Date(new Date().getTime()-10*24*60*60*1000);// 10 days before
if (data[i][paid].toLowerCase() != 'yes' && (data[i][reminder] == ''||(data[i][reminder] == null || data[i][submitted]< tendaysBefore)) { // not 'yes' and one of the 3 other conditions
MailApp.sendEmail("___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
So here's the code for the loop I tried based on Serge's very kind initial thought.
for (var i = 1; i < data.length; i++) {
if (data[i][paid].toLowerCase() != 'yes' &&
(data[i][submitted]<tendaysBefore &&
(data[i][reminder] == ''||
data[i][reminder] == null))) {
MailApp.sendEmail("___", "Reminder About Dues for Newcomers & Neighbors", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
}
I changed the order of the if statement because I'm not sure I've adequately articulated in English what I'm trying to get it to do.
What I WANT it to say is IF they haven't paid AND 10 days have passed since they submitted their form AND EITHER the reminder cell is blank or has a null value, THEN send the e-mail.
(Once I get THIS statement working, I'll go on to say if 10 days go by after we send the first e-mail and they STILL haven't paid, we send another e-mail. That's why I'm going through all this machination to put a date in reminder rather than just something like "sent".)
The code I have works. EXCEPT, if you run it, send out the first batch of e-mails, let it add today's date to reminder, and then run it again, it sends the e-mails out all over again.
In short,
(data[i][reminder] == ''||
data[i][reminder] == null))
doesn't seem to be accomplishing what is supposed to do, which is make the if statement fail for any row that has ANYTHING in the reminder column. That's why I initially came at this with "how do I deal with empty cells"? Because--for the life of me, I can't understand why
(data[i][reminder] == ''||
data[i][reminder] == null))
isn't bulletproof.
As I suggested in my comment to Serge's answer, this is starting to make me crazy. I, therefore, cannot thank anybody enough for ANY thoughts you have. Thanks in advance!
In response to Serge's question that I capture some values from the log, here's the output from the log after I added his requested code to the loop:
Paid=yes date subm=Sat Jun 02 2012 14:44:27 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=reminder=undefined
Paid=yes date subm=Wed Jun 27 2012 16:22:35 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Fri Jun 29 2012 09:07:21 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:11:20 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:16:56 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 10:17:00 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:26:36 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 10:30:23 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 11:02:19 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 12:33:57 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Mon Jul 09 2012 13:48:54 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 18:19:22 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:07:05 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:44:13 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Mon Jul 09 2012 21:53:55 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Tue Jul 10 2012 11:09:03 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Tue Jul 10 2012 12:57:41 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Wed Jul 11 2012 18:36:49 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Thu Jul 12 2012 07:14:53 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Tue Jul 17 2012 14:54:16 GMT-0400 (EDT)reminder=undefined
Paid=yes date subm=Wed Jul 18 2012 20:26:23 GMT-0400 (EDT)reminder=undefined
Paid= date subm=Thu Jul 19 2012 13:43:09 GMT-0400 (EDT)reminder=undefined
I have no idea what to make of this, but I'm sure smarter people than I do see something interesting here?
OK, following Serge's diligent trouble shooting with me, here's the code that worked for this problem. Many, MANY thanks to Serge!
function sendDuesReminder() {
var paid = 3;
var name = 1;
var submitted = 0;
var allowance = 9;
var ms = 86400000; // Number of milliseconds in a day
var today = new Date();
var reminder = 72;
var reminderArray = reminder - 1;
var tendaysBefore = new Date(new Date().getTime()-10*24*60*60*1000);
var data = SpreadsheetApp.openById('___').getSheetByName('Master').getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][paid].toLowerCase() != 'yes' &&
(data[i][submitted]<tendaysBefore &&
(data[i][reminderArray] == ''||
data[i][reminderArray] == null))) {
MailApp.sendEmail("___", "___", "___") ;
SpreadsheetApp.openById('___').getSheetByName('Master').getRange(i+1, reminder).setValue(today);
}
SpreadsheetApp.flush();
Logger.log('Paid='+data[i][paid].toLowerCase()+' date subm='+data[i][submitted]+'reminder='+data[i][reminder])
}
Browser.msgBox("OK. Reminder e-mails have been sent. !")
}