How to get array with values into one column - arrays

In excel I have two columns (A and B) filled with text values and I want to get all the values from the two column into one column (C) and it needs to be dynamic
example:
Column A: {car, plane, boat}
Column B: {bike, motor}
Column C: {car, plane, boat, bike, motor}
I hope someone can help me!

use:
=QUERY(FLATTEN(A:C); "where Col1 is not null")

This will work in both Excel(any version) and Google Sheets: Put this in C1 and copy down till you have enough cells filled to capture both lists maximum lengths:
=INDEX(A:B,IF(ROW($ZZ1)>COUNTA(A:A),ROW($ZZ1)-COUNTA(A:A),ROW($ZZ1)),IF(ROW($ZZ1)>COUNTA(A:A),2,1))&""
With Office 365 Excel:
=LET(
rng1st,A:A,
rng2nd,B:B,
cnt1st,COUNTA(rng1st),
cnt2nd,COUNTA(rng2nd),
sq,SEQUENCE(cnt1st+cnt2nd),
INDEX(CHOOSE({1,2},rng1st,rng2nd),IF(sq>cnt1st,sq-cnt1st,sq),IF(sq>cnt1st,2,1)))
Put that in C1 and the results will spill automatically:

Google Sheets has a FLATTEN function which allows you to do this, but there is no equivalent function in Excel.
There is a workaround though, which does combines the 2 columns in the order of their rows:
This works in Excel Version 2019 or later
=FILTERXML("<a><b>"&TEXTJOIN("</b><b>",TRUE,A:B)&"</b></a>","//b")

=IF(SEQUENCE(ROWS(range1)+ROWS(range2))<ROWS(range1)+1,range1,INDEX(range2,MOD(SEQUENCE(ROWS(range1)+ROWS(range2),,ROWS(range2)-ROWS(range1)),ROWS(range2))+1,SEQUENCE(1,COLUMNS(range2))))
This will stack range2 under range1 in Excel (365) this also works for ranges with 2 columns, or more

If the amount of the rows won't be changed
=IFERROR(INDEX($A$1:$A$3, ROWS(C1:$C$1)), IFERROR(INDEX($B$1:$B$2, ROWS(C1:$C$1)-ROWS($A$1:$A$3)), ""))
ctrl + shift + enter
If the amount of the rows can be changed
=IFERROR(INDEX(INDIRECT("$A$1:$A$"&COUNTIF(A:A,"")), ROWS(C1:$C$1)), IFERROR(INDEX(INDIRECT("$B$1:$B$"&COUNTIF(B:B,"")), ROWS(C1:$C$1)-ROWS(INDIRECT("$A$1:$A$"&COUNTIF(A:A,"*")))), ""))
ctrl + shift + enter

Related

How do you use ArrayFormula with arrays (after aggregation)?

In my example:
https://docs.google.com/spreadsheets/d/1QQNTw_r9-q-FqVNwUoYklup73niZCFyO0VDUYImP5fo/edit?usp=sharing
I'm using Google Forms as an eBay clone to sell rare items. Each bid is outputted from the form to the "Data" worksheet and then I have ArrayFormulas set up inside the "Processed" worksheet. The idea is that I want to process the bids so that we filter everything except the items with the highest bids. All data should be automatically updated, hence why I want to use ArrayFormulas.
My strategy is that in colum A, I first filter all unique items (=unique(filter(Data!A2:A,Data!A2:A<>""))) and end up with:
Jurassic Park 6-Pog Hologram Set
Princess the Bear TY Beanie Baby
Holographic 1st Ed Charizard
However, then in column B, we have to find the highest bid that corresponds to that unique item, e.g.:
=IF(ISBLANK(A2),,ArrayFormula(MAX(IF(Data!A2:A=A2,Data!B2:B))))
However, I don't want to have A2 be a single cell (A2) but an array (A2:A) so that it doesn't have to be manually copied down the rows. Similarly, I also want columns D and E to be automatic as well. Is there any way to achieve this?
Not sure if it would be considered easier than the previously posted answer, but in case this thread is found in the future, I think that this is a slightly simpler way to solve these kinds of problems:
Try this on a fresh tab in cell A1:
=FILTER(Data!A:D,COUNTIFS(Data!A:A,Data!A:A,Data!B:B,">"&Data!B:B)=0)
I did some research and found an answer very similar to what you were looking for. After rearranging the formula slightly to match your sheet, I was able to get this to work:
=ArrayFormula(vlookup(query({row(Data!A2:A),sort(Data!A2:C)},"select max(Col1) where Col2 <> '' group by Col2 label max(Col1)''",0),{row(Data!A2:A),sort(Data!A2:D)},{2,3,4,5},0))
This formula automatically populates product name, highest bid, username, and timestamp. I ran some tests, adding my own random names and values into the data sheet, and the formula worked great.
Reference: https://webapps.stackexchange.com/a/75637
use:
={A1:D1; SORTN(SORT(A2:D, 1, , 2, ), 9^9, 2, 1, )}
translated:
{A1:D1} - headers
SORT(A2:D, 1, , 2, ) - sort 1st column then 2nd column descending
9^9 - output all possible rows
2 - use 2nd mode of sortn which will group selected column
1 - selected column to be marged based on unique values

