Skip Navigation Links.
Expand VBAVBA
엑셀프로그래밍이 필요한 이유
Expand ExcelExcel
Expand External LibraryExternal Library
Expand SolutionSolution
Expand EssayEssay

Debugging|On Error GoTo|On Error Resume Next|Resume|Error Code|
|Immediate Window|Locals Window|
|Watch Window|Debug.Print|
|Error Handling Block|Break Point|Break Mode|
|Err.Number|Err.Description|

On Error Resume Next...

사람이 생활하는데는 지극히 필요한것인데
하기 싫은 일들이 천지에 널렸다
운동을 해야겠는데 죽어도 하기 싫다
사람의 도리를 지키기 위하여 인사도 해야 하는데 정말 귀찮다
이눔의 일을 끝내기는 해야겠는데 정말 골치가 아프다
쉬운 일만 골라서 하면서,문제의 일은 하지 않고 밀어 둔다
마음 한 구석에 걸려서 소화도 안되고 온몸이 가렵고
구역질도 나고 가지,가지 효과가 나타난다
그러면서 인생을 살아간다

그런데 컴퓨터프로그래밍에서는 그렇게 어영부영은 안통한다
컴퓨터 프로그래밍에서 에러는 항상 발생할 소질이 있고
에러를 최소화하려는것이 프로그래밍이다

엑셀프로그래밍을 처음 맛본 사람들은 신이 난다
뭐가 아주 잘 돌아 가고 자동화의 귀재가 되는 기분이 든다
그러나 이것을 곧바로 남에게 주면 잘 돌아 가던 것이
금방 에러가 퍽퍽나서 개망신을 당한다
만드는 사람은 시야가 좁다
그냥 자신이 만드는것에 심취하여 초점이 무지하게 좁다
넓게 볼 여유가 없다
여기에서도 프로와 아마츄어는 차이가 나게 된다
프로는 목적을 위하여 하기 싫은 일도 하는 사람이고
아마츄어는 그냥 하기 좋은 일만 하는 사람이다
그러니
프로그래밍에서 에러잡기는 죽어도 하기 싫고 귀찮은 일이고
하기 싫은 일을 열심히 하는 사람은 프로이고
그렇지 않으면 아마츄어인것이다
사람의 몸도 수시로 에러가 난다
발생한 에러를 수정하지 않으면
곧바로 맛이 간다
사람은 거냥,저냥 맛이 간대로 골골 앓으면서
살아 갈수도 있겠지만

여러분이 열심히 작성하는 코드에서의 에러는
잡지 않으면 가치가 없다
이것을 수시로 때려 잡지 않으면
한참 작성후에 애를 먹인다..특히 초보때는 더더욱 그렇다
재수없으면 날밤도 샌다
초보님들이 익히고 있어야할 몇가지를 생각나는대로 정리해 보자

가장 흔하게 사용하는것이

On Error Resume Nex

일것이다
On Error (에러가 났을때)
Resume(에러가 났다고 시끄럽게 떠들거나,죽지 말고 다시 일을 해라)
Next(에러 부분 빼고 다음 명령줄을 진행해라!!)

라는 소리인것이다

만약 다음과 같은 구문에서

On Error Resume Next If Not Intersect(Target,Range("myRange")) Is Nothing Then [A라는 일을 한다!!] Else [B라는 일을 한다!!] End If

와 같은 구문에 있어서 Range("myRange")라는 것이 존재하지 않는다면
에러가 나고 메시지가 뜨고..코드의 실행이 덜커덕중단이 되지만
On Error Resume Next
명령문이 있으므로 에러가 나도 다음 줄이 계속 실행된다
그런데 문제는 까딱 잘못 생각하는것이
에러가 나서 다음줄을 실행하라고 하였으니까..
[B라는 일을 한다!!]라는 명령줄로 갈것으로 생각한다
흔하게 착각하는 일이다
바로 다음줄(Immediate Next Line)이니까..
[A라는을 한다!!]를 하게 되는 것이다
뭔소린지 아래를 크릭해보시기 바란다

[까딱 잘못 예상하는 다음 명령문] [실제 실행하는 명령문]

On Error Resume Next
If Not Intersect(Target,Range("myRange")) Is Nothing Then
     [A라는 일을 한다!!]
Else
     [B라는 일을 한다!!]
End If

엉뚱한 일을 하게 되는것이다
그래서 에러가 났을때는 그냥 무책임하게
On Error Resume Next
라고 하는 것 보다는
(물론 다음줄을 실행해도 상관없다고 생각할때는 괞찮지만)

