2010-04-19 3 views
3

Application.Evaluate 또는 ActiveSheet.Evaluate 메서드를 사용하여 루틴을 호출 할 때 서브 루틴 내부에서 찾기 루프를 실행하는 데 문제가 있습니다. 예를 들어, 아래 코드에서 시트의 "xxx"문자열을 검색하는 서브 루틴 FindSub()을 정의합니다. 루틴 인 CallSub()은 표준 Call 문과 Evaluate를 사용하여 FindSub() 루틴을 호출합니다.평가에서 호출 할 때 VBA 찾기 루프가 실패하는 이유는 무엇입니까?

Call FindSub를 실행하면 모든 것이 예상대로 작동합니다. 일치하는 각 주소가 직접 창에 출력되고 코드 완료시 최종 메시지 "Finished up"이 표시됩니다. 그러나 Application.Evaluate "FindSub()"을 수행하면 첫 번째 일치 주소 만 인쇄되고 "Finished up"메시지에는 도달하지 않습니다. 즉, 루프가 계속되어야하는지 평가하려고 시도하고 런타임 오류가 인쇄되지 않고 프로그램 실행이 중지 될 때 Cells.FindNext 행 다음에 오류가 발생합니다.

이 경우 동일한 결과를 산출하기 위해 FindSub 및 Application.Evaluate "FindSub()"를 모두 호출해야합니다. 누군가가 왜 그런지 설명 할 수 없으며 가능한 경우이를 고칠 수있는 방법이 있습니까? 감사.

참고 :이 예에서는 분명히 평가를 사용할 필요가 없습니다. 이 버전은보다 복잡한 상황에서 내가 겪고있는 특정 문제에 초점을 맞추기 위해 단순화되었습니다.

Sub CallSub() 
    Call FindSub 
    Application.Evaluate "FindSub()" 
End Sub 

Sub FindSub() 
    Dim rngFoundCell As Range 
    Dim rngFirstCell As Range 

    Set rngFoundCell = Cells.Find(What:="xxx", after:=ActiveCell, LookIn:=xlValues, _ 
     LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
     MatchCase:=False, SearchFormat:=False) 

    If Not rngFoundCell Is Nothing Then 
     Set rngFirstCell = rngFoundCell 
     Do 
      Debug.Print rngFoundCell.Address 
      Set rngFoundCell = Cells.FindNext(after:=rngFoundCell) 
     Loop Until (rngFoundCell Is Nothing) Or (rngFoundCell.Address = rngFirstCell.Address) 
    End If 

    Debug.Print "Finished up" 
End Sub 
+0

: http://stackoverflow.com/questions/2611929/stop-vba-evaluate-from-calling-target-function-twice –

+0

@ 리차드 ,이 질문의 저자가 =) –

+0

@Joel, Ooops. 그것은 나에게별로 관여하지 않았다. 고마워 :) 그래도, 다른 사람들이 어떤 사람들을 만나면 복습하는 것이 좋은 질문입니다. 홀수 함을 평가하십시오. –

답변

1

을 시도 할 수 있습니다. UDF는 할 수있는 것에 대해 무거운 제한을두고 있습니다. 특히 속성을 설정하거나 다른 기능을 호출하지 않아도됩니다. 여기에서 수행 된 작업을 정확히 분리 할 수는 없지만 여기에있는 내용이 이러한 제한 사항에 위배되는 것으로 상상해보십시오.

시트 수식에서 VB 오류가 발생하지 않기 때문에 오류가 자동으로 삼키는 경우가 있습니다. 수식 오류로 인해 VB 대화 상자가 끊어지면 Excel 사용자 인터페이스가 중단됩니다.

UDF 제한에 대한 자세한 내용은 http://support.microsoft.com/kb/170787을 참조하십시오.

편집 : 좋아요, 여기에 문제에 대한 설명이 있습니다. 평가하는 동안 코드가 아무 말없이 오류가 발생하는 곳을 알고 있습니다. 이 코드를 사용 :

