Dealing with empty cells in Google Apps Script - 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. !")
}

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.

Apps Script JDBC reads DATETIME with wrong timezone

I'm trying to read from a DATETIME field in MySQL using the Apps Script JDBC service. The database has its timezone set to UTC (##global.time_zone == ##session.time_zone == '+00:00'), and I've double-checked this by doing SELECT UNIX_TIMESTAMP(COL) FROM TABLE. My script is also set to use UTC.
However, when I read the value from the JDBC result set using getTimestamp, it is skewed forwards by 8 hours. This occurs regardless of whether I pass a timezone to getTimestamp (indeed, there is no change whatsoever, regardless of what timezone I pass), and regardless of whether useJDBCCompliantTimeZoneShift is enabled or not.
If I read the result using getString, it gives the correct time (in UTC). Barring using getString and parsing it into a JavaScript Date, how can I fix this issue?
Edit
Here's a testing script I used, and its output:
export function tzTest(): void {
const dbIp = DB_IP
const dbPw = DB_PW
let conn = Jdbc.getConnection(`jdbc:mysql://${dbIp}/mydb`, { user: "myuser", password: dbPw })
let stmt = conn.prepareStatement("SELECT COL FROM MYTABLE WHERE OWNER_ID=1")
stmt.execute()
let res = stmt.getResultSet()
res.next()
console.log("==== DEFAULT ====")
console.log("=== getTimestamp ===")
console.log(`plain: ${new Date(res.getTimestamp(1).getTime())} (${res.getTimestamp(1).getTime()})`)
console.log(`utc: ${new Date(res.getTimestamp(1, "UTC").getTime())} (${res.getTimestamp(1, "UTC").getTime()})`)
console.log("=== getTime ===")
console.log(`plain: ${new Date(res.getTime(1).getTime())} (${res.getTime(1).getTime()})`)
console.log(`utc: ${new Date(res.getTime(1, "UTC").getTime())} (${res.getTime(1, "UTC").getTime()})`)
console.log("=== getDate ===")
console.log(`plain: ${new Date(res.getDate(1).getTime())} (${res.getDate(1).getTime()})`)
console.log(`utc: ${new Date(res.getDate(1, "UTC").getTime())} (${res.getDate(1, "UTC").getTime()})`)
conn.close()
conn = Jdbc.getConnection(`jdbc:mysql://${dbIp}/mydb`, { user: "myuser", password: dbPw, useJDBCCompliantTimeZoneShift: true })
stmt = conn.prepareStatement("SELECT COL FROM MYTABLE WHERE OWNER_ID=1")
stmt.execute()
res = stmt.getResultSet()
res.next()
console.log("==== useJDBCCompliantTimeZoneShift ====")
console.log("=== getTimestamp ===")
console.log(`plain: ${new Date(res.getTimestamp(1).getTime())} (${res.getTimestamp(1).getTime()})`)
console.log(`utc: ${new Date(res.getTimestamp(1, "UTC").getTime())} (${res.getTimestamp(1, "UTC").getTime()})`)
console.log("=== getTime ===")
console.log(`plain: ${new Date(res.getTime(1).getTime())} (${res.getTime(1).getTime()})`)
console.log(`utc: ${new Date(res.getTime(1, "UTC").getTime())} (${res.getTime(1, "UTC").getTime()})`)
console.log("=== getDate ===")
console.log(`plain: ${new Date(res.getDate(1).getTime())} (${res.getDate(1).getTime()})`)
console.log(`utc: ${new Date(res.getDate(1, "UTC").getTime())} (${res.getDate(1, "UTC").getTime()})`)
conn.close()
}
This results in the following output:
==== DEFAULT ====
=== getTimestamp ===
plain: Sat Dec 21 2019 15:39:17 GMT+0000 (Coordinated Universal Time) (1576942757000)
utc: Sat Dec 21 2019 15:39:17 GMT+0000 (Coordinated Universal Time) (1576942757000)
=== getTime ===
plain: Thu Jan 01 1970 15:39:17 GMT+0000 (Coordinated Universal Time) (56357000)
utc: Thu Jan 01 1970 15:39:17 GMT+0000 (Coordinated Universal Time) (56357000)
=== getDate ===
plain: Sat Dec 21 2019 08:00:00 GMT+0000 (Coordinated Universal Time) (1576915200000)
utc: Sat Dec 21 2019 00:00:00 GMT+0000 (Coordinated Universal Time) (1576886400000)
==== useJDBCCompliantTimeZoneShift ====
=== getTimestamp ===
plain: Sat Dec 21 2019 15:39:17 GMT+0000 (Coordinated Universal Time) (1576942757000)
utc: Sat Dec 21 2019 15:39:17 GMT+0000 (Coordinated Universal Time) (1576942757000)
=== getTime ===
plain: Thu Jan 01 1970 15:39:17 GMT+0000 (Coordinated Universal Time) (56357000)
utc: Thu Jan 01 1970 15:39:17 GMT+0000 (Coordinated Universal Time) (56357000)
=== getDate ===
plain: Sat Dec 21 2019 08:00:00 GMT+0000 (Coordinated Universal Time) (1576915200000)
utc: Sat Dec 21 2019 00:00:00 GMT+0000 (Coordinated Universal Time) (1576886400000)
For comparison, SELECT COL,(UNIX_TIMESTAMP(COL) * 1000) FROM MYTABLE WHERE OWNER_ID=1 gives 2019-12-21 07:39:17 and 1576913957000.
This issue seems to be a bug in the past and should already be fixed.
Including useJDBCCompliantTimezoneShift=true in the connection parameter should fix the issue to interpret the timezone correctly.
Noting here that the timezone shown when converting a JavaScript Date to a string will always be the timezone of the server (in this case UTC) that's why your workaround fixed it.

