Find column with specific value, then get average of cells below - google-sheets

My Google Sheets has sheets that look something like this
Sheet1:
Date
Object 1
Object 2
Group A
Any Date
1
3
Group B
Any Date
2
4
Sheet2:
Date
Object 2
Object 5
a
b
Group C
Any Date
5
6
Now what I want is a formula for any a and b, that checks which object it belongs to, and gets all values, in the last 6 months, in the column of that object across all specified sheets, obviously without including itself.
In this case, a would be the average of 5, 3 and 4, so 4. Because 5 is in the same column as a, and 3 & 4 are in the column with object 2, which is the object a is in.
Basically because a is in the object 2 column, I want the average of all values of object 2.
In the case of b however, 6 should be the result because there is no object 5 in the other sheet (it may be in other sheets though) and therefore it takes the average of just 6.
Sheet1 does not care what is in Sheet2, there is at least one other Sheet, aside from Sheet1, that Sheet2 will get its values from.
Currently Im doing it manually, but for any change I have to check all sheets for cells that that would be affected. That would take too much time in the future though, as the amount of data will increase.
The formula for now looks like this:
=(SUMIF($D6:$D;">=" & edate(today();-6); S6:S) + SUMIF('Sheet1'!$D6:$D;">=" & edate(today();-6); 'Sheet1'!S6:S))/(COUNTIF($D6:$D;">=" & edate(today();-6)) + (COUNTIF('Sheet1'!$D6:$D;">=" & edate(today();-6))))
In my sheets column D has the Dates, and starting with Column S comes the Data. a and b are all in the first 5 rows, so they are never included.
This can probably be done with a Query or Arrayformula, but Im not good enough with those. I was at most able to recreate the edate portion of the formula.

Related

How to sum up arrays to then find the minimum

Here's my problem: I have 2 sheets in my document (lets call them Sheet 1 and Sheet 2). They contain similar stuff and both look like this (Names may differ, as well as values):
Column A, C, D and F contain times (in m:ss).
Column B and E both calculate the time-difference between NameX and NameY and add ">, < or ~ ~" depending on the actual difference (ignore the coloring).
Now here comes my problem: I want to find 3 minima (on Sheet 3).
Minimum 1 is easy, as I can just use this function (it automatically filters out column B and E):
MIN('Sheet 1'!A2:F2, 'Sheet 2'!A2:F2)
Minimum 2 and 3 are were I struggle.
Minimum 2: Using the example values, I want to find the minimum of (1:01+1:02), (1:02+1:05), (1:01+1:01) and (1:01+1:02) (+ whatever times are on sheet 2). Result should be 2:02.
Minimum 3: Again, using the example values, I want to find the minimum of (1:01+1:02+1:03), (1:02+1:05+0:30), (1:01+1:01+1:12) and (1:01+1:02+2:02) (+ whatever times are on sheet 2). Result should be 2:37.
I am currently using this formula (for minimum 3):
=MIN(
IFERROR(FILTER(IFERROR(ARRAYFORMULA({'Sheet 1'!A2:F2}+{'Sheet 1'!A3:F3}+{'Sheet 1'!A4:F4})),
IFERROR(ARRAYFORMULA({'Sheet 1'!A2:F2}+{'Sheet 1'!A3:F3}+{'Sheet 1'!A4:F4}))<>0)),
IFERROR(FILTER(IFERROR(ARRAYFORMULA({'Sheet 2'!A2:F2}+{'Sheet 2'!A3:F3}+{'Sheet 2'!A4:F4})),
IFERROR(ARRAYFORMULA({'Sheet 2'!A2:F2}+{'Sheet 2'!A3:F3}+{'Sheet 2'!A4:F4}))<>0))
)
Some notes: The inner IFERROR-function is needed to filter out errors that obviously occur when trying to add up column B and E. FILTER-function filters out columns that are empty (there's none in this example). The second IFERROR-function filters out FILTER-functions that return an error when they get no input at all (all columns in a sheet are empty). I want to filter of these since I don't want to get 0:00 as result
My problem is this: In my actual sheet I have 11 sheets with 16 rows to add up, but I don't want to use the formula above and create an insane monster of a formula that would x-times as long as the formula above.
So my question is: Is there an easier way to solve this problem for mimimum 3 (and therefore 4, 5, 6 ...) that I'm not seeing?
It's a little monstrous, but this might work:
=MIN(FILTER({
MMULT(SEQUENCE(1,ROWS(Sheet1!A2:F),1,0),N(Sheet1!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet2!A2:F),1,0),N(Sheet2!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet3!A2:F),1,0),N(Sheet3!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet4!A2:F),1,0),N(Sheet4!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet5!A2:F),1,0),N(Sheet5!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet6!A2:F),1,0),N(Sheet6!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet7!A2:F),1,0),N(Sheet7!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet8!A2:F),1,0),N(Sheet8!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet9!A2:F),1,0),N(Sheet9!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet10!A2:F),1,0),N(Sheet10!A2:F));
MMULT(SEQUENCE(1,ROWS(Sheet11!A2:F),1,0),N(Sheet11!A2:F))},
{1,0,1,1,0,1}))

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.

