Jul 15 2022 10:08 AM
Hi guys, I'm looking for a formula for one of my projects which can help in removing certain parts of a cell (Cell A - names separated by a ;) based on the values in Cell B (similar format as Cell A).
Example
Cell A - cat;dog;rat;rabbit
Cell B - rabbit;dog
Result needs to be - cat;rat
Jul 15 2022 12:41 PM
Here is a custom VBA function:
Function Subtract(s1 As String, s2 As String) As String
Dim a1() As String, a2() As String
Dim v As Variant
a1 = Split(s1, ";")
a2 = Split(s2, ";")
For Each v In a2
a1 = Filter(a1, v, False)
Next v
Subtract = Join(a1, ";")
End Function
Use like this:
=Subtract(CellA,CellB)
Jul 16 2022 10:30 AM
@Hans Vogelaar thank you so much for your input on this and this works perfectly fine. Although I'm running a cloud flow using power automate on this excel and don't want it to affect by using VBA as my connector is excel online. Is there any way I could achieve this same result without using VBA?
Jul 16 2022 11:04 AM
It might be possible using the new string manipulation functions such as TEXTSPLIT but I don't have those yet. Let's see if someone else comes up with a formula-based solution.
Jul 16 2022 01:47 PM
Hi @githinmg99
With Excel Online you can't use FILTERXML to split A2/B2. Until TEXTSPLIT is released, define name TEXT_SPLIT with formula:
=LAMBDA(value,delim,
LET(
seq, SEQUENCE(LEN(value)+1),
Positions, LAMBDA(string,d,s,
LET(
split, MID(string,s,1),
arr, IF(split = d, s),
FILTER(arr, ISNUMBER(arr))
)
),
Start, Positions(delim & value, delim, seq),
End, Positions(value & delim, delim, seq),
MID(value, Start, End-Start)
)
)
then in D2:
=LET(
value, TEXT_SPLIT(A2,";"),
TEXTJOIN(";",,FILTER(value,ISNA(XMATCH(value,TEXT_SPLIT(B2,";")))))
)
When TEXTSPLIT is released
- Replace TEXT_SPLIT with TEXTSPLIT in the above formula
- Delete TEXT_SPLIT in the Named Manager
Jul 16 2022 04:07 PM - edited Jul 16 2022 04:26 PM
Jul 17 2022 12:23 AM
Jul 17 2022 12:39 AM - edited Jul 17 2022 12:50 AM
A #NAME? error means what it means :) - one or more of your defined name or variable isn't recognized
Difficult to say more without seeing your formulas. Could you share your test workbook with i.e OneDrive, Google Drive... ?
Jul 17 2022 03:19 AM
@githinmg99 With Microsoft 365 you can use below formula-
=TEXTJOIN(";",TRUE,LET(x,FILTERXML("<t><s>"&SUBSTITUTE(A2,";","</s><s>")&"</s></t>","//s"),y,FILTERXML("<t><s>"&SUBSTITUTE(B2,";","</s><s>")&"</s></t>","//s"),FILTER(x,NOT(ISNUMBER(XMATCH(x,y,0))))))
Jul 17 2022 06:10 AM
SolutionIn attached file, a different approach for TEXT_SPLIT:
=LAMBDA(Value,Delimiter,
LET(
Positions, LAMBDA(String,Delim,Sequence,
LET(
k, SCAN(0,Sequence, LAMBDA(acc,s, IF(MID(String,s,1)=Delim, acc+s, 0))),
FILTER(k, k > 0)
)
),
Seq, SEQUENCE(LEN(Value)+1),
Start, Positions(Delimiter & Value, Delimiter, Seq),
End, Positions(Value & Delimiter, Delimiter, Seq),
MID(Value, Start, End-Start)
)
)
Updated previous Result formula to account for nothing to return and added a couple of other options that avoid spliting A2 (better IMHO)
in D2:
=LET(
value, TEXT_SPLIT(A2,";"),
TEXTJOIN(";",,FILTER(value,ISNA(XMATCH(value,TEXT_SPLIT(B2,";"))),""))
)
in F2:
=LET(
Removed, REDUCE(A2&";",TEXT_SPLIT(B2,";"),
LAMBDA(value,arr, SUBSTITUTE(value,arr&";",""))
),
IF(LEN(Removed) = 0, "", LEFT(Removed, LEN(Removed)-1))
)
in H2:
=LET(
Removed, REDUCE(LOWER(A2)&";",TEXT_SPLIT(LOWER(B2),";"),
LAMBDA(value,arr, SUBSTITUTE(value,arr&";",""))
),
IF(LEN(Removed) = 0, "", LEFT(Removed, LEN(Removed)-1))
)
Jul 18 2022 09:29 AM
@L z. thanks again. My TEXT_SPLIT formula is still not getting recognized and is giving me the #NAME? error. I have copied the same formula to my name manager. Did I miss out anything?
Jul 18 2022 09:36 AM
On which Excel version you are ? Perhaps SCAN() is not available. Alternatively
textSplit_ =
LAMBDA( str, sep,
LET(
n, LEN(str) - LEN(SUBSTITUTE(str,sep, "") ) + 1,
fakeSep, UNICHAR(9999),
strWithFakeSep, SUBSTITUTE(str, sep, fakeSep, n-1),
fakeSepPosition, FIND( fakeSep, strWithFakeSep ),
head, LEFT( strWithFakeSep, fakeSepPosition - 1 ),
tail, RIGHT(strWithFakeSep, LEN(strWithFakeSep) - fakeSepPosition ),
IF( n=1, IF(str = "", "", str),
IF( SEQUENCE(,n) < n ,
textSplit_( head , sep ),
tail )
)
))
Jul 18 2022 09:54 AM
I'm at lost. In your reply to @Hans Vogelaar you said you were working with Excel Online where LAMBDA, SCAN, REDUCE... functions are available
The 1st version of TEXT_SPLIT I shared did not involve SCAN and you already reported a #NAME? error
IMHO it's more than time to clarify the exact version you're working with - Thanks
Jul 18 2022 10:26 AM
I'm using excel online for this project (linked to my flows in power automate) and like you mentioned LAMBDA function is available in excel online.
Since I'm unable to define name using excel online, I'm using the desktop version (MS 365 ver 16) to just add in the LAMBDA formula under name manager where I'm getting the error. Could you please guide me on the right approach here?
Jul 18 2022 11:56 AM
@L z. I think I can combine both your formula to create a single longer one which would work without errors. Not sure if this is an efficient way but kind of works! Thanks a lot!
LET(
value, LAMBDA(Value,Delimiter,
LET(
Positions, LAMBDA(String,Delim,Sequence,
LET(
k, SCAN(0,Sequence, LAMBDA(acc,s, IF(MID(String,s,1)=Delim, acc+s, 0))),
FILTER(k, k > 0)
)
),
Seq, SEQUENCE(LEN(Value)+1),
Start, Positions(Delimiter & Value, Delimiter, Seq),
End, Positions(Value & Delimiter, Delimiter, Seq),
MID(Value, Start, End-Start)
)
)(A2,";"),
TEXTJOIN(";",,FILTER(value,ISNA(XMATCH(value,LAMBDA(Value,Delimiter,
LET(
Positions, LAMBDA(String,Delim,Sequence,
LET(
k, SCAN(0,Sequence, LAMBDA(acc,s, IF(MID(String,s,1)=Delim, acc+s, 0))),
FILTER(k, k > 0)
)
),
Seq, SEQUENCE(LEN(Value)+1),
Start, Positions(Delimiter & Value, Delimiter, Seq),
End, Positions(Value & Delimiter, Delimiter, Seq),
MID(Value, Start, End-Start)
)
)(B2,";"))),""))
)
Jul 18 2022 12:10 PM
Just to check...
Entered the following in Excel desktop before loading the file to OneDrive
C1: =TEXT_SPLIT(A1,",")
D1: =SPLITTEXT(A1, ",")
F1: =textSplit_(A1,", ")
Edited the file in Excel online and added:
C5: =TEXT_SPLIT(A1,",")
D5: =SPLITTEXT(A1, ",")
F2: =textSplit_(A1,", ")
Can't repro. the #NAME? error - Sorry but no idea right now
Jul 18 2022 10:08 PM
Thanks for sharing a sample workbook with the #NAME? error (attached here in case someone can find a reasonable explaination as I don't)
Opened your file (#NAME? in C2) > Evaluated the formula:
Though it could be a corrupted workbook or something similar. In 2 steps Copied/Pasted the name TEXT_SPLIT then the lambda formula from your workbook to a new workbook ==> No issue
Went back to your workbook, tried in a new cell =TEXT_SPLIT, pressed <Tab> ==> No auto. opening parenthese showing the function parameters (???)
Still from the workbook you shared:
- Renamed TEXT_SPLIT as HELLO ==> No more #NAME? error
- Renamed HELLO as TEXT_SPLIT ==> Still no error
(Windows Defender didn't report any issue on your file)
Jul 19 2022 01:49 AM
As a comment, it's not necessary to jump between Excel online and desktop versions. You may install Advanced Formula Environment add-in on Excel for web and work with it.
Jul 17 2022 06:10 AM
SolutionIn attached file, a different approach for TEXT_SPLIT:
=LAMBDA(Value,Delimiter,
LET(
Positions, LAMBDA(String,Delim,Sequence,
LET(
k, SCAN(0,Sequence, LAMBDA(acc,s, IF(MID(String,s,1)=Delim, acc+s, 0))),
FILTER(k, k > 0)
)
),
Seq, SEQUENCE(LEN(Value)+1),
Start, Positions(Delimiter & Value, Delimiter, Seq),
End, Positions(Value & Delimiter, Delimiter, Seq),
MID(Value, Start, End-Start)
)
)
Updated previous Result formula to account for nothing to return and added a couple of other options that avoid spliting A2 (better IMHO)
in D2:
=LET(
value, TEXT_SPLIT(A2,";"),
TEXTJOIN(";",,FILTER(value,ISNA(XMATCH(value,TEXT_SPLIT(B2,";"))),""))
)
in F2:
=LET(
Removed, REDUCE(A2&";",TEXT_SPLIT(B2,";"),
LAMBDA(value,arr, SUBSTITUTE(value,arr&";",""))
),
IF(LEN(Removed) = 0, "", LEFT(Removed, LEN(Removed)-1))
)
in H2:
=LET(
Removed, REDUCE(LOWER(A2)&";",TEXT_SPLIT(LOWER(B2),";"),
LAMBDA(value,arr, SUBSTITUTE(value,arr&";",""))
),
IF(LEN(Removed) = 0, "", LEFT(Removed, LEN(Removed)-1))
)