Returning Dates In A Formatted Format (Iteration)

I am trying to create tabs with each tab name being the date of the start of each week in the year. So, "Jan 01" then "Jan 08" then "Jan 14" etc.
Essentially, taking x date then adding +7 days and returning that value as a date 7 days from x date.
function CreateWeekTabs(){
var TotalsSheet = spreadsheet.getSheetByName("Totals");
var StartingWeek = new Date(TotalsSheet.getRange("B1").getValue()); //Typically always "Jan 01" shwon. Cell Formatting is MMM DD. Cell Value is 01/01/2019
var CurrentWeek = new Date();
var NextWeek = new Date();
spreadsheet.toast("Please wait...","Creating Tabs");
for (var WeekNum = 1;WeekNum <= 2;WeekNum++){
var DayIncrease = 7 - (7 * WeekNum); //Should produce 0,7,14,21,28.... So first iteration won't increase any value from Jan 01.
CurrentWeek.setDate(StartingWeek.getDate()+DayIncrease); //E.g. First Iteration = Jan 01 + 0 = Jan 01; Second Iteration = Jan 01 + 7 = Jan 08;
NextWeek.setDate(CurrentWeek.getDate()+7); //Should be +7 days from CurrentWeek Value.
var WeekSheetName = Utilities.formatDate(NextWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM DD"); //Should return the date formatted.
Logger.log(WeekNum+" - "+WeekSheetName);
}
}
With Each Iteration, I intend to create WorkSheets with the First Date of each Week Starting from Value of CurrentWeek
Eg: Jan 01, Jan 08, Jan 15, Jan 22, Jan 29, Feb 05, etc...
UPDATE:
I since changed the code to:
function CreateWeekTabs(){
var TotalsSheet = spreadsheet.getSheetByName("Totals");
var CurrentWeek = new Date(TotalsSheet.getRange("B1").getValue()); //Typically always "Jan 01" shown. Cell Formatting is MMM dd. Cell Value is 01/01/2019
// var CurrentWeek = new Date();
var NextWeek = new Date();
spreadsheet.toast("Please wait...","Creating Tabs");
for (var WeekNum = 1;WeekNum <= 12;WeekNum++){
var DayIncrease = (7 * WeekNum) - 7; //Should produce 0,7,14,21,28.... So first iteration won't increase any value from Jan 01.
CurrentWeek.setDate(CurrentWeek.getDate()+DayIncrease); //E.g. First Iteration = Jan 01 + 0 = Jan 01; Second Iteration = Jan 01 + 7 = Jan 08;
NextWeek.setDate(CurrentWeek.getDate()+DayIncrease+7); //Should be +7 days from CurrentWeek Value.
var WeekSheetName = Utilities.formatDate(NextWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM dd"); //Should return the date formatted.
Logger.log("Week Number: "+WeekNum+" - Current Week: "+Utilities.formatDate(CurrentWeek,spreadsheet.getSpreadsheetTimeZone(),"MMM dd")+" Next Week: "+WeekSheetName);
}
}
and the Log is producing the following as outputs. (so I can see what it's producing for Variables 'CurrentWeek' and 'NextWeek'
[19-06-14 14:40:00:463 EDT] Week Number: 1 - Current Week: Jan 01 Next Week: Jun 08
[19-06-14 14:40:00:464 EDT] Week Number: 2 - Current Week: Jan 08 Next Week: Jun 22
[19-06-14 14:40:00:464 EDT] Week Number: 3 - Current Week: Jan 22 Next Week: Jul 13
[19-06-14 14:40:00:465 EDT] Week Number: 4 - Current Week: Feb 12 Next Week: Aug 09
[19-06-14 14:40:00:466 EDT] Week Number: 5 - Current Week: Mar 12 Next Week: Sep 16
[19-06-14 14:40:00:467 EDT] Week Number: 6 - Current Week: Apr 16 Next Week: Oct 28
[19-06-14 14:40:00:468 EDT] Week Number: 7 - Current Week: May 28 Next Week: Dec 16
[19-06-14 14:40:00:468 EDT] Week Number: 8 - Current Week: Jul 16 Next Week: Feb 10
[19-06-14 14:40:00:469 EDT] Week Number: 9 - Current Week: Sep 10 Next Week: Apr 13
[19-06-14 14:40:00:470 EDT] Week Number: 10 - Current Week: Nov 12 Next Week: Jun 21
[19-06-14 14:40:00:471 EDT] Week Number: 11 - Current Week: Jan 21 Next Week: Sep 06
[19-06-14 14:40:00:471 EDT] Week Number: 12 - Current Week: Apr 07 Next Week: Nov 30
Why the blazes? Current Value is calculating correctly, but the value of Next Week is way off, it should be showing +7 days from Current Week.
Try these:
The first calculates the start of week tab name for this week. You can pick the start of week day Sun-Sat is 0-6. The second calculates the start of week tab name for next week.
function thisWeeksStartOfWeekTabname(sow){
var sow=sow || 1;//Sun-0, Sat=6
var ss=SpreadsheetApp.getActive();
var dt=new Date();
while(dt.getDay()>0) {
dt=new Date(dt.setDate(dt.getDate()-1));
}
dt=new Date(dt.setDate(dt.getDate()+sow));
Logger.log(Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd"));
return Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd");
}
function nextWeeksStartOfWeekTabname(sow){
var sow=sow || 1;//Sun-0, Sat=6
var ss=SpreadsheetApp.getActive();
var dt=new Date();
while(dt.getDay()>0) {
dt=new Date(dt.setDate(dt.getDate()+1));
}
dt=new Date(dt.setDate(dt.getDate()+sow));
Logger.log(Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd"));
return Utilities.formatDate(dt, Session.getScriptTimeZone(), "MMM dd");
}

Set age group based on DOB

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.";
}
}
}

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)