Index and Match multiple matches - excel

I need help with the following query. There are 2 excel sheet and I need to find out in Sheet 1 in Column A what are the different accounts matching, the refernce is Sheet 2.
I am looking for a formula, which can give me all the account in sheet 1 in corressponds to the position nr. The anwser is in sheet 2. Can someone please help?
eg. 5001 = should give me 41150100, 41150101, 41200000
Position
Account
5001
5031
5051
Account
Position
41150100
5001
41150101
5001
78589545
5051
I am looking for a formula, which can give me all the account in sheet 1 in corressponds to the position nr. The anwser is in sheet 2. Can someone please help?
eg. 5001 = should give me 41150100, 41150101, 41200000

Assuming no Excel version constraints as per the tags listed in the question, you can try the following (formula 1):
=LET(pos, A2:A4, accnt, B2:B4, REDUCE({"Account","Position"}, pos, LAMBDA(ac,p,
VSTACK(ac,LET(f,TEXTSPLIT(#FILTER(accnt,pos=p),,","), HSTACK(f, IF(f=f, p)))))))
Here is the output:
Notes:
You would need to clean up your input because in some cases the delimiter is just a comma and in other cases, a space is added.
If the question refers to doing it backward, as #ScottCraner suggested in the comments, then assuming the output from the previous screenshot is now the input, then we have (formula 2):
=LET(acc, D2:D8, pos, E2:E8, ux, UNIQUE(pos), out, MAP(ux, LAMBDA(p,
TEXTJOIN(",",,FILTER(acc, pos=p)))), HSTACK(ux, out))
formula 1: Uses the REDUCE/VSTACK pattern, check my answer to the question: how to transform a table in Excel from vertical to horizontal but with different length for more details on how to use it. In this case, we use the header to initiate the accumulator.
TEXTSPLIT is used to split the account information by , into rows. We use implicit intersection (#) to convert the FILTER output (array of one element only) into a single string to be able to use TEXTSPLIT, otherwise, it returns the first element only.
We use the condition IF(f=f, p) to generate a constant array with the position value (p). HSTACK is used to generate the output on each iteration in the format we want (first account, then position).
A more verbose formula, but maybe easier to understand, since it doesn't use the VSTACK/REDUCE pattern, could be the following:
=LET(pos, A2:A4, accnt, B2:B4, split, TEXTSPLIT(TEXTJOIN(";",,accnt), ",",";"),
mult, MMULT(1-ISNA(split), SEQUENCE(COLUMNS(split),,1,0)),
outP, TOCOL(TEXTSPLIT(TEXTJOIN(";",,REPT(pos&",",mult)),",",";",1),2),
HSTACK(TOCOL(split,2), outP))
The main idea is to use TOCOL. The name split, generates the array with the account information. The name mult, calculates the number of columns with values. Now we know how many times we need to repeat position values. We use REPT to repeat the value and generate an array via TEXTSPLIT.

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 extract specific text from a sentence in Excel?

I have a database that exports data like this:
How can I get for instance, the Net Rentable Area with the values needed:
E.G.
Net Rentable Area
I tried the TextSplit function but I got a spill.
Please let me know what can be done, thanks!
Also it would be nice to see it working in something such as the Asking Rate, which has a different format.
In cell C2 you can put the following formula:
=1*TEXTSPLIT(TEXTAFTER(A2, B2&" ")," ")
Note: Multiplying by 1 ensures the result will be a number instead of a text.
and here is the output:
If all tokens to find are all words (not interpreted as numbers), then you can use the following without requiring to specify the token to find:
=LET(split, 1*TEXTSPLIT(A2," "), FILTER(split, ISNUMBER(split)))
Under this assumption you can even have the corresponding array version as follow:
=LET(rng, A2:A100, input, FILTER(rng, rng <>""), IFERROR(DROP(REDUCE(0, input,
LAMBDA(acc,text, LET(split, 1*TEXTSPLIT(text," "),
nums, FILTER(split, ISNUMBER(split),""), VSTACK(acc, nums)))),1),"")
)
Note: It uses the trick for creating multiple rows using VSTACK within REDUCE. An idea suggested by #JvdV from this answer. It assumes A1 has the title of the column, if not you can use A:A instead.

How/which formula to use, to show combine text results for false condition (for pending task reporting usage)?

Wanted to check if CONCATENATE is the one to use (not sure if my excel has TEXTJOIN), and how to show just the text that has empty value in the cells.
For example in my attachment below, I want the intended result shown like in B2 and B3, where the texts shown with delimiter, when the values are false (empty).
If I were to use CONCATENATE like in Row 10 and Row 11, it's rather manual and it only capture "positive values" as in non-blank cells.
Purpose: To show pending tasks (empty/blank status cells)
Use MID with CONCATENATED IFS:
=MID(IF(C2="","/"&$C$1,"")&IF(D2="","/"&$D$1,"")&IF(E2="","/"&$E$1,"")&IF(F2="","/"&$F$1,"")&IF(GC2="","/"&$G$1,"")&IF(H2="","/"&$H$1,""),2,999)
I would use TEXJOIN and FILTER if you have the newest version of Excel.
For example: =TEXTJOIN("/",1,FILTER($E$2:$I$2, ISBLANK(E3:I3)))
EDIT: For older versions, a temporary workaround is as follows:
make a temporary array the same size as your original dataframe where each value is determined by a formula such as =IF(ISBLANK(E3), E$2&"/","")
Use something like =LEFT(CONCAT(E15:J15), LEN(CONCAT(E15:J15))-1) to get the desired result (where E15:J15 is where I elected to store the first row of the temporary array created in step 1).
I am not sure of your Excel version, but I think this would work in older versions (formatted for readability - will work if you paste it directly into cell B2 and copy down):
=LEFT(CONCAT( INDEX( CHOOSE({1;2;3},$C$1:$H$1,{"/","/","/","/","/","/"},{"","","","","",""}),
INDEX( IF(ISBLANK(C2:H2),{1;2},{3;3}),
MOD(COLUMN(A1:INDEX(1:1,,12))-1,2)+1,
(COLUMN(A1:INDEX(1:1,,12))-1)/2+1 ),
(COLUMN(A1:INDEX(1:1,,12))-1)/2+1 ) ),
SUM(7*ISBLANK(C2:H2))-1 )
Notes
As this is an array formula, you may have to enter it with CTRL + SHIFT + ENTER with an older version of Excel.
The stat labels must all have a length of 6 characters as shown in your post. If not, then they must at least have the same length and the last line SUM(7*ISBLANK(C2:H2))-1 must be changed to replace the 7 with the string length + 1, e.g. a length of 9 would be SUM(10*ISBLANK(C2:H2))-1.
If they don't have the same length, the LEFT( can be removed along with the SUM(10*ISBLANK(C2:H2))-1) at the end. You will end up having a trailing / delimiter at the end. You could fix that for the case of stat F being the last part by changing {"/","/","/","/","/","/"} to {"/","/","/","/","/",""}, but the other cases would still have a trailing /. Another approach is much more complex, but the component SUM(10*ISBLANK(C2:H2))-1) could be shaped to identify what to cut off or maybe a helper column could be built - in any case, let's hope your situation is that the stat labels all have the same length.
The delimiter "/" can be changed, but must always be a single character. If not, then then last line must be changed to SUM( [label length + delimiter length] *ISBLANK(C2:H2))-1.
This formula is fixed to 6 stat columns. If you need for it to accommodate more, it is possible by extending the {"/","/","/","/","/","/"} and {"","","","","",""} (one element for each new column) and replacing every 12 with 2 times the number of columns. Also, obviously, the references $C$1:$H$1 and C1:H2 must be changed to read in your new columns.

Excel: How to find six different combinations of words in string?

I have been working for several days on this and have researched everything looking for this answer. I'd appreciate any help you can give.
In Excel I am searching a string of text in column A:
Bought 1 HD Sep 3 2021 325.0 Call # 2.75
I am detecting the first word (in this case "Bought") and detecting the last word before "#" symbol (in this case "Call").
I am then detecting the price following the "#" symbol (in this case "2.75"). This number will go into column B (header "Open") or column C (header "Close") depending on the combination of words found:
Sold/Put=Close
Sold/Call=Open
Bought/Put=Open
Bought/Call=Close
Sold (by itself)=Open
Sold (by itself)=Close.
Bought 1 HD Sep 3 2021 325.0 Call # 2.75
The combination found in the above string is: "Bought Call". Therefore the number at the end ("2.75"), goes into "Open" column.
Here's another example:
Sold 4 AI Sep 17 2021 50.0 Put # 1.5
The combination found in the above string is: "Sold Put". Therefore the number at the end ("1.5") goes into "Close" column.
I am currently using this formula to determine if the string contains "Sold" and "Call" and get the desired number and it does work:
=IF(AND(
ISNUMBER(SEARCH({"Sold","Call"},A10))),
TRIM(MID(A10,SEARCH("#",A10)+LEN("#"),255))," ")
But, I don't know how to search for all the other possible combinations.
The point behind this is to be able to paste the transaction from the broker and have most of the entry process automated. I'm sure many will benefit from this as I've not found anything like this.
I'd appreciate any help and if possible, an explanation of the formula so I can better learn.
Thanks!
I think you have the right idea, but would just extend the IF statement.
Something like the below might work for you:
=IF(ISNUMBER(SEARCH("Call", $A1)),
IF(ISNUMBER(SEARCH({"Bought","Sold"}, $A1)),
NUMBERVALUE(RIGHT($A1, LEN($A1)-SEARCH("#", $A1))),""),
IF(ISNUMBER(SEARCH({"!!!","!!!","Bought","Sold"}, $A1)),
NUMBERVALUE(RIGHT($A1, LEN($A1)-SEARCH("#", $A1))),""))
Just enter in column B and drag down; columns B through E should fill as needed.
For example:
Note that the search for "!!!" is just random characters, it can be anything that you don't think has a good chance of appearing in the string.
Here/screenshots refer:
(requires Office 365 compatible version Excel)
Main lookup
=LET(fn_1,MATCH("*"&$H$7:$H$12&"*",B4,0),fn_2,MATCH("*"&$I$7:$I$12&"*",B4,0),IFERROR(INDEX($J$7:$J$12,MATCH(1,IF($I$7:$I$12="",fn_1*ISNUMBER(fn_2),fn_1*fn_2),0)),))
EDIT:
Other Excel versions:
=IFERROR(INDEX($J$7:$J$12,MATCH(1,IF($I$7:$I$12="",MATCH("*"&$H$7:$H$12&"*",B4,0)*ISNUMBER(MATCH("*"&$I$7:$I$12&"*",B4,0)),MATCH("*"&$H$7:$H$12&"*",B4,0)*MATCH("*"&$I$7:$I$12&"*",B4,0)),0)),)
(all that falls away is the 'Let' formula, replacing fn_1 and fn_2 with respective functions in index formula within the let making first equation somewhat longer, but otherwise identical)
Example applications
Have provided 2 examples of how one might customize to insert numeric in one of the columns (the key part to this question is really how to do lookup in first instance, from thereon it's a matter of finetuning/taking appropriate action)...
Assuming calls/buys are "long" position and strike price go in first col (here, D), and puts/sales are "short" position with strike price going in 2nd col (here, E):
Long - insert strike price col D
=IF(LET(fn_1,MATCH("*"&$H$7:$H$12&"*",B4,0),fn_2,MATCH("*"&$I$7:$I$12&"*",B4,0),IFERROR(INDEX($K$7:$K$12,MATCH(1,IF($I$7:$I$12="",fn_1*ISNUMBER(fn_2),fn_1*fn_2),0)),))=1,MID(SUBSTITUTE(B4," ",""),SEARCH("#",SUBSTITUTE(B4," ",""))+1,LEN(SUBSTITUTE(B4," ",""))),"")
EDIT
Other Excel versions:
=IF(IFERROR(INDEX($K$7:$K$12,MATCH(1,IF($I$7:$I$12="",MATCH("*"&$H$7:$H$12&"*",B4,0)*ISNUMBER(MATCH("*"&$I$7:$I$12&"*",B4,0)),MATCH("*"&$H$7:$H$12&"*",B4,0)*MATCH("*"&$I$7:$I$12&"*",B4,0)),0)),)=1,MID(SUBSTITUTE(B4," ",""),SEARCH("#",SUBSTITUTE(B4," ",""))+1,LEN(SUBSTITUTE(B4," ",""))),"")
Short - insert strike price col E
=IF(LET(fn_1,MATCH("*"&$H$7:$H$12&"*",B4,0),fn_2,MATCH("*"&$I$7:$I$12&"*",B4,0),IFERROR(INDEX($K$7:$K$12,MATCH(1,IF($I$7:$I$12="",fn_1*ISNUMBER(fn_2),fn_1*fn_2),0)),))=2,MID(SUBSTITUTE(B4," ",""),SEARCH("#",SUBSTITUTE(B4," ",""))+1,LEN(SUBSTITUTE(B4," ",""))),"")
EDIT
Other Excel versions:
Follow same routine in previous Edits (remove Let, replace fn_1 & fn_2 with respective formulae...)
Note similarity in all 3 equations above: 2nd and 3rd contain 1st (effectively they just wrap a big old 'if' statement around 1st, use lookup_2 col (here, col K), and use mid/search to extract rate after the hashtag.
Assumes you don't have other hashtags in the sentence..
Customize as required.

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

Resources