Google Sheets SUMIFS comparing one column to another - google-sheets

I am wondering if there is a way to use column comparisons in a SUMIF or SUMIFS function or the DSUM function even. Specifically, I want to compare one value in a row with another value in the same row of data.
For example, let's say I have the following table of data:
Date 1 | Date 2 | Money Earned
1/2/22 | 1/5/22 | $23.00
1/5/22 | 1/3/22 | $11.00
I want to write a formula that sums the values in the 3rd column if Date 1 is last week and if Date 2 is later than or equal to Date 1.
I have completed a workaround solution with 2 hidden columns as follows:
Last week --> =IF(EQ(WEEKNUM(TODAY()) - WEEKNUM(A2), 1), "YES", "NO")
Date 2 After Date 1 --> =IF(B2>=A2, "YES", "NO")
Then I use:
=SUMIFS(C2:C3,D2:D3,"YES",E2:E3,"YES")
It all works, but I am trying to learn to do this a cleaner way without hidden columns that someone might move or delete.
All the examples I can find of SUM or SUMIF rely on the criteria being compared to a singular value that is either hardcoded in the formula or the value of a single cell. I want to compare data from column 1 to column 2 directly for each row. Is this possible with these formulas or any formula in Google Sheets?

In order to check if a date was "last week", you need to consider that the current week might be the first one of the year. So, instead of comparing the WEEKNUM of today with the WEEKNUM of the other date, just compare it to the WEEKNUM of 7 days ago.
Secondly, instead of using "YES" or "NO", you could have used TRUE/FALSE values and remove the need to write IF statements, like this:
last week: =(WEEKNUM(TODAY()-7)=WEEKNUM(A2))
date 2 after date 1: B2>=A2
From there, while it is possible to build an arrayformula for SUMIFS or QUERY, it is easier to just filter the table and sum the results from column C:
=SUM(FILTER(C2:C,WEEKNUM(TODAY()-7)=WEEKNUM(A2:A),B2:B>A2:A))

Related

Populating columns with days based on a selection

I am trying to build a sleep tracker in Google Sheets (link). The idea is to select a year and a month from a drop-down list in cells A1 and A2, which would then populate columns based on the number of days in that month. I have tried different formulas that I found on stack overflow and elsewhere, but could not get them to work.
In short:
I am looking for a formula that will populate the columns with days of that month and a name of the day in a row bellow.
Looking for a way to summarize the time of sleep at the end of the each day, based on a ticked checkbox.
I am not sure how the year and month selectors should be formatted (as plain number or a date).
Is there a way to automatically insert check-boxes to the days of the month?
This is the formula that I have tried to adjust:
=INDEX({TEXT(SEQUENCE(1; DAY(EOMONTH(A2&"/"&A1;0)); A2&"/"&A1; 1); {"d"; "ddd"}); {"Total"; ""}})
But it returns with "Error In ARRAY_LITERAL, an Array Literal was missing values for one or more rows."
Please note that ";" is used as an argument separator instead of "," (regional settings).
Thank you in advance!
I think that with a very small adaptation and date formatting you'll be able to easily do it. First with your selector in A2, you could set it as actual dates, but format them as mmmm:
Then, repeat the sequence in both rows starting in C2 and C3:
=SEQUENCE(1,DAY(EOMONTH(A2,0)),A2)
But formatting row 3 as ddd:
PS: yes, you can do row 3 with TEXT and INDEX. Choose your preferred one:
=INDEX(TEXT(SEQUENCE(1,DAY(EOMONTH(A2,0)),A2),"dddd"))
UPDATE with TEXT VALUES
Return to your previous A2 dropdown and try this, using MATCH to find the number of the month, and DATE to locate the correct beginning of the month in that year:
For row 2:
=SEQUENCE(1,DAY(EOMONTH(DATE(A1,MATCH(A2,{"January","February","March","April","May","June","July","September","October","November","December"},0),1),0)),
DATE(A1,MATCH(A2,{"January","February","March","April","May","June","July","September","October","November","December"},0),1))
For row 3:
=INDEX(TEXT(SEQUENCE(1,DAY(EOMONTH(DATE(A1,MATCH(A2,{"January","February","March","April","May","June","July","September","October","November","December"},0),1),0)),
DATE(A1,MATCH(A2,{"January","February","March","April","May","June","July","September","October","November","December"},0),1)),"dddd")
)

Array formula with filter and index values depending on countif

