Filtering by dates in Google Sheets - google-sheets

I'm trying to create a filtered sheet (tab) inside Google Sheets by the end of the year. I already have it set up to filter by Department, but I can't get it to filter by year.
I have a DataSheet tab where people can go in and put their raw data for Departments, Project Title, and Year. In the Validation tab, I used =UNIQUE(DataSheet!A4:A) to get the drop-down menu items list for the Reporting Tab.
Reporting Tab View
=IF(B2="All Years", "", " AND LOWER(B) = LOWER('"&B2&"') ")
=IF(A2="All Departments", "", " AND LOWER(A) = LOWER('"&A2&"') ")
`=QUERY(DataSheet!A3:C, "SELECT * WHERE 1=1"& IF(A2="All Departments", "", " AND LOWER(A) = LOWER('"&A2&"') ") & IF(B2="All Years", "", " AND LOWER(B) = LOWER('"&B2&"') "), 1)`
Above is the code that queries the DataSheet table and filters based on what I chosen for the Departments Involved and Years, but whenever I try to filter by Years it doesn't work. I was getting an error of:
Unable to parse query string for Function QUERY parameter 2:"
I tried using TO_TEXT() on the Years data in the DataSheet and in the equation from above but that did not work either. Any advice?
Below is a link to the google sheet I am working on:
https://docs.google.com/spreadsheets/d/1FoesYRCM53R_IKSqym_U3l9q_27Xo7_rJHrb35RMOaQ/edit#gid=1009160987

the formula should be:
=QUERY(DataSheet!A3:C, "where 1=1 "&
IF(A2="All Departments",, " and lower(A) = '"&LOWER(A2)&"'")&
IF(B2="All Years",, " and C = "&B2), 1)

Related

Query function in Google Sheets isn't pulling rows after a certain date

I have a Google sheet document with 2 tabs: 1 for raw data and the other tab uses a Query function to search for entered criteria. The function is not pulling any rows after the 11/9/2022 date.
In other words, if I type "Beacon light is Inop", I get the 11/9/2002 row in the results. But if I type "radar alt inop", nothing shows up.
What I've tried: making sure all entries in column B are text.
Here is the URL's address for those who want to tweak or try their hand:
https://docs.google.com/spreadsheets/d/17HIljpouuSN9maog8iA2U6hC9pkIgcQ1Q3QZpqv9XSo/edit?pli=1#gid=168025446
Thoughts?
use:
=QUERY(RawData!A2:H, "SELECT A,B,C,D,E,F,G WHERE 1=1 "&
IF(C1="",, " and H = '"&C1&"'")&
IF(C2="",, " and A = '"&C2&"'"), 0)
correct output based on your dataset is one single row:

How can I make correct formula for Age diff in Google sheet?

So, I wanted to claculate age from user birthdate to current date in Google sheet in my expected format. I tried few formula's from some sources, but it is just not happening.
Can anyone please guide me?
For reference and test purpose, I'm attaching one Google sheet public link. No worries if email address will be shown in Googe sheet.
Link: https://docs.google.com/spreadsheets/d/1jRlr6A3YRJIo1Ah1TSlRsDcLEDV_2BJ8YaBRS3YVC6Q/edit#gid=0
Assume birthday date is placed in range 'A2'.
Current age:
=DATEDIF(A2,TODAY(),"Y")&" year(s) "&DATEDIF(A2,TODAY(),"YM")&" month(s) "&DATEDIF(A2,TODAY(),"MD")&" day(s)"
you could use:
=INDEX(JOIN(" ",DATEDIF(A2, NOW(),
{"Y", "YM", "MD"})&{" year(s)", " month(s)", " day(s)"}))
but to make it "smart" (not show null values and use plural only when needed) try:
=INDEX(JOIN(" ", LAMBDA(a, LAMBDA(x, IF(x=0,,IF(x>1, x&a&"s", x&a)))
(DATEDIF(A2, NOW(), {"Y", "YM", "MD"})))({" year", " month", " day"})))
and for array it would be:
=INDEX(IF(ISDATE_STRICT(A2:A), TRIM(FLATTEN(QUERY(TRANSPOSE(
IFERROR(LAMBDA(a, LAMBDA(x, IF(x=0,,IF(x>1, x&a&"s", x&a)))
(DATEDIF(A2:A, NOW(), {"Y", "YM", "MD"})))({" year", " month", " day"}))),,9^9))), ))

