5

Is there a way to swap many instances of strings at once without nesting?

For instance, say I want to drop all instances of the following values from a string:

  • Target
  • Walmart
  • CVS

Input String: "I went to Target instead of Walmart but I really wanted to go to CVS"
Output String: "I went to instead of but I really wanted to go to "


I tried =SUBSTITUTE(A1,H1:H3,"") where A1 is the input and H1:H3 are the strings to replace but this only swaps the first string

I know how to do this in VBA but this project cannot use VBA

JvdV
  • 70,606
  • 8
  • 39
  • 70
urdearboy
  • 14,439
  • 5
  • 28
  • 58
  • 1
    Short Answer...No. It is the most frustrating thing. Maybe with Lamda... – Scott Craner Aug 06 '21 at 17:10
  • I know I was thinking about Lamda earlier! Bummer. There is about 60 values I need to swap so nested substitutions is a big no-go @ScottCraner. Thanks for confirming my worst fears :P – urdearboy Aug 06 '21 at 17:11
  • VBA my Friend...Write your own UDF, then answer here so we all can steal it. :) – Scott Craner Aug 06 '21 at 17:13
  • 4
    Here is the reference to using lambda for multiple replace (well done JvdV) https://stackoverflow.com/questions/65364904/excel-how-can-we-replace-multiple-characters-or-whole-words-in-a-cell-using-la – Tom Sharpe Aug 06 '21 at 17:21
  • @ScottCraner when is that function being made available to all? – urdearboy Aug 06 '21 at 17:37
  • 1
    Which function? LAMBDA? I am not sure. Not sure anyone outside Microsoft knows. – Scott Craner Aug 06 '21 at 17:43
  • You can get it on an individual basis now by signing up to Microsoft's Insider program, but I don't know how that would help in a work environment. – Tom Sharpe Aug 06 '21 at 17:45
  • 1
    @TomSharpe yea not scalable. Would be fun to play with but no added value in prod – urdearboy Aug 06 '21 at 17:46
  • @TomSharpe has it finally been rolled to all insiders? I know they were doing it in groups, not all got it at the same time. – Scott Craner Aug 06 '21 at 17:46
  • Isn't LAMBDA available in Excel365 without signing up for the Insider program? – norie Aug 06 '21 at 17:48
  • I had to register for the Insider program then select the Beta channel, but that was several weeks ago. – Tom Sharpe Aug 06 '21 at 17:49
  • 1
    I had done that in January and still do not have it. @TomSharpe – Scott Craner Aug 06 '21 at 17:50
  • 1
    The Insider program isn't mentioned here - https://support.microsoft.com/en-us/office/lambda-function-bd212d27-1cd1-4321-a34a-ccbf254b8b67 – norie Aug 06 '21 at 17:53
  • Yes, it looks as though it's become a standard function for Excel 365 users doesn't it? – Tom Sharpe Aug 06 '21 at 17:58
  • 1
    @ScottCraner I didn't see this being a hot topic question lol. I thought this post would die when you said "Short Answer...No" lol – urdearboy Aug 06 '21 at 19:42

3 Answers3

7

Update 27-4-'22:

Since LAMBDA() and it's helper functions have now been released to the production versions of ms365, one could use REDUCE():

=TRIM(REDUCE(A1,{"Target","Walmart","CVS"},LAMBDA(a,b,SUBSTITUTE(a,b,""))))

Or, even try:

=TEXTJOIN(" ",,TEXTSPLIT(A1,{" ","Target","Walmart","CVS"}))

But, be aware of possible false positives, however SUBSTITUTE() and TEXTSPLIT() are both case-sensitive so for these proper words it seemed to work out fine. To counter false positives, 1st change spaces to tripple spaces for example and go from there (or use the old answer which is still valid). Another option is to nest FILTER():

=TEXTJOIN(" ",,REDUCE(TEXTSPLIT(A1," ",,1),{"Target","Walmart","CVS"},LAMBDA(a,b,FILTER(a,a<>b))))

Old Answer (Still valid since it avoids false positives):

I guess I'd go with a "Yes it's possible, but..." answer. It may be a stretch but I noticed you haven't used any punctuation which lead me to believe we can split a string on the space and filter out the unwanted parts that way, piecing back together the wanted parts:

enter image description here

Formula in A2:

