If statement status dependent on dates (3 columns).TODAY() does not work - google-sheets

Hi all I have a situation where I have 3 columns which results in 3 results.
3 columns are empty, display "0"
First column has a date <= today(), 2nd and 3rd column empty, result is "1"
First column has a date > today(), 2nd and 3rd column empty, result is "0"
Second column has a date and third column is empty (First col can be empty or filled), result = "2"
Third column has a date, result = "3"
Here is my code below:
=if(and(ISBLANK(A6), ISBLANK(B6), ISBLANK(C6)),"0",IF(and(A6<=NOW(), ISBLANK(B6), ISBLANK(C6)),"1",if(and(NOT(ISBLANK(A6)),B6<=NOW(), ISBLANK(C6)),"2",IF(C6<=NOW(),"3","0"))))
However I am getting mixed results, especially if the date in the first column is greater than the today's date, it shows up a result of "2" and not the expected "0"

So despite your somewhat mismatched directives - here is a start - I am still unsure about which of your rules actually overrides - so when you updated that I will update the formula:
=if(counta(A1:C1)=0,0,IF(LEN(C1)>0,3,IF(LEN(B1)>0,2,IF(AND(LEN(A1)>0,COUNTA(B1:C1)=0,A1>TODAY()),0,IF(AND(LEN(A1)>0,COUNTA(B1:C1)=0,A1<=TODAY()),1,)))))
A couple things I am doing here:
Part of the reason your formula is having issues is two major things -
1) you need to reverse the order of your IF statements to allow the cells in C or B to trump the other rules, if that is the result you want. This way if you always want a 3 when anything is in column C, that should be the second check after checking if all 3 are blank
2) when using things like <= a date or time - it treats blank cells as always being less than. So change/add one more check within your AND function to check that the length of it is greater than 0 so make sure there is a valid value in there.

Related

ArrayFormula & Vlookup: exclude the current row from Vlookup range

I'm building a simple booking system using GoogleSheets.
Each entry (Row) is a "booking request".
The intervals being entered on the sheet (via a form) are fixed to 1, 2 or 3 hours (which makes this a "simple booking system"). I'm validating these "booking requests" based on "overlaps" in Start & End Time in a couple separate columns L, M, N.
Sheet Data
The Formula
IF(ROW($A:$A)=1,
"CheckEndDateTimes (1 hour after Start)",
IF(ISERROR(VLOOKUP($E1:$E+1/24,$G$2:$G,1,FALSE)),
"",
"overlaps 1 hour ahead of start"
)
)
)
I'm using ArrayFormula, such that it auto-updates Sheet data as entries are added via a form. I'm using VLOOKUP because it seems to work well with ArrayFormula (as opposed to Index/Match).
The generalized issue:
Column E contains the search_key values (i.e. $E1:$E) (Start Datetime).
Column G contains the range (i.e. $G:$G) (End Datetimes), which I am using to compare intervals (1, 2, 3 hours) ADDED to the search_key value (Column E)
SO far this works fine, EXCEPT that the Row that is being evaluated ALWAYS evaluates to an overlap; clearly, the mere existence of the End Time in the Row being evaluated is always resulting in an overlap.
My Question
Is there a way I can EXCLUDE the current row from the range being evaluated in the VLOOKUP function. (I tried adding "<>", as follows, but it results in NO matches being found:
VLOOKUP($E1:$E+1/24,$G$2:$G<>$G1:$G,1,FALSE)
Or even (to test),
VLOOKUP($E1:$E+1/24,$G$2:$G<>$G$4,1,FALSE)
Any help would be appreciated, Thank you kindly. :)
On reflection I think you need to use countifs to check for any rows with a matching overlapped time and with a row number not equal to the current row like this:
=ArrayFormula(if(A2:A="",,countifs(C2:C,A2:A+1/24,row(C2:C),"<>"&row(A2:A))))
Then you can test whether the result is non-zero and display a message:
=ArrayFormula(if(A2:A="",,if(countifs(C2:C,A2:A+1/24,row(C2:C),"<>"&row(A2:A)),"overlaps 1 hour",)))
and similarly for 2 and 3 hours.
BTW I don't think row three does overlap at one hour.

