수색…


소개

컴파일 된 코드는 런타임에 오류가 발생할 수 있습니다. 이 항목에서는 가장 일반적인 항목과 그 원인 및이를 방지하는 방법을 나열합니다.

런타임 오류 '3': GoSub없이 반환

틀린 코드

Sub DoSomething()
    GoSub DoThis
DoThis:
    Debug.Print "Hi!"
    Return
End Sub

왜이 기능이 작동하지 않습니까?

실행은 DoSomething 프로 시저를 입력하고 DoThis 레이블로 점프하여 "Hi!"를 인쇄합니다. 디버그 출력, GoSub 호출 후 즉시 명령을 반환 합니다, "안녕!" 다시 GoSub 문으로 여기에 도착하지 않았기 때문에 Return 문을 만나지 만 현재로 돌아갈 곳이 없습니다.

올바른 코드

Sub DoSomething()
    GoSub DoThis
    Exit Sub
DoThis:
    Debug.Print "Hi!"
    Return
End Sub

왜이게 효과가 있니?

도입함으로써 Exit Sub 전과 지시 DoThis 회선 레이블을, 우리는 분리했다 DoThis 대한 EXECUTE 할 수있는 유일한 방법 - 프로 시저 본문의 나머지 서브 루틴 DoThis 서브 루틴은 경유 GoSub 점프.

기타주의 사항

GoSub / Return 은 더 이상 사용되지 않으므로 실제 프로 시저 호출에 찬성하여 피해야합니다. 프로시 저는 오류 핸들러가 아닌 서브 루틴을 포함하지 않아야합니다.

이것은 런타임 오류 '20' 과 매우 유사합니다. 오류없이 다시 시작하십시오 . 두 경우 모두 해결 방법은 정상 실행 경로 가 명시적인 점프없이 (라인 On Error GoTo 레이블에 의해 식별 된) 서브 루틴에 진입 할 수 없도록 보장하는 것입니다 ( On Error GoTo명시적인 점프 로 간주 됨).

런타임 오류 '6': 오버플로

틀린 코드

Sub DoSomething()
    Dim row As Integer
    For row = 1 To 100000
        'do stuff
    Next
End Sub

왜이 기능이 작동하지 않습니까?

Integer 데이터 유형은 최대 값이 32,767 인 16 비트 부호있는 정수입니다. 그것보다 큰 값을 지정하면 (자), 타입이 오버 플로우되어이 에러가 발생합니다.

올바른 코드

Sub DoSomething()
    Dim row As Long
    For row = 1 To 100000
        'do stuff
    Next
End Sub

왜이게 효과가 있니?

대신 Long (32 비트) 정수를 사용하여 카운터 변수 유형을 오버플로하지 않고 32,767 회 이상 반복하는 루프를 만들 수 있습니다.

기타주의 사항

자세한 정보는 데이터 유형 및 한계 를 참조하십시오.

런타임 오류 '9': 아래 첨자 범위 벗어났습니다.

틀린 코드

Sub DoSomething()
    Dim foo(1 To 10)
    Dim i As Long
    For i = 1 To 100
        foo(i) = i
    Next
End Sub

왜이 기능이 작동하지 않습니까?

foo 는 10 개의 항목을 포함하는 배열입니다. i 루프 카운터가 11의 값에 도달하면 foo(i)범위를 벗어납니다 . 이 오류는 해당 배열이나 컬렉션에없는 인덱스로 배열이나 컬렉션에 액세스 할 때마다 발생합니다.

올바른 코드

Sub DoSomething()
    Dim foo(1 To 10)
    Dim i As Long
    For i = LBound(foo) To UBound(foo)
        foo(i) = i
    Next
End Sub

왜이게 효과가 있니?

LBoundUBound 함수를 사용하여 각각 배열의 아래쪽 경계와 위쪽 경계를 결정합니다.

기타주의 사항

인덱스가 문자열 인 경우 (예 : ThisWorkbook.Worksheets("I don't exist") ,이 오류는 제공된 이름이 쿼리 된 컬렉션에 없음을 의미합니다.

실제 오류는 구현에 따라 다릅니다. Collection 런타임 오류 5 "잘못된 프로 시저 호출 또는 인수가"발생합니다.

Sub RaisesRunTimeError5()
    Dim foo As New Collection
    foo.Add "foo", "foo"
    Debug.Print foo("bar")
End Sub

런타임 오류 '13': 형식이 일치하지 않습니다.

틀린 코드

Public Sub DoSomething()
    DoSomethingElse "42?"
End Sub

Private Sub DoSomethingElse(foo As Date)
'    Debug.Print MonthName(Month(foo))
End Sub

왜이 기능이 작동하지 않습니까?

VBA는 "42?" 를 변환하려고 정말 열심히 노력하고 있습니다. 인수를 Date 값으로 변환합니다. VBA가 전달할 날짜를 알지 못하기 때문에 DoSomethingElse 대한 호출을 실행할 수 없으므로 인수 유형이 예상 유형과 일치하지 않으므로 런타임 오류 13 유형 불일치 가 발생합니다. 암묵적으로도 변환되지 않음).