Sub FindSub() 
    Dim rngFoundCell As Range 
    Dim rngFirstCell As Range 

    Set rngFoundCell = Cells.Find(What:="xxx", after:=ActiveCell, LookIn:=xlValues, _ 
     LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _ 
     MatchCase:=False, SearchFormat:=False) 

    If Not rngFoundCell Is Nothing Then 
     Set rngFirstCell = rngFoundCell 
     Do 
      Debug.Print "FOUND: " & rngFoundCell.Address 
      Set rngFoundCell = Cells.FindNext(after:=rngFoundCell) 
      Debug.Print "FIND NEXT: " & IIf(rngFoundCell Is Nothing, " NOTHING", " SOMETHING") 
     Loop Until (rngFoundCell Is Nothing) Or (rngFoundCell.Address = rngFirstCell.Address) 
     Debug.Print "ESCAPED LOOP" 
    End If 

    Debug.Print "Finished up" 
End Sub 

내가 직접 실행 창에 다음과 같은 출력을 얻을 :

findsub 
FOUND: $G$6 
FIND NEXT: SOMETHING 
FOUND: $D$11 
FIND NEXT: SOMETHING 
ESCAPED LOOP 
Finished up 

그래서 좋아. 하지만 :

callsub 
FOUND: $G$6 
FIND NEXT: SOMETHING 
FOUND: $D$11 
FIND NEXT: SOMETHING 
ESCAPED LOOP 
Finished up 
FOUND: $G$6 
FIND NEXT: NOTHING 

여기에는 최소한 세 가지 사항이 있습니다.

  1. 이 함수는 두 번 호출됩니다.이것은 Evaluate에서 알려진 문제입니다. Excel에서 시트의 계산을 처리하는 방법과 관련이 있습니다. 이것이 하나의 Evaluate에서 여러 번 호출 될 수 있기 때문에 데이터를 기록하는 함수에 Evaluate를 사용해서는 안됩니다.
  2. 두 번째 루프에서 다음 찾기는 다른 셀을 찾지 못합니다. 이것은 수수께끼이지만, Evaluate는 실제로 시트 주위를 돌아 다니는 함수를 실행하는 데 사용되어서는 안되기 때문에, 이것은 정의되지 않은 동작이며 실제로 버그로 간주 될 수 없습니다. Evaluate는 수식에서 모든 셀 참조가 명시 적으로 매핑되는 수식을 실행하기위한 것입니다. 내 자신의 이론은 현재 셀이 아닌 셀 참조를 사용하려고하기 때문에 다음 찾기가 작동하지 않으며, 평가는 이러한 종류의 불법 활동을 막으려 고합니다.
  3. 당신의 버그. Loop Until 줄에서 Or 테스트를 처리합니다. 문제는 rngFoundCellNothing 인 경우 두 번째 테스트에서 오류가 발생합니다. VBA가 전체 식을 처리하려고 시도하고이 경우에는 rngFoundCell.Address을 계산할 수 없습니다. 코드는 UDF로 실행할 때 (즉, 평가 내에서) 오류 대화 상자없이 즉시 종료됩니다. 그래서 평가에서 "Finished up"을 보지 못합니다. 이 질문에서 .Evaluate의 제한 사항에 대한 몇 가지 흥미로운 토론이 있습니다
+0

방금이 말을하려고했으나 OP가 Sub를 평가하고 있다는 사실을 아직도 모르고있었습니다. 그렇게 생각하지 않아도됩니다. '. Find'와 동일합니다. 나는 문서화되지 않은 '평가'의 기이함까지 그것을 분필 할 것입니다 ... – jtolle

+0

이것은 하나의 UDF 죄를 저지르는 것입니다, 물론, 당신이 그들을 바꾸 든 그렇지 않든 상관없이, 뒤에서 다른 셀들과 함께 놀 것입니다. , 그것은 의존성 트리를 깨뜨릴 것이다). 찾기가 상처가 없어지는 것이 이상하다는 것을 알았습니다. 아마 없어야 해. –

+0

매우 유익한 후속 조치 ... 감사합니다! – jtolle

0

다음 작업을해야합니다 :

Call FindSub 
Call Application.Run("FindSub") 

은 나를 위해 .Evaluate는 &는 아무것도하지 않는다 실패합니다.

Call Application.Run("FindSub()") (괄호 포함)을 사용하는 경우 ("부분"두 번째 호출)와 동일한 동작이 나타납니다. 이 워크 시트 수식에서 호출되는 것처럼 -

또한 원인이 UDF로 함수를보고있다 평가하는 것이 가장 가능성이 Application.Evaluate "FindSub"

관련 문제