Index rows and columns unexpected results - excel

I'm trying to understand the following behaviour:
If I have the following data:
A
B
a
1
b
2
c
3
If I use =INDEX($A$1:$B$3,,)
It will correctly show the whole range.
If I use =INDEX($A$1:$B$3,1,)
It will correctly show the data for the first row for both columns.
If I use =INDEX($A$1:$B$3,SEQUENCE(2),)
I expect it to show the data for the first two rows for both columns. Instead it shows the data of the first two rows, not showing data for the second column.
How come INDEX loses the column reference here?

INDEX reads its parameters as a pair of lists.
For example, using array constants, you can type:
=INDEX(A1:B3,{1,3},{1,2})
which gives:
a 3
because Excel reads this as {1,1}, {3,2}.
With SEQUENCE, an array constant is returned, and so SEQUENCE(2) returns {1;2}. When used twice, Excel processes {1,1};{2,2}.
You can use SEQUENCE to return a vertical array constant, such as
SEQUENCE(1,2)
which returns {1,2}.
Now it works:
=INDEX(A1:B3,SEQUENCE(2),SEQUENCE(1,2))
Or, using a mix of horizontal and vertical array constants
=INDEX(A1:B3,{1;2},{1,2})
Ref:
https://support.microsoft.com/en-us/office/guidelines-and-examples-of-array-formulas-7d94a64e-3ff3-4686-9372-ecfd5caa57c7
Create one and two-dimensional array constants

Related

Comparing two columns and their values and outputting the greater value

I'm trying to compare two columns ("Shows") from different tables and showing which one has the greater number ("Rating") associated with it in another table.
Ignore the operation column above as part of the solution that I'm trying to get, it's just to illustrate for you what I'm trying to compare.
Important note: If the names are duplicated. Compare the matching pair in their corresponding order. (1st with 1st, 2nd with 2nd, 3rd with 3rd etc..) illustrated in the table below:
Thanks
You can try the following in cell F3 for an array solution that spills the entire result at once:
=LET(sA, A3:A6, rA, B3:B6, sB, C3:C6, rB, D3:D6, CNTS, LAMBDA(x,
LET(seq, SEQUENCE(ROWS(x)), MAP(seq, LAMBDA(s,ROWS(FILTER(x,(x=INDEX(x,s))
*(seq<=s))))))), cntsA, CNTS(sA), cntsB, CNTS(sB), eval, MAP(sA, rA, cntsA,
LAMBDA(s,r,c,IF(r > FILTER(rB, (sB=s) * (cntsB=c)), "Table 1", "Table 2"))),
HSTACK(sA, eval))
Here is the output:
Explanation
The main idea is to count repeated show values. We use a user LAMBDA function CNTS, to avoid repetition of the same formula twice. Once we have the counts (cntsA, contsB), we use MAP to iterate over Table 1 elements with the counts and look for specific show and counts to compare with Table 2 columns. The FILTER function will return always a single value (based on sample data). Finally, we prepare the output as expected using HSTACK.
Try-
=IF(INDEX(FILTER($B$3:$B$6,$A$3:$A$6=G3),COUNTIFS($G$3:$G3,G3))>INDEX(FILTER($E$3:$E$6,$D$3:$D$6=G3),COUNTIFS($G$3:$G3,G3)),"Table-1","Table-2")

How to find out Max<List<List>> in Excel?

