Append two dynamic arrays vertically [duplicate] - arrays

I have two tables on two sheets - let's say tblFruits1 and tblFruits2.
Both have a column "Name".
Apple - for example - exists on both lists.
The lists might have a different number of rows
tblFruits1 on Sheet1
Name
Color
Apple
red
Peach
yellow
Ananas
yellow
tblFruits2 on Sheet2
Name
Color
Apple
red
Cherries
red
Banana
yellow
Melone
green
Now I would like to get - on a third sheet - a UNIQUE list of names of both tables.
expected result on Sheet3
Name
Apple
Peach
Ananas
Cherries
Banana
Melone
=UNION((tblFruits1[Name],tblFruits2[Name])) returns an error.
I tried variants with SEQUENCE and INDEX but didn't succeed.
So the question is:
How can I "construct" the matrix-parameter for UNIQUE from two column-ranges on two different sheets?
(What I am looking for is a non-VBA-solution - I know how to handle this in VBA.)

The VSTACK function makes the Union obsolete (only available to insiders at time of writing)
Since finding the Union of several ranges is a quite usefull function on its own, I use a LAMBDA to do that. The output of that can then be passed to UNIQUE
The Lambda, which I call, unimaginatively, UNION
=LAMBDA(tabl1, tabl2,
LET(rowindex, SEQUENCE(ROWS(tabl1)+ROWS(tabl2)),
colindex, SEQUENCE(1,COLUMNS(tabl1)),
IF(rowindex<=ROWS(tabl1),
INDEX(tabl1,rowindex,colindex),
INDEX(tabl2,rowindex-ROWS(tabl1),colindex)
)
)
)
Then
=UNIQUE(Union(tblFruits1[Name],tblFruits2[Name]))
gives the result you seek

Try:
=LET(X,CHOOSE({1,2},tblFruits1[Name],tblFruits2[Name]),Y,COUNTA(X),Z,MOD(SEQUENCE(Y)-1,Y/2)+1,A,INDEX(X,Z,CEILING(SEQUENCE(Y)/(Y/2),1)),UNIQUE(FILTER(A,NOT(ISNA(A)))))

This is a solution I created where you can replace a2# and c2# with any two arrays, dynamic arrays, etc. It also deduplicates and sorts it. This works on Excel for Mac (FILTERXML is not supported)
=LET(
firstArray, a2#,
secondArray, c2#,
totalCount, COUNTA(firstArray)+COUNTA(secondArray),
firstCount, COUNTA(firstArray),
SORT(UNIQUE(MAKEARRAY(totalCount,1,LAMBDA(r,c,IF(r<=firstCount,INDEX(firstArray,r),INDEX(secondArray,r-firstCount+1))))))
)

Can you try like this and make your Sheet1 data and Sheet2 data into Table
an in your Sheet3 cell A2 copy paste the formula below
=UNIQUE(FILTERXML(""&TEXTJOIN("",1,(IFNA(IF({0,1},Table1[Name],Table2[Name]),"")))&"","//b"),FALSE,FALSE)

There is a new function that simplifies this: VSTACK
For a unique (distinct) union (as per the original question), try this:
=UNIQUE((tblFruits1[Name],tblFruits2[Name]))
And to sort them:
=SORT(UNIQUE((tblFruits1[Name],tblFruits2[Name])))

I don't have VSTACK or HSTACK at this point (or LAMDA either), unless I resort to keeping workbooks on slow-and-clunky Excel Online. But say you have 3 dynamic arrays (named three, four and five), each with 2 columns and a variable number of rows. Then (to keep things readable) use a named formula combo defined as =SEQUENCE(ROWS(three)+ROWS(four)+ROWS(five)). Then this works:
=IFS(
combo<=ROWS(three), three,
combo<=ROWS(three)+ROWS(four), INDEX(four,combo-ROWS(three),{1,2}),
TRUE, INDEX(five,combo-ROWS(three)-ROWS(four),{1,2})
)
You can wrap UNIQUE and/or SORT around this, if you like. If the arrays have 3 columns rather than 2 then use {1,2,3} in the formula.
Obviously you can expand this to more than 3 arrays by building more conditions into the IFS formula.
Perhaps it's worth noting that three is the same thing as INDEX(three,combo,{1,2}). And using COLUMN(three) would make the syntax more generalisable, though it doesn't allow you to re-order the columns if you want something like {2,1,3} in your output. Also, TRUE is effectively how you say "ELSE" in an IFS formula--it's a bit more concise here than combo<=ROWS(three)+ROWS(four)+ROWS(five). Using these longer forms would make the formula more symmetrical but a lot wordier!
(It would be nice if VSTACK ever becomes available on the desktop.)

