VBA in Excel 在多个选项卡和 return 位置搜索字符串
VBA in Excel to search for string over multiple tabs and return locations
我已经编写了代码来进行搜索,问题是试图让它找到多个结果。目前它将 return 每个选项卡上字符串的第一个位置,然后继续。当我实现当前被注释掉的 While 循环时,它似乎找到第一个结果然后退出循环。
我不确定 VBA 循环是否有我遗漏的怪癖,或者我的 while 检查不太正确,但我尝试通过分解它并使用消息框来进行调试,但是除了缩小我认为问题出在 while 循环代码中的位置之外无济于事。
Public Function GetSearchArray(strSearch As String) As String
Dim strResults As String
Dim SHT As Worksheet
Dim rFND As Range
Dim sFirstAddress As Range
For Each SHT In ThisWorkbook.Worksheets
'MsgBox "Looping over worksheets"
Set rFND = Nothing
With SHT.UsedRange
'MsgBox "Searching for" & strSearch
Set rFND = .Cells.Find(What:="*" & strSearch & "*", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
If Not rFND Is Nothing Then
'Save first result so we can exit the loop
If sFirstAddress Is Nothing Then
MsgBox "We have a result and sFirstAddress is nothing"
Set sFirstAddress = rFND
End If
'Need to loop within the sheet to keep finding results
'While (Not rFND Is Nothing) And rFND <> sFirstAddress
'Deal with the results and build a string
If strResults = "" Then
'MsgBox "No prev results"
strResults = "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
MsgBox "First result " & strResults
Else
strResults = strResults & "|" & "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
MsgBox strResults
End If
Set rFND = .FindNext(rFND)
'Wend
End If
End With
MsgBox "End sheet loop.."
Next
MsgBox "Finished going over sheets"
MsgBox strResults
End Function
您需要在代码到达 While
循环之前循环回到 Set rFND = .Cells.Find(What:="*" & strSearch & "*", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
行,目前不会发生这种情况并且 rFND always 等于sFirstAddress.
我不确定存储地址结果然后在循环时检查它们的最有效方法,但我相信有人可以在最后一部分帮助您。我怀疑它将把每个结果存储在一个数组中,并根据数组检查每个新结果,直到没有找到新结果,然后移动到下一个 sheet.
您可能还必须更改查找命令以从最后找到的结果开始,如果它每次都从同一个地方开始,我认为它会一遍又一遍地找到相同的结果。我不确定,我没怎么用过Find。
像这样的东西应该适合你:
Public Function GetSearchArray(strSearch As String) As String
Dim ws As Worksheet
Dim rngFound As Range
Dim strFirst As String
Dim strWSname As String
For Each ws In ActiveWorkbook.Sheets
Set rngFound = ws.UsedRange.Find(strSearch, ws.UsedRange.Cells(ws.UsedRange.Cells.Count), xlValues, xlPart)
If Not rngFound Is Nothing Then
strWSname = ws.Name
If InStr(1, ws.Name, " ", vbTextCompare) > 0 Then strWSname = "'" & strWSname & "'"
strFirst = rngFound.Address
Do
GetSearchArray = GetSearchArray & "|" & strWSname & "!" & rngFound.Address
Set rngFound = ws.UsedRange.Find(strSearch, rngFound, xlValues, xlPart)
Loop While rngFound.Address <> strFirst
End If
Next ws
If Len(GetSearchArray) > 0 Then GetSearchArray = Mid(GetSearchArray, 2)
End Function
然后调用该函数,使用类似这样的东西:
Sub tgr()
MsgBox Replace(GetSearchArray("test"), "|", Chr(10))
End Sub
我已经编写了代码来进行搜索,问题是试图让它找到多个结果。目前它将 return 每个选项卡上字符串的第一个位置,然后继续。当我实现当前被注释掉的 While 循环时,它似乎找到第一个结果然后退出循环。
我不确定 VBA 循环是否有我遗漏的怪癖,或者我的 while 检查不太正确,但我尝试通过分解它并使用消息框来进行调试,但是除了缩小我认为问题出在 while 循环代码中的位置之外无济于事。
Public Function GetSearchArray(strSearch As String) As String
Dim strResults As String
Dim SHT As Worksheet
Dim rFND As Range
Dim sFirstAddress As Range
For Each SHT In ThisWorkbook.Worksheets
'MsgBox "Looping over worksheets"
Set rFND = Nothing
With SHT.UsedRange
'MsgBox "Searching for" & strSearch
Set rFND = .Cells.Find(What:="*" & strSearch & "*", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
If Not rFND Is Nothing Then
'Save first result so we can exit the loop
If sFirstAddress Is Nothing Then
MsgBox "We have a result and sFirstAddress is nothing"
Set sFirstAddress = rFND
End If
'Need to loop within the sheet to keep finding results
'While (Not rFND Is Nothing) And rFND <> sFirstAddress
'Deal with the results and build a string
If strResults = "" Then
'MsgBox "No prev results"
strResults = "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
MsgBox "First result " & strResults
Else
strResults = strResults & "|" & "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
MsgBox strResults
End If
Set rFND = .FindNext(rFND)
'Wend
End If
End With
MsgBox "End sheet loop.."
Next
MsgBox "Finished going over sheets"
MsgBox strResults
End Function
您需要在代码到达 While
循环之前循环回到 Set rFND = .Cells.Find(What:="*" & strSearch & "*", LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
行,目前不会发生这种情况并且 rFND always 等于sFirstAddress.
我不确定存储地址结果然后在循环时检查它们的最有效方法,但我相信有人可以在最后一部分帮助您。我怀疑它将把每个结果存储在一个数组中,并根据数组检查每个新结果,直到没有找到新结果,然后移动到下一个 sheet.
您可能还必须更改查找命令以从最后找到的结果开始,如果它每次都从同一个地方开始,我认为它会一遍又一遍地找到相同的结果。我不确定,我没怎么用过Find。
像这样的东西应该适合你:
Public Function GetSearchArray(strSearch As String) As String
Dim ws As Worksheet
Dim rngFound As Range
Dim strFirst As String
Dim strWSname As String
For Each ws In ActiveWorkbook.Sheets
Set rngFound = ws.UsedRange.Find(strSearch, ws.UsedRange.Cells(ws.UsedRange.Cells.Count), xlValues, xlPart)
If Not rngFound Is Nothing Then
strWSname = ws.Name
If InStr(1, ws.Name, " ", vbTextCompare) > 0 Then strWSname = "'" & strWSname & "'"
strFirst = rngFound.Address
Do
GetSearchArray = GetSearchArray & "|" & strWSname & "!" & rngFound.Address
Set rngFound = ws.UsedRange.Find(strSearch, rngFound, xlValues, xlPart)
Loop While rngFound.Address <> strFirst
End If
Next ws
If Len(GetSearchArray) > 0 Then GetSearchArray = Mid(GetSearchArray, 2)
End Function
然后调用该函数,使用类似这样的东西:
Sub tgr()
MsgBox Replace(GetSearchArray("test"), "|", Chr(10))
End Sub