Converting full names to 'Surname, First name' format on Google Spreadsheets

I have a Google Spreadsheet that record some author names like this:
A
A. Dagliati
A. Zambelli
A.H.M. ter Hofstede
Agnes Bates Koschmider
Ágnes Vathy-Fogarassy
Ahmed B. Najjar
Ala Norani
I want column B to receive some formula such that B will display the last name, a comma, and the first/middle name, like this:
A B
A. Dagliati Dagliati, A.
A. Zambelli Zambelli, A.
A.H.M. ter Hofstede Hofstede, A.H.M. ter
Agnes Bates Koschmider Koschmider, Agnes Bates
Ágnes Vathy-Fogarassy Vathy-Fogarassy, Ágnes
Ahmed B. Najjar Najjar, Ahmed B.
Ala Norani Norani, Ala
How can I do that?
Try this formula on row 2 of your sheet, with an empty column below it.
=ArrayFormula(IF(LEN(A2:A),REGEXEXTRACT(A2:A,".+\s(.+)") &", " & LEFT(A2:A,LEN(A2:A)-LEN(REGEXEXTRACT(A2:A,".+\s(.+)") )),""))
Image:
=CONCAT(RIGHT(A1,LEN(A1)-FIND("#",SUBSTITUTE(A1," ","#",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))),1)), CONCAT(", ", LEFT(A1, FIND("#",SUBSTITUTE(A1," ","#",LEN(A1)-LEN(SUBSTITUTE(A1," ",""))),1))))
Basically, we are cutting off text from last index of " " (whitespace), append comma and do same from beginning.
Your best bet is probably to use regular expression replacement. It's not pretty, but it's the easiest way to search for the delimiter and perform the replacement using capture groups. I am still working on how to properly support cases where there is a single name like "A". For now it assumes it is the surname. Here is the formula:
=REGEXREPLACE(A1,"(.*?)([^ ]+)$", "$2, $1")
This function will search for any character non-greedily (.*? see the docs for RE2 here) which will allow the second capture group to find all the characters from the end of the string to the first delimiter which is a space in this case. Since we are using capture groups in the regular expression we can reference them in the replacement string using the $1 and $2 placeholders.
The output is as desired:
You could use a combination of:
SPLIT()
COLUMNS()
INDEX()
ARRAY_CONSTRAIN()
JOIN()
=JOIN(
", ",
INDEX(SPLIT(A2, " "), 1, COLUMNS(SPLIT(A2, " "))),
JOIN(" ", ARRAY_CONSTRAIN(SPLIT(A2, " "), 1, COLUMNS(SPLIT(A2, " "))-1))
)
Get the last name
Split up the name by space SPLIT(A2, " ")
Get the number of names COLUMNS(SPLIT(A2, " "))
Select on the last name INDEX(SPLIT(A2, " "), 1, COLUMNS(SPLIT(A2, " ")))
Get the other names
Split up the name by space again SPLIT(A2, " ")
Get all names except the last name ARRAY_CONSTRAIN(SPLIT(A2, " "), 1, COLUMNS(SPLIT(A2, " "))-1)
Join them back together JOIN(" ", ARRAY_CONSTRAIN(SPLIT(A2, " "), 1, COLUMNS(SPLIT(A2, " "))-1))
Join in desired order
JOIN(", ", LAST_NAME_FORMULA, OTHER_NAMES_FORMULA)

Easiest way to query multiple sheets that are named by year, for all time?

