I have been struggling with the Google Sheets query for several hours and maybe getting confused how to combine HLookup and VLookup (or any other function) in a way that can find the first and last occurrence of a value in a sheet based on the date header above it.
Here is an example sheet for reference which is very clear, but I will try explain verbally as well ... https://docs.google.com/spreadsheets/d/1rBVM7EtW3IREundWs_f2ftic-h4fEB97u4k4sZyIFNY/edit#gid=0
Given that I have a 2d range of cafeteria locations serving food on certain day (so the Y-axis headers of the table are cateteria locations and the X-axis headers are dates and the value is the name of the food served that day such as "Pizza") ... I want to have another table below that has a lookup for the first and last date that the food was offered. In my reference sheet I denoted that by Yellow highlight.
It seems like something that should be doable in a spreadsheet tool; unless it is impossible and I am not realizing it. Is such an operation possible?
delete range B10:C and use:
=INDEX(IFNA(VLOOKUP(A10:A, QUERY(SPLIT(FLATTEN(B1:E1&"×"&B2:E8), "×"),
"select Col2,min(Col1),max(Col1) group by Col2", ), {2,3}, 0)))
See if this helps
=query(ArrayFormula(split(flatten(text(B1:E1, "yyyy-mm-dd")&"~"&B2:E5), "~")), "Select Col2, min(Col1), max(Col1) where Col2 <> '' group by Col2 label Col2 'Food', min(Col1) 'First Offered', max(Col1) 'Last Offered' format min(Col1) 'yyyy-mm-dd', max(Col1) 'yyyy-mm-dd'", 0)
Change range to suit.
Related
I made columns that simply lists all the schools for each student under a date column header. I only need to count the schools - I don't want to see any student data. I have a form that needs to be submitted to the state and there is a cell with the date we are submitting. I want to use an IMPORTRANGE to go to the other spreadsheet and find the column where the date matches the form date and pull back the count of schools in that column. I tried using INDEX/MATCH, etc., and while I have those working on the form for other data already on my spreadsheet - I can't seem to get them to work on the 'outside' spreadsheet. Any help is appreciated! I'm attaching an example spreadsheet with more explanation. I hope it's clear. Thank you.
Example Document
ztiaa has provided a good solution. I will suggest another which pivots the data differently. I feel that having the dates go across columns is going to quickly become unwieldy. So this approach leaves the dates running down the right side with the schools running as column headers. My solution also includes exceptions such as snow days, as those will likely be important to see at a glance as well. Just be careful to use the same notation for such exceptions. For instance, always use "snowday" (not, eg., "snow day") or "prep day" (not, e.g., "prep").
In Sheet1, use IMPORTRANGE to bring in the data exactly as you have it listed in your sample sheet (i.e., dates at top, school names or exceptions under each date header).
Then, in a new sheet, place the following formula in cell A1:
=ArrayFormula({QUERY(SPLIT(FLATTEN(FILTER(Sheet1!1:1&"~"&INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!1:1<>"")),"~",1,0),"Select Col1, COUNT(Col1) WHERE Col2 Is Not Null GROUP BY Col1 PIVOT Col2 FORMAT Col1 'mmm dd'"),TRANSPOSE({"District Totals",MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!1:1<>"")="",0,1))})})
This assumes that the first sheet is, in fact, named Sheet1. If it is not, you'll need to change every instance of that sheet name in the formula.
It will probably further aid visual ease if you freeze Row 1 and Column 1 (View > Freeze > 1 row / 1 column).
ADDENDUM (after seeing realistic copy of OP's sheet)
=ArrayFormula({TRANSPOSE(QUERY(SPLIT(FLATTEN(FILTER(Sheet1!1:1&"~"&INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")),"~",1,0),"Select Col1, COUNT(Col1) WHERE Col2 Is Not Null GROUP BY Col1 PIVOT Col2 FORMAT Col1 'mmm dd'"));{"District Totals",MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")<>"",1,0))}})
If you prefer to see the name of the exception (e.g., "snowday") rather than the count of 1 for each exception in the "District totals" line:
=ArrayFormula({TRANSPOSE(QUERY(SPLIT(FLATTEN(FILTER(Sheet1!1:1&"~"&INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")),"~",1,0),"Select Col1, COUNT(Col1) WHERE Col2 Is Not Null GROUP BY Col1 PIVOT Col2 FORMAT Col1 'mmm dd'"));{"District Totals",IF(MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")<>"",1,0))=1,FILTER(Sheet1!2:2,Sheet1!2:2<>""),MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")<>"",1,0)))}})
If you want exceptions (e.g., "snowday") to always appear at the bottom instead of in alphabetical order within the school-name list:
=ArrayFormula({TRANSPOSE(QUERY(SPLIT(FLATTEN(FILTER(Sheet1!1:1&"~"&IF(REGEXMATCH(UPPER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A))),INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A))),,"‡")&INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")),"~",1,0),"Select Col1, COUNT(Col1) WHERE Col2 Is Not Null AND Col2 <> '‡' GROUP BY Col1 PIVOT Col2 FORMAT Col1 'mmm dd'"));{"District Totals",IF(MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")<>"",1,0))=1,FILTER(Sheet1!2:2,Sheet1!2:2<>""),MMULT(SEQUENCE(1,ROWS(Sheet1!A2:A),1,0),IF(FILTER(INDIRECT("Sheet1!2:"&ROWS(Sheet1!A:A)),Sheet1!2:2<>"")<>"",1,0)))}})
Try this out
=ArrayFormula({query(split(flatten(text(A1:E1,"mmm/d")&"❄️"&A2:E),"❄️"),"select Col2, count(Col2) where not Col2 matches '|Snowday' group by Col2 pivot Col1");{"District Total",transpose(MMult(transpose(N(filter(A2:E,not(RegexMatch(A2:E2,"Snowday")))<>"")),sequence(rows(A2:E))^0))}})
I'm looking for an efficient way to gather and aggregate some date in Google Sheets. I've been looking at the query function, pivot tables, and Index + Match formulas, but so far I've not found a way that brings me to the result I'm looking for. I have a set of data which looks more or less as follows.
The fields with an X represent irrelevant data which I don't want to show up in my end result. They only serve to illustrate that there are columns of data that I don't want in between the columns of data that I do want. The data in those columns is of varying types and of varying values per type, they are not actually fields with an "X" in it. Only the fields with numbers are of interest along with the related names at the top and left of those. The intent is to create a list that looks more or less like this.
I've highlighted those yellow fields because that data has been aggregated. For example, in the original file field D3 shows a relation between Laura and Pete with the number 1, and field L3 also shows a relation between Laura and Pete, so the number in that field is to be added to the number in the other field resulting in an aggregated total of 2 for that particular combination.
I would really appreciate any suggestions that can help me get to an elegant and efficient solution for this. The only solutions I can come up with would involve multiple "in-between" sheets and there just has to be a better way.
UPDATE:
Solved by applying the solution in player0's answer. I just had to switch around the order of Col1 and Col2 in the formula to get the table sorted the way I needed it. Formula looks like below now. Many thanks to both player0 and Erik Tyler for their efforts.
=INDEX(QUERY(SPLIT(FLATTEN(A2:A&"×"&D1:N1&"×"&D2:N), "×"),
"select Col2,Col1,sum(Col3)
where Col2 is not null
and Col3 is not null
group by Col2,Col1
label sum(Col3)''", ))
try:
=INDEX(QUERY(SPLIT(FLATTEN(A2:A&"×"&D1:N1&"×"&D2:N), "×"),
"where Col3 is not null and Col2 is not null", ))
update:
=INDEX(QUERY(SPLIT(FLATTEN(A2:A&"×"&D1:N1&"×"&D2:N), "×"),
"select Col1,Col2,sum(Col3)
where Col3 is not null
and Col2 is not null
group by Col1,Col2
label sum(Col3)''", ))
Given your current data set (which only appears to extend to Col N), place the following somewhere to the right of Col N:
=ArrayFormula(SPLIT(TRANSPOSE(QUERY(TRANSPOSE(QUERY(SPLIT(QUERY(FLATTEN(FILTER(IF(NOT(ISNUMBER(D2:N)),,D1:N1&"~ "&A2:A&"|"&D2:N),A2:A<>"")),"Select * WHERE Col1 Is Not Null"),"|"),"Select Col1, SUM(Col2) GROUP BY Col1 LABEL SUM(Col2) ''")&"~ "),,2)),"~ ",0,1))
It would be better if this were placed in a different sheet from the original data. Supposing that your original data sheet is named Sheet1, place the following version of the above formula into a new sheet:
=ArrayFormula(SPLIT(TRANSPOSE(QUERY(TRANSPOSE(QUERY(SPLIT(QUERY(FLATTEN(FILTER(IF(NOT(ISNUMBER(INDIRECT("Sheet1!D2:"&ROWS(Sheet1!A:A)))),,Sheet1!D1:1&"~ "&Sheet1!A2:A&"|"&INDIRECT("Sheet1!D2:"&ROWS(Sheet1!A2:A))),Sheet1!A2:A<>"")),"Select * WHERE Col1 Is Not Null"),"|"),"Select Col1, SUM(Col2) GROUP BY Col1 LABEL SUM(Col2) ''")&"~ "),,2)),"~ ",0,1))
This separate-sheet approach and formula allows for the original data to extend indefinitely past Col N.
I have some data. One of the columns (Column D) has data such as "yes", "no", 'Credit", "n/a", "half".
At the top of that column, I have created a function which allows me to get percentage of "yes" responses, but not as a percentage of all responses, but just as a percentage of the responses that are "Yes", "No" and "Half"
Formula below
=iferror((COUNTIF(C3:C, "yes") / (COUNTIF(C3:C, "no") + COUNTIF(C3:C, "half") + COUNTIF(C3:C, "yes"))))
Below that, starting at row 3, is the data.
What I want to do is put data this into a pivot table. One of my other Columns is date, and I want to be able to group the data by month (actually by week, but I have already worked that out).
I am looking for my grand total value to be summarised using the formula above, which doesn't exist as one of the standard summary options.
I am interested to hear your ideas on the best way to solve this.
Thanks
Edit: here is a link to a sheet with the basics of what I am trying to do. Thanks for your help with this.
https://docs.google.com/spreadsheets/d/1ew4pPv4qtJCZJCaUgg_I7VdL5F00t-PFhIlg2bs8sh0/edit?usp=sharing
One "extended" solution is
get all yes per month in L3
=query({arrayformula(EOMONTH(B$3:B,0)),C3:C},"select Col1, count(Col2) where Col2='yes' group by Col1 label count(Col2) 'Exercice-yes' ")
get all yen/no/half per month in N3
=query({arrayformula(EOMONTH(B$3:B,0)),C3:C},"select Col1, count(Col2) where Col2='yes' or Col2='no' or Col2='half' group by Col1 label count(Col2) 'Exercice-yes|no|half' ")
get all unique monthes in G3
=arrayformula(unique(if(B3:B="","",eomonth(B3:B,0))))
and finally find the %
=arrayformula(iferror(VLOOKUP(G3:G,L:M,2,0)/VLOOKUP(G3:G,N:O,2,0)))
I'm wondering if there is a decent way to do this (without scripts) - if not, I can attempt creating a script for it but some users of this sheet will be using Excel on their computers so I'm trying to keep it scriptless as much as possible.
I have a sheet set up to display text based on certain conditions that is meant to be copied and pasted into an external program.
There is a column for months jan-dec and a column next to that where the user can input a number from 1-10 (and those numbers are associated with strings that are found with Vlookup on another sheet. They're basically "error codes" just to keep the sheet clean. But I'm just omitting this part because it's not needed for this question)
Right now, the text that populates shows:
Jan: 1
Feb: 2
Apr: 1
How could I group these by the value instead of listing them separately? Something like:
1: Jan, Apr
2: Feb
Is it possible to grab the items from that months list and put them in their own lists?
This is the current formula for reference:
=if(countif(Calculator!B2:B13,">0"),CONCATENATE(C2:C13),"None")
(Calculator sheet)B2:B13 --> column with the numbers
(Data sheet)C2:C13 --> a concatenated string that contains the month name from one cell and the number (or technically the string associated with that number as I mentioned before)
Each cell in the C column has the Jan: 1, Feb: 2 data and any month without data is left blank. When I concatenate the C cells together, it automatically omits the blank cells which is helpful but now I'd really like to group them by that value instead.
Here is the example sheet that reflects this
delete A15 and paste this in A14:
={""; ARRAYFORMULA(TEXTJOIN(CHAR(10), 1, REGEXREPLACE(TRIM(
TRANSPOSE(QUERY(QUERY({A2:A13&",", B2:B13&":"},
"select max(Col1)
where not Col2 matches ':'
group by Col1
pivot Col2"),,9^9))), ",$", )))}
UPDATE:
if order matters...
={""; ARRAYFORMULA(TEXTJOIN(CHAR(10), 1, REGEXREPLACE(TRIM(
TRANSPOSE(QUERY(QUERY({"♦"&ROW(A2:A13)&"♦"&A2:A13&",", B2:B13&":"},
"select max(Col1)
where not Col2 matches ':'
group by Col1
pivot Col2"),,9^9))), "♦\d+♦|,$", )))}
UPDATE:
={""; ARRAYFORMULA(JOIN(CHAR(10), SUBSTITUTE(REGEXREPLACE(TRIM(QUERY(QUERY({
SORT(FILTER({SUBSTITUTE(A1:A12, "'", "/"&20)*1, B1:B12&":"}, B1:B12<>""), 2, 1, 1, 1)},
"select max(Col1)
group by Col1
pivot Col2
format max(Col1) 'Mmm♦yy,'"),,99^99)), ",$", ), "♦", CHAR(39))))}
I have a sheet with
Date|Amount Date|Amount Date|Amount ...
columns and from that I would like to get Month-Year:Total amount if it can be done with some Google spreadsheet functions/script.
I already have tried with many functions including ArrayFormula, Query, Text, etc. But They might require a range of data while I have broken range and didn't find any functions helpful.
This is how I would like to have:
Can it be done?
=ARRAYFORMULA(QUERY({TEXT({A:A;C:C;E:E;G:G}, "mmm - yyyy"), {B:B;D:D;F:F;H:H}},
"select Col1,sum(Col2) where Col2 is not null group by Col1 label sum(Col2)''", 0))