On Error GoTo [SomeWhere]

라고 에러가 나면 갈곳을 지정해주는것이 좋은것이다
알아서 실행하겠지!!
라고 생각하는것 보다는 어떤 경우에는 어디로 가라!!
라는 구체적으로 제시하는것이 좋은것이다

에러가 나면 빨강색라벨위치로 이동하여 노랑색명령을 실행하게
구체적으로 지시하는것이다

On Error GoTo  ThisLine
If Not Intersect(Target,Range("myRange")) Is Nothing Then
     [A라는 일을 한다!!]
Else
ThisLine:
     [B라는 일을 한다!!]
End If

Resume라는 명령문은 3종류가 있다

Resume
Resume Next
Resume [Label]

위의 3개중의

On Error Resume Next

는 에러가 나더라도 따져보고나 대책을 세우는것이 아니고
별 상관없으니 그냥 바로 다음줄로
통과하라!!라는 이야기가 되는것이다
확실하게 다음줄을 실행해도 아무지장이 없음이 코딩시
확인이 된다면 On Error Resume Next가 나쁜것도 아니지만
아무튼 게으른 명령문이라고 할수 있겠다

Resume를 사용하는 꼼꼼한 코드를 보자

통합문서에 "MySheet"라는 워크시트가 없다
그런데 아래와 같은 구문을 실행하면
Worksheets("MySheet").Select
에서 에러가 퍽나게 된다
아래의 번호를 하나하나 크릭해 보시기 바란다

1 2 3 4 5 6

Sub HandleError()
On Error GoTo HANDLE_ERR
Worksheets("MySheet").Select
ActiveSheet.Range("A1:A10") = "TEST"
Exit Sub
HANDLE_ERR:
Worksheets.Add.Name = "MySheet"
Resume
End Sub



다음은 Resume [Label] 구문을 해보자
VBA엔진은 Err오브젝트를 제공해준다
Err엔진은 에러가 날때 에러를 분석하여 어떤 유형의 에러인지를
판단해주는 오브젝트이다
예를 들어서 아래와 같은 구문 Worksheets("시트이름")에서 에러가
난다면 [시트이름]이라는 정보로는 시트를 찾을수가 없다는
[아래 첨자 사용이 잘못되었습니다]라는 설명과
에러 번호등의 관련 정보를 얻을수 있는것이다

아래의 구문을 번호대로 크릭해 보시기 바란다

1 2 3 4 5 6 7

Sub HandleError()
On Error GoTo HANDLE_ERR
Worksheets("MySheet").Select
ThisLable:
ActiveSheet.Range("A1:A10") = "TEST"
Exit Sub
HANDLE_ERR:
If Err.Number=9 Then
MsgBox "작업하고자 하는 [MySheet]라는" _
        & "이름의 시트가 없습니다..현재시트에 작업합니다!!"
Resume ThisLabel
End If
End Sub



Err오브젝트는 아래의 그림과 같이 VBA가 갖고있는 오브젝트이고
해당 에러의 내용을 알려주는 편리한 것이니
활용하는것이 좋을것이다



아래의 표는 에러의 유형들이 종류가 많다는것을 보기 위한것이고,
여러분들이 갖고 있는 도움말에 있는 내용들이다
관련된 자세한 정보가 도움말에 더 있으니 필요할때마다 참조하시면 될것이다
여러분이 엑셀프로그래밍을 하여 남에게 배포할때는
아래와 같은 에러들이 언제 어디서 나타날지 모르니
섬세함과 정성을 갖고 만들어야 할것이다