How do I display the value of a cell in one column based on the value of a cell in a different column?

I have a simple table.
Column A are dates (rows 2 to 100) that reflect approximately the next 3 months.
Column C are percentages that range from 0 to 1 (i.e. 0% to 100%). The %s are derived from a =FORECAST function.
I want to query a date in column A based on a value of 100% in column C. However, the QUERY function does not work because it's reading the =FORECAST formula in column C rather than the text or value of "100%" itself. (In other words, if I remove the =FORECAST formula and type in the string "100%", the query works.
How can I pull the date value in Column A and keep the formulas used in column C?
This sounds like a lookup to find the value in column A on the first row where column C contains the value 100%. Try this:
=vlookup(100%, { C2:C, A2:A }, 2, false)
In the event multiple rows in column C may contain 100%, and you want to get all such dates, try this:
=filter(A2:A, C2:C = 100%)
In the event your forecast() numbers do not produce exact percentages but figures like 100.04%, use this:
=filter(Forecast!A2:A, round(Forecast!C2:C, 2) = 100%)
Thanks to everyone who contributed. My workaround was replacing the = sign with a > sign, as shown:
=QUERY(StageHist!A:H, "SELECT A WHERE C>.99")
since I couldn't figure out how to make the 100% figure an exact 100%. Apparently the =FORECAST formula is designed to give a result with 8 or 9 digits to the right of the decimal. (Although I'm sure that I could nest a =ROUNDing function inside of FORECAST and get an exact 1.0 value. (A project for another day!)

How can I get the last numerical value value in a column in Google Sheets?

