Google sheets Average function is not calculating correctly - google-sheets

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())))

Related

Google sheets: Is there a way to quickly/easily add a date range to ~300 cells each with different countifs formulas?

I am using the countifs function to add up a lot of different conditions - I need help to simplify the process so that it doesn't require so much manual formatting every time.
Here is a screenshot of a hypothetical spreadsheet. Here is a hypothetical scenario that will help convey my question. Let's say I am working with 3 clients, Macy's, abercrombie, and gap, to fill several open positions. We are reviewing multiple candidates. When I have reviewed them and approved, I select "yes" in the verdict column (E). When they have been processed, I selected yes in the F column. If I do not approve them, I select No in the column. So on and so forth.
So now I'd like to keep track of how many candidates I've approved and processed for each client for each open position. Here is my spreadsheet for that. I have used the countifs function from the previous spreadsheet, called "Review Document" as follows:
Column C, Row 2 - counting sales associate for abercrombie who have been approved and not yet processed:
=COUNTIFS(
'Review Document'!$B:$B,"abercrombie",
'Review Document'!$C:$C, "sales associate",
'Review Document'!$E:$E,"yes",
'Review Document'!$F:$F,"no")
I essentially do this for every single client, for every single role, for both column C and D. Imagine that there are ~300 rows with different companies and roles - The formula text changes every time to count if "position" and "company".
What I would like to do is now find an easy way to automatically apply a date range to all of these cells, without having to manually add a date criterion for every single formula. For example, in the first spreadsheet, there are dates in Feb, Mar, And April. Is there a way to apply a date range on my second spreadsheet so that it only counts the dates I specify? E.G. - apply some date range to ALL cells in that sheet so that it only counts if the date is 2/15/2022-3/31-2022? I would ultimately like to be able to change the date range quickly without having to manually add a date criterion to 300 cells, and then change it every time I want to see the numbers for a different date range. I was tinkering with conditional formatting but I haven't figured it out.
Thanks!
use:
=INDEX(QUERY(QUERY({A2:A, PROPER(B2:C),
IF((E2:E="yes")*(F2:F<>"yes"), 1, 0),
IF((E2:E="yes")*(F2:F= "yes"), 1, 0)},
"select Col2,Col3,sum(Col4),sum(Col5)
where Col1 is not null "&
IF(J1="",," and Col1 >= date '"&TEXT(J1, "yyyy-mm-dd")&"'")&
IF(J2="",," and Col1 <= date '"&TEXT(J2, "yyyy-mm-dd")&"'")&"
group by Col2,Col3"),
"offset 1", ))

Google Sheets - IF Statement Formula

I need to write a formula that enters 'Y' if the patient is up to date with their immunizations based on their record and age, and 'N' if they are not. Age (D$) is in months and I have a column for every immunization (8 weeks(E$), 12 weeks(F$), 16 weeks(G$), 1 year(H$), 3 years and 4 months(I$)) which is marked as either ("Y" or colored Grey) as well as a final column which the formula is being entered into(J$). Any ideas what formula I need to use?
So far I have been thinking to use an IFS statement { =IFS(D$>=2, AND(E$="Y"),"Y")}. Although I can see the limitations to using this.
For every immunization, the patient is not up to date if the corresponding cell is blank and their age is older than the immunization date. You want to check this for multiple immunizations. You can use COUNTIFS to evaluate two (or more) conditions.
=IF(COUNTIFS(E3:I3,"",E$1:I$1,"<="&D3)>0,"N","Y")
Explanation:
COUNTIFS returns the number of shots for which the patient is not up to date.
IF returns N if the previous value is greater than 0, Y otherwise.
Note that I'm assuming the information on the number of months corresponding to each immunization (E$1:I$1 in the formula above) is present somewhere in the sheet or that you can add it. If this is not the case, you would indeed need to use IFS or something similar.

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.

When using SUMIF function, is there a way to accept timestamp values (e.g. 2/12/2019 19:56:16) as the range to test against the criteria?

I'm working with two columns,
column A: a list of timestamps
column B: a list of numbers
I'm trying to use the sumif(range, criteria, [sum range]) function to check if the month in column A is January, and so on for all months.
The issue is that I need a way to either convert the range for the sumif to month names, or use criteria other than a string (because a timestamp isn't going to ever be "=January".
My thought was that I could do either
=sumif(TEXT(TO_DATE(A2:A),"mmmm"), "=January", B2:B)
or
=sumif(A2:A, TEXT(TO_DATE(A2:A),"mmmm")="January", B2:B)
these are more or less pseudo-code, I'm trying to convey my thought process
I understand I could create a new column that converts the timestamps into months, but is there anyway I can preform this sumif, without having to make a new column?
Using SUMIFS, with dates you set the extents, this works in excel and google sheets:
=SUMIFS(B:B,A:A,">=" & DATE(2019,1,1),A:A,"<" & DATE(2019,2,1))
With Google Sheets you can also use filter:
=SUM(FILTER(B:B,MONTH(A:A)=1))
"=2" = February, "=3" = March, etc.
=ARRAYFORMULA(SUMIF(MONTH(A2:A), "=2", B2:B))
if you want to select it from a drop-down menu use:
=ARRAYFORMULA(SUMIF(MONTH(A2:A), "="&MONTH(F2&1), B2:B))

Reference Specific Row in Named Range within another Named Range

I'm writing a spreadsheet to keep track of a small business' financials. They operate a few Rooms for rent, and the structure of the document is made so that each sheet holds a year's worth of booking for all the rooms.
Essentially, each row is defines a specific date, while each rooms spans a few columns (reason is that they don't just want to track whether or not a room is booked, but also record names of clients & other remarks), among which the daily calculated income (some factors alter the daily rate each room will generate).
So this is all fine and dandy, and I've created named ranges for each month of the year, and for each room.
For example, rows 6:36 will represent the month of January, while columns C:I will represent Room 1. Room 2 will span J:P and so forth.
Now, in another sheet, I wanted to make a dashboard which lists the earning for each room, per month. It's a very simple table with 12 rows (one for each month) and 10 columns (1 for each room) where I planned to sum up all the earnings.
So my issue is that I can't find a way to retrieve a specific column of a named range for a room ('vertical named range'), which is also limited in a named range for a month ('horizontal named range'). I had read about using ARRAYFORMULA(INDEX(named_range, ,wished_column)) but that only works for a single named range. My knowledge of these two functions being non-existent, I didn't manage to extend it to a 2-named-range version...
(I mean I did try something along the lines of ARRAYFORMULA(INDEX(January, , INDEX(Room1, , 3))) but that didn't work)
So because there isn't a one-to-one relation from the Dashboard cells to the Rooms cells, my current only solution is to manually reference everything, which you'll understand is inefficient and time-consuming...
My question, in fine, is: How can I retrieve a range that results of the intersection of 2 (or more) named ranges ? Once I have that resulting range, I know it will be very easy to use INDEX().
Define a named range Base as
A:Z
Define a range named Horizontal as
6:36
Define a range named Vertical as
C:I
Then the intersection of the vertical and horizontal ranges is given by:
index(Base,row(Horizontal),COLUMN(Vertical)):index(Base,row(Horizontal)+rows(Horizontal)-1,COLUMN(Vertical)+columns(Vertical)-1)
This can be verified by using it in a function e.g.
=countblank(index(Base,row(Horizontal),COLUMN(Vertical)):index(Base,row(Horizontal)+rows(Horizontal)-1,COLUMN(Vertical)+columns(Vertical)-1))
gives the result 7 * 31 = 217 in my sheet because I haven't filled in any of the cells.
The Offset version of this would be:
=countblank(offset(A1,row(Horizontal)-1,COLUMN(Vertical)-1):offset(A1,row(Horizontal)+rows(Horizontal)-2,COLUMN(Vertical)+columns(Vertical)-2))
or more simply:
=countblank(offset(A1,row(Horizontal)-1,COLUMN(Vertical)-1,rows(Horizontal),COLUMNS(Vertical)))
So this works well in OP's case where you have two fully overlapping ranges like this:
Partial Overlap
Suppose you have two partially overlapping ranges like this:
You can use a variation on the standard overlap formula (This is one of the early references to it as used with a date range)
max(start1,start2) to min(end1,end2)
So the previous formula becomes
=countblank(index(Base,max(row(index(Partial1,1,1)),row(index(Partial2,1,1))),max(COLUMN(index(Partial1,1,1)),column(index(Partial2,1,1)))):
index(Base,min(row(index(Partial1,1,1))+rows(Partial1)-1,row(index(Partial2,1,1))+rows(Partial2)-1),min(COLUMN(index(Partial1,1,1))+columns(Partial1)-1,column(index(Partial2,1,1))+columns(Partial2)-1)))
and the offset version is
=countblank(offset(A1,max(row(offset(Partial1,0,0)),row(offset(Partial2,0,0)))-1,max(COLUMN(offset(Partial1,0,0)),column(offset(Partial2,0,0)))-1):
offset(A1,min(row(offset(Partial1,0,0))+rows(Partial1)-2,row(offset(Partial2,0,0))+rows(Partial2)-2),min(COLUMN(offset(Partial1,0,0))+columns(Partial1)-2,column(offset(Partial2,0,0))+columns(Partial2)-2)))
I have tested this on ranges C2:F10 and D3:G11 which gives the result 24 as expected.
However, if there is no overlap, this can still give a non-zero result, so a suitable test needs adding to the formula:
=if(and(max(row(index(Partial1,1,1)),row(index(Partial2,1,1)))<=min(row(index(Partial1,1,1))+rows(Partial1)-1,row(index(Partial2,1,1))+rows(Partial2)-1),
max(column(index(Partial1,1,1)),column(index(Partial2,1,1)))<=min(column(index(Partial1,1,1))+columns(Partial1)-1,column(index(Partial2,1,1))+columns(Partial2)-1)),"Overlap","No overlap")
Perhaps the best approach in Google Sheets is to go back to the full version of the Offset call OFFSET(cell_reference, offset_rows, offset_columns, [height], [width]) . Although this is rather long, it will return a #Value! error if there is no overlap:
=Countblank(offset(A1,
max(row(offset(Partial1,0,0)),row(offset(Partial2,0,0)))-1,
max(COLUMN(offset(Partial1,0,0)),column(offset(Partial2,0,0)))-1,
min(row(offset(Partial1,0,0))+rows(Partial1),row(offset(Partial2,0,0))+rows(Partial2))-max(row(offset(Partial1,0,0)),row(offset(Partial2,0,0))),
min(COLUMN(offset(Partial1,0,0))+columns(Partial1),column(offset(Partial2,0,0))+columns(Partial2))-max(COLUMN(offset(Partial1,0,0)),column(offset(Partial2,0,0)))
))
Notes
Why did I have to introduce some more indexes (indices?) in the second formula to make it work? Because if you use the row function with a range in an array context, you get an array of row numbers which isn't what I want. As it happens, in the first formula you are not using it in an array context, so you just get the first row and column of the given range which is fine. In the second formula, Max and Min try to evaluate all the rows in the array, which gives the wrong answer, so I have used Index(range,1,1) to force it to look only at the top left hand corner of each range. The other thing is that both index and offset return a reference, so it is valid to use the construct Index(...):Index(...) or Offset(...):Offset(...) to define a new range.
I have also tested the above in Excel (where as mentioned the Index version would be preferable). In this case Base would be set to $1:$1048576.
Although in Excel you have the Intersect Operator (single space) so it's not necessary to use an Index or Offset formula at all e.g. the first example above would simply be:
=COUNTBLANK(Vertical Horizontal)
and if there is no overlap the formula returns a #NULL! error.
"I've created named ranges for each month of the year, and for each
room. For example, rows 6:36 will represent the month of January,
while columns C:I will represent Room 1. Room 2 will span J:P and so
forth."
What I suggest is that if "January" is defined for columns C to whatever (the last column of the last room), then that's all you need.
You haven't shown us the layout of the dashboard. But let's assume that at the very least you're interested in the income generated by each room.
=query({January},"select sum(Col3) label sum(Col3)'' ")
In this image, the range called "January" is highlighted. Note that it does NOT include the header. Note also that it can be many columns wide; in this example, I've just made up a few columns, but your range should cover all the columns for rooms 1 to n.
Syntax: QUERY(data, query, [headers])
Data: This formula queries the range called "January". That range can be on the same sheet, on on another sheet (such as your Dashboard). Reminder: in this screenshot, "my version of "January" is highlighted.
Query to count Number of People: "select sum(Col3) label sum(Col3)'' "
Query to sum the income earned: "select count(Col2) label count(Col2)'' "
Col2 & Col4 = Number of People for Room#1 and Room#2 respectively.
Col3 & Col5 = Income for Room#1 and Room#2 respectively.
[headers]: You can ignore them.
This formula delivers just the value of the query; even though it includes a "label", the label will not print.
Modify and adapt these formulae to create the other information required for your Dashboard.

Resources