因此,当我回答this question时,我发现自己不得不处理似乎是一个非常特殊的错误。
简而言之,当在工作表中搜索字符串的所有匹配项时,如果在合并的单元格中仅发现一个匹配项,并且此单元格是通过合并来自不同行的单元格来构造的,则.FindNext
不会像it is supposed to那样环绕。
因此,如果在通过合并同一列的2个单元格而构成的单元格中找到关键字的第一个(也是唯一的)出现,则.FindNext
将返回Nothing
。
怪异的部分是,如果出现多个事件,或者如果该单元格是通过合并同一行的单元格而构建的,它将按预期工作。
我已经通过引入Nothing
的支票来解决这个问题,但是我很好奇为什么会这样。
是错误吗?我想念什么吗?
为完成起见,以下是代码:
Sub main()
Dim wbk As Workbook
Set wbk = ThisWorkbook
Debug.Print numOfOccurrences("test", wbk) 'call the search function and print the number of occurrences to the immediate window
End Sub
Public Function numOfOccurrences(keyword As String, wb As Workbook) As Long
Dim sht As Worksheet
Dim found As Range
Dim count As Long
Dim firstOccurence As String
count = 0
For Each sht In wb.Worksheets 'loop through sheets
Set found = sht.Cells.Find(what:=keyword) 'search for the first occurrence if any
If Not found Is Nothing Then 'if the keyword is found once, then we need to search for more occurrences
firstOccurence = found.Address 'store the address of the first occurence
Do
Set found = sht.Cells.FindNext(found) 'search for the next occurrence in the same sheet
count = count + 1 'keep track of the number of occurences
If found Is Nothing Then
GoTo DoneFinding 'this deals with what seems to be a bug when using .FindNext with merged cells
End If
Loop Until found.Address = firstOccurence 'repeat until the search goes full circle back to the first occurrence
End If
DoneFinding:
Next sht
numOfOccurrences = count
End Function
答案 0 :(得分:0)
从我所见,Excel将合并的区域视为单个单元格,因此,如果只有一个合并的区域具有该值,则FindNext不会找到另一个存在的单元格。您可以使用Range.MergeArea
来访问完整范围的地址。这是一个通用的FindAll函数,如果您愿意的话,它将拉回某个范围内的合并区域。
Private Function FindAll(What, _
Optional SearchWhat As Variant, _
Optional LookIn, _
Optional LookAt, _
Optional SearchOrder, _
Optional SearchDirection As XlSearchDirection = xlNext, _
Optional MatchCase As Boolean = False, _
Optional MatchByte, _
Optional SearchFormat, _
Optional IncludeMerged As Boolean = False) As Range
'LookIn can be xlValues or xlFormulas, _
LookAt can be xlWhole or xlPart, _
SearchOrder can be xlByRows or xlByColumns, _
SearchDirection can be xlNext, xlPrevious, _
MatchCase, MatchByte, and SearchFormat can be True or False. _
Before using SearchFormat = True, specify the appropriate settings for the Application.FindFormat _
object; e.g. Application.FindFormat.NumberFormat = "General;-General;""-""" _
Set IncludeMerged to 'True' to include all cells within a merged area
Dim SrcRange As Range
If IsMissing(SearchWhat) Then
Set SrcRange = ActiveSheet.UsedRange
ElseIf TypeOf SearchWhat Is Range Then
Set SrcRange = IIf(SearchWhat.Cells.Count = 1, SearchWhat.Parent.UsedRange, SearchWhat)
ElseIf TypeOf SearchWhat Is Worksheet Then
Set SrcRange = SearchWhat.UsedRange
Else: SrcRange = ActiveSheet.UsedRange
End If
If SrcRange Is Nothing Then Exit Function
'get the first matching cell in the range first
With SrcRange.Areas(SrcRange.Areas.Count)
Dim FirstCell As Range: Set FirstCell = .Cells(.Cells.Count)
End With
Dim CurrRange As Range: Set CurrRange = SrcRange.Find(What:=What, After:=FirstCell, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If Not CurrRange Is Nothing Then
Set FindAll = IIf(IncludeMerged = True, CurrRange.MergeArea, CurrRange)
Do
Set CurrRange = SrcRange.Find(What:=What, After:=CurrRange, LookIn:=LookIn, LookAt:=LookAt, _
SearchDirection:=SearchDirection, MatchCase:=MatchCase, MatchByte:=MatchByte, SearchFormat:=SearchFormat)
If CurrRange Is Nothing Then Exit Do
If Application.Intersect(FindAll, CurrRange) Is Nothing Then
Set FindAll = Application.Union(FindAll, IIf(IncludeMerged = True, CurrRange.MergeArea, CurrRange))
Else: Exit Do
End If
Loop
End If
End Function