I need to find the last numerical value in a column. I was using this formula to get the last value in column G, but I made some changes and it no longer works: =INDEX(G:G, COUNTA(G:G), 1). My column now looks like this:
645
2345
4674.2345
123.1
"-"
"-"
"-"
...and the formula returns "-". I want it to return 123.1. How can I do this?
There are many ways to go about this. Here is one of them:
=QUERY(FILTER({G:G,ROW(G:G)},ISNUMBER(G:G)),"Select Col1 ORDER BY Col2 Desc LIMIT 1")
FILTER creates a virtual array of only numeric values in G in the first column and the row of those numeric values in the second column.
QUERY returns flips the order by row number and returns only the new top value from the first column (which winds up being your last numeric value in the original range).
However, if your numeric values start at G1, and if there are only numeric values up to where you start adding hyphens in cells, you could just alter your original formula like this:
=INDEX(G:G,COUNT(G:G))
This would work because COUNT only counts numeric values while COUNTA counts all non-null values (including errors BTW).
Not to take anything away from the accepted answer, but I've been working on this a bit lately in relation to this for the never-ending last row discussion and thought I'd share some potential similar solutions. These ideas are inspired by a pattern of google sheet array questions that seem to be coming up more often. I am also intentionally using different ways to do the same thing just to give people some ideas (i.e. left and Regex).
Last Row that is...
Number: =max(filter(row(G:G),isnumber(G:G)))
Text: =max(filter(row(G:G),isText(G:G)))
An error: =max(filter(row(G:G),iserror(G:G)))
Under 0 : =max(filter(row(G:G),G:G<0))
Also exists in column D: =max(filter(row(G:G),ISNUMBER(match(G:G,D:D,0))))
Not Blank: =max(filter(row(A:A),NOT(ISBLANK(A:A))))
Starts with ab: =max(filter(row(G:G),left(G:G,2)="ab"))
Contains the character !: =max(filter(row(G:G),isnumber(Find("!",G:G))))
Starts with a number: =max(filter(row(G:G),REGEXMATCH(G:G,"^\d")))
Only contains letters: =max(filter(row(G:G),REGEXMATCH(G:G,"^[a-zA-Z]+$")
Last four digits are upper case: =Max(filter(row(G:G),REGEXMATCH(G:G,"[A-Z]{4}$")))
To get the actual value (which I realize was the actual question), just wrap an index function around the Max function. So for this question, a solution could be :
=Index(G:G,max(filter(row(G:G),isnumber(G:G))))

if value between 10 & 20 then display 20% of value in another cell

i want to find the percentage of the values in range. for eg : if value between 10 & 20 then display the 20% of value, if value between 20.01 & 50 then display the 10% of value.
a sheet is attached here for more clarification.
https://docs.google.com/spreadsheets/d/1HlIflx8GkoCesl2jWdoHe30PzzAbuXUQE9XGasE7Iys/edit?usp=sharing
I have added three sheets to your sample spreadsheet.
The sheet called "Erik Help - Option 1" is self-contained. See the stand-alone array formula in cell B1:
=ArrayFormula({"UPDATED PRICE"; IF(A2:A="","",IFS(A2:A<=7,9.95, A2:A<=10,11.45, A2:A<=20,A2:A*20%, A2:A<=50,A2:A*10%, A2:A,A2:A*5%))})
This formula creates a virtual array by using curly brackets { }. First, the header is placed. Then a simple IF statement checks for whether there is anything in each cell of Column A. If there is not, then Column B will be null; if there is, then Column B will check the value of each cell in Column A against the elements of the IFS function.
The second sheet, entitled "Erik Help - Option 2," relies on the third sheet, entitled "Values." This would allow you more ease in changing assigned values.
The array formula in cell B1 of "Erik Help - Option 2" is as follows:
=ArrayFormula({"UPDATED PRICE"; IF(A2:A="","",IF(VLOOKUP(A2:A,Values!A2:C,3,TRUE)>=1,VLOOKUP(A2:A,Values!A2:C,3,TRUE),A2:A*VLOOKUP(A2:A,Values!A2:C,3,TRUE)))})
This works the same as the previous formula except that instead of referencing IFS for values, this formula references the sheet "Values" with a LOOKUP.
After checking for null values, another IF statement checks to see if the lookup value from Values!C2:C >=1 (i.e., whether it is a dollar amount or a percentage):
If this is TRUE (i.e., if the corresponding Values!C2:C value a dollar amount), the VLOOKUP runs again, comparing values from 'Erik Help - Option 2!'A2:A with the values in Values!A2:A and returning the value in Values!C2:C.
If this is FALSE (i.e., if the corresponding Values!C2:C value is a percentage amount), the values from 'Erik Help - Option 2'!A2:A are multiplied by the corresponding values in Values!C2:C.
As you can see, the results from "Erik Help - Option 1" and "Erik Help - Option 2" are identical. So it comes down to preference. If you want a self-contained option and feel comfortable editing the formula itself in the future if values change, use Option 1. If you prefer the ease of changing the values in chart form, use Option 2 with the Values chart.
NOTE: In my sheets, I also applied currency formatting (Format > Number > Currency) to all cells that contain or might contain dollar values.

How to autofill dates using arrayformula

I'm using Google sheets for data entry that auto-populates data from my website whenever someone submits to a form. The user's data imports into my sheet with a timestamp (column A).
Using the Arrayformula function, I'd like a column to autofill all the dates of a timestamp within that month. For example, if 1/5/2016 is entered as a timestamp, I'd like the formula to autofill in the dates 1/1/2016 - 1/31/2016.
Additionally, I'd like other months added in the Arrayformula column. For example, if both 1/5/2016 and 2/3/2016 are entered in column A, I'd like the formula to fill in the dates from 1/1/2016 - 2/29/2016.
I know I can manually write in the dates and drag them down the column, but I have a lot of sheets, and using an Arrayformula will save me a lot of time. I've tried a similar formula in column B, but it doesn't autofill in the date gaps. Is what I'm looking for possible?
Here's a copy of the editable spreadsheet I'm referring to: https://docs.google.com/a/flyingfx.com/spreadsheets/d/1Ka3cZfeXlIKfNzXwNCOWV15o74Bqp-4zaj_twC3v1KA/edit?usp=sharing
Short answer
Cell A1
1/1/2016
Cell A2
=ArrayFormula(ADD(A1,row(INDIRECT("A1:A"&30))))
Explanation
In Google Sheets dates are serialized numbers where integers are days and fractions are hours, minutes and so on. Once to have this in mind, the next is to find a useful construct.
INDIRECT(reference_string,use_A1_notation) is used to calculate a range of the desired size by given the height as a hardcoded constant, in this case 30. You should not worry about circular references in this construct.
ROW(reference) returns an array of consecutive numbers.
A1 is the starting date.
ADD(value1,value2). It's the same as using +. As the first argument is a scalar value and second argument is an array of values, it returns an array of the same size of the second argument.
ArrayFormula(array_formula) displays the values returned by array_formula
As A1 is a date, by default the returned values will be formatted as date too.
Increment by Month
If anyone wants to be able to increment by month, here's a way I've been able to accomplish that. Your solution #ptim got me on the right track, thanks.
Formula
Placed in B1
First_Month = 2020-11-01 [named range]
=ARRAYFORMULA(
IF(
ROW(A:A) = 1,
"Date",
IF(
LEN(A:A),
EDATE( First_Month, ROW( A:A ) -2 ),
""
)
)
)
Result
ID Month
1 2020-11-01
2 2020-12-01
3 2021-01-01
4 2021-02-01
5 2021-03-01
I have an alternative to the above, which allows you to edit only the first row, then add protection (as I like to do with the entire first row where I use this approach for other formulas):
=ARRAYFORMULA(
IF(
ROW(A1:A) = 1,
"Date",
IF(
ROW(A1:A) = 2,
DATE(2020, 1, 1),
DATE(2020, 1, 1) + (ROW(A1:A) - 2)
)
)
)
// pseudo code!
const START_DATE = 2020-01-01
if (currentRow == 1)
print "Date"
else if (currentRow == 2)
print START_DATE
else
print START_DATE + (currentRow - 2)
Notes:
the initial date is hard-coded (ensure that the two instances match!)
ROW(A1:1) returns the current row number, so the first if statement evaluates as "if this is Row 1, then render Date"
"if this is row 2, render the hard-coded date"
(nB: adding an integer to a date adds a day)
"else increment the date in A2 by the (adjusted) number of rows" (the minus two accounts for the two rows handled by the first two ifs (A1 and A2). Eg: in row 3, we want to add 1 to the date in row 2, so current:3 - 2 = 1.
Here's a live example (I added conditional formatting to even months to assist sanity checking that the last day of month is correct):
https://docs.google.com/spreadsheets/d/1seS00_w6kTazSNtrxTrGzuqzDpeG1VtFCKpiT_5C8QI/view#gid=0
Also - I find the following VScode extension handy for syntax highlighting Google Sheets formulas: https://github.com/leonidasIIV/vsc_sheets_formula_extension
The Row1 header trick is courtesy of Randy via https://www.tillerhq.com/what-are-your-favorite-google-spreadsheet-party-tricks/
nice. thanks.
To get the list length to adapt to the number of days in the selected month simply replace the static 30 by eomonth(A1;0)-A1. This accommodates for months with 31 days, and for February which can have either 28 or 29 days.
=ArrayFormula(ADD(A1,row(INDIRECT("A1:A"&eomonth(A1;0)-A1))))
Updated for 2022:
This can now be done pretty easily with the SEQUENCE function, it's also a bit more adaptable.
Below will list all of the days in columns but you can swap the first 2 values to place in rows instead:
=SEQUENCE(1,7,today()-7,1)
More specific to your example, below will take the date entered (via cell, formula, or named cell) and give you the full month in columns:
=SEQUENCE(1,day(EOMONTH("2016-1-5",0)),EOMONTH("2016-1-5",-1)+1,1)

Resources