I've several straight-forward planners, like this:
| date | person | person 2 | description |
2013-03-01 peter pam painting
2013-03-18 john carl cleaning
2013-03-20 max anne washing
On a different sheet, I want to filter the 'events' for the next 2 weeks only. How can I achieve this? I tried several ways, but none of them are working.
With =ARRAYFORMULA(DAYS360(B2:B;NOW())) I can get a daynumber in a different column. 0 = today, 1 = yesterday, -1 tomorrow et cetera. In fact, I need to filter the days -1 to -14. Sometimes there are only 2 events, sometimes 5 in 2 weeks.
Edit: Some things I found
First, I filter the correct daynumbers with =filter(A2:A50;A2:A50>-14;A2:A50<0)
Then, I do a vlookup =vlookup(G32,A1:E49;5;false)
(where G32 is the filtercommand, A2:A50 the daynumbers, A1:E49 all the data)
This is a good opportunity for the QUERY command and Query Language.
I'm assuming your data is in 4 columns, A:D, in "sheet 1".
=query('sheet 1'!A:D,"select * where datediff( A, now()) < 14 and datediff( A, now()) > 0")
Related
Master Data
Group-Value pairs
1 | 1
1 | 2
1 | 3
2 | 5
2 | 8
3 | 10
3 | 12
Work Data
Group-Value pairs + desired result
1 | 4 | 3 (3≤4, max in group 1)
1 | 2 | 2 (2≤2, max in group 1)
2 | 6 | 5 (5≤6, max in group 2)
3 | 7 | no result (both 10 and 12 > than 7)
The task is to find the maximum possible matched number from a group, the number should be less or equal to the given number.
For Group 1, value 4:
=> filter Master Data (1,2,3) => find 3
Will have no problem with doing it once, need to do it with arrayformula.
My attempts to solve it were using modifications of the vlookup formula, with wrong outputs so far.
Samples and my working "arena":
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit?usp=sharing
Notes: no need to solve it in a single formula, because it may slow down the result.
I used
=ArrayFormula(VLOOKUP(D4:D8&text(E4:E8,"0000"),A4:A10&text(B4:B10,"0000"),1,true))
starting in J4
then
=ArrayFormula(if(--left(J4:J8)=D4:D8,--right(J4:J8,4),""))
starting in K4.
Needs further refinement but doesn't make any assumptions about max of previous group.
EDIT
So after further work it would look like this
=ArrayFormula(if(D4:D="",,
if(D4:D=
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),A4:A},A4:A<>""),2,true),
vlookup(D4:D&text(E4:E,"0000"),filter({A4:A&text(B4:B,"0000"),B4:B},A4:A<>""),2,true),"")))
A lot like #player0's solution in fact.
I guess you could make it a bit more general by doing something like
=text(B4,rept("0",ceiling(log10(max(B4:B)))))
assuming these are positive integers.
Alternative method
I think this is a better way. Find the start row of each group and how many rows r less than or equal to the required group/value pair are in that group. Then just go forward r-1 rows from the first line of the group to find the matching value:
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{A4:A,row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),B4:B},2,false),))
Assuming of course that the Master data is sorted by group and value - otherwise you would have to use sort():
=ArrayFormula(if(countifs(A4:A,D4:D,B4:B,"<="&E4:E)>0,
vlookup(
vlookup(D4:D,{sort(A4:A,A4:A,1,B4:B,1),row(A4:A)},2,false)+countifs(A4:A,D4:D,B4:B,"<="&E4:E)-1,{row(A4:A),SORT(B4:B,A4:A,1,B4:B,1)},2,false),))
My solution was based on the technique of finding the maximum number by a row. The sample formula is here:
https://docs.google.com/spreadsheets/d/1VY157ykKsCVDqEKDBp3oAVaG0LTXAz8wUCggCrFXMDM/edit#gid=628408999
My whole solution is here:
https://docs.google.com/spreadsheets/d/11Cd2BGpGN-0h2bL0LQ_EpIDBKKT2hvTVHoxGC6i8uTE/edit#gid=0
Step 1
Get joined numbers by groups from a Master Table.
1 | 3,2,1
2 | 8,5
3 | 12,10
Used offset to achieve this ↑. And used vlookup to match this semi-result with work table.
Step 2
Used if + split to check if the resulted value was ≤ than my work value, and in the same formula used query to find the maximum by each row.
compose a query: used join + sequence
=IF(M3=0,,"select "&JOIN(", ",INDEX("max(Col"&SEQUENCE(M3)&")")))
result:
select max(Col1), max(Col2), max(Col3), max(Col4), max(Col5)
Found the maximum by each group:
=index(TRANSPOSE(QUERY(TRANSPOSE(data), "select ...")))
This final formula was the 🔑 to solving the problem.
Note: the result: 0 of my formula means "no matches". This is fine for me.
try:
=INDEX(IFNA(IF(E4:E>=
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2),
VLOOKUP(D4:D&TEXT(E4:E, "00000"), {A4:A&TEXT(FILTER(B4:B, B4:B<>""), "00000"), B4:B}, 2), 0)))
I have been able to use Google Sheet's SEQUENCE formula to provide me with sequenced dates for Partner 1 but then the formula stops and doesn't move on to Partner 2.
I have tried nesting within an Google's ArrayFormula but still cannot get it to function properly.
I'd like to avoid having to do each partner manually then copying and pasting each partner below the other.
Formulas I've tried:
For creating partner repeats based on number of days
=ARRAYFORMULA(TRIM(TRANSPOSE(SPLIT(QUERY( REPT($L$3:$L$16&",",$Q$3:$Q$16),,2^100),","))))
For sequencing dates, but only does the first range
=ARRAYFORMULA(TO_DATE(SEQUENCE(Q3,1,O3)))
CURRENT DATA
| Partner| Start Date| End Date | Total Days|
|:-------|:---------:|:--------:|----------:|
|Partner1| 3/1/2021 | 3/8/2021| 7 |
|Partner2| 3/1/2021 | 3/9/2021| 8 |
WANTED FORMAT
Partner Date
Partner 1 3/1/2021
Partner 1 3/2/2021
Partner 1 3/3/2021
Partner 1 3/4/2021
Partner 1 3/5/2021
Partner 1 3/6/2021
Partner 1 3/7/2021
Partner 1 3/8/2021
Partner 2 3/1/2021
Partner 2 3/2/2021
Partner 2 3/3/2021
Partner 2 3/4/2021
Partner 2 3/5/2021
Partner 2 3/6/2021
Partner 2 3/7/2021
Partner 2 3/8/2021
Partner 2 3/9/2021
You can do it generally by doing a vlookup of sequence number in the cumulative sum of the days.
For partner:
=ArrayFormula(vlookup(sequence(sum(D2:D),1,0),{sumif(row(D2:D),"<"&row(D2:D),D2:D),A2:A},2,true))
For date:
=ArrayFormula(to_date(sequence(sum(D2:D),1,0)
-vlookup(sequence(sum(D2:D),1,0),sumif(row(D2:D),"<"&row(D2:D),D2:D),1,true)
+vlookup(sequence(sum(D2:D),1,0),{sumif(row(D2:D),"<"&row(D2:D),D2:D),B2:B},2,true)))
You can use the following formula
=INDEX({SPLIT(A2&"#"&SEQUENCE(C2-B2,1,B2),"#");
SPLIT(A3&"#"&SEQUENCE(C3-B3,1,B3),"#");
SPLIT(A4&"#"&SEQUENCE(C4-B4,1,B4),"#")})
If still having issues, please share more info.
(do adjust ranges and locale syntax to meet your needs)
So I have a Spreadsheet with Game Statistics and I wanna display a pie chart with win percentages in general and per game.
I've created my main data table like so
Date | Game | Player 1 | Player 2
---------|--------|----------|----------
01.01.17 | Game 1 | 1 | 0
02.01.17 | Game 2 | 0 | 1
03.01.17 | Game 2 | 0.5 | 0.5
Now calculating the sum of wins per player is easy. But generating it per game is not that straight forward.
Right now I have a second table where the calculations are happening with a Table which looks like this:
Game | Player 1 | Player 2
-------|----------|----------
Game 1 | 1 | 0
Game 2 | 0.5 | 1.5
I'm using an UNIQUE for the list of games and a DSUM for each cell.
This has two problems.
I need to copy the DSUM Statement each time a new Game is added (the Sheet is only for two players so I don't need to cover the case when a new Player is added)
When there are two different games which share a part of the name (like "Phase 10" and "Phase 10 Brettspiel" the wins of the second game do count to the wins of the first game
My Statement looks like this
DSUM(Data!B1:D100, E1, {"Game";D2})
where Data contains the first table, Game is the column with the unique games and E1 contains the player name.
The first Problem is actually not that severe but I would like to fix the second Problem. I'm not really experienced with Google Sheets which is why I wanna solve this in pure Sheets commands and not with a custom script.
Any help would be appreciated.
Instead of unique and dsum, I suggest using query which can do both things at once. It eliminates the need to copy-paste any formulas, as a single query performs all the calculations. For example, if your data is in A:D, the query could be
=query(B:D, "select B, sum(C), sum(D) where B <> '' group by B order by B asc", 1)
which means:
add up the contents of C and D for each distinct entry in B
ignore the rows where B is empty
sort the results by B alphabetically
the range B:D has 1 header row (specified by the last argument, so it's not mistaken for data)
If other headers for the result are preferred, use "label" as follows:
=query(B:D, "select B, sum(C), sum(D) where B <> '' group by B order by B asc label sum(C) 'Player 1', sum(D) 'Player 2'", 1)
I've got a Google Sheet which holds the results of a monthly competition. The format is
Name | Date | Score
--------------------------------
Alan Smith | 14/01/2016 | 500
Bob Dow | 14/01/2016 | 450
Bob Dow | 16/01/2016 | 470
Clare Allie| 16/01/2016 | 550
Declan Ham | 16/01/2016 | 350
Alan Smith | 10/02/2016 | 490
Bob Dow | 10/02/2016 | 425
Declan Ham | 12/02/2016 | 400
Declan Ham | 12/02/2016 | 390
Clare Allie| 12/02/2016 | 560
I want to do 2 things with this data
I want to create a new sheet which holds the latest 'best' results. For the data presented here that would be
Alan Smith | 10/02/2016 | 490
Bob Dow | 10/02/2016 | 425
Declan Ham | 12/02/2016 | 400
Clare Allie| 12/02/2016 | 560
i.e. The results from February with the 'best' score per person. Here Declan Ham's lower score of '390' was removed.
I want another sheet to hold the tournament ranking. People are ranked by their top 3 monthly scores. i.e. The best score for each person for each month is obtained and the top 3 scores are combined to give their place in the tournament.
So far I've attempted to use Google queries, vlookups, filters to get these new sheets. But, just focusing on 1), the best I've been able to achieve is
=FILTER(Results!$A:$B, MONTH(Results!$B:$B) = MONTH(MAX(Results!$B:$B)))
Which will get me the results from the latest month. But it does not remove duplicates entries by people.
Does anyone have a suggestion for how I can achieve these requirements? Feel like I'm treading water at the moment.
Rather than trying to remove duplicates, you need to identify the maximum score by each person; you can do that by grouping values by person, then aggregating using max(). Here's how that would look, for the month of February 2016:
=query(Results!A1:C,"select A,max(C) where todate(B) > date '2016-2-1' group by A")
Instead of using a fixed value for the start of the latest month, we can get the year and month using spreadsheet formulas, and concatenate our query with them:
=query(Results!A1:C,"select A,max(C) where todate(B) > date '"&year(max(Results!B2:B))&"-"&month(max(Results!B2:B))&"-1' group by A")
That addresses your first question.
Tournament ranking
Your second goal is too complex for a single spreadsheet formula, in my opinion. Here's a way to accomplish it with multiple formulas, though!
The X & Y axes are filled out by spreadsheet formulas. On the X axis (orange), we populate participants names using this in cell A3:
=unique(Results!A2:A)
The Y axis consists of dates (green). These are the start dates of each unique month that there are scores for, calculated using the following formula in cell D2. This results in strings, e.g. 2016-01-1, and that format is specifically required for the later formulas to work.
=TRANSPOSE(SORT(UNIQUE(ARRAYFORMULA(TEXT(Results!B2:B13,"YYYY-MM-1")))))
Here's the formula for cell D3, which will calculate the sum of the 3 highest scores recorded for the user whose name appears in A3, for the month appearing in D2. (Copy & Paste the formula across the full range of participants & months, and it will adjust.)
=sum(query(Results!$A$1:$C,"select C where A='"&$A2&"' and todate(B) >= date '"&B$1&"' and todate(B) < date '"&IF(ISBLANK(C$1),TEXT(TODAY()+1,"yyyy-mm-dd"),C$1)&"' order by C desc limit 3 label C ''"))
Key points about that formula:
The query range needs to used fixed values so it isn't transposed when copied to additional cells. However, it's still open-ended, to absorb additional rows of scores on the "Results" sheet.
Results!$A$1:$C
A WHERE clause is used to select rows from the Results sheet that are for the given participant (A='"&$A2&"') and fall within the month that heads the column (C$1).
...and todate(B) < date '"&IF(ISBLANK(C$1),TEXT(TODAY()+1,"yyyy-mm-dd"),C$1)&"'
The best 3 scores for the month are found by first sorting the above result descending, then limiting the result to 3 rows.
...order by C desc limit 3
Finally, the QUERY headers are suppressed by this little trick, so that we get a single number as the result:
...label C ''
Individual tournament totals appear in column C, with a range SUM across the row, e.g. for cell C3:
SUM(D3:3)
The corresponding ranking in column B is then:
RANK(C3,C$3:C)
Tidy
For simpler copy/paste, you can do some error checking in these formulas, so that they can be placed in the sheet before the corresponding data is - for example, at the start of your season. Using IF(ISBLANK(... or IFERROR(... can be very effective for this.
B3 & down:
=IFERROR(RANK(C3,C$3:C))
C3 & down:
=IF(ISBLANK(A3),"",sum(D3:3))
D3 & rest of field:
=IFERROR(sum(query(Results!$A$1:$C,"select C where A='"&$A3&"' and todate(B) >= date '"&D$2&"' and todate(B) < date '"&IF(ISBLANK(E$2),TEXT(TODAY()+1,"yyyy-mm-dd"),E$2)&"' order by C desc limit 3 label C ''")))
Alternatively for the first part of your question (the latest 'best' results) , in addition to the solution provided by Mogsdad, this should also work.. :-)
=ArrayFormula(iferror(vlookup(unique(A2:A), sort(A2:C, 2, 0, 3, 0), {1,3}, 0)))
EDIT: This formula sorts the table with dates (col B) descending and col C descending and then (ab)uses the fact that vlookup only returns the first match to return the first and last column.
I'm having kind of a problem to make this question since I don't know if the terms that I'm using are correct, so bear in mind that maybe they aren't, so "array" and "position" maybe aren't what I mean. I worked a lot on the explanation, trying to make as simple as possible, I really hope it's helpful.
I have a Google Spreadsheet with twenty three sheets. All of them are related to a specific season of the Barclays Premier League and one is for calculation purposes.
I'm calculating now how high in the attacking ranks, a team that had the 10th best defense was. It looks like this:
1 A | B | C | D |
2 Season | 10th Defense (Goals Conceded) | Finished Position | Attack Position |
3 1992-93 | 55 | 5 | ? |
My problem is that unlike B3, where I get the quantity of the goals conceded, in D3 I don't want the same thing. What I'm trying to do is it to get the "array" of goals by each team in '1992-93'!G1:G23 and it to tell me where their attack finished (1st, 2nd, etc). So it needs to get the position of the team in C3 to know which attack belonged to the team and them look on '1992-93'!G1:G23 to know the position of the attack.
You want RANK and INDEX.
RANK(INDEX('1992-93'!G1:G23,C3),'1992-93'!G1:G23)