The function I expected
some_function(original_text, "search_text", "replacement_text")
The value of the second & third parameters will be multiple characters. For example. The result will replace the character based on the location of the character at the second & third parameters
some_function("9528", "1234567890", "abcdefghij")
1 -> a
2 -> b
3 -> c
...
8 -> h
9 -> i
0 -> j
The result of some_function will be iebh. The nested SUBSTITUTE function can archive the goal but I hope to compact the complexity.
The way you described your requirement is best written out via REDUCE(), a lambda-related helper function and recently announced to be in production:
=REDUCE("9528",SEQUENCE(10),LAMBDA(x,y,SUBSTITUTE(x,MID("1234567890",y,1),MID("abcdefghij",y,1))))
Needless to say, this would become more vivid when used with cell-references:
Formula in A3:
=REDUCE(A1,SEQUENCE(LEN(B1)),LAMBDA(x,y,SUBSTITUTE(x,MID(B1,y,1),MID(C1,y,1))))
Another, more convoluted way, could be:
=LET(A,9528,B,1234567890,C,"abcdefghij",D,MID(A,SEQUENCE(LEN(A)),1),CONCAT(IFERROR(MID(C,FIND(D,B),1),D)))
Or, as per the sceenshot above:
=LET(A,A1,B,B1,C,C1,D,MID(A,SEQUENCE(LEN(A)),1),CONCAT(IFERROR(MID(C,FIND(D,B),1),D)))
Function Multi_Replace(Original As String, Search_Text As String, Replace_With As String) As String
'intEnd represents the last character being replaced
Dim intEnd As Long: intEnd = WorksheetFunction.Min(Len(Search_Text), Len(Replace_With))
'necessary if Search text and replace text are different lengths;
Dim intChar As Long 'to track which character we're replacing
'Replace each character individually
For intChar = 1 To intEnd
Original = Replace(Original, Mid(Search_Text, intChar, 1), Mid(Replace_With, intChar, 1))
Next
Multi_Replace = Original
End Function
Maybe simpler if you do not have lambda yet: =TEXTJOIN(,,CHAR(96+MID(A1,SEQUENCE(LEN(A1)),1)))
*Note that this will not return 0 as the expected result.
Let's say you have a list of countries in column A and aim to replace all the abbreviations with the corresponding full names. you start with inputting the "Find" and "Replace" items in separate columns (D and E respectively), and then enter this formula in B2:
=XLOOKUP(A2, $D$2:$D$4, $E$2:$E$4, A2)
Translated from the Excel language into the human language, here's what the formula does:
Search for the A2 value (lookup_value) in D2:D4 (lookup_array) and return a match from E2:E4 (return_array). If not found, pull the original value from A2.
Double-click the fill handle to get the formula copied to the below cells, and the result won't keep you waiting:
Since the XLOOKUP function is only available in Excel 365, the above formula won't work in earlier versions. However, you can easily mimic this behavior with a combination of IFERROR or IFNA and VLOOKUP:
=IFNA(VLOOKUP(A2, $D$2:$E$4, 2, FALSE), A2)
This question already has answers here:
How to add multiple links in excel cell?
(2 answers)
Closed 1 year ago.
TLDR:
Unknown error appears if you have a formula constructed like this:
IFNA(Link1;Link2)
However, below example works which is basically the same thing,
A1: Link1
A2: IFNA(A1;Link2)
Edit: Formula in URLTEXT when IFNA function contains two LINK functions might be the culprit.
Any ideas why this might be?
Hi,
i am trying to make a dynamic link on cell C1. From a search string it looks through column A to find the search string on cell A1. I have added an IFNA function that checks if entery is missing in column A. If this happens then it looks for the search string A1 again but in column B.
The problem and unknown error,
when it matches with a string on column B then the dymanic link throws an error:
(Rough translation from swedish)
"file:///(long path)/ABCD%3F" is not an absolut URL that can be sent to an external program be opened."
However, each dynamic link works seperatly. It is when i combine them with the IFNA that this problem occur.
It seems like the constructed link is equal to the URLTEXT from the first lookup when it is supposed to be the row number from the second lookup.
I suspect this is the reason the link fails. I might be wrong though and i cant see why this would happen.
When breaking down the components into smaller parts all looks good:
Picture showing the setup and component breakdown
Picture showing formulas
Below is the setup for replicating this issue. Formulas and their belonging cells:
A1 = "ABC"
A3 = "acol"
A4 = "AB"
A5 = "CD"
B3 = "bcol"
B3 = "ABCD"
B4 = "CDEF"
C3 = "acode"
D3 = "bcode"
Renamed cells:
lookup_search_cell = A1
lookup_code_arr = A4:D5
translated_lookup_search_cell = B1
lookup_acode_col = C4:C5
lookup_bcode_col = D4:D5
B1:
=CONCATENATE(,
IF(CODE(MID(UPPER(A1),1,1))=0,CODE(MID(UPPER(A1),1,1))),
IF(CODE(MID(UPPER(A1),2,1))=0,CODE(MID(UPPER(A1),2,1))),
IF(CODE(MID(UPPER(A1),3,1))=0,CODE(MID(UPPER(A1),3,1))),
IF(CODE(MID(UPPER(A1),4,1))=0,CODE(MID(UPPER(A1),4,1))))
C1:
=IF(lookup_search_cell="","Enter🔎",
IFNA(
IFNA(
LINK("#sheet1.$A$" &
MATCH(translated_lookup_search_cell&"*",lookup_acode_col,0)+3 & ":" & "$B$" &
MATCH(translated_lookup_search_cell&"*",lookup_acode_col,0)+3,
IFERROR(
INDEX(lookup_code_arr,
MATCH(translated_lookup_search_cell&"*",lookup_acode_col,0),1
)&"?","Cant find acol entery"
)
),
LINK("#sheet1.$A$"&
MATCH(translated_lookup_search_cell&"*",lookup_bcode_col,0)+3 & ":" & "$B$" &
MATCH(translated_lookup_search_cell&"*",lookup_bcode_col,0)+3,
IFERROR(
INDEX(lookup_code_arr,
MATCH(translated_lookup_search_cell&"*",lookup_bcode_col,0),2
)&"?","Cant find bcol entery"
)
)
),"Cant find entery"
)
)
C4:
=CONCATENATE(,
IF(CODE(MID(UPPER(A4),1,1))=0,CODE(MID(UPPER(A4),1,1))),
IF(CODE(MID(UPPER(A4),2,1))=0,CODE(MID(UPPER(A4),2,1))),
IF(CODE(MID(UPPER(A4),3,1))=0,CODE(MID(UPPER(A4),3,1))),
IF(CODE(MID(UPPER(A4),4,1))=0,CODE(MID(UPPER(A4),4,1))))
C5:
=CONCATENATE(,
IF(CODE(MID(UPPER(A5),1,1))=0,CODE(MID(UPPER(A5),1,1))),
IF(CODE(MID(UPPER(A5),2,1))=0,CODE(MID(UPPER(A5),2,1))),
IF(CODE(MID(UPPER(A5),3,1))=0,CODE(MID(UPPER(A5),3,1))),
IF(CODE(MID(UPPER(A5),4,1))=0,CODE(MID(UPPER(A5),4,1))))
D4:
=CONCATENATE(,
IF(CODE(MID(UPPER(B4),1,1))=0,CODE(MID(UPPER(B4),1,1))),
IF(CODE(MID(UPPER(B4),2,1))=0,CODE(MID(UPPER(B4),2,1))),
IF(CODE(MID(UPPER(B4),3,1))=0,CODE(MID(UPPER(B4),3,1))),
IF(CODE(MID(UPPER(B4),4,1))=0,CODE(MID(UPPER(B4),4,1))))
D5:
=CONCATENATE(,
IF(CODE(MID(UPPER(B5),1,1))=0,CODE(MID(UPPER(B5),1,1))),
IF(CODE(MID(UPPER(B5),2,1))=0,CODE(MID(UPPER(B5),2,1))),
IF(CODE(MID(UPPER(B5),3,1))=0,CODE(MID(UPPER(B5),3,1))),
IF(CODE(MID(UPPER(B5),4,1))=0,CODE(MID(UPPER(B5),4,1))))
Sorry, i think this was a repost, found answer here.
How to add multiple links in excel cell?
This question can be deleted. If true then thanks to Didier for the information.
Here is another solution instead if anyone find it interesting,
=OM(lookup_search_cell=""
;
"Enter🔎"
;
LÄNK("#sheet1.$A$"&
OMSAKNAS(
PASSA(translated_lookup_search_cell&"*";lookup_acode_col;0)+3&":"&"$B$"&
PASSA(translated_lookup_search_cell&"*";lookup_acode_col;0)+3
;
PASSA(translated_lookup_search_cell&"*";lookup_bcode_col;0)+3&":"&"$B$"&
PASSA(translated_lookup_search_cell&"*";lookup_bcode_col;0)+3
)
;
OMSAKNAS(
INDEX(lookup_code_arr;
PASSA(translated_lookup_search_cell&"*";lookup_acode_col;0);1
)&"?"
;
INDEX(lookup_code_arr;
PASSA(translated_lookup_search_cell&"*";lookup_bcode_col;0);2
)&"?"
)
)
)
Conclution, you cant have multiple links in the same cell but you can mold the one and only link to what you want it to be.
I want to join a list of words in Excel (not in VBA... with an Excel formula in the worksheet) to the following specifications:
Formula should ignore empty cells.
Formula should concatenate the words with "and" before final item if there is more than one item in the array of cells.
Formula should add "," between items if there are more than two items.
Examples:
A1=dog
A2=cat
A3=bird
A4=fish
Result would be: dog, cat, bird, and fish
A1=dog
A2=cat
A3=(empty cell)
A4=fish
Result would be: dog, cat, and fish
A1=dog
A2=(empty cell)
A3=bird
A4=(empty cell)
Result would be: dog and bird
A1=dog
A2=(empty cell)
A3=(empty cell)
A4=(empty cell)
Result would be: dog
Pretty please? I promise I've searched and searched for the answer.
Edit: Thank you, ExcelArchitect, I got it! This was the first time I'd ever used a custom function. You use it just like any other function in the worksheet! This is so great.
Not to push my luck, but how to do I get two cells to concatenate with my result if there is only one word in the result and two other cells if there is more than one word? Example: If the function you made for me returns just "dog", I'd want it to concatenate a cell with the text (B1) "My favorite thing to wear is a " and then "dog" and then another cell (B2) that says " costume." to make the sentence "My favorite thing to wear is a dog costume." But if it returns more than one animal, it would concatenate two other cells like this: Cell C1 "My favorite things to wear are " and "dog, cat, and bird" and Cell C2 " costumes." so that it would say "My favorite things to wear are dog, cat, and bird costumes."
If you're curious, my data really has nothing to do with animals or costumes. I am writing a program that will score a psychological test and then create an interpretive report from the test scores (I'm a psychologist).
-Mary Anne
Mary Anne:
This would be a great time to use VBA! But if you don't want to, there is a way to accomplish your goal without it.
You have to account for all of the possible outcomes here. With 4 different animals that means you have 15 outcomes:
Your equation just has to take into account all 15. It is VERY long and drawn out as a result. As such, if you have more than 4 animals that you'd like to turn into phrases, you should go the VBA route.
Here is my set up:
The formula in A7 is the following:
=IF(AND(A2<>"", A3="", A4="", A5=""), A2, IF(AND(A2="", A3<>"", A4="", A5=""), A3, IF(AND(A2="", A3="", A4<>"", A5=""), A4, IF(AND(A2="", A3="", A4="", A5<>""), A5, IF(AND(A2<>"", A3<>"", A4="", A5=""), A2&" and "&A3, IF(AND(A2<>"", A3="", A4<>"", A5=""), A2&" and "&A4, IF(AND(A2<>"", A3="", A4="", A5<>""), A2&" and "&A5, IF(AND(A2="", A3<>"", A4<>"", A5=""),A3&" and "&A4, IF(AND(A2="", A3<>"", A4="", A5<>""), A3&" and "&A5, IF(AND(A2="", A3="", A4<>"", A5<>""),A4&" and "&A5, IF(AND(A2<>"", A3<>"", A4<>"", A5=""), A2&", "&A3&", and "&A4, IF(AND(A2<>"", A3<>"", A4="", A5<>""), A2&", "&A3&", and "&A5, IF(AND(A2<>"", A3="", A4<>"", A5<>""), A2&", "&A4&", and "&A5, IF(AND(A2="", A3<>"", A4<>"", A5<>""), A3&", "&A4&", and "&A5, A2&", "&A3&", "&A4&", and "&A5))))))))))))))
Here it is via Excel:
Mary Anne - I'm such a nerd that I had to do this. Here is the VBA solution, and you can have as many names as you want! Paste this code into a new module in the workbook (go to Developer -> Visual Basic, then Insert -> New Module, and paste), then you can use it in your worksheet like a regular function. Just give it the range where the names are and you should be good to go! -Matt
Function CreatePhrase(NamesRng As Range) As String
'Creates a comma-separated phrase given a list of words or names
Dim Cell As Range
Dim l As Long
Dim cp As String
'Add commas between the values in the cells
For Each Cell In NamesRng
If Not IsEmpty(Cell) And Not Cell.Value = "" And Not Cell.Value = " " Then
cp = cp & Cell.Value & ", "
End If
Next Cell
'Remove trailing comma and space
If Right(cp, 2) = ", " Then cp = Left(cp, Len(cp) - 2)
'If there is only one value (no commas) then quit here
If InStr(1, cp, ",", vbTextCompare) = 0 Then
CreatePhrase = cp
Exit Function
End If
'Add "and" to the end of the phrase
For l = 1 To Len(cp)
If Mid(cp, Len(cp) - l + 1, 1) = "," Then
cp = Left(cp, Len(cp) - l + 2) & "and" & Right(cp, l - 1)
Exit For
End If
Next l
'If there are only two words or names (only one comma) then remove the comma
If InStr(InStr(1, cp, ",", vbTextCompare) + 1, cp, ",", vbTextCompare) = 0 Then
cp = Left(cp, InStr(1, cp, ",", vbTextCompare) - 1) & Right(cp, Len(cp) - InStr(1, cp, ",", vbTextCompare))
End If
CreatePhrase = cp
End Function
Hope that helps!
Matt, via ExcelArchitect.com
VBA is simpler. A formula is quite complicated, since Excel has no native functions allowing concatenation of a range. However, given that you have written that you would have up to eight animals, it is doable with the following formula which concatenates the contents of A1:A8 according to your rules. You can change those locations in the formula in the obvious locations.
I made one change: I may be wrong, but I believe English rules indicate that the comma preceding the last and should be omitted, so I did so. It could be added in if necessary. EDIT: Further investigation reveals a difference between US and UK rules: US rules are as you requested, UK rules omit the comma before the conjunction. I will modify the formulas and UDF to comply with US conventions.
In the formulas, the modification is to place a comma immediately prior to the and. The change in the UDF is likewise minor.
The formula was constructed from the following sequences:
So putting those formulas together, so as only to refer to A1:A8, we wind up with this monster:
=SUBSTITUTE(IFERROR(SUBSTITUTE(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","),2,LEN(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","))-2),",",",and ",LEN(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","),2,LEN(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","))-2))-LEN(SUBSTITUTE(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","),2,LEN(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","))-2),",",""))),MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","),2,LEN(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(CONCATENATE(",",A1,",",A2,",",A3,",",A4,",",A5,",",A6,",",A7,",",A8,","),",,",","),",,",","),",,",","))-2)),",",", ")
Here is a VBA solution which will allow for any number of items; it concatenate according to the same rules as above.
Option Explicit
Function ConcatRangeWithAnd(RG As Range, Optional Delim As String = ", ")
Dim COL As Collection
Dim C As Range
Dim S As String
Dim I As Long
Set COL = New Collection
For Each C In RG
If Len(C.Text) > 0 Then COL.Add C.Text
Next C
Select Case COL.Count
Case 0
Exit Function
Case 1
ConcatRangeWithAnd = COL(1)
Case 2
ConcatRangeWithAnd = COL(1) & " and " & COL(2)
Case Else
For I = 1 To COL.Count - 1
S = S & COL(I) & ", "
Next I
ConcatRangeWithAnd = S & "and " & COL(COL.Count)
End Select
End Function
With the new TEXTJOIN function, this can be done very easily.
Step 1: Use TEXTJOIN function with the ", " delimiter, and set the ignore_empty to TRUE. This will give you comma separated, concatenated string, ignoring the blank values.
Step 2: Count the number of not blank entries in the list using COUNTA function. And subtract 1 from it. You might want to floor the value at 1 using the MAX function at this point.
Step 3: Use the SUBSTITUTE function to replace the last instance of the comma, which was calculated in Step 2, with a " and ".
Putting it all together:
=SUBSTITUTE(TEXTJOIN(", ",TRUE,A1:A14),", "," and ",MAX(1,COUNTA(A1:A14)-1))
Plug in any Range you want instead of A1:A14 in the above formula, and you will get a comma separated concatenate with an and before the last word.
Regarding duplicates:
Firstly, I really love Matt's solution and I've added this to my collection of custom functions.
What I do miss though is the possibility to remove duplicates from the phrase without removing them from the original range.
As you can't create a virtual range (a range that you can just play with in VBA independently from your source data), the solution would probably involve converting the range to an array, running some deduplication code and then creating the phrase from that.
My solution (albeit inelegant) is just to use the UNIQUE and FILTER functions to get a deduplicated list elsewhere on the spreadsheet (can be hidden if it bothers you) and to use Matt's function on that.
=UNIQUE(FILTER(yourRange,yourRange<>""))
I have an error in this excel formula and I can't just figure it out:
=LEFT(B3,FIND(",",B3&",")-1)&","&RIGHT(B3,LEN(B3)-FIND("&",B3&"&")),RIGHT(B3,LEN(B3)-SEARCH("#",SUBSTITUTE(B3," ","#",LEN(B3)-LEN(SUBSTITUTE(B3," ",""))))&", "&SUBSTITUTE(RIGHT(B3,LEN(B3)-FIND("&",B3&"&")-1),RIGHT(B3,LEN(B3)-SEARCH("#",SUBSTITUTE(B3," ","#",LEN(B3)-LEN(SUBSTITUTE(B3," ",""))))),""))
It may seem like a big formula, but all it's intended to do is if no ampersand is in a cell, return an empty cell, if no comma but ampersand exists, then return this, for example:
KNUD J & MARIA L HOSTRUP
into this:
HOSTRUP,MARIA L
Otherwise, there is no ampersand but there is a comma so we just return: LEFT(A1,FIND("&",A1,1)-1).
Seems basic, but formula has been giving me error message and doesn't point to the problem.
Your error is here:
=LEFT(B3,FIND(",",B3&",")-1)&","&RIGHT(B3,LEN(B3)-FIND("&",B3&"&")),
At this point, the comma doesn't apply to anthing, because the right operator has matching parens
As far as what you want? Let's break that up into what you actually asked for:
if no ampersand in a cell, return empty cell,
B4=Find("&", B3&"&")
B5=IF(B4>LEN(B3),"",B6)
if no comma but ampersand exists
B6=IF(FIND(",", B3&",")>LEN(B3),B8,B7)
then turn this, for example:
KNUD J & MARIA L HOSTRUP
into this:
HOSTRUP,MARIA L
I'm presuming you mean to put the last whole word? Let's mark the last whole word:
B9=SUBSTITUTE(B3," ","#",LEN(B3)-LEN(SUBSTITUTE(B3," ","")))
B10=RIGHT(B7,LEN(B9)-FIND("#",B9))
And the stuff between the ampersand and the last word
B11=TRIM(MID(B9,B4 + 1, LEN(B9)-FIND("#",B9)-1))
Then calculating it is easy
B7=B10&","&B11
Otherwise, there is no ampersand but there is a comma so we just return:
LEFT(A1,FIND("&",A1,1)-1).
Well, if you want that, let's just put that in B8
B8=LEFT(A1,FIND("&",A1,1)-1)
(But I think you actually mean B3 instead of A1)
B8=LEFT(B3,FIND("&",B3,1)-1)
And there you have it (B5 contains the information you're looking for) It took a few cells, but it's easier to debug this way. If you want to collapse it, you can (but doing so is more code, because we can reduce duplication by referencing a previously calculated cell on more than one occasion).
Summary:
B3=<Some Name with & or ,>
B4=FIND("&", B3&"&")
B5=IF(B4>LEN(B3),"",B6)
B6=IF(FIND(",", B3&",")>LEN(B3),B7,B8)
B7=B10&","&B11
B8=LEFT(B3,FIND("&",B3,1)-1)
B9=SUBSTITUTE(B3," ","#",LEN(B3)-LEN(SUBSTITUTE(B3," ","")))
B10=RIGHT(B9,LEN(B9)-FIND("#",B9))
B11=TRIM(MID(B9,B4 + 1, LEN(B9)-FIND("#",B9)-1))
When I put in "KNUD J & MARIA L HOSTRUP", I get "HOSTRUP,MARIA" in B5.