=TEXTJOIN(" ",,FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s["&TEXTJOIN(" and ",,".!= '"&B1:B3&"'")&"]"))

Now you can add as many values to your range of unwanted strings without further adaptation to your formula.

  • Note that this does require Excel 2019 or later for the TEXTJOIN() to work. With Excel 2019 you'd also need to confirm through CtrlShiftEnter.
  • Also note that this will need some adaptation the minute you start using punctuation.
  • A last remark is that FILTERXML() is case-sensitive.
JvdV
  • 70,606
  • 8
  • 39
  • 70
  • 1
    Yo yall are crazy. This is amazing. I've said it before and i'll say it again, FILTERXML makes for impressive solutions always. It only makes sense in the context of a problem and solution but I have never been able to implement myself – urdearboy Aug 06 '21 at 19:41
6

There is no way with SUBSTITUTE outside of nesting to do what is wanted. In the future LAMBDA will be an option.

For now and for backwards compatibility, here is a UDF that creates a function that takes many inputs and replaces them with the desired output.

It uses a param array so one can also create individual replacements:

Function SUBALL(str As String, ParamArray arr() As Variant) As String
    Dim i As Long
    For i = LBound(arr) To UBound(arr) Step 2
        Dim rngarr As Variant
        rngarr = arr(i)
        
        If UBound(arr) > i Then
            Dim rpArr As Variant
            rpArr = arr(i + 1)
        Else
            Dim df As Boolean
            df = True
        End If
        
        If TypeName(rngarr) = "String" Then
            If df Then
                str = Replace(str, rngarr, "")
            Else
                str = Replace(str, rngarr, rpArr)
            End If
        Else
            Dim j As Long
            For j = LBound(rngarr, 1) To UBound(rngarr, 1)
                If df Then
                    str = Replace(str, rngarr(j, 1), "")
                Else
                    str = Replace(str, rngarr(j, 1), rpArr(j, 1))
                End If
            Next j
        End If
    Next i
    
    SUBALL = str
End Function

It defaults to a replace of ""

So in this instance:

=SUBALL(A1,H1:H3)

enter image description here

But we can also do where we specify the output:

=SUBALL(A1,H1:H3,I1:I3)

enter image description here

Or we can put the options as strings in the formula itself with their desired replacements:

=SUBALL(A1,"Target","MyVal","Walmart","","CVS","Long Receipt Place")

enter image description here


As with all UDF, there are some rules that must be followed. The pairs must have the same number of arguments. You CANNOT do:

=SUBALL(A1,H1:H3,"Word")

It will fail. But:

=SUBALL(A1,H1:H3,{"Word";"Word";"Word"})

Will work.

enter image description here


With SCAN and LAMBDA:

=LET(rpl,H1:H3,str,A1,INDEX(SCAN(str,rpl,LAMBDA(a,b,SUBSTITUTE(a,b,""))),COUNTA(rpl)))

enter image description here

If we want to replace words with other words we can use:

=LET(orig,H1:H3,rpl,I1:I3,str,A1,cnt,COUNTA(rpl),INDEX(SCAN(str,SEQUENCE(cnt),LAMBDA(a,b,SUBSTITUTE(a,INDEX(orig,b),INDEX(rpl,b)))),COUNTA(rpl)))

enter image description here

Scott Craner
  • 148,073
  • 10
  • 49
  • 81
  • 1
    Incredible @Scott Craner now we have Lamba alternative :) – Rajput Aug 06 '21 at 18:39
  • This is amazing! * quietly deletes my answer before anybody notices * lol – urdearboy Aug 06 '21 at 19:04
  • Hi @ScottCraner, I voted the answer as it's neat! Two small remarks; you may want to include `CLEAN()` or some other way to counter the double spaces left after removal. Another thing I see is that you would replace substrings too. As in "US" from "USA". Thought I'd let you know. – JvdV Aug 06 '21 at 19:42
  • 1
    @jvdv I wanted to make it as close to SUBSTITUTE as possible. Just in case the user wants all that left. They can always wrap the full formula in `TRIM()` and provide values with the spaces on the ends, just like SUBSTITUTE. If I put in my interpretations too much it becomes too narrow. – Scott Craner Aug 06 '21 at 19:46
  • Fair enough =). OP mentioned in another comment, word-boundaries won't be a thing to consider anyways. – JvdV Aug 06 '21 at 19:46
  • +1 just for "long receipt place". The param array means you can have as many arguments as possible as long as they are in pairs? – findwindow Apr 27 '22 at 17:32
  • 1
    That is correct, as long as they are in pairs. – Scott Craner Apr 27 '22 at 17:44
1

I was hoping to find a manageable spreadsheet formula to do this but it sounds like VBA is needed until Lambda is available to the masses.

Public Function ARR_REPLACE(xInput As String) As String

Dim Arr
Arr = Array("Target", "Walmart", "CVS")

Dim i As Long

For i = LBound(Arr) To UBound(Arr)
    xInput = Replace(xInput, Arr(i), "", , , vbTextCompare)
Next i

ARR_REPLACE = xInput

End Function
urdearboy
  • 14,439
  • 5
  • 28
  • 58