올바른 코드

Public Sub DoSomething()
    DoSomethingElse Now
End Sub

Private Sub DoSomethingElse(foo As Date)
'    Debug.Print MonthName(Month(foo))
End Sub

왜이게 효과가 있니?

Date 매개 변수를 필요로하는 프로 시저에 Date 인수를 전달하면 호출이 성공할 수 있습니다.

런타임 오류 '91': 개체 변수 또는 With 블록 변수가 설정되어 있지 않습니다.

틀린 코드

Sub DoSomething()
    Dim foo As Collection
    With foo
        .Add "ABC"
        .Add "XYZ"
    End With
End Sub

왜이 기능이 작동하지 않습니까?

개체 변수에 대한 참조를 개최하고, 참조는 사용하여 설정 될 필요가 Set 키워드를. 이 오류는 참조가 Nothing 인 개체에 대한 멤버 호출이있을 때마다 발생합니다. 이 경우에는 foo A는 Collection 참조하지만, 초기화되지, 그래서 참조가 포함되어 있지 않습니다 Nothing - 우리가 호출 할 수 없습니다 .AddNothing .

올바른 코드

Sub DoSomething()
    Dim foo As Collection
    Set foo = New Collection
    With foo
        .Add "ABC"
        .Add "XYZ"
    End With
End Sub

왜이게 효과가 있니?

Set 키워드를 사용하여 개체 변수에 유효한 참조를 할당하면 .Add 호출이 성공합니다.

기타주의 사항

종종 함수 나 속성이 객체 참조를 반환 할 수 있습니다. 일반적으로 Excel의 Range.Find 메서드가 Range 객체를 반환합니다.

Dim resultRow As Long
resultRow = SomeSheet.Cells.Find("Something").Row

그러나이 함수는 Nothing 매우 잘 반환 할 수 있으므로 (검색 단어를 찾을 수없는 경우) 체인화 된 .Row 멤버 호출이 실패 할 가능성이 높습니다.

개체 멤버를 호출하기 전에 참조가 If Not xxxx Is Nothing 조건으로 설정되어 있는지 확인합니다.

Dim result As Range
Set result = SomeSheet.Cells.Find("Something")

Dim resultRow As Long
If Not result Is Nothing Then resultRow = result.Row

런타임 오류 '20': 오류없이 다시 시작

틀린 코드

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

CleanFail:
    Debug.Print Err.Number
    Resume Next
End Sub

왜이 기능이 작동하지 않습니까?

DoSomethingElse 프로 시저가 오류를 발생 CleanFail 실행은 CleanFail 행 레이블로 점프하고 오류 번호를 인쇄하며 Resume Next 명령은 오류가 발생한 행 바로 뒤에있는 명령으로 점프합니다 (이 경우 Debug.Print 명령 : 오류 처리 서브 루틴은 오류 컨텍스트없이 실행되고 Resume Next 명령에 도달하면 다시 시작할 곳이 없기 때문에 런타임 오류 20이 발생합니다.

올바른 코드

Sub DoSomething()
    On Error GoTo CleanFail
    DoSomethingElse

    Exit Sub    
CleanFail:
    Debug.Print Err.Number
    Resume Next
End Sub

왜이게 효과가 있니?

CleanFail 행 레이블 앞에 Exit Sub 명령을 도입하여 CleanFail 오류 처리 서브 루틴을 나머지 프로 시저 본문과 분리했습니다 CleanFail 오류 처리 서브 루틴을 실행하는 유일한 방법은 On Error 점프를 통한 것입니다. 따라서 실행 경로가 런타임 오류 20을 피하는 오류 컨텍스트 외부의 Resume 명령에 도달하지 않습니다.

기타주의 사항

이것은 런타임 오류 '3' 과 매우 유사합니다. GoSub없이 돌아 가기 ; 두 경우 모두 해결 방법은 정상 실행 경로 가 명시적인 점프없이 (라인 On Error GoTo 레이블에 의해 식별 된) 서브 루틴에 진입 할 수 없도록 보장하는 것입니다 ( On Error GoTo명시적인 점프 로 간주 됨).



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow