'Can you use SUBSTITUTE for many values without nesting?

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



Solution 1:[1]

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

Solution 2:[2]

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.

Solution 3:[3]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3