In this Article
- Searching in a One-Dimensional Array
- Find values that match the Filter
- Find values that DO NOT match the Filter
- Case Sensitive Filters
- Option Compare Text
- Using a Loop to Search through an array
- Searching in a Multi-Dimensional Array
This tutorial will demonstrate how to Search for (Find) a Value in an Array in VBA
There are a number of ways you can search for a string in an array – depending on whether the array is a one dimensional or multi-dimensional.
Searching in a One-Dimensional Array
To search for a value in a one-dimensional array, you can use the Filter Function.
Dim z As Variant
'filter the original array
z = Filter(Array, String, True, vbCompareBinary)
The Syntax of the Filter option is a follows
Filter(Source Array, Match as String, [Include as Boolean], [Compare as vbCompareMethod])
The Source Array and the Match as String are required while the Include as Boolean and the Compare as vbCompareMethod are optional. If these are not included they are set to True and vbCompareBinary respectively.
Find values that match the Filter
Sub FindBob()
'Create Array
Dim strName() As Variant
strName() = Array("Bob Smith", "John Davies", "Fred Jones", "Steve Jenkins", "Bob Williams")
'declare a variant to store the filter data in
Dim strSubNames As Variant
'filter the original array
strSubNames = Filter(strName, "Bob")
'if you UBound value is greater than -1, then the value has been found
If UBound(strSubNames ) > -1 Then MsgBox ("I found Bob")
End Sub
The second array will hold the values found by the filter. If your UBound values are not -1, then the array has managed to find the value that you were searching for.
You can also see how many times the text appears in the original array.
Sub CountNames()
'Create array
Dim strName() As Variant
strName() = Array("Bob Smith", "John Davies", "Fred Jones", "Steve Jenkins", "Bob Williams")
'declare an array to store the filter data in
Dim strSubNames As Variant
'filter the original array
strSubNames = Filter(strName, "Bob")
'if you add 1 to the UBound value, we will get the number of times the text appears
Msgbox UBound(strSubNames) + 1 & " names found."
End Sub
Find values that DO NOT match the Filter
The [Include as Boolean] option allows you to find how many values in your array which DO NOT match your filter
Sub CountExtraNames()
'create array
Dim strName() As Variant
strName() = Array("Bob Smith", "John Davies", "Fred Jones", "Steve Jenkins", "Bob Williams")
'declare an array to store the filter data in
Dim strSubNames As Variant
'filter the original array
strSubNames = Filter(strName, "Bob", False)
'if you add 1 to the UBound value, we will get the number of times the text appears
Msgbox UBound(strSubNames) + 1 & " names found."
End Sub
we have therefore amended this line:
strSubNames = Filter(strName, "Bob")
with this line:
strSubNames = Filter(strName, "Bob", False)
Using this line in the code, would return all the names that do NOT match “Bob”.
Case Sensitive Filters
You will find that the filter is case sensitive by default. This is true for all VBA functions. If you want to search for text that is not case sensitive, you need to amend your code slightly.
z = Filter(strName, "bob",, vbTextCompare)
Adding vbTextCompare to your filter line will enable your code to find “bob” or “Bob”. If this is omitted, VBA by default uses vbBinaryCompare which will only look for data that is an EXACT match. Notice in the example above, we have left out the [Include as Boolean] argument so True is assumed.
Option Compare Text
Alternatively, you can add the text Option Compare Text to the top of your module – this will make all the functions that you write in that particular module case insensitive.
VBA Coding Made Easy
Stop searching for VBA code online. Learn more about AutoMacro — A VBA Code Builder that allows beginners to code procedures from scratch with minimal coding knowledge and with many time-saving features for all users!
Learn More
Using a Loop to Search through an array
Using a loop is a little bit more complicated than using the Filter function. We can create a function that will loop through all the values in the array.
Sub LoopThroughArray()
'create array
Dim strName() As Variant
strName() = Array("Bob Smith", "John Davies", "Fred Jones", "Steve Jenkins", "Bob Williams")
Dim strFind as string
strFind = "Bob"
Dim i As Long
'loop through the array
For i = LBound(strName, 1) To UBound(strName, 1)
If InStr(strName(i), strFind) > 0 Then
MsgBox "Bob has been found!"
Exit For
End If
Next i
End Sub
In order to find a part of the text string ie “Bob” instead of “Bob Smith” or “Bob Williams”, we needed to use the Instr Function in the If Statement. This looked in the string returned by the loop from the Array to see if “Bob” was in the string, and as it was in the string, it would return a message box and then Exit the Loop.
Searching in a Multi-Dimensional Array
We also use the loop to search through a multi-dimensional array. Once again, we need to create a function than enables us to loop through all the values in the array, but this time, we also need to loop through each dimension of the array.
Function LoopThroughArray()
Dim varArray() As Variant
Dim strFind As String
strFind = "Doctor"
'declare the size of the array
ReDim varArray(1, 2)
'initialise the array
varArray(0, 0) = "Mel Smith"
varArray(0, 1) = "Fred Buckle"
varArray(0, 2) = "Jane Eyre"
varArray(1, 0) = "Accountant"
varArray(1, 1) = "Secretary"
varArray(1, 2) = "Doctor"
'declare variables for the loop
Dim i As Long, j As Long
'loop for the first dimension
For i = LBound(varArray, 1) To UBound(varArray, 1)
'loop for the second dimension
For j = LBound(varArray, 2) To UBound(varArray, 2)
'if we find the value, then msgbox to say that we have the value and exit the function
If varArray(i, j) = strFind Then
MsgBox "Doctor has been found!"
Exit Function
End If
Next j
Next i
End Function
-
#2
Filter works on partial matches, so «a» is in the final array in the form of «a-b». Your second to last example works correctly for me
-
#3
Filter works on partial matches, so «a» is in the final array in the form of «a-b». Your second to last example works correctly for me
If Filter works on partial matches then that is where I am going wrong. Can you (or anyone else) suggest an alternate method of checking whether an item is in an array?
Edit: yes you are write about my second last example. That actually does work correctly. I got that example the wrong way around. But I think people should be able to get my drift.
Last edited: Sep 2, 2013
-
#4
Perhaps more resilient, but not fool proof:
Code:
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = InStr(1, vbCr & Join(arr, vbCr) & vbCr, vbCr & stringToBeFound & vbCr)
End Function
Though it’s worth mentioning, that looping through arrays in memory is pretty fast, so shouldn’t be ruled out. These approaches also will only work on arrays with a single dimension — they fail in the case of a 2d array which are very common in Excel
-
#5
Hi Harry
Filter does not perform an exact match.
Another option:
Code:
IsInArray = Not IsError(Application.Match(stringToBeFound, arr, 0))
snb_
Well-known Member
-
#6
Code:
Sub M_snb()
sn = Array("aa1", "aa2", "bb3")
c00 = "aa1"
c01 = "b"
c02 = "Exact match: "
MsgBox c02 & Format(InStr("~" & Join(sn, "~|~") & "~", "~" & c00 & "~"), "yes/no")
MsgBox c02 & Format(InStr("~" & Join(sn, "~|~") & "~", "~" & c01 & "~"), "yes/no")
MsgBox c02 & Format(UBound(Filter(Split("~" & Join(sn, "~|~") & "~", "|"), "~" & c00 & "~")) > -1, "yes/no")
MsgBox c02 & Format(UBound(Filter(Split("~" & Join(sn, "~|~") & "~", "|"), "~" & c01 & "~")) > -1, "yes/no")
MsgBox c02 & Format(Not IsError(Application.Match(c00, sn, 0)), "yes/no")
MsgBox c02 & Format(Not IsError(Application.Match(c01, sn, 0)), "yes/no")
End Sub
-
#7
Hi Harry
Filter does not perform an exact match.
Another option:
Code:
IsInArray = Not IsError(Application.Match(stringToBeFound, arr, 0))
Thank you that was exactly what I was looking for.
This problem has a small piece of the jigsaw puzzle that I posted in this thread:
http://www.mrexcel.com/forum/excel-…-value-exists-new-collection.html#post3561227
Which was itself a small piece in a larger jigsaw puzzle.
My original question was how could I check if an item was in a New Collection, which I never figured out. So I thought I would try passing my New Collection to an array and find someway to check that.
Thanks to Kyle123 and snb_ as well for their input too. Much appreciated. I am teaching myself VBA from books and I no one at my work knows anything about it, thus the learning process involves a lot of persistence and trial and error. So I am really grateful for the pointers I get from this forum.
As it happens I am quite glad that I now have two methods at my disposal, and for the larger problem that I am working finding partial matches will also be very useful, and I will ultimately incorporate both approaches in my code. Cheers.
snb_
Well-known Member
-
#8
Code:
Sub M_snb()
On Error Resume Next
With New Collection
.Add "aaa", "bbb"
x3 = .Item("bb1")
If Err.Number <> 0 Then MsgBox "item doesn't exist"
End With
End Sub
-
#9
You’re welcome. Thanks for the feedback.
-
#10
As long as your ‘arr’ variable will always be a one-dimensional array, you could write your function this way…
Code:
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
IsInArray = InStr(Chr(1) & Join(arr, Chr(1)) & Chr(1), Chr(1) & stringToBeFound & Chr(1)) > 0
End Function
To check if a value exists in an array, we can loop through its elements. However there is another solution! You can use the INDEX () function, native to Excel and in the case of two-dimensional arrays use a combination of the INDEX/MATCH function. However, if the value is not found, Application.Match returns an error. You will need to take into account any possible errors, as well as the number of dimensions of the array variable. This small function will help you out.
Using the Match function
Function EstDans(mot As String, Tabl) As Boolean Dim Dimension As Byte, j As Integer On Error Resume Next If IsError(UBound(Tabl, 2)) Then Dimension = 1 Else Dimension = 2 On Error GoTo 0 Select Case Dimension Case 1 On Error Resume Next EstDans = Application.Match(mot, Tabl, 0) On Error GoTo 0 Case 2 For j = 1 To UBound(Tabl, 2) On Error Resume Next EstDans = Application.Match(mot, Application.Index(Tabl, , j), 0) On Error GoTo 0 If EstDans = True Then Exit For Next End Select End Function
Invoking the function
Sub test() Dim Tb(), i As Integer 'tb 2 dimensions : Tb = Range("A2:C16").Value Debug.Print EstDans(MaValeur, Tb) Erase Tb 'tb 1 dimension : ReDim Preserve Tb(15) For i = 0 To 14 Tb(i) = Cells(i + 2, 1) Next Debug.Print EstDans(MaValeur, Tb) End Sub
Using a loop
The structure of this function is similar to the one using Match.
Function BoucleSurTabl(mot As String, Tb) Dim Dimension As Byte, i As Long, j As Long On Error Resume Next If IsError(UBound(Tb, 2)) Then Dimension = 1 Else Dimension = 2 On Error GoTo 0 Select Case Dimension Case 1 For j = LBound(Tb) To UBound(Tb) If Tb(j) = mot Then BoucleSurTabl = True: Exit Function Next Case 2 For i = LBound(Tb, 1) To UBound(Tb, 1) For j = LBound(Tb, 2) To UBound(Tb, 2) If Tb(i, j) = mot Then BoucleSurTabl = True: Exit Function Next j Next i End Select End Function
Observations
Against all odds, you will get a better result with the loop function on large arrays than using Application.Match. Testing a 2-dimensional array with a the following Range («A1: Y20002»).
- Using the Match function: 8.300781 seconds.
- Using the loop: 0.4375 seconds.
Testing a one-dimensional array:
- Using the Match function: instant
- Using the loop: 0.015625 seconds
Download link
- You can download the sample workbook here.
More Excel questions? Check out our forum!
To check if a value exists in an array, copy this function into a module:
Function in_array(my_array, my_value)
'https://www.excel-pratique.com/en/vba_tricks/search-in-array-function
in_array = False
For i = LBound(my_array) To UBound(my_array)
If my_array(i) = my_value Then 'If value found
in_array = True
Exit For
End If
Next
End Function
The in_array function will return True or False depending on the result.
Here’s a simple example that will look for the presence of the value of the «test_value» variable in the «test_array» array and display True or False in a MsgBox:
Sub test()
test_array = Array(23, 67, 38, 17, 854, 9, 92)
test_value = 17
MsgBox in_array(test_array, test_value)
End Sub