2016-09-29 3 views
1

Excel에서 모든 워크 시트에서 특정 함수의 모든 인스턴스를 찾는 VBA 매크로를 만들었습니다. 나는 성공적으로 그것을 만들 수 있었지만, 내가 찾고있는 함수를 현명하게 수행하는 가장 좋은 방법이 무엇인지 알아 내려고하고있다. 큰 통합 문서로 많은 시간을 잠재적으로 사용할 수있다.VBA Find 메서드를 사용하여 셀을 빠르게 검색하거나 모든 셀을 검색합니까?

두 가지 방법을 사용했습니다.

방법 1 - 각 개별 셀을 반복하고 "instr"함수를 사용하여 셀 수식에 해당 함수가 들어 있는지 확인하십시오.

방법 2 - Find 루프와 함께 Find 및 FindNext 메서드를 사용하여 실제로 함수가있는 셀을 순환합니다.

많은 수의 함수가있을 때 놀랐습니다. 방법 1은 훨씬 빠릅니다 (메서드 2가 매우 빠르게 작동하는 경우).

누구나 그 방법을 설명 할 수 있습니까?

다음은 예제 코드 예제입니다.

"Sheet1"에서 "MyFunction"이라는 사용자 정의 함수를 A1 : J5000 셀에 배치했습니다. 그런 다음 셀 A5001 : J10000에서 비워 뒀지 만 사용 된 범위가 A1 : J10000이되도록 황색으로 표시했습니다.

는 방법 1이 평균 실행이 약 1531 인이 훨씬 빨리 50,000 세포가

방법 1의 평균 실행이 약 171 MS 및 방법입니다 발견을 통해서만 루프 방법이보다 10 만 개 세포를 통해 반복하더라도 ms. 방법 1과 방법 2에 대한 내 코드의

예 :

방법 1

Private Sub TestMethod1() 
    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationManual 

    Dim MySheet As Worksheet, MyRange As Range, MyCell As Range 
    Dim MyCellAddress As String, MyCellFormula As String, MyFunction As String 
    Dim CountTotalCells As Long, CountTotalFunctions As Long 

    Dim sw, swEndTime As Long 
    Set sw = New StopWatch 
    sw.StartTimer 

    MyFunction = "=MyFunction(" 
    CountTotalCells = 0 
    CountTotalFunctions = 0 

    Set MySheet = Sheets("Forum Question") 
    Set MyRange = MySheet.UsedRange 

    For Each MyCell In MyRange 
     MyCellFormula = MyCell.Formula 

     CountTotalCells = CountTotalCells + 1 
     If InStr(1, MyCellFormula, MyFunction) > 0 Then 
      CountTotalFunctions = CountTotalFunctions + 1 
     End If 
    Next 

    Application.ScreenUpdating = True 
    Application.Calculation = xlCalculationAutomatic 

    swEndTime = sw.EndTimer 

    MsgBox CountTotalCells & ", " & CountTotalFunctions & ", " & swEndTime & " ms" 
End Sub 

방법은 2

Private Sub TestMethod2() 
    Application.ScreenUpdating = False 
    Application.Calculation = xlCalculationManual 

    Dim MySheet As Worksheet, MyRange As Range, MyCell As Range 
    Dim MyCellAddress As String, MyCellFormula As String, MyFunction As String, MyCellFirst As String 
    Dim CountTotalCells As Long, CountTotalFunctions As Long 

    Dim sw, swEndTime As Long 
    Set sw = New StopWatch 
    sw.StartTimer 

    MyFunction = "=MyFunction(" 
    CountTotalCells = 0 
    CountTotalFunctions = 0 

    Set MySheet = Sheets("Forum Question") 
    Set MyRange = MySheet.UsedRange 

    Set MyCell = MyRange.Cells.Find(_ 
     What:=MyFunction, _ 
     After:=[A1], _ 
     LookIn:=xlFormulas, _ 
     LookAt:=xlPart, _ 
     SearchOrder:=xlRows, _ 
     SearchDirection:=xlNext, _ 
     MatchCase:=True _ 
    ) 

    If Not MyCell Is Nothing Then 
     MyCellFirst = MyCell.Address 
     Do 
      Set MyCell = MyRange.FindNext(After:=MyCell) 
      MyCellAddress = MyCell.Address 
      MyCellFormula = "z" & MyCell.Formula 

      CountTotalCells = CountTotalCells + 1 
      If InStr(1, MyCellFormula, MyFunction) > 0 Then 
       CountTotalFunctions = CountTotalFunctions + 1 
      End If 

      If MyCell Is Nothing Or MyCellAddress = MyCellFirst Then 
       Exit Do 
      End If 
     Loop 
    End If 

    Set MyCell = Nothing 

    swEndTime = sw.EndTimer 

    Application.ScreenUpdating = True 
    Application.Calculation = xlCalculationAutomatic 

    MsgBox CountTotalCells & ", " & CountTotalFunctions & ", " & swEndTime & " ms" 
End Sub 
+0

이 게시물은 [StackExchange] (http://codereview.stackexchange.com/)에 더 적합하지 않습니까? – user3598756

답변

1

의 코드를 분해하자. 두 모듈 모두 모든 셀을 순환하고 테스트하여 셀에있는 수식을 확인합니다. 을 참조하십시오. 그러나 Excel에서는 .Find에 대한 호출을 평가할 때 Range 대상의 모든 셀을 검사합니다.

각 루프에서 워크 시트를 터치하는 함수 호출을 계산해 봅시다. 방법 1은 정확히 1이 있습니다

MyRange.FindNext 
MyCell.Address 
MyCell.Formula 
... 플러스 이러한 비교 ...

MyCell Is Nothing 
MyCellAddress = MyCellFirst 
... 플러스 문자열 연결 :

MyCell.Formula 

방법 2는 다음과 같습니다

MyCellFormula = "z" & MyCell.Formula 

전자 손상.

Set MyCell = MyRange.Cells.Find: 0 seconds 
MyCellFirst = MyCell.Address: 0.421875 seconds 
Set MyCell = MyRange.FindNext(After:=MyCell): 4.3125 seconds 
MyCellFormula = "z" & MyCell.Formula: 0.34375 seconds 
If MyCell Is Nothing Or MyCellAddress = MyCellFirst Then Exit Do: 0.015625 seconds 

그래서 큰의 performace 돼지가 .FindNext이, 놀라운 일이 아니다 : 나는 (훨씬 더 큰 샘플 또는 세포) 그 라인의 각에 소요되는 총 시간을 테스트하기 위해 프로파일 링 코드를 추가하는 자유를했다 . 그것은 방법 1에서 건너 뛰는 단순한 검색 및 값 문자열 비교를 수행하는 7 가지 매개 변수 만 평가하면되는 내부적으로 많은 작업을 수행합니다.

+0

응답 주셔서 감사합니다, 그러나, 나는 사용량을 얻으려고 애 쓰고 있지 않습니다. 테스트 용으로 예제에 사용했습니다. 내가하려고하는 것은 함수의 모든 인스턴스에 대한 통합 문서를 검색 한 다음 함수가있는 정확한 셀에 대해 다른 것들을 수행하는 것이다. – ptownbro

+0

이런 식으로 생각하십시오 ... 아주 간단한 버전은 제 기능이있는 모든 셀에 노란색으로 표시됩니다. 내가하고있는 것이 아니라, 이것이 성취해야 할 논리 유형의 좋은 예입니다. – ptownbro

+0

@ptownbro - 편집을 참조하십시오. – Comintern

관련 문제