I have a sample data (1,2,3,4) on A2:D2 columns and on F1, I have (1,3), and on G1 (2,3,4).
I was suggested to use this formula
=INDEX($A2:$D2,AGGREGATE(15,6,ROW($A2:$D2)/ISNUMBER(SEARCH(TEXT($A2:$D2,"000,"),F$1&",")),1))
on F2, and G2 which is supposed to give the matching values on F2 and G2 respectively. Since both values (1,3) match, the result should be (1,3) on F2, and (2,3,4) on G2.
So basically this formula is supposed to work like index/match formula but instead of single values, it works on comma separated 2 or 3 values.
When I try to use the formula I keep getting #NUM! error. Can I get a little help to make this formula work, please?
Thanks.
Note: I am open to alternative solutions, but if it requires VBA, it has to be with a user defined formula. Without UDF, it is not useful for me.
A UDF should look like this
Option Explicit
Function MultFind(r As Range, s As String) As String
Dim c As Range
Dim result As String
For Each c In r
If InStr("," & s & ",", "," & c & ",") <> 0 Then result = result & c & ","
Next c
If Len(result) > 0 Then result = Left(result, Len(result) - 1)
MultFind = result
End Function
Called as
=MultFind($A2:$D2,F1)
Edit
Here it is with optional parameter for delimiter:
Option Explicit
Function MultFind(r As Range, s As String, Optional delimiter As String = ",") As String
Dim c As Range
Dim result As String
' Check each cell in range against search string
For Each c In r
If InStr(delimiter & s & delimiter, delimiter & c & delimiter) <> 0 Then result = result & c & delimiter
Next c
' Delimiter may be more than one character
If Len(result) > 0 Then result = Left(result, Len(result) - Len(delimiter))
MultFind = result
End Function
Related
I have a scenario where I have to read through values in one cell which is comma separated and retrieve only values from that array to match with a particular lookup value. For eg:
So what I need is a function to retrieve all Task(or any other issuetype which could vary) from row 2 Links column
expected result: Against A2 I want to retrieve A4 and A6
This is something I modified so that you could customize it to any lookup value
Function GetLinkedItem(link As String, targetLinkType As String)
Dim temp(0 To 0) As String
GetLinkedItem = "None"
If Trim(link) = "" Then Exit Function
Dim links() As String, i As Long
links = Split(link, ",")
For i = 0 To UBound(links)
'select the links that are targetLinkType
Dim j As Long
j = GetRow(Trim(links(i)))
If Sheets("Data").Cells(j, ISUUETYPE_COL) = targetLinkType Then
temp(0) = temp(0) & " " & Sheets("Data").Cells(j, ID_COL) & ","
End If
GetLinkedItem = Join(temp, ",")
Next i
End Function
You can create a UDF to perform this lookup. In a new module in your VBE, paste the following:
Function getTasks(tasklist As Range, availabletasks As Range) As String
'tasklist is the incoming array in Column C
'availabletasks is the stuff in Column A
'Array for output
Dim tasks() As String: ReDim tasks(0 To 0)
'Loop through each item in taslist using an array
For Each task In Split(tasklist.Value, ", ")
'Search availabletasks
If Not availabletasks.Find(task) Is Nothing Then
'pop the array
If tasks(0) <> "" Then ReDim Preserve tasks(0 To UBound(tasks) + 1)
tasks(UBound(tasks)) = task
End If
Next
'Return what we found
getTasks = Join(tasks, ", ")
End Function
Now in your spreadsheet you can use this function just like a regular formula:
=getTasks(C1,$A$1:$A$6)
Where C1 has the list like A4, A25, A22, A6, A29, A42 and $A$1:$A$6 are just like your example Column A. This will return A4, A6
Thanks so much. I added the code in a new module and used the function as formula. I was getting just 1 value instead of 2(Just got A4 and not A6).
In Excel, I need to Concatenate every other cell into one "master" cell. I have used this formula to conquer before =SUBSTITUTE(TRIM(G2 & " " & BC2 & " " & BE2 & " " & BG2), " ", ", ") but this alters the data when the data I am concatenate has a comma in it.
The range of cells that I need to concatenate is every other cell ranging from G2 all the way to BG2. What would be the best course of action to make this happen handling concatenation that involves comma lists?
EDIT
By what I mean with alters data is that this
S223 - Pills, S2323 - Patterns - Backstock, 1/Var
becomes this with the formula above
S223, -, Pills,, S2323, -, Patterns, -, Backstock,, 1/Var
Use the UDF on: VLOOKUP with multiple criteria returning values in one cell
The formula:
=TEXTJOIN(", ",TRUE,IF(MOD(COLUMN(G2:BG2),2)=1,G2:BG2,""))
Being an array formula it would need to be confirmed with Ctrl-Shift-Enter.
The following UDF from answers.microsoft.com should be what you're after
Function TEXTJOIN(delimiter As String, ignore_empty As String, ParamArray textn() As Variant) As String
Dim i As Long
For i = LBound(textn) To UBound(textn) - 1
If Len(textn(i)) = 0 Then
If Not ignore_empty = True Then
TEXTJOIN = TEXTJOIN & textn(i) & delimiter
End If
Else
TEXTJOIN = TEXTJOIN & textn(i) & delimiter
End If
Next
TEXTJOIN = TEXTJOIN & textn(UBound(textn))
End Function
Quite some while ago, i found this code online as i needed it for a personal project of mine. What this does is it takes a string and replace every "unallowed" value by a specified character. In your case I would imagine you allowing every character except "," and replace it by "" or " ". This way, A, -, B, -, C, would become A - B - C
Function cleanString(text As String) As String
Dim output As String
Dim c
For i = 1 To Len(text)
c = Mid(text, i, 1)
If (c >= "a" And c <= "z") Or (c >= "0" And c <= "9") Or (c >= "A" And c <= "Z" Or c = " " Or c = "-" Or c = "é" Or c = "É" Or c = "_") Then ' <=list of allowed values in a string
output = output & c
Else
output = output & " " '<= what unallowed values gets replaced by
End If
Next
cleanString = output
End Function
Hope this can help, I considered VBA as you added the tag in your question.
I have a list of cells with values like the below:
a,a,b,c,d
f,g,h,h,h,j
a,b,b
f,f,f,y,y,u,u
I want a formula that will give me the below (unique list of above). I should be able to write it for one row and copy it down.
a,b,c,d
f,g,h,j
a,b
f,y,u
There is no way to do this with a formula that will return comma-separated unique results into one cell, using only the built-in worksheet functions.
But, it is very simple to achieve the same thing with a User Defined Function (UDF).
Just place this small routine in a standard code module:
Public Function UniqueList(s)
Dim i&, k$, v
v = Split(s, ",")
For i = 0 To UBound(v)
If InStr(k, v(i)) = 0 Then k = k & "," & v(i)
Next
UniqueList = Mid$(k, 2)
End Function
If your source string is in cell A1 then in cell B1 enter this formula:
=UniqueList(A1)
That's it. Now copy the formula downward as far as needed.
Considering the repeated letters are in order, as in your sample, this should do the trick:
Function UniqueLetters(ByVal cell As Range) As String
letters = Split(cell.Value, ",")
For Each letter In letters
If letter <> current_letter Then
current_letter = letter
unique_letters = unique_letters + letter + ","
End If
Next
UniqueLetters = Left(unique_letters, Len(unique_letters) - 1)
End Function
I have a column that contains strings with values that i want to search.
Example:
Column A (my raw data): SMS APP, SMS Solutions
Column B (my search criterias):SMS
Column C: =vlookup(Column B, Column C, FALSE)
As shown above, I would like to ensure that Column C will display the results of my search on my raw data. Is there a vlookup way to do it?. It must match a string shown in Column B. thanks!
If you want a full blown UDF that will give you back a list of all the cells that contained the word in B then (note this works with multi-column ranges as well):
=ListAll(B1, A1:A100)
(code)
Function ListAll(ByVal text As String, _
ByVal cell_range As Range, _
Optional seperator As String = ", ") As String
Dim result As String
Dim i As Long, j as Long
Dim rawData As Variant
rawData = cell_range.Value
For i = 1 To UBound(rawData, 1)
For j = 1 To UBound(rawData, 2)
If InStr(1, rawData(i, j), text) <> 0 Then
result = result & (rawData(i, j) & seperator)
End If
Next
Next
If Len(result) <> 0 Then
result = Left$(result, Len(result) - Len(seperator))
End If
ListAll = result
End Function
Notice I set it up so that each value found is seperated by a comma, but you can do other stuff like line breaks:
=ListAll(B1, A1:A100, CHAR(10))
You can also do this with the =SEARCH(find_text, within_text) formula, which returns an integer if find_text is found within_text, and returns #VALUE! if the text is not found. So, just make column D which searches values in column A for values in Column B. If column D is integer, that means match. If column D is #VALUE - no match.
Need help in creating an Excel Macro.I have an Excel sheet.The Excel sheet is not consistent.
I am planning to make it uniform and structured.
Eg.
A B C D
1 test tester tester
2 hai test
3 Bye test tested
4 GN test tested Fine
A B C D
1 test testertester
2 hai test
3 Bye testtested
4 GN testtestedFine
Basically I have to find the last cell where element is placed so based on that I can write my CONCATENATE funciton.
In this case it would be Column D and hence my concatenate function would have been
=CONCATENATE(B1,C1,D1)
Again I would like the result to be in B1 but not a problem if I have to hide.
Can anyone help me in doing this?
You could use the following VBA function which joins (concatenates) the values from an arbitrary range of cells, with an optional delimiter.
Public Function Join(source As Range, Optional delimiter As String)
Dim text As String
Dim cell As Range: For Each cell In source.Cells
If cell.Value = "" Then GoTo nextCell
text = text & cell.Value & delimiter
nextCell:
Next cell
If text <> "" And delimiter <> "" Then
text = Mid(text, 1, Len(text) - Len(delimiter))
End If
Join = text
End Function
For an example of how to use the function, enter =JOIN(A1:D1) into a cell anywhere on the spreadsheet.
=B1&C1&D1
or
Adam's function that I have optimized.
Function Join(source As Range, Optional delimiter As String) As String
'
' Join Macro
' Joins (concatenates) the values from an arbitrary range of cells, with an optional delimiter.
'
'optimized for strings
' check len is faster than checking for ""
' string Mid$ is faster than variant Mid
' nested ifs allows for short-circuit
' + is faster than &
Dim sResult As String
Dim oCell As Range
For Each oCell In source.Cells
If Len(oCell.Value) > 0 Then
sResult = sResult + CStr(oCell.Value) + delimiter
End If
Next
If Len(sResult) > 0 Then
If Len(delimiter) > 0 Then
sResult = Mid$(sResult, 1, Len(sResult) - Len(delimiter))
End If
End If
Join = sResult
End Function