I'd like to find out largest sum of numbers separated by empty row. In this example I am looking to get number 6 (3+3)
1
1
2
2
3
3
Brute forcing this I would =MAX(SUM(A1:A2),SUM(A4:A5),SUM(A7:A8)) which does the job but obviously not practical. How can I express above more elegantly without hardcoding anything?
Thinking out loud, I would like to
Ingest all numbers, split by empty row into some kind of List<List>
Iterate over this list, sum numbers in child list and pick a winner
How can this be done in Excel?
There are multiple ways of doing it, this is just one of them. In cell C1 you can put the following formula:
=LET(set, A1:A9, matrix, 1*TEXTSPLIT(SUBSTITUTE(TEXTJOIN(",",
FALSE, set),",,",";"),",",";", TRUE),m, COLUMNS(matrix), ones, SEQUENCE(m,1,,0),
MAX(MMULT(matrix, ones))
)
and here is the output:
Note: The third input argument of TEXTSPLIT set to TRUE ensures you can have more than one empty row in the middle of the range. The second input argument of TEXTJOIN set to FALSE is required to ensure to generate of more than one comma (,), which is our condition to replace by the row delimiter (;) so we can split by row and columns. MMULT requires numbers and TEXTSPLIT converts the information into texts. we need to coerce the result into a number by multiplying it by 1.
The formula follows the approach you suggested, you can test the intermediate step. Instead of having as output MAX result the variable you want to verify, for example:
=LET(set, A1:A9, matrix, 1*TEXTSPLIT(SUBSTITUTE(TEXTJOIN(",",
FALSE, set),",,",";"),",",";", TRUE),m, COLUMNS(matrix), ones, SEQUENCE(m,1,,0),
TMP, MAX(MMULT(matrix, ones)), matrix
)
will produce the following output:
1 1
2 2
3 3
An alternative to MULT is to use BYROW array function (less verbose):
=LET(set, A1:A8, matrix, 1*TEXTSPLIT(SUBSTITUTE(TEXTJOIN(",",
FALSE, set),",,",";"),",",";", TRUE),MAX(BYROW(matrix, LAMBDA(m, SUM(m))))
)

Sumproduct with OR and Right function