Formula to Test for Blanks in two Columns Against a Third Column

So I am using a conditional formatting custom formula to highlight a cell if the column it is summing from another spreadsheet has blanks, but I don't know how to do it with changing ranges. Basically what I want to do is use a third column, say column A, to determine the length of the range (of rows) I want to scan with CountBlank, and if it picks up a blank in there to return a "True".
So basically:
Column A Column B Column C Column D
Person 1 5:30AM 3:00PM 9.5
Person 2 5:00AM 8
Person 3 4:30AM 4:00PM 10.5
So ideally, the cell sums the fourth column with a different function (already have that), and it conditionally formats itself if a blank is picked up in Columns B or C, going all the way down to the last row of column A that has a value. Any help here would be appreciated, thank you.
If I understand you correctly, the custom formula for conditional formatting should be:
=or(countifs(A2:A,"<>",B2:B,""),countifs(A2:A,"<>",C2:C,""))
Suppose you had a list of people's names starting in F2 and their total hours starting in G2. Then you could alter the formula to:
=or(countifs(A$2:A,F2,B$2:B,""),countifs(A$2:A,F2,C$2:C,""))

Google Sheets value function

Hi First off I am a beginner with Google Sheets, and I am tasked with this issue.
I'd like to create a sheet (sheet 3) that can take values from sheet 2 but have a different value in sheet 3.
Here is my idea using the values in mind;
I want the "present" value from sheet 2 to equal "0" value in sheet 3
I want the "less than 10mins" value from sheet 2 to equal "+1" value in sheet 3
I want the "more than 10mins" value from sheet 2 to equal "+2" value in sheet 3
I want the "unexcused" value from sheet 2 to equal "+5" value in sheet 3
I want the "excused" value from sheet 2 to equal "0" value in sheet 3
There are multiple columns that account for single individuals.
So if person A, had the value "unexcused" in sheet 2 on 03/07/19, I want person A to have +5 added to his total from before, maybe from previous weeks his total was 2, so after the value "unexcused" was added on 03/07/19, he would now have 7 for his up to date total. I'd also like to be able to manually add or subtract a number from the data but not alter the function if possible.
I apologize if I have done a poor job of explaining, or have omitted some details, thank you for your time.
=IF(Sheet2!A1="present",0,)
=IF(Sheet2!A1="less than 10mins","+1",)
=IF(Sheet2!A1="more than 10mins","+2",)
=IF(Sheet2!A1="unexcused","+5",)
=IF(Sheet2!A1="excused",0,)

Google Sheets Query Group By / First-N-Per-Group

I'm trying to find a simple solution for first-n-per-group.
I have a table of data, first column dates and rest data. I want to group based around the date, as multiple entries per date are allowed. For the second column some numbers, but want the FIRST record.
Currently the aggregate function I could possibly use is MIN() but that will return the lowest value and not the first.
A B
01/01/2018 10
01/01/2018 15
02/01/2018 10
02/01/2018 2
02/01/2018 100
02/01/2018 20
03/01/2018 5
03/01/2018 2
Desired output
A B
01/01/2018 10
02/01/2018 10
03/01/2018 5
Current results using MIN() - undesired
A B
01/01/2018 10
02/01/2018 2
03/01/2018 2
It's a shame there isn't a FIRST() aggregate function in Google Sheets, which would make this a lot easier.
I saw a couple of examples of using the Row Number and ArrayQuery, but that doesn't seem to work for me. There are about 5000 rows of data so trying to keep this as efficient as possible, and not have to recalculate the entire sheet on any change, each taking a few seconds.
Currently I have this, which appends a third column with the Row Number:
=query({A1:B, arrayformula(row(A1:B))}, "select min(Col1),min(Col2) group by Col1")
Thanks
EDIT 1
A suggested solution was =SORTN(A:B,2^99,2,1,1), which is a clean simple one. However, this requires a large range of "free space" to display the returned dataset. Imagine 3000+ rows.
I was hoping for a QUERY() -based solution, as I wanted to do further operations with the results. Specifically, count the occurrences of distinct values.
For example: I wanted a returned dataset of
A B
01/01/2018 10
02/01/2018 10
03/01/2018 5
Yet I want to count the occurrences of those values (and then ignoring the dates). For example:
B C
10 2
5 1
Perhaps I've confused the situation by using numbers? the "data" in ColB is TEXT (short 3 letter codes), however I used numbers to show I couldn't use MIN() function as that returns the numerically lowest value.
So in brief:
Go through all rows (3000+ rows) and group by the FIRST row of a particular date
return the FIRST value of that row
COUNT() all unique occurrences of those FIRST values, disregarding the date. Just a list with the unique values and their count (again, only the first one of any particular day)
=SORTN(A:B,2^99,2,1,1)
If your data is sorted as in the sample, You can easily remove duplicates with SORTN()

Resources