Related

How to use COUNTIFS based on multiple criteria over different sized ranges?

I have an attendance tracker in which I'm trying to account for each employee type per day.
I have a summary page (sheet1) in which I want the count of each type (A,B,C,D,E) based on the day in cell C2 whether or not they have an X on sheet2 for that day.
Using =COUNTIF(FILTER(Sheet2!$A$5:$GG$969,Sheet2!$A$5:$GG$5=$C$2),"X") I am able to get a total of "X" based on the date in cell C2.
However, I'm having trouble getting the formula to work counting each employee type.
=COUNTIFS(Sheet2!A5:AM31,A7,(FILTER(Sheet2!A5:AM31=C2)),"X")
This gives me an error "Array arguments to COUNTIFS are of different size."
I'm not sure how else to configure this. Below is a link to my sample sheet:
Appreciate any help!
https://docs.google.com/spreadsheets/d/1OdJTwbFsNcR1hO1qzMBGUY4iXcWgDwIAJmBAVE9cs0k/edit?usp=sharing
I think this would work, dragged down for the other groups.
=COUNTIFS(Sheet2!A$6:A$31,A7,FILTER(Sheet2!$6:$31,Sheet2!$5:$5=C$2),"X")
However, I would encourage you to look at this sample sheet (a copy of yours) where I've added a new tab called MK.Help, designed to be hidden, but used as a sort of helper tab to make all sorts of things you might like to do easier. Including the count you asked about.
It has one single formula in cell A2 where you can see what it does.
=ARRAYFORMULA(QUERY(SPLIT(FLATTEN(Sheet2!C5:5&"|"&Sheet2!A6:A31&"|"&Sheet2!B6:B31&"|"&Sheet2!C6:31),"|",0,0),"where Col3<>'' order by Col1"))
try:
={"", ""; QUERY(FILTER(Sheet2!A6:A31, FILTER(Sheet2!6:31, Sheet2!5:5=C2)="X"),
"select Col1,count(Col1) where Col1 is not null group by Col1 label count(Col1)''");
"Total", COUNTA(IFNA(FILTER(Sheet2!A6:A31, FILTER(Sheet2!6:31, Sheet2!5:5=C2)="X")))}

Populating Cells Based on Dropdowns in Google Sheets

Alright. I'm setting up a character sheet for a D&D esque combat system for something. I have a chart with two columns; A and B. We'll call this Sheet1. Column A is trait names, column B is their corresponding descriptions.
On a separate sheet, Sheet2, I have a data validation drop down in column B corresponding to the trait names in column A on Sheet1. I need Sheet2, column C to auto populate with the trait description from Sheet1 column B corresponding to the selected trait from the drop down.
I have googled this with every possible change of phrasing I can think of and I cannot find a solution. If I could get Google sheets to understand Python I'd be golden and have this done already, but sadly I cannot. Can anyone help? I thought about just daisy chaining =(IF)'s but theres going to be about 50 different traits to choose from and that's just not efficient.
try:
=INDEX(IFNA(VLOOKUP(B2:B, Sheet1!A:B, 2, 0)))

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

Excel - Retrieve value in an array

