Google Sheets - transpose column data in groups into rows - google-sheets

I am trying to transpose data from column A to single rows. The original data has 3 rows for each name. But there could be either 1 or several jobs for each day. Each day needs to be treated separately, but this maybe best handled by manually adding at the beginning of each day.
This is for a fortnightly timesheet, therefore the number of rows in unpredictable.
The 1st image is my original data. the 2nd is the desired end result.
The data is to transposed to any blank rows in columns b, c, d, e,
as long as there are no blank rows, I can then reference them with my formulas.
to place the information into the appropriate cells within
the timesheet. I already have working formulas to do this.
the transpose section is what I need help with
Here is a link to my file
https://docs.google.com/spreadsheets/d/1PhuFXDB2H1c9ua6szjhJEgJR91yXHhZAmn_2UGOBvIo/edit?usp=sharing

try:
=ARRAYFORMULA({QUERY(IF(REGEXMATCH(A12:A, "\d+:\d+.*"), VLOOKUP(ROW(A12:A),
IF(IF(IFERROR(RIGHT(A12:A, 4)*1)>2000, A12:A, )<>"", {ROW(A12:A),
IF(IFERROR(RIGHT(A12:A, 4)*1)>2000, A12:A, )}), 2, 1), ), "where Col1 is not null"),
QUERY(IF((IFERROR(RIGHT(A12:A, 4)*1)>2000)+(REGEXMATCH(A12:A, "\d+:\d+.*")),, A12:A),
"where Col1 is not null skipping 2"),
QUERY(QUERY(IF((IFERROR(RIGHT(A12:A, 4)*1)>2000)+(REGEXMATCH(A12:A, "\d+:\d+.*")),, A12:A),
"where Col1 is not null offset 1", 0), "skipping 2"),
FILTER(A12:A, REGEXMATCH(A12:A, "\d+:\d+.*"))})

If you want a solution with a formula in one cell only, try:
=arrayformula({"date","name","job type","start - end time";query(split(flatten(query(iferror(datevalue(A12:A),),"where Col1 is not null",0)&split(flatten(split(textjoin(char(9999),1,if(regexmatch(to_text(A12:A),":+.*-+"),A12:A&char(9998),if(iferror(datevalue(A12:A),)<>"",char(10001),A12:A))),char(10001))),char(9998))),char(9999)),"where Col2 is not null",0)})

in put B12 :
=IFERROR(if(FIND("2021",A12)>=1,0,""),B11+1)
in put C12 :
=if(B12=0,A12,C11)
in D12 :
=if(mod(B12,3)=1,TRANSPOSE(A12:A14),"")
and drag downwards. Then in F12 put :
=FILTER(C:F,F:F<>"")
and drag downwards.
Idea : use transpose() with a conditional counter. use (F12)filter to remove blank.
Please if it works/understandable/not.

Related

Dynamically offset data of multiple rows to match the header column in Google Sheets