Err.NumberErr.Description
3 GoSub가 없는 Return입니다
5 프로시저 호출이 잘못되었습니다
6 숫자가 너무 큽니다
7 메모리가 부족합니다
9 아래 첨자 사용이 잘못되었습니다
10 이 배열은 고정되었거나 일시적으로 잠금 상태입니다
11 0으로 나누었습니다
13 형식이 일치하지 않습니다
14 문자열 공간이 부족합니다
16 식이 너무 복잡합니다
17 요청된 작업을 수행할 수 없습니다
18 사용자 인터럽트가 발생하였습니다
20 오류 없는 Resume입니다
28 스택 공간이 부족합니다
35 Sub, Function 또는 Property가 정의되지 않았습니다
47 코드 리소스나 DLL 응용 프로그램 클라이언트가 너무 많습니다
48 코드 리소스나 DLL을 로드하는 중 오류가 발생하였습니다
49 코드 리소스나 DLL 호출 규정이 잘못되었습니다
51 내부 오류입니다
52 파일 이름 또는 번호가 잘못되었습니다
53 파일을 찾을 수 없습니다
54 파일 모드가 잘못되었습니다
55 파일이 이미 열려있습니다
57 장치 입출력 오류입니다
58 파일이 이미 존재합니다
59 레코드 길이가 잘못되었습니다
61 디스크에 여유 공간이 없습니다
62 파일 끝을 넘어가는 입력입니다
63 레코드 번호가 잘못되었습니다
67 파일이 너무 많습니다
68 사용할 수 없는 장치입니다
70 권한이 없습니다
71 디스크가 준비되지 않았습니다
74 다른 드라이브로 이름을 변경할 수 없습니다
75 경로/파일 액세스 오류입니다
76 경로를 찾을 수 없습니다
91 개체 변수 또는 With 문의 변수가 설정되어 있지 않습니다
92 For 루프를 초기화하지 않았습니다
93 패턴 문자열이 잘못되었습니다
94 Null 사용이 잘못되었습니다
97 클래스 정의 인스턴스가 아닌 개체에서 Friend 프로시저를 호출할 수 없습니다
98 속성이나 메서드 호출은 인수나 반환값으로 전용 개체에 참조를 포함할 수 없습니다
298 시스템 리소스나 DLL을 불러올 수 없습니다
320 지정된 파일 이름에는 문자 입출력 장치 이름을 사용할 수 없습니다
321 파일 형식이 잘못되었습니다
322 필요한 임시 파일을 작성할 수 없습니다
325 리소스 파일의 형식이 잘못되었습니다
327 명명된 데이터 값을 찾을 수 없습니다
328 잘못된 매개 변수입니다. 배열을 기록할 수 없습니다
335 시스템 레지스트리에 액세스할 수 없습니다
336 구성 요소가 올바르게 등록되지 않았습니다
337 구성 요소를 찾을 수 없습니다
338 구성 요소가 올바르게 실행되지 않았습니다
360 이미 로드한 개체입니다
361 개체를 로드하거나 메모리에서 지울 수 없습니다
363 지정된 컨트롤을 찾을 수 없습니다
364 개체가 메모리에서 지워졌습니다
365 이 구문 내에서는 메모리에서 지울 수 없습니다
368 지정된 파일은 더 이상 유효하지 않습니다. 이 프로그램은 새 버전이 필요합니다
371 지정된 개체는 Show에 대한 소유 폼으로 사용될 수 없습니다
380 속성값이 잘못되었습니다
381 속성 배열 인덱스가 잘못되었습니다
382 실행 모드에서는 Property Set을 실행할 수 없습니다
383 Property Set을 읽기 전용 속성과 함께 사용할 수 없습니다
385 속성 배열 인덱스가 필요합니다
387 Property Set을 사용할 수 없습니다
393 실행 모드에서는 Property Get을 실행할 수 없습니다
394 Property Get을 쓰기 전용 속성과 함께 사용할 수 없습니다
400 폼이 이미 나타나 있으므로 모달로 표시할 수 없습니다
402 코드는 먼저 맨 위의 모달 폼을 닫아야 합니다
419 개체 사용 권한이 없습니다
422 속성을 찾을 수 없습니다
423 속성이나 메서드를 찾을 수 없습니다
424 개체가 필요합니다
425 개체 사용이 잘못되었습니다
429 구성 요소는 개체를 만들거나 이 개체에 대한 참조를 반환할 수 없습니다
430 클래스가 자동화를 지원하지 않습니다
432 자동화 작업 중 파일 이름이나 클래스 이름을 찾을 수 없습니다
438 개체가 이 속성 또는 메서드를 지원하지 않습니다
440 자동화 오류입니다
442 원격 프로세스를 위한 형식 라이브러리나 개체 라이브러리와 연결이 소실되었습니다
443 자동화 개체가 기본값을 갖고 있지 않습니다
445 개체는 이 동작을 지원하지 않습니다
446 개체는 명명된 인수를 지원하지 않습니다
447 개체는 현재의 로케일 설정을 지원하지 않습니다
448 명명된 인수를 찾을 수 없습니다
449 선택적 인수가 아니거나 속성 지정이 잘못되었습니다
450 인수의 개수나 속성 지정이 잘못되었습니다
451 컬렉션이 아닌 개체입니다
452 서수가 잘못되었습니다
453 지정한 코드 리소스를 찾을 수 없습니다
454 코드 리소스를 찾을 수 없습니다
455 코드 리소스 잠금 오류입니다
457 키는 이 컬렉션의 한 요소와 이미 연결되어 있습니다
458 변수가 Visual Basic에서 지원하지 않는 형식을 사용하고 있습니다
459 이 구성 요소는 이벤트 집합을 지원하지 않습니다
460 클립보드 형식이 잘못되었습니다
461 메서드나 데이터 구성원을 찾을 수 없습니다
462 원격 서버 컴퓨터가 없거나 사용할 수 없습니다
463 클래스를 사용자의 컴퓨터에 등록할 수 없습니다
480 AutoRedraw 이미지를 만들 수 없습니다
481 그림이 잘못되었습니다
482 프린터 오류입니다
483 프린터 드라이버가 지정된 속성을 지원하지 않습니다
484 시스템의 프린터 정보를 확인하는 데 문제가 있습니다. 프린터 설정이 정확한지 확인하십시오
485 그림 형식이 잘못되었습니다
486 이 프린터로는 폼 이미지를 인쇄할 수 없습니다
520 클립보드를 비울 수 없습니다
521 클립보드를 열 수 없습니다
735 파일을 TEMP 디렉터리에 저장할 수 없습니다
744 찾는 문자열이 없습니다
746 바꿀 문자열이 너무 깁니다
31001 메모리가 부족합니다
31004 개체가 없습니다
31018 클래스가 설정되지 않았습니다
31027 개체를 활성화할 수 없습니다
31032 포함 개체를 만들 수 없습니다
31036 파일에 저장하는 중에 오류가 발생하였습니다
31037 파일을 로드하는 중에 오류가 발생하였습니다