I use a big nasty formula to query multiple sheets in the same Google Sheet document named according to year (2020, 2019, 2018, etc...) to sum up a total value. Because I need to query a filtered range in a complex way, I've figured out the best way to do this without running into other troubleshooting issues is to SUM multiple queries like so:
=SUM(
IFERROR(QUERY(FILTER({EOMONTH(INDIRECT("'"&**TO_TEXT(YEAR(TODAY()))&"'!A1:A"&ROWS(INDIRECT("'"&TO_TEXT(YEAR(TODAY()))&"'!K2:K"))), 0),INDIRECT("'"&TO_TEXT(YEAR(TODAY()))&"'!K2:K")}, [filter conditions]), "select Col2 label Col2' ' ")),
IFERROR(QUERY(FILTER({EOMONTH(INDIRECT("'"&TO_TEXT(YEAR(TODAY()-365))&"'!A1:A"&ROWS(INDIRECT("'"&TO_TEXT(YEAR(TODAY()-365))&"'!K2:K"))),0),INDIRECT("'"&TO_TEXT(YEAR(TODAY()-365))**&"'!K2:K")}, [filter conditions]),
"select Col2 label Col2' ' "))
)
For some context, you can see the much larger IF formula that this SUM is meant to be nested into, in the "Example Matrix" tab of the sheet. My focus for this question is on the INDIRECT references, which I have been using to dynamically reference the most current year's sheet and the previous year's sheet.
The problem is, if I want to keep doing this for every sheet as the years go on, I have to manually add a whole other query into my SUM using INDIRECT("'"&TO_TEXT(YEAR(TODAY()-730))&"'!K2:K") and INDIRECT("'"&TO_TEXT(YEAR(TODAY()-1095))&"'!K2:K") and so on, and that is just not an option considering how many of them I would need to add to multiple formulas in multiple sheets.
Is there any way I can adapt this for simplicity or perhaps make it into a script to accomplish summing queries for all sheets that are named by year for all time?
Here's a copy of my Example Sheet: https://docs.google.com/spreadsheets/d/1b29gyEgCDwor_KJ6ACP2rxdvauOzacDI9FL2K-jgg5E/edit#gid=1652431688
Thank you, any help is appreciated.
Usually an array formula would be a way to go in such case, but INDIRECT does not work inside array formulas.
There are a few approaches using scripting like this.
Here I will describe another approach: formula generation. We'll get a string with the formula and manually place it in a cell. It would be nice to put it in an inverted FORMULATEXT function, but unfortunately there is no such function at the moment, so we'll just paste it manually.
Step 1
Set the year limits (sheet names) in some cells. The first year of the period will be in K22, and the last will be in M22.
I set the period to from 2005 to 2040.
All the year numbers will e easily generated with SEQUENCE. If there were arbitrary names, a range of those names set manually would've been needed.
Step 2
Write a formula generator for what you need. We just generate a string here, in that string will be a formula you would normally type manually. It is not hard, but there are a lot of repetition and it would be tedious to write it manually.
Here is the generator:
=ARRAYFORMULA(
"=SUM(
FILTER(
{
" & JOIN(
";" & CHAR(10) & " ",
"IFERROR('" & SEQUENCE(M22 - K22 + 1, 1, K22, 1) & "'!D2:D, 0)"
) & "
},
ISNUMBER(
{
" & JOIN(
";" & CHAR(10) & " ",
"IFERROR('" & SEQUENCE(M22 - K22 + 1, 1, K22, 1) & "'!D2:D, 0)"
) & "
}
),
REGEXMATCH(
{
" & JOIN(
";" & CHAR(10) & " ",
"IFERROR('" & SEQUENCE(M22 - K22 + 1, 1, K22, 1) & "'!A2:A, 0)"
) & "
},
""(?i)^TOTAL$""
),
REGEXMATCH(
{
" & JOIN(
";" & CHAR(10) & " ",
"IFERROR('" & SEQUENCE(M22 - K22 + 1, 1, K22, 1) & "'!C2:C, 0)"
) & "
},
""(?i)^"" & IF(F19 = ""Condition 1 Count"", ""Condition 1"", ""Condition 2"") & ""$""
)
)
)"
)
Compared to the original formula the resulting formula is heavily changed, simplified. For example there is no actual need for INDIRECT with this approach, EOMONTH wasn't used anywhere and so on.
Step 3
Copy that result as text, remove enclosing quotes, replace double double quotes with single double quotes: "" -> ".
Now we've got our formula to paste somewhere as we could've typed manually. Here is a part of it:
=SUM(
FILTER(
{
IFERROR('2005'!F2:F, 0);
IFERROR('2006'!F2:F, 0);
...
IFERROR('2039'!F2:F, 0);
IFERROR('2040'!F2:F, 0)
},
ISNUMBER(
{
IFERROR('2005'!F2:F, 0);
IFERROR('2006'!F2:F, 0);
...
IFERROR('2039'!F2:F, 0);
IFERROR('2040'!F2:F, 0)
}
),
REGEXMATCH(
{
IFERROR('2005'!C2:C, 0);
IFERROR('2006'!C2:C, 0);
...
IFERROR('2039'!C2:C, 0);
IFERROR('2040'!C2:C, 0)
},
"(?i)^TOTAL$"
),
REGEXMATCH(
{
IFERROR('2005'!E2:E, 0);
IFERROR('2006'!E2:E, 0);
...
IFERROR('2039'!E2:E, 0);
IFERROR('2040'!E2:E, 0)
},
"(?i)^" & IF(F19 = "Condition 1 Count", "Condition 1", "Condition 2") & "$"
)
)
)
Step 4
Manually place this resulting formula into some cell.
It does what it supposed to do, dropdown reference works, non-existing sheets are tolerated.
There is no 2021 sheet for example, but when it will be crated there will be no need to change the formula, data from that new sheet will be used.
You'll need to repeat the process in two cases: the formula needs some change in logic or it is almost 2040 and you want to add another 50 years to the period. Still that process of generation is faster than making changes manually to the resulting monster.
A few notes on the original formula:
YEAR(TODAY() - 365) ➡ YEAR(TODAY()) - 1. With your approach there will be an error because of leap years. Depends on the years number, but at the beginning of a year it will emerge for sure.
"select Col2 label Col2' ' " ➡ "select Col2 label Col2 ''". Do you really need a column with a header name ' ' (just a space)? I'm guessing it meant to be blank.
No need for TO_TEXT.