In my organisation, there are a couple of excel functions that return large array like more than 2000 rows and several columns.
Dummy Code / Dummy Example :
{=FunctionThatReturnArray(param1)}
where param1 is the date
I need to retrieve the selling price for the combination « Shoes » « Yellow » for different dates.
I don’t want to display an entire array, for every date I’m interested in.
Instead, I would like to display only the value that I need.
I tried to used the Index function as below, but as the combination Shoes/Yellow isn’t always at the fifth row, it doesn’t work.
{=INDEX(FunctionThatReturnArray(param1),5,4)}
where 5 is the RowNumber and 4 the ColNumber
I believe I need to use the Match Function somehow, but on the 2 different column.
How could I do that without displaying the entire array on my worksheet ?
Thanks in advance and kind regards
Largo
I'm not sure if this is the answer you want, but you are right, you would have to match on both the 2nd and 3rd columns then index into the 4th column like this:
=INDEX({43466,"Pants","Yellow",40;43466,"Shirt","Green",20;43466,"Shoes","Blue",70;43466,"Shoes","Yellow",75},MATCH(1,
(INDEX({43466,"Pants","Yellow",40;43466,"Shirt","Green",20;43466,"Shoes","Blue",70;43466,"Shoes","Yellow",75},0,2)=B2)*
(INDEX({43466,"Pants","Yellow",40;43466,"Shirt","Green",20;43466,"Shoes","Blue",70;43466,"Shoes","Yellow",75},0,3)=C2),0),4)
Where I have used an array constant to test it, you would need multiple references to your Array Function to achieve this.
BTW the 43466 is the number representation of 1/1/2019.

VLOOKUPs to Populate an Excel Table

I'm having trouble writing a VLOOKUP to sort some data.
I have one table that has data that looks like this:
MarkAsOfDate MaturityDate ZeroRate
05-May-15 05-May-15 0.006999933
05-May-15 06-May-15 0.006999933
05-May-15 05-Jun-15 0.008996562
05-May-15 06-Jul-15 0.008993128
... ....
I want to make a table with every instance where the interval between the dates in the first and second columns is exactly one month (such as 05 - May - 15 and 05 - Jun - 15), and with blanks where no such value exists.
So I made a second table which looks like:
MarkAsofDate MaturityDate Zero Rate 1M
5-May-15 5-Jun-15
6-May-15 6-Jun-15
7-May-15 7-Jun-15
8-May-15 8-Jun-15
9-May-15 9-Jun-15
.... ....
I want to populate this table using data from the first table. I've tried to write a VLOOKUP for it but I'm not sure how to do it with two columns instead of one.
Thanks in advance.
Vlookup has some limitations, as you're starting to see. Another suggestion is Index/Match. Use this in your second table.
Note: I assume your top table is in Sheet1. Put this in your C2, in the second table (under the "Zero Rate 1M" header):
=Index(Sheet1!$C:$C,match(A2&B2,Sheet1!$A:$A&Sheet1!$B:$B,0)) and enter by pressing CTRL+SHIFT+ENTER.
There are a lot of ways to do it - if your data is sorted first by MarkAsofDate and then by Maturity date, the simplest method will be to add a helper column on your raw data tab - let's say column E. In column E, starting at E2 and copied down, type [Assuming MarkAsofDate is column A & MaturityDate is column E]:
=IF(MONTH(B1)-MONTH(A1)=1,A1,"")
This column will show the MarkAsOfDate for every item which has a MaturityDate 1 month after the MarkAsOfDate; for all other rows it will show "".
In your special data results tab, use the MATCH function to find the row in column E which matches your current row's MarkAsOfDate. We will also use the INDEX function to return the value from that row in column C. Assuming your first sheet with raw data is sheet1 and your special data results is on sheet2, type this into E2 on sheet2 and drag down:
=INDEX(Sheet1!C:C,MATCH(A2,Sheet1!A:A,0))
Another alternative (apart from BruceWayne's recommended Array Formula) would be to use the OFFSET function. OFFSET creates a new range based on a starting point, moving a number of cells to the right/left/up/down, for a given height and width. In this case, we will first use MATCH to find the first time that the MarkAsOfDate on Sheet1 matches Sheet2. We will use that info and the OFFSET function to create a new range which starts there, and ends at the bottom of your data, like so:
=OFFSET(Sheet1!A1,MATCH(A2,Sheet1!A:A,0),1,COUNT(Sheet1!C:C),2)
Then we just need to use VLOOKUP on the range we created above, like so:
=VLOOKUP(B2,OFFSET(Sheet1!A1,MATCH(A2,Sheet1!A:A,0),1,COUNT(Sheet1!C:C),2),0)
This second alternative avoids needing a helper column, but is more complex and could be prone to errors if your rows/columns change (because we had to hardcode a couple of things in the OFFSET function). Also, OFFSET is volatile, meaning it recalculates whenever any cell calculates, so it can slow down your workbook if you have a lot of rows of it. Based on that, I recommend you either use the helper column method above, or if you are comfortable with Array Formulas, using BruceWayne's answer.

Resources