Excel VBA를 사용하여 워크북에서 모든 일치 항목 찾기
나는 글을 쓰려고 노력하고 있습니다.VBA
문자열을 사용하여 주어진 Excel 워크북을 검색하고 가능한 모든 일치 항목을 나에게 반환하는 루틴입니다.
나는 현재 작동하는 구현체를 가지고 있지만, 그것은 루프를 위한 이중이기 때문에 매우 느립니다.물론 기본 제공되는 ExcelFind
함수는 단일 일치 항목을 찾기 위해 "최적화"되지만, 추가 방법을 적용할 수 있는 초기 일치 항목 배열을 반환하고 싶습니다.
내가 이미 가지고 있는 것의 유사 코드를 게시할 것입니다.
For all sheets in workbook
For all used rows in worksheet
If cell matches search string
do some stuff
end
end
end
앞서 언급했듯이, 이 이중 루프는 일을 매우 느리게 진행하기 때문에 가능하다면 이것을 제거하려고 합니다.좋은 의견이라도 있나?
갱신하다
아래 답변들은 제 방법을 개선했을 것이지만, 저는 여러 가지 질문을 반복적으로 해야 하기 때문에 약간 다른 것을 하게 되었습니다.
대신 문서의 모든 행을 반복하고 각 고유 행에 대한 키를 포함하는 사전을 만들기로 결정했습니다.이 값이 가리키는 값은 가능한 일치 항목의 목록이 되므로 나중에 쿼리할 때 해당 항목이 있는지 확인하고, 있는 경우 빠른 일치 항목 목록을 얻을 수 있습니다.
기본적으로 관리 가능한 구조에 모든 것을 저장하기 위해 초기 스위프를 한 번만 수행하고 다음에 수행할 수 있는 구조를 쿼리합니다.O(1)
시간을
범위 사용.위에서 지적한 것처럼 워크북의 각 워크시트에 대한 루프와 함께 방법 찾기가 가장 빠른 방법입니다.예를 들어 다음은 각 워크시트에서 "Question?" 문자열을 찾아 "Answered!" 문자열로 대체합니다.
Sub FindAndExecute()
Dim Sh As Worksheet
Dim Loc As Range
For Each Sh In ThisWorkbook.Worksheets
With Sh.UsedRange
Set Loc = .Cells.Find(What:="Question?")
If Not Loc Is Nothing Then
Do Until Loc Is Nothing
Loc.Value = "Answered!"
Set Loc = .FindNext(Loc)
Loop
End If
End With
Set Loc = Nothing
Next
End Sub
Ahmed의 답변을 바탕으로 다른 "찾기" 매개 변수를 포함하여 정리 및 일반화한 후 이 기능을 어떤 상황에서도 사용할 수 있습니다.
'Uses Range.Find to get a range of all find results within a worksheet
' Same as Find All from search dialog box
'
Function FindAll(rng As Range, What As Variant, Optional LookIn As XlFindLookIn = xlValues, Optional LookAt As XlLookAt = xlWhole, Optional SearchOrder As XlSearchOrder = xlByColumns, Optional SearchDirection As XlSearchDirection = xlNext, Optional MatchCase As Boolean = False, Optional MatchByte As Boolean = False, Optional SearchFormat As Boolean = False) As Range
Dim SearchResult As Range
Dim firstMatch As String
With rng
Set SearchResult = .Find(What, , LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)
If Not SearchResult Is Nothing Then
firstMatch = SearchResult.Address
Do
If FindAll Is Nothing Then
Set FindAll = SearchResult
Else
Set FindAll = Union(FindAll, SearchResult)
End If
Set SearchResult = .FindNext(SearchResult)
Loop While Not SearchResult Is Nothing And SearchResult.Address <> firstMatch
End If
End With
End Function
사용법은 기본값과 동일합니다.다음은 요청에 따라 사용 예를 찾을 수 있습니다.
Sub test()
Dim SearchRange As Range, SearchResults As Range, rng As Range
Set SearchRange = MyWorksheet.UsedRange
Set SearchResults = FindAll(SearchRange, "Search this")
If SearchResults Is Nothing Then
'No match found
Else
For Each rng In SearchResults
'Loop for each match
Next
End If
End Sub
Function GetSearchArray(strSearch)
Dim strResults As String
Dim SHT As Worksheet
Dim rFND As Range
Dim sFirstAddress
For Each SHT In ThisWorkbook.Worksheets
Set rFND = Nothing
With SHT.UsedRange
Set rFND = .Cells.Find(What:=strSearch, LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlRows, SearchDirection:=xlNext, MatchCase:=False)
If Not rFND Is Nothing Then
sFirstAddress = rFND.Address
Do
If strResults = vbNullString Then
strResults = "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
Else
strResults = strResults & "|" & "Worksheet(" & SHT.Index & ").Range(" & Chr(34) & rFND.Address & Chr(34) & ")"
End If
Set rFND = .FindNext(rFND)
Loop While Not rFND Is Nothing And rFND.Address <> sFirstAddress
End If
End With
Next
If strResults = vbNullString Then
GetSearchArray = Null
ElseIf InStr(1, strResults, "|", 1) = 0 Then
GetSearchArray = Array(strResults)
Else
GetSearchArray = Split(strResults, "|")
End If
End Function
Sub test2()
For Each X In GetSearchArray("1")
Debug.Print X
Next
End Sub
찾기 루프를 수행할 때 무한 루프에 빠지지 않도록 주의하십시오.처음 발견된 셀 주소를 참조하고 각 "다음 찾기" 문 이후를 비교하여 처음 발견된 셀로 되돌아가지 않았는지 확인합니다.
범위를 사용할 수 있습니다.방법 찾기:
http://msdn.microsoft.com/en-us/library/office/ff839746.aspx
검색 문자열이 포함된 첫 번째 셀이 표시됩니다.다음 셀로 "이후" 인수를 설정하고 이 작업을 반복하면 첫 번째 항목으로 돌아갈 때까지 다른 모든 항목이 표시됩니다.
이것이 훨씬 더 빠를 것 같습니다.
B Hart의 답에 기초하여, 범위에서 값을 검색하고 발견된 모든 범위(셀)를 반환하는 함수의 내 버전은 다음과 같습니다.
Function FindAll(ByVal rng As Range, ByVal searchTxt As String) As Range
Dim foundCell As Range
Dim firstAddress
Dim rResult As Range
With rng
Set foundCell = .Find(What:=searchTxt, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not foundCell Is Nothing Then
firstAddress = foundCell.Address
Do
If rResult Is Nothing Then
Set rResult = foundCell
Else
Set rResult = Union(rResult, foundCell)
End If
Set foundCell = .FindNext(foundCell)
Loop While Not foundCell Is Nothing And foundCell.Address <> firstAddress
End If
End With
Set FindAll = rResult
End Function
전체 워크북에서 값 검색하기
Dim wSh As Worksheet
Dim foundCells As Range
For Each wSh In ThisWorkbook.Worksheets
Set foundCells = FindAll(wSh.UsedRange, "YourSearchString")
If Not foundCells Is Nothing Then
Debug.Print ("Results in sheet '" & wSh.Name & "':")
Dim cell As Range
For Each cell In foundCells
Debug.Print ("The value has been found in cell: " & cell.Address)
Next
End If
Next
데이터를 배열로 읽을 수 있습니다.여기서 한 번에 하나의 셀을 읽는 대신 메모리에서 일치를 수행할 수 있습니다.
아래 코드는 무한 루프 생성을 방지합니다.XYZ가 워크북에서 찾고 있는 문자열이라고 가정합니다.
Private Sub CommandButton1_Click()
Dim Sh As Worksheet, myCounter
Dim Loc As Range
For Each Sh In ThisWorkbook.Worksheets
With Sh.UsedRange
Set Loc = .Cells.Find(What:="XYZ")
If Not Loc Is Nothing Then
MsgBox ("Value is found in " & Sh.Name)
myCounter = 1
Set Loc = .FindNext(Loc)
End If
End With
Next
If myCounter = 0 Then
MsgBox ("Value not present in this worrkbook")
End If
End Sub
언급URL : https://stackoverflow.com/questions/19504858/find-all-matches-in-workbook-using-excel-vba
'programing' 카테고리의 다른 글
MacOS X에 Node.js, nvm 및 npm을 설치하는 권장 방법은 무엇입니까? (0) | 2023.05.08 |
---|---|
분기를 헤드로 빠르게 전달하는 방법 (0) | 2023.05.08 |
파이썬을 컴파일하는 동안 --enable-optimization은 무엇을 합니까? (0) | 2023.05.08 |
System.console()이 null을 반환합니다. (0) | 2023.05.03 |
ALTER TABLE, null이 아닌 열에 null 설정, PostgreSQL 9.1 (0) | 2023.05.03 |