I'm trying to dynamically offset data of multiple rows to match the header column in Google Sheets. The first tab contains data of multiple fruits and how many are harvested on a particular day. Each fruit starts harvesting on different dates, and the dates might not be continuous.
The second tab, "Fruit bank", shows how many fruits are harvested in total for each day. Column D is a continuous set of dates. In cell E1, a QUERY formula dynamically pulls the names of the fruits so whenever a new fruit is added, it shows up here as well. In cell E2 and the rest of the row, I use VLOOKUP formulas to pull the data from the first tab. What I need help with is to write a formula on cell E2 that expands to the rest of the row so I don't have to manually type in the lookup range every time a new fruit is added.
Also, I suspect there're better functions to use than the VLOOKUP because the way VLOOKUP pulls data is very slow. I could literally see it loading even with this small dataset.
Yellow cells contain formula.
I appreciate anyone who can take a look at my spreadsheet (linked below) and see what's the best solution for this. The 3rd tab is editable.
https://docs.google.com/spreadsheets/d/14GeJKgxadInNWVVyft2gilae7HOIEvKXRop-Kz_On-Q/edit#gid=53523977
Thanks! J
Use filter(), like this:
=arrayformula(
ifna(
vlookup(
$D2:$D,
{
filter(
'Fruits data'!$B2:$AA,
'Fruits data'!$A1:$Z1 = E1
),
filter(
'Fruits data'!$A2:$Z,
'Fruits data'!$A1:$Z1 = E1
)
},
2, false
)
)
)
See your sample spreadsheet.
you can try either. added solutions here and here
=BYROW(D2:D,LAMBDA(dx,IF(dx="",,BYCOL(E1:1,LAMBDA(ex,IF(ex="",,XLOOKUP(dx,FILTER('Fruits data'!1:46,COLUMN('Fruits data'!1:1)=MATCH(ex,'Fruits data'!1:1,0)-1),FILTER('Fruits data'!1:46,'Fruits data'!1:1=ex),)))))))
OR
=MAKEARRAY(COUNTA(D2:D),COUNTA(E1:1),LAMBDA(r,c,XLOOKUP(INDEX(D2:D,r),FILTER('Fruits data'!1:46,COLUMN('Fruits data'!1:1)=MATCH(INDEX(E1:1,,c),'Fruits data'!1:1,0)-1),FILTER('Fruits data'!1:46,'Fruits data'!1:1=INDEX(E1:1,,c)),)))
try this with dates:
=ARRAYFORMULA(QUERY({
FLATTEN(FILTER('Fruits data'!A2:100, ISODD(COLUMN('Fruits data'!A2:2)))),
FLATTEN(FILTER('Fruits data'!A2:100, ISEVEN(COLUMN('Fruits data'!A2:2)))),
FLATTEN(IF(FILTER('Fruits data'!A2:100, ISEVEN(COLUMN('Fruits data'!A2:2)))="",,
FILTER('Fruits data'!A1:1, ISEVEN(COLUMN('Fruits data'!A2:2)))))},
"select Col1,sum(Col2) where Col2 is not null group by Col1 pivot Col3"))
which could be simplified:
=ARRAYFORMULA(LAMBDA(x, QUERY({
FLATTEN(FILTER(x, ISODD(COLUMN(X)))),
FLATTEN(FILTER(x, ISEVEN(COLUMN(x)))),
FLATTEN(IF(FILTER(x, ISEVEN(COLUMN(x)))="",,
FILTER(OFFSET(x, -1,,1), ISEVEN(COLUMN(x)))))},
"select Col1,sum(Col2) where Col2 is not null group by Col1
pivot Col3 label Col1'Date'"))('Fruits data'!A2:100))

How can I separate a column into multiple columns based on values?

I have searched on a lot of pages but I cannot find a solution to my problem except in reverse order. I have simplified what I do, but I have a query that comes looking for information in my data sheet. Here there are 3 columns, the date, the amount and the source.
I would like, with a query function, to be able to make different columns which counts the information of column C based on the values of its cells per month, like this
I'm okay with the start of the formula
=QUERY(A2:C,"select month(A)+1, sum(B), count(C) where A is not null group by month(A)+1")
But as soon as I try a little different things by putting 2 query together in an arrayformula, obviously the row count doesn't match as some minus are 0 for some sources.
Do you have a solution for what I'm trying to do? Thank you in advance :)
Solution:
It's not possible in Google Query Language to have a single query statement that has one result grouped by one column and another result grouped by another.
The first two columns can be like this:
=QUERY(A2:C,"select month(A)+1, sum(B) where A is not null group by month(A)+1 label month(A)+1 'Month', sum(B) 'Amount'")
To create the column labels for the succeeding columns, use in the first row, in my example, I1:
=TRANSPOSE(UNIQUE(C2:C))
Then from cell I2, enter this:
=COUNTIFS(arrayformula(month($A$2:$A)),$G2,$C$2:$C,I$1)
Then drag horizontally and vertically to apply to the entire table.
Results:
try:
=INDEX({
QUERY({MONTH(A2:A), B2:C},
"select Col1,sum(Col2) where Col2 is not null group by Col1 label Col1'month',sum(Col2)'amount'"),
QUERY({MONTH(A2:A), B2:C, C2:C},
"select count(Col3) where Col2 is not null group by Col1 pivot Col4")})

Selecting nth value based on set of cells Google Sheets

I have a set of ID's to compare to a SDE, and I would like to pull multiple rows from the SDE using the ID's as a reference. The reason I want to lookup nth instances is because I have multiple columns in which each column will pull a different instance so all the data can be store horizontally instead of vertically. There will be more ID's but the two on there are just for testing purposes.
The current function I have is =ARRAYFORMULA(IF(C4:C="",,INDEX(SDE_materials_mat,SMALL(IF(C4:C=SDE_materials_id,ROW(SDE_materials_mat)),1))))
That function displays the following alarm:
Array arguments to EQ are of different size.
Here is a copy of the sheet:
https://docs.google.com/spreadsheets/d/1uPgFYKjfkcLfBTAcuPL__gDYeCmn1Nwu473CFMepaUk/edit?usp=sharing
Thank you in advance for any help, it's very appreciated!
try:
=ARRAYFORMULA(IFERROR(SPLIT(IFNA(VLOOKUP(C4:C, SPLIT(FLATTEN(QUERY(QUERY(FILTER(
{SDE_invTypeMaterials!B2:B&"¤"&SDE_invTypeMaterials!C2:C, SDE_invTypeMaterials!A2:A&"×"},
REGEXMATCH(SDE_invTypeMaterials!A2:A&"", TEXTJOIN("|", 1, C4:C)),
COUNTIFS(SDE_invTypeMaterials!A2:A, SDE_invTypeMaterials!A2:A,
ROW(SDE_invTypeMaterials!A2:A), "<="&ROW(SDE_invTypeMaterials!A2:A))<7),
"select max(Col1) where Col1 is not null group by Col1 pivot Col2"),,9^9)), "×"), 2, 0)), "¤ ", 1)))

How could I form a string of items grouped by a matching value? (e.g. "Red: Apples, Cherries")

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

How to use Averageifs or Sumifs in an Arrayformula

I'll post a link to the spreadsheet at the bottom of this write-up.
I'm trying to work out the average of a column of numbers that fall between a date range. The formula below works but I have to drag it down the column, I want it to be an array so it auto updates.
=iferror(averageifs(B$2:B,A$2:A,">="&C2,A$2:A,"<="&D2),1)
So I created it as an array as follows:
=iferror(ArrayFormula(averageifs(B$2:B,A$2:A,">="&C2:C,A$2:A,"<="&D2:D)),1
But it stops after the first cell. So I broke up the average function into sum & count in order to divide.
The count array works using this formula:
=iferror(ArrayFormula(countifs(A$2:A,">="&C2:C,A$2:A,"<="&D2:D)),1)
However the sum array does not even go past the first cell:
=iferror(ArrayFormula(SUMIFS(B$2:B,A$2:A,">="&C2:C,A$2:A,"<="&D2:D)),1)
And the combination gets past the first cell but the calculations all come to zero:
=ArrayFormula(iferror(SUMIFS(B$2:B,A$2:A,">="&C2:C,A$2:A,"<="&D2:D)/countifs(A$2:A,">="&C2:C,A$2:A,"<="&D2:D),1))
What I'm trying to achieve is an average for the previous month.
If anyone can help me I'd be very grateful!
https://docs.google.com/spreadsheets/d/1XhoLl5hB-MpXFz9VS2aLqJOWbXk1d_7apnwKWFdDUlg/edit?usp=sharing
you are trying to apply a bit weird structural logic with lots of repeating values with no reason. basically, it looks like you need this:
=ARRAYFORMULA(QUERY({TEXT(A2:A, "yyyy-mmm"), B2:B},
"select Col1,avg(Col2)
where Col2 is not null
group by Col1
order by avg(Col2) desc
label avg(Col2)''", 0))
but if you really really need so:
=ARRAYFORMULA(IF(LEN(A2:A),
IFERROR(VLOOKUP(TEXT(DATE(YEAR(A2:A), MONTH(A2:A)-1, 1), "yyyy-mmm"),
QUERY({TEXT(A2:A, "yyyy-mmm"), B2:B},
"select Col1,avg(Col2)
where Col2 is not null
group by Col1", 0), 2, 0), 0), ))

Resources