Debugging Tool


위의 표를 보고 억장이 막히는 분이 있을수도 있겠지만
실은 그렇지도 않다
코딩을 하면서 수시로 점검하고 정리하고
체계적으로 작성해 나간다면 에러의 발생을 최소화 할수 있다
이런것을 놓치지 않게 하기 위하여 VBA편집기가 제공하는
도구가 Debugging 도구인것이다

Debugging도구라고 해서 별것이 아니다
예를 들어서 MsgBox를 잘 활용해도 Debugging도구인것이다
실행을 시키면서 어떤 값이 어떤 시점에서 어떻게 변하는가를
관찰해 보는것도 흐름을 관측할수 있는 방법인것이다
아래와 같이 순환을 하면서 셀에 접근할때
의도한대로 셀에 접근하는 관측할수 있도록 MsgBox에 의하여
정지되고 선택되는것을 보는것이다

For iX =1 To 10
    For iY=1 To 10
        Cells(iX,iY)=Int(Rnd()*100)+100
        Cells(iX,iY).Select
        MsgBox Cells(iX,iY).Address
   Next
Next 

또 중단점(Break Point)설정/해제를 활용한다
미심쩍은 구문에 커서를 놓고 F9키를 반복하여 누르면
(혹은 마우스로 행머리크릭/혹은 디버그메뉴에서 중단점설정/해제)
설정/해제가 토글링이 된다

중단점설정(F9키) 실행시작 F8키로 한줄씩 이동 관찰 아직 실행안된 명령문
직접실행창활용_1 직접실행창활용_2 지역창의 활용 조사식창의 활용

미심적은 구문줄에 커서를 놓고 F9키를 크릭하거나
디버그메뉴의 중단점설정을 하거나 행머리를 크릭하거나..




이 페이지를 자세히 열심히 보시는 분은 없었을것이다
초보님들은 특히 보기 싫어 한다
Debugging이라는 단어 자체가 귀찮은 작업이다
그러나 이 페이지의 내용이 자연스러운 습관이 될때
프로그래밍을 한다고 말할수 있다는 점!!
귀찮아도 숙달 시켜야 한다는 점!!
나중에 느낌이 올때 이 페이지는 다시 보시기 바란다

아래의 화일에서는

  • 찾고자 하는 오브젝트의 이름이 존재하여 에러가 없이 실행될때
  • 찾고자 하는 오브젝트의 이름이 존재하지 않아서 에러가 나지만
    에러처리를 하지 않아서 황당한 결과
  • 찾고자 하는 오브젝트의 이름이 존재하지 않아서 에러가 나지만
    에러처리를 하여 정상적으로 실행되는 경우

의 3장의 시트로 본다


Handle Error.