Use query to combine data from ever-changing tab list

I am building a Sheet that will be taking imported data from other tabs and combining it in a summary sheet, for me to use elsewhere. The problem is, the tabs will be imported monthly, so there will be dozens of them very quickly, and I don't want to edit the query function every month. They will all have the same naming format, but I'm wondering if anyone has an idea about how to formulate the query with variables for the sheet name that I can pull from another cell. For example, I could import the tab names into another row, and have the query pull the sheet names from that row, but I am not familiar with how to do this. Here is an example of the query formula I'm using in a similar sheet:
=QUERY({'2019 TEAM SALES'!A2:ZY; '2020 TEAM SALES'!A2:ZY}, "select * Where Col1 is not null",1)
With this one, updated once a year isn't a big deal. But this new sheet will be monthly, so it will be unwieldy in just a few months. Is there a way using query to take the sheet names via cell info? Like if in row 1, I concatanate the sheet names with the range, so that A1 contains "'2019 TEAM SALES'!A2:ZY" and the next in B1 and so on, and then the query formula is:
=QUERY(A1:ZZ1, "select * Where Col1 is not null",1)
This way, it will always pull in all the current tabs necessary to combine.
Incidentally, I'm open to using other formulas or even a script to get this done, as it's the result I'm after, not the method.
I have seen a lot of answers similar to what's here, but this still forces extremely long formulas that I don't think are very efficient, given that this sheet will eventually have 50 or more tabs in it.
Thanks for any insights!
to generate list of sheets from start date to today's date +3 months in advance:
=ARRAYFORMULA(UNIQUE(TEXT(ROW(INDIRECT(
DATEVALUE("2020-4-1")&":"&
DATEVALUE(TODAY()+90))), "yyyy mmmm")))
converting it into ranges for query:
=ARRAYFORMULA("INDIRECT("""&UNIQUE(TEXT(ROW(INDIRECT(
DATEVALUE("2020-4-1")&":"&
DATEVALUE(TODAY()+90))), "yyyy mmmm"))&"!A:C"")")
to avoid possible errors for sheets that do not exist yet:
=ARRAYFORMULA("IFERROR(INDIRECT("""&UNIQUE(TEXT(ROW(INDIRECT(
DATEVALUE("2020-4-1")&":"&
DATEVALUE(TODAY()+90))), "yyyy mmmm"))&"!A:C""), {"&
TEXTJOIN(",", 1, SPLIT(REPT("""""♥", COLUMNS(A:C)), "♥"))&"})")
next we join it to create one single reference for query:
=ARRAYFORMULA("{"&TEXTJOIN("; ", 1,
"IFERROR(INDIRECT("""&UNIQUE(TEXT(ROW(INDIRECT(
DATEVALUE("2020-4-1")&":"&
DATEVALUE(TODAY()+90))), "yyyy mmmm"))&"!A:C""), {"&
TEXTJOIN(",", 1, SPLIT(REPT("""""♥", COLUMNS(A:C)), "♥"))&"})")&"}")
then we can build our query:
={""; ARRAYFORMULA("=QUERY({"&TEXTJOIN("; ", 1,
"IFERROR(INDIRECT("""&UNIQUE(TEXT(ROW(INDIRECT(
DATEVALUE("2020-4-1")&":"&
DATEVALUE(TODAY()+90))), "yyyy mmmm"))&"!A:C""), {"&
TEXTJOIN(",", 1, SPLIT(REPT("""""♥", COLUMNS(A:C)), "♥"))&"})")
&"}, ""select Col1,Col2 where Col3 is not null"", 0)")}
this way we generated our query formula as a string in G2 so the next step is either manually copy-paste this each month where you need it or you can use script which will auto-copy content of G2 and auto-paste it where you need it on any change so you dont need to touch it anymore
function onEdit() {
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1'); // sheet name
var src = sheet.getRange("G2"); // cell which holds the formula
var str = src.getValue();
var cell = sheet.getRange("G10"); // cell where I want the results
cell.setFormula(str);
}
spreadsheet demo
Solution
In order to use cell values (your variables) in your formula in order to automate the whole thing you can use the formula indirect which lets you use cell values in formulas. Therefore, you would end up with something like this:
=QUERY({INDIRECT(A1);INDIRECT(A1)}, "select * Where Col1 is not null",1)
where A1 is the cell containing 2019 TEAM SALES!A2:Y2
I hope this has helped you. Let me know if you need anything else or if you did not understood something. :)

EXCEL: Create Array Formula out of INDEX/MATCH with multiple results

my aim is to convert a massive excel sheet with different projects, employees and hours worked per month into an overview per employee. It should be possible to display the projects the employee is involved in and how many hours he worked per project per month.
The original sheet looks something like this:
I managed to find the projects Person A worked in by filtering through the INDEX/MATCH function. I applied the formula to the whole row where the employees are listed and receive multiple results of projects. My question is how to transform the formula into something more effective to copy all of the matched results (projects) into a column (see 1).
This is what I have so far, if matches the employee name in a certain area; the output is the first match of the project he is involved in:
=INDEX(B2:J3;1;MATCH("Person A";Sheet1!B3:E3;0))
How can I copy this to the bottom cells to copy all of the matched results? Does it help to create an array formula with this?
You can use he following formula in cell B9:
=IFERROR(INDEX($2:$2,SMALL(IF($3:$3=$B$8,COLUMN($3:$3)-COLUMN(INDEX($3:$3,1,1))+1),ROWS(A$1:A1))),"")
It indexes row 2 and looks for the column number of the first match in row 3 that equals the value in B8 (=Person A). When dragging down it will look for the second match ROWS(A$1:A1) will become ROWS(A$1:A2) = 2.
For Person B you can use this formula in cell B14:
=IFERROR(INDEX($2:$2,SMALL(IF($3:$3=$B$13,COLUMN($3:$3)-COLUMN(INDEX($3:$3,1,1))+1),ROWS(A$1:A1))),"")
I hope this is what you where looking for.
PS
if you paste the following formula in cell C9 you will get the sum result for Person A on Project XY in month 10 2019:
=IF(OR($B9="",C$8=""),"",SUMPRODUCT(($B$2:$K$2=$B9)*($B$3:$K$3=$B$8)*($A$4:$A$6=C$8),B4:K6))
Note: That is provided that the value in cell C8 equals the value in cell A4.

Comparing two rows with array formula to indentify differences and return "Last Change Date"

I currently have an Excel Table which is edited by multiple users. I wrote some formula to compare the actual status with the last saved file. It works well, but as any array formula, it is extremely slow:
Macro copies all entries when I open the workbook (Mirror FEP Sheet)
Array Formula compares corresponding rows in the original Table and the Mirror Table to find any differences; if there was some modification, it returns TODAY(). If not, the previous date is written...
=IFERROR(IF(AND(EXACT([#[PTI-Nr]]:[#KIFA];INDIRECT("'Mirror FEP'!" & "B" & (2+MATCH([#[EAARCH-Nr]]; Table3[EAARCH-Nr]; 0))):INDIRECT("'Mirror FEP'!"&SUBSTITUTE(ADDRESS(1; COUNTA($2:$2);4); 1; "")&(2+MATCH([#[EAARCH-Nr]]; Table3[EAARCH-Nr]; 0))))); INDIRECT("'Mirror FEP'!" & "A" & (2+MATCH([#[EAARCH-Nr]]; Table3[EAARCH-Nr]; 0))); TODAY()); TODAY())
The formula is complex in order to find the right row in Mirror FEP even when the user changes the order of the original table.
I am familiar with the VBA solution, but my users need to Ctrl + Z all the time. Do you have any suggestion on how to speed up my Workbook? Alternative solutions are more than welcome!

Excel quartile function with variable array criteria (like countif)

hoping someone can help with my Excel query.
I want to use the quartile function (or similar, could use percentile if that's easier). I have data in a column but I want to limit the data I use from that column.
I have job departments in column A, people's salaries in column B (and other data in the other columns e.g name).
I want to use my one main data list (c. 2,000 rows) to pick out the quartiles for the 10 or so depts I have but I don't want to have to make 10 specific lists to calculate the quartile of each dept.
Is there an option to use a countif or similar function so that I can have a drop down list of my 10 depts and depending on what dept I select my summary table will show the quartiles relevant for just that dept?
Thanks
Use an array formula =quartile(if(A1:A1000=C2,B1:B1000),.75) press control + shift + enter after entering the formula. Note: C2 = the department which quartile you are calculating.

Resources