수색…
소개
컴파일 된 코드는 런타임에 오류가 발생할 수 있습니다. 이 항목에서는 가장 일반적인 항목과 그 원인 및이를 방지하는 방법을 나열합니다.
런타임 오류 '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
왜이게 효과가 있니?
LBound
및 UBound
함수를 사용하여 각각 배열의 아래쪽 경계와 위쪽 경계를 결정합니다.
기타주의 사항
인덱스가 문자열 인 경우 (예 : 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
- 우리가 호출 할 수 없습니다 .Add
에 Nothing
.
올바른 코드
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
가 명시적인 점프 로 간주 됨).