In column A are IDs like "1.23.1". The first and last numbers are the ones I use to identify the IDs I am looking for. The middle numbers range from 1 to 999, so IDs could be "1.1.1" OR "1.231.1. This information is only important to show that not all IDs have the same amount of characters.
I need to add the numbers from column B that match the IDs I am looking for.
A ----------- B
1.21.1 ------------5
1.314.2 ----------6
2.2.1 -------------3
I am getting a #VALUE! error with the following formula.
=SUMPRODUCT(OR((RIGHT(A4:A6,1)="1")+0,RIGHT(A4:A6,1)="2")+0,LEFT(A4:A6,1)="1",B4:B6
I would like to add the 5 and 6 because their IDs both end with 1 or 2 and start with 1.
Example
=SUMPRODUCT((LEFT(A4:A6)="1")*((RIGHT(A4:A6)="1")+(RIGHT(A4:A6)="2"))*B4:B6)
Using the OR function will only return a single value; hence your arrays will not be all the same length; hence the #VALUE! error.
Using addition will return an array of the OR test for each cell, instead of a single OR for the entire array.
If you want to use the function with separate arrays, where you convert each test array to it's numeric equivalent, (as in your example) you can use:
=SUMPRODUCT(N(LEFT(A4:A6)="1"),N((RIGHT(A4:A6)="1")+(RIGHT(A4:A6)="2")),B4:B6)

Using tbl.Lookup to match just part of a column value

This question relates to the Schematiq add-in for Microsoft Excel.
Using =tbl.Lookup(table, columnsToSearch, valuesToFind, resultColumn, [defaultValue]) the values in the valuesToFind column have a consistent 3 characters to the left and then varying characters after (e.g. 908-123456 or 908-321654 - i.e. 908 is always consistent)
How can I tell the function to lookup the value based on the first 3 characters only? The expected answer should be the sum of the results of the above, i.e. 500 + 300 = 800
tbl.Lookup() works by looking for an exact match - this helps ensure it's fast but in this case it means you need an extra step to calculate a column of lookup values, something like this:
A2: =tbl.CalculateColumn(A1, "code", "x => LEFT(x, 3)", "startOfCode")
This will give you a new column that you can use for the columnsToSearch argument, however tbl.Lookup() also looks for just one match - it doesn't know how to combine values together if there is more than one matching row in the table, so I think you also need one more step to group your table by the first 3 chars of the code, like this:
A3: =tbl.Group(A2, "startOfCode", "amount")
Because tbl.Group() adds values together by default, this will give you a table with a row for each distinct value of startOfCode and the subtotal of amount for each of those values. Finally, you can do the lookup exactly as you requested, which for your input table will return 800:
A4: =tbl.Lookup(A3, "startOfCode", "908", "amount")

Return a row number that matches multiple criteria in vbs excel

I need to be able to search my whole table for a row that matches multiple criteria. We use a program that outputs data in the form of a .csv file. It has rows that separate sets of data, each of these headers don't have any columns that are unique in of them self but if i searched the table for multiple values i should be able to pinpoint each header row. I know i can use Application.WorksheetFunction.Match to return a row on a single criteria but i need to search on two three or four criteria.
In pseudo-code it would be something like this:
Return row number were column A = bill & column B = Woods & column C = some other data
We need to work with arrays:
There are 2 kinds of arrays:
numeric {1,0,1,1,1,0,0,1}
boolean {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
to convert between them we can use:
MATCH function
MATCH(1,{1,0,1,1,1,0,0,1},0) -> will result {TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}
simple multiplication
{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE}*{TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE} -> will result {1,0,1,1,1,0,0,1}
you can can check an array in the match function, entering it like in the picture below, be warned that MATCH function WILL TREAT AN ARRAY AS AN "OR" FUNCTION (one match will result in true
ie:
MATCH(1,{1,0,1,1,1,0,0,1},0)=TRUE
, YOU MUST CTR+SHIFT+ENTER !!! FOR IT TO GIVE AN ARRAY BACK!!!
in the example below i show that i want to sum the hours of all the employees except the admin per case
we have 2 options, the long simple way, the complicated fast way:
long simple way
D2=SUMPRODUCT(C2:C9,(A2=A2:A9)*("admin"<>B2:B9)) <<- SUMPRODUCT makes a multiplication
basically A1={2,3,11,3,2,4,5,6}*{0,1,1,0,0,0,0,0} (IT MUST BE A NUMERIC ARRAY TO THE RIGHT IN SUMPRODUCT!!!)
ie: A1=2*0+3*1+11*1+3*0+2*0+4*0+5*0+6*0
this causes a problem because if you drag the cell to autocomplete the rest of the cells, it will edit the lower and higher values of
ie: D9=SUMPRODUCT(C9:C16,(A9=A9:A16)*("admin"<>B9:B16)), which is out of bounds
same as the above if you have a table and want to view the results in a diferent order
the fast complicated way
D3=SUMPRODUCT(INDIRECT("c2:c9"),(A3=INDIRECT("a2:a9"))*("admin"<>INDIRECT("b2:b9")))
it's the same, except that INDIRECT was used on the cells that we want not be modified when autocompleting or table reorderings
be warned that INDIRECT sometimes give VOLATILE ERROR,i recommend not using it on a single cell or using it only once in an array
f* c* i cant post pictures :(
table is:
case emplyee hours totalHoursPerCaseWithoutAdmin
1 admin 2 14
1 him 3 14
1 her 11 14
2 him 3 5
2 her 2 5
3 you 4 10
3 admin 5 10
3 her 6 10
and for the functions to check the arrays, open the insert function button (it looks like and fx) then doubleclick MATCH and then if you enter inside the Lookup_array a value like
A2=A2:A9 for our example it will give {TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE} that is because only the first 3 lines are from case=1
Something like this?
Assuming that you data in in A1:C20
I am looking for "Bill" in A, "Woods" in B and "some other data" in C
Change as applicable
=IF(INDEX(A1:A20,MATCH("Bill",A1:A20,0),1)="Bill",IF(INDEX(B1:B20,MATCH("Woods",B1:B20,0),1)="Woods",IF(INDEX(C1:C20,MATCH("some other data",C1:C20,0),1)="some other data",MATCH("Bill",A1:A20,0),"Not Found")))
SNAPSHOT
I would use this array* formula (for three criteria):
=MATCH(1,((Range1=Criterion1)*(Range2=Criterion2)*(Range3=Criterion3)),0)
*commit with Ctrl+Shift+Enter

Resources