Google Sheet Advanced Search using Query function

I'm trying to use Google Sheets to manage a database. I've figured out how to use the query function to do a simple search, but I'd like to know if an advanced search is possible. Here's what I mean:
Example I made (refer to the second sheet)
Each row has a number of attributes, and the search sheet has a number of fields that can be entered. I'd like to be able to search for one without having to keep the other fields filled in as well, but I'm not sure how to mess around with the query function to get what I need.
Any help would be very much appreciated. Thank you!
Where must only appear at the beginning of the filtering, not before every conditional.
This can be done with FILTER and some if statements or keep the query and adjust it similarly like this:
= IFERROR(
query(
Database!B3:G13,
"select B,C,D,E,F,G
where " &
IF(LEN($C$4), "lower(C) contains lower('"&$C$4&"')", "1=1") & " and " &
IF(LEN($E$4), "lower(D) contains lower('"&$E$4&"')", "1=1") & " and " &
IF(LEN($G$4), "lower(E) contains lower('"&$G$4&"')", "1=1") & " and " &
IF(LEN($I$4), "lower(F) contains lower('"&$I$4&"')", "1=1") & " and " &
IF(LEN($K$4), "lower(G) contains lower('"&$K$4&"')", "1=1")),
"No Results")
It essentially checks if the filter is specified and if not puts 1=1 (TRUE) as a placeholder.

Resources