I need an array formula only in column Date_2 with results like on screenshot and that will
insert last day of month depending on Date_0 (if bunch of Color&Fruit&Meal doesn't repeat in table)
insert first minimum date of column Date_1 (if bunch of Color&Fruit&Meal repeats first time) - 1
insert second minimum date of column Date_1 (if bunch of Color&Fruit&Meal repeats second time) - 1
and so on...
Is is possible to solve it with array formula?
I've tried but I can't..
=ArrayFormula(IF(A2:A="","",IF(COUNTIF(B2:B&C2:C&D2:D,B2:B&C2:C&D2:D)>1,INDEX(FILTER(B2:E,E2:E<>""),1,4),EOMONTH(A2:A,0))))
Google Sheets
I'm not quite sure what you need for Date_1 but try this arrayformula in cell F2 for Date_2:
=ARRAYFORMULA({"Date_2";if(IF(B2:B&""&C2:C&""&D2:D<>"",if(A2:A<>"",COUNTIFS(B2:B&"|"&C2:C&"|"&D2:D,B2:B&"|"&C2:C&"|"&D2:D,ROW(A2:A),"<="&ROW(A2:A)),),)=1,eomonth(A2:A,0),)})
I've added a duplicate sheet ("Erik Help") with the following formula in F1:
=ArrayFormula({"Date_2";IF(A2:A="",,IFERROR(VLOOKUP(B2:B&C2:C&D2:D&TEXT(COUNTIFS(B2:B&C2:C&D2:D,B2:B&C2:C&D2:D,ROW(A2:A),"<="&ROW(A2:A))+1,"000"),{B2:B&C2:C&D2:D&TEXT(COUNTIFS(B2:B&C2:C&D2:D,B2:B&C2:C&D2:D,ROW(A2:A),"<="&ROW(A2:A)),"000"),E2:E},2,FALSE)-1,EOMONTH(A2:A,0)))})
This formula creates the header (which you can change within the formula) and all results for Column F.
To lookup the "next instance of the group if there is one," I just wrote the formula to VLOOKUP that grouping plus a text rendering of the COUNTIFS-as-of-that-row-plus-1 for that grouping within a virtual array of each-grouping-plus-unique-count-thus-far in one column and the E2:E data in the next column. For instance, for Row 2, the formula VLOOKUPs redapplepie002
(002 being the text rendition of 001, which is the count of redapplepie as of row 2).

In Google Sheets, how to check if Cell A (Date) is within the Date range of Cell B and C

I have a sheet with a timeline that shows a month per row in column A and an amount in USD next to that month in column B.
I want to be able to specify amounts in column G with a start and end date for that amount in columns E and F.
What I am trying to achieve is that the values in column B are automatically calculated by looking at the start and end dates specified in columns E and F and then taking the corresponding value from column G if the date in column A falls in between the date range specified in E and F.
I have found many suggestions for similar problems online but wasn't able to get any of them to work for my specific case. Any help is very welcome
You could do it as an array formula like this:
=ArrayFormula(mmult((text(indirect("A2:A"&count(A2:A)+1),"YYMM")>=text(TRANSPOSE(indirect("`E3:E"&count(E3:E)+2)),"YYMM"))*(text(indirect("A2:A"&count(A2:A)+1),"YYMM")<=text(transpose(indirect("F3:F"&count(F3:F)+2)),"YYMM"))*transpose(indirect("G3:G"&count(G3:G)+2)),(INDIRECT("G3:G"&count(G3:G)+2)+2)^0))
The idea is to develop a 2D array where the rows are the months and the columns are the amounts for matching time periods. Then use the standard Mmult method to get the row totals of the array.
Using indirect for the ranges makes the formula longer but using full-column references would be slow as it would result in a nearly 1000 X 1000 array for a default-sized sheet.
EDIT 1
Or shorter
=ArrayFormula(mmult((text(indirect("A2:A"&count(A2:A)+1),"YYMM")>=text(TRANSPOSE(indirect("E3:E"&count(E3:E)+2)),"YYMM"))
*(text(indirect("A2:A"&count(A2:A)+1),"YYMM")<=text(transpose(indirect("F3:F"&count(F3:F)+2)),"YYMM"))
,INDIRECT("G3:G"&count(G3:G)+2)))
because you can combine the row totals step with multiplication by column G.
EDIT 2
Alternatively you could just employ a much simpler pull-down formula using SUMIFS:
=ArrayFormula(sumifs(G$3:G,eomonth(E$3:E,-1)+1,"<="&A2,F$3:F,">="&A2))
This uses Eomonth to change all the start dates to the first of the month so they can be compared to the dates in column A correctly. The formula still has to be entered as an array formula because of the Eomonth calculation.
Note
The equivalent pull-down formula to the original array formulas above would be
=ArrayFormula(sumifs(G$3:G,text(E$3:E,"YYMM"),"<="&text(A2,"YYMM"),text(F$3:F,"YYMM"),">="&text(A2,"YYMM")))
but this gives zero for all rows - the reason for this is not obvious to me at time of writing.

Google sheets Average function is not calculating correctly

I'm using Google Sheets to create a financial record.
What i'm trying to do is create a formula that takes 3 columns in my data range in to consideration. The three columns are a date, a word and a number.
The first part of the formula will check that the date is the current month (not within 30 days, but the current month). The second part will check whether the word "Yes" is present in the second column, and if those two are true, then it will take the average of column 3 for all other rows that are also completely true.
Column C is Date
Column W is Word
Column Y is Number
I've tried a number of methods, the first one was to use a average IF function, where i used a filter to check the dates, and then the word Yes in the criterion. This resulted in a number, although it was incorrect, as the formula first gathered the sequence of Yes and No's, once it had the sequence it applied it to the third column but it started from my earliest entry (not my current month). This code is below.
So alternatively i tried another method. Which was using a query function. Although i'm stuck on how to compare the month of a date to the current today() month. This gives no results, even though the current month is 8, and the dates month is also 8. I've also inputted this code below.
=AVERAGEIF(filter(W8:W800,month(C8:C800)=month(today())),"Yes",Y8:Y800)
=query(query(A8:Z800,"select month(C)+1, W, Y where W ='Yes'",0),"select Col1, Col3, Col4 where Col1 ='"&month(today())&"'",1)
results explained in background
Your nesting is a bit off. If you're using FILTER, use plain AVERAGE instead of AVERAGEIF, and make sure you're grabbing the right column to aggregate. Lastly, don't forget to wrap in IFERROR to handle your empty case.
=IFERROR(AVERAGE(FILTER(Y8:Y800, MONTH(C8:C800)=MONTH(TODAY()), W8:W800="Yes")), 0)
if you have multiple criterions you need to use AVERAGEIFS instead of AVERAGEIF
=ARRAYFORMULA(AVERAGEIFS(C2:C, B2:B, "yes", MONTH(A2:A), MONTH(TODAY())))

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