Professional Documents
Culture Documents
This page describes VBA functions that can be used to find all the occurrences of a
value on a single worksheet or on multiple worksheets.
Introduction
If you are looking for the FindAll.xla add-in, please go to the FindAll Add-In page.
The Find method of the Range object is bit tricky to work with until you understand how
it works. The logic to find all of the cells that contain a searched-for value is more
complicated than just calling Find andFindNext.
Suppose we have data in cells A1:A10 as shown below. You might be tempted to write
code like the following to find occurrences of the value 'a'.
Unfortunately, this will not work for several reasons. First, unless specified otherwise,
the Find method start searching after the the first cell, so the first cell found
is A5 not A1. Second, the FindNext method will continue to find cell A5; as written, it
won't really continue find the subsequent cells. To remedy this, we need to specify
which cell after which the search should look for a value. In the call to Findwe need to
specify the last cell in A1:A10 so searching will begin at the end of the range and loop
back up to the top of the range. We can do this with code like the following (additonal
code is shown in yellow).
With the After paramater set to the last cell of the range, the code will immediately
loop back to the top of the range and cell A1 is the first found cell. However, we still
have a problem with the FindNext method. On the first call to FindNext, the code will
correctly find the next occurrence in cell A5, but every subsequent call to FindNext will
continue to find cell A5. It won't really find the next cell. To fix this problem, we need to
provide the After parameter to FindNext. This is shown below:
FindAll
The FindAll procedure finds all occurrences of a value in a specified range and
returns a Range object that contains all of the cell in which the searched-for value was
found. Moreover, it the ranges that make up this range object are in the order you would
be expect, upper-left cell to lower-right cell, in either by-row or by-column order.
Since FindAll returns a Range object, you can use a For Each loop to iterate
through the found cells.
Sub TestFindAll()
End Sub
CompMode = BeginEndCompare
If BeginsWith <> vbNullString Or EndsWith <> vbNullString Then
XLookAt = xlPart
Else
XLookAt = LookAt
End If
On Error GoTo 0
Set FoundCell = SearchRange.Find(what:=FindWhat, _
after:=LastCell, _
LookIn:=LookIn, _
LookAt:=XLookAt, _
SearchOrder:=SearchOrder, _
MatchCase:=MatchCase)
Loop
End If
End Function
FindAllOnWorksheets
VBA provides no built-in method for searching for a value in multiple worksheets. To do
this, you need to loop through all of the worksheets that you want to search and then do
a regular search on each sheet. The FindAllOnWorksheets automates this for you. It
will search a range on any number of worksheets. It returns an array of Range objects,
one element for each sheet that was searched. If the value was not found on a sheet,
that sheet's element in the returned array is Nothing.
Sub TestFindAllOnWorksheets()
'''''''''''''''''''''''''''''''''''''''''''''''''''''
' TestFindAllOnWorksheets
' This illustrates the FindOnAllWorksheets function.
'''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Find all occurences of 'a' in Sheet1 and Sheet3
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
FoundRanges = FindAllOnWorksheets(InWorkbook:=ThisWorkbook, _
InWorksheets:="Sheet1:Sheet3", _
SearchAddress:="A1:C10", _
FindWhat:="a", _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
MatchCase:=False)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Loop through all of the FoundRanges elements, one element
' per worksheet searched.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
For N = LBound(FoundRanges) To UBound(FoundRanges)
If Not FoundRanges(N) Is Nothing Then
'''''''''''''''''''''''''''''''''''''''''''''
' If FoundRanges(N) is not Nothing, at least
' one occurence was found on the sheet.
'''''''''''''''''''''''''''''''''''''''''''''
Found = True
'''''''''''''''''''''''''''''''''''''''''''''
' Loop through all the found cells on the
' worksheet.
'''''''''''''''''''''''''''''''''''''''''''''
For Each FoundCell In FoundRanges(N).Cells
S = S & FoundCell.Worksheet.Name & ": " & _
FoundCell.Address(False, False) & vbCrLf
Next FoundCell
End If
Next N
''''''''''''''''''''''''''''''''''''
' Display MsgBox with results.
''''''''''''''''''''''''''''''''''''
If Found = True Then
S = "Search Results: " & vbCrLf & S
Else
S = "Search Results: " & vbCrLf & "Not Found"
End If
MsgBox S
End Sub
FindAllOnWorksheets Listing
The code for the FindAllOnWorksheets function is shown below:
'''''''''''''''''''''''''''''''''''''''''''
' Determine what Workbook to search.
'''''''''''''''''''''''''''''''''''''''''''
If InWorkbook Is Nothing Then
Set WB = ActiveWorkbook
Else
Set WB = InWorkbook
End If
'''''''''''''''''''''''''''''''''''''''''''
' Determine what sheets to search
'''''''''''''''''''''''''''''''''''''''''''
If IsEmpty(InWorksheets) = True Then
''''''''''''''''''''''''''''''''''''''''''
' Empty. Search all sheets.
''''''''''''''''''''''''''''''''''''''''''
With WB.Worksheets
ReDim WSArray(1 To .Count)
For WSNdx = 1 To .Count
WSArray(WSNdx) = .Item(WSNdx).Name
Next WSNdx
End With
Else
'''''''''''''''''''''''''''''''''''''''
' If Object, ensure it is a Worksheet
' object.
''''''''''''''''''''''''''''''''''''''
If IsObject(InWorksheets) = True Then
If TypeOf InWorksheets Is Excel.Worksheet Then
''''''''''''''''''''''''''''''''''''''''''
' Ensure Worksheet is in the WB workbook.
''''''''''''''''''''''''''''''''''''''''''
If StrComp(InWorksheets.Parent.Name, WB.Name,
vbTextCompare) <> 0 Then
''''''''''''''''''''''''''''''
' Sheet is not in WB. Get out.
''''''''''''''''''''''''''''''
Exit Function
Else
''''''''''''''''''''''''''''''
' Same workbook. Set the array
' to the worksheet name.
''''''''''''''''''''''''''''''
ReDim WSArray(1 To 1)
WSArray(1) = InWorksheets.Name
End If
Else
'''''''''''''''''''''''''''''''''''''
' Object is not a Worksheet. Get out.
'''''''''''''''''''''''''''''''''''''
End If
Else
'''''''''''''''''''''''''''''''''''''''''''
' Not empty, not an object. Test for array.
'''''''''''''''''''''''''''''''''''''''''''
If IsArray(InWorksheets) = True Then
'''''''''''''''''''''''''''''''''''''''
' It is an array. Test if each element
' is an object. If it is a worksheet
' object, get its name. Any other object
' type, get out. Not an object, assume
' it is the name.
''''''''''''''''''''''''''''''''''''''''
ReDim WSArray(LBound(InWorksheets) To
UBound(InWorksheets))
For WSNdx = LBound(InWorksheets) To
UBound(InWorksheets)
If IsObject(InWorksheets(WSNdx)) = True Then
If TypeOf InWorksheets(WSNdx) Is
Excel.Worksheet Then
''''''''''''''''''''''''''''''''''''''
' It is a worksheet object, get name.
''''''''''''''''''''''''''''''''''''''
WSArray(WSNdx) = InWorksheets(WSNdx).Name
Else
''''''''''''''''''''''''''''''''
' Other type of object, get out.
''''''''''''''''''''''''''''''''
Exit Function
End If
Else
'''''''''''''''''''''''''''''''''''''''''''
' Not an object. If it is an integer or
' long, assume it is the worksheet index
' in workbook WB.
'''''''''''''''''''''''''''''''''''''''''''
Select Case
UCase(TypeName(InWorksheets(WSNdx)))
Case "LONG", "INTEGER"
Err.Clear
'''''''''''''''''''''''''''''''''''
' Ensure integer if valid index.
'''''''''''''''''''''''''''''''''''
Set WS =
WB.Worksheets(InWorksheets(WSNdx))
If Err.Number <> 0 Then
'''''''''''''''''''''''''''''''
' Invalid index.
'''''''''''''''''''''''''''''''
Exit Function
End If
''''''''''''''''''''''''''''''''''''
' Valid index. Get name.
''''''''''''''''''''''''''''''''''''
WSArray(WSNdx) =
WB.Worksheets(InWorksheets(WSNdx)).Name
Case "STRING"
Err.Clear
'''''''''''''''''''''''''''''''''''''
' Ensure valid name.
'''''''''''''''''''''''''''''''''''''
Set WS =
WB.Worksheets(InWorksheets(WSNdx))
If Err.Number <> 0 Then
'''''''''''''''''''''''''''''''''
' Invalid name, get out.
'''''''''''''''''''''''''''''''''
Exit Function
End If
WSArray(WSNdx) = InWorksheets(WSNdx)
End Select
End If
'WSArray(WSNdx) = InWorksheets(WSNdx)
Next WSNdx
Else
''''''''''''''''''''''''''''''''''''''''''''
' InWorksheets is neither an object nor an
' array. It is either the name or index of
' the worksheet.
''''''''''''''''''''''''''''''''''''''''''''
Select Case UCase(TypeName(InWorksheets))
Case "INTEGER", "LONG"
'''''''''''''''''''''''''''''''''''''''
' It is a number. Ensure sheet exists.
'''''''''''''''''''''''''''''''''''''''
Err.Clear
Set WS = WB.Worksheets(InWorksheets)
If Err.Number <> 0 Then
'''''''''''''''''''''''''''''''
' Invalid index, get out.
'''''''''''''''''''''''''''''''
Exit Function
Else
WSArray =
Array(WB.Worksheets(InWorksheets).Name)
End If
Case "STRING"
'''''''''''''''''''''''''''''''''''''''''''''''''''
' See if the string contains a ':' character.
If
' so, the InWorksheets contains a string of
multiple
' worksheets.
'''''''''''''''''''''''''''''''''''''''''''''''''''
If InStr(1, InWorksheets, ":",
vbBinaryCompare) > 0 Then
''''''''''''''''''''''''''''''''''''''''''
' ":" character found. split apart sheet
' names.
''''''''''''''''''''''''''''''''''''''''''
WSS = Split(InWorksheets, ":")
Err.Clear
N = LBound(WSS)
If Err.Number <> 0 Then
'''''''''''''''''''''''''''''
' Unallocated array. Get out.
'''''''''''''''''''''''''''''
Exit Function
End If
If LBound(WSS) > UBound(WSS) Then
'''''''''''''''''''''''''''''
' Unallocated array. Get out.
'''''''''''''''''''''''''''''
Exit Function
End If
''''''''''''''''''''''''''''''''''''''''
' SearchAddress is valid for all sheets.
' Call FindAll to search the range on
' each sheet.
''''''''''''''''''''''''''''''''''''''''
ReDim ResultRange(LBound(WSArray) To UBound(WSArray))
For WSNdx = LBound(WSArray) To UBound(WSArray)
Set WS = WB.Worksheets(WSArray(WSNdx))
Set SearchRange = WS.Range(SearchAddress)
Set FoundRange = FindAll(SearchRange:=SearchRange, _
FindWhat:=FindWhat, _
LookIn:=LookIn, LookAt:=LookAt, _
SearchOrder:=SearchOrder, _
MatchCase:=MatchCase, _
BeginsWith:=BeginsWith, _
EndsWith:=EndsWith, _
BeginEndCompare:=BeginEndCompare)
End Function