-
Excel 매크로 (VBA) - 019. 런타임 에러 처리 (1)Excel/Excel 매크로 2022. 9. 12. 10:03728x90
전체 목차
- 001. 특정 행을 복사하여 삽입하기
- 002. 선택하여 붙여 넣기 기능 정리
- 003. 변수/Assignment/Loop/비교
- 004. 데이터가 있는 셀의 범위 알아내기
- 005. 데이터 시트(쉘) 순회하기
- 006. 셀 병합 하기
- 007. 변수에 저장되어 있는 데이터 확인하기 (디버그 기능)
- 008. 정렬하기 (Sort)
- 009. 버튼 컨트롤 (Excel Form vs. ActiveX)
- 010. 콤보 상자 컨트롤 (Excel Form vs. ActiveX)
- 011. 확인란/옵션단추 컨트롤(Excel Form vs. ActiveX)
- 012. 스핀단추 컨트롤(스피너, Excel Form vs. ActiveX)
- 013. 자동필터(Auto Filter)
- 014. 함수(function) (전편)
- 015. 함수(function) (후편)
- 016. 중복 데이터 제거하기
- 017. 텍스트 나누기 (공백, 특수문자)
- 018. Vlookup으로 데이터 조회하기(주식 종목 코드 조회)
포스트 목차.
01. 런타임 에러
02. 에러 처리 방식
03. 처리 예제
01. 런타임 에러
런타임 에러는 프로시저를 실행 시간에 발생하는 에러를 의미한다.
다음과 같은 Sub 프로시저가 있다고 생각해보자.
1234567891011121314Sub gotoExample0()Dim divisor As DoubleDim dividend As DoubleDim quotient As Doubledivisor = ActiveSheet.Cells(2, 2).Valuedividend = ActiveSheet.Cells(2, 1).Valuequotient = dividend / divisorActiveSheet.Cells(2, 3).Value = quotientEnd Subcs 활성화된 시트의 A2셀의 값으로 B2셀의 값을 나눈후에 C2셀에 저장하는 루틴이다.
VBA 문법적인 에러나 컴파일 시에는 에러가 발생하지 않을 것으로 보인다.
정상적인 값(?)을 입력했을 때는 연산이 잘 된다.
B2셀에 0을 입력한 후에 Sub 프로시저를 실행해보자.
0으로 나누는 행위 자체가 오류이기 때문에 런타임 오류가 발생했다는 메시지와 함께 경고창이 팝업된다.
사용자는 종료할지, 디버그를 선택하여 코드 창을 열어볼지를 선택할 수 있다.
(위에서 11은 에러의 종류를 나타내는 코드이다.)
02. 에러처리 방식
(1) 로직에 포함하여 처리
우리는 우리가 작성하는 로직에 에러처리 루틴을 포함시킬 수 있다.
에러처리 방식을 다루면서 GoTo문도 함께 다루려고 한다.
GoTo는 프로그램의 흐름을 제어하는 명령이다. 특정 라인으로 프로그램의 흐름을 넘긴다.
특정 라인을 명시하기 위해서 레이블을 사용하는데, 레이블은 레이블명 + 콜론으로 만들수 있다.
다음 예제를 살펴보자
1234567891011121314151617181920212223242526Sub gotoExample1()Dim divisor As DoubleDim dividend As DoubleDim quotient As Doubledivisor = ActiveSheet.Cells(2, 2).Valuedividend = ActiveSheet.Cells(2, 1).ValueIf divisor = 0 ThenGoTo Error01End Ifquotient = dividend / divisorActiveSheet.Cells(2, 3).Value = quotientExit SubError01:ActiveSheet.Cells(2, 3).Value = "0으로 나눔"End Subcs divisor에 0이 할당될 경우 특수처리를 위해 GoTo Error01 문장을 실행하게 되면 11번 라인에서 22번 라인으로 프로그램의 흐름이 변경된다.
0으로 나눔이라는 문장을 C2셀에 표기하면서 Sub 프로시저가 종료된다.
22번 라인의 Error01: 이 레이블의 사용 예라고 볼 수 있다.
반면에 divisor가 0이 아니라면 프로그램은 정상적인 흐름으로 15번째 라인으로 넘어갈 것이다.
19번 라인의 Exit Sub은 Sub 루틴을 종료하는 기능을 담당한다.
코딩을 하는 사람이 예측 가능한 런타임에러는 로직으로 처리가 가능하다.
(2) On Error Resume Next 사용
모든 런타임 에러를 예측하여 로직에 처리루틴을 녹이는 것은 힘든 작업일 수 있다. 런타임 에러가 발생할 경우 특정 동작을 수행할 수 있다면 에러처리가 더 편할 것이다.
On Error라는 키워드를 활용하여 에러처리를 하는 것이 가능하다.
이번에는 에러가 발생했을 때 그냥 다음라인으로 넘어가는 On Error Resume Next 명령을 사용해보자.
1234567891011121314151617181920Sub errorExample0()On Error Resume NextDim divisor As DoubleDim dividend As DoubleDim quotient As Doubledivisor = ActiveSheet.Cells(2, 2).Valuedividend = ActiveSheet.Cells(2, 1).Valuequotient = dividend / divisorIf divisor = 0 ThenActiveSheet.Cells(2, 3).Value = "0으로 나눔"ElseActiveSheet.Cells(2, 3).Value = quotientEnd IfEnd Subcs divisor의 값이 0이 되면 13번 라인에서 에러가 발생할 것이다.
그러나 3번라인에서 On Error Resume Next를 작성했기 때문에 에러가 발생해도 다음라인으로 넘어가게 된다.
divisor 가 0인 경우 0으로 나눔이라는 문구를 셀에 출력하는 코드를 작성하여 에러에 대처할 수 있다.
경고창이 뜨면서 프로그램이 멈추는 것을 막을 수 있지만 에러 발생 이후 처리에 대해 신경써서 처리해야 한다.
사실 위의 코드도 0으로 나누는 에러 외에는 처리 할 수 없는 코드이다.
(3) On Error GoTo 사용
이번에는 에러가 발생했을 때 특정라인으로 넘어가는 On Error GoTo 명령을 사용해보자.
12345678910111213141516171819202122232425Sub gotoExample2()On Error GoTo Error01:Dim divisor As DoubleDim dividend As DoubleDim quotient As Doubledivisor = ActiveSheet.Cells(2, 2).Valuedividend = ActiveSheet.Cells(2, 1).Valuequotient = dividend / divisorActiveSheet.Cells(2, 3).Value = quotientExit SubError01:If divisor = 0 ThenActiveSheet.Cells(2, 3).Value = "0으로 나눔"ElseActiveSheet.Cells(2, 3).Value = "미식별 에러"End IfEnd Sub
csdivisor의 값이 0이 되면 13번 라인에서 에러가 발생할 것이다.
그러나 3번라인에서 On Error Goto Error01를 작성했기 때문에 에러가 발생하면 19번 라인으로 넘어가게 된다.
19번 라인 이후에서는 프로그래머가 예상할 수 있는 0으로 나누는 에러의 경우 "0으로 나눔"을 표기해주고, 그 외의 오류의 경우는 "미식별 에러"를 표기해 줄 수 있다.
런타임 에러가 발생하지 않은 경우에는 14~16번 라인이 실행되며 나눗셈의 몫이 B3셀에 출력될 것이다.
03. 처리 예제
이전 포스트에서 VLookup 함수를 VBA에서 사용하는 방법에 대해 다룬 적이 있다.
https://eggdrop.tistory.com/34
123456789101112131415161718192021Sub vlookupTest()Dim title As StringDim section As RangeDim code As String'B1 셀의 내용을 title에 저장한다.title = ActiveSheet.Cells(1, 2).Value'종목데이터 시트의 A1:AE823 영역을 range 객체에 할당한다.Set section = Worksheets("종목데이터").Range("A1:AE823")'VLookup함수를 실행한다. B1에 있는 데이터는 종목데이터 시트에서 찾아서'2번째 열의 데이터를 가져온다.code = Application.WorksheetFunction.VLookup(title, section, 2, False)'C3 셀의 서식을 텍스트로 변경한다.ActiveSheet.Cells(3, 3).NumberFormatLocal = "@"'VLookup함수의 결과값을 C3에 저장한다.ActiveSheet.Cells(3, 3).Value = codeEnd Subcs 간단하게 요약하면 KOSPI에 상장된 주식의 종목명을 입력했을 때, VLookup을 사용하여 종목코드를 가져오는 매크로였다.
이 매크로는 주식 리스트에 없는 데이터를 조회할 경우 다음과 같은 에러를 발생 시킨다.
리스트에 없는 "삼진전자"를 조회한 경우 위와 같은 에러가 발생한다.
위에서 다룬 On Error GoTo 문을 이용하여, 에러 처리 루틴을 추가해보자.
1234567891011121314151617181920212223242526272829Sub vlookupTestErrorHandling0()On Error GoTo Error01:Dim title As StringDim section As RangeDim code As String'B1 셀의 내용을 title에 저장한다.title = ActiveSheet.Cells(1, 2).Value'종목데이터 시트의 A1:AE823 영역을 range 객체에 할당한다.Set section = Worksheets("종목데이터").Range("A1:AE823")'VLookup함수를 실행한다. B1에 있는 데이터는 종목데이터 시트에서 찾아서'2번째 열의 데이터를 가져온다.code = Application.WorksheetFunction.VLookup(title, section, 2, False)'C3 셀의 서식을 텍스트로 변경한다.ActiveSheet.Cells(3, 3).NumberFormatLocal = "@"'VLookup함수의 결과값을 C3에 저장한다.ActiveSheet.Cells(3, 3).Value = codeExit SubError01:If code = "" ThenActiveSheet.Cells(3, 3).Value = "VLookup 에러"ElseActiveSheet.Cells(3, 3).Value = "미식별 에러"End IfEnd Subcs code에 아무값이 할당되지 않은경우 "VLookup 에러" 메시지를 C3셀에 출력한다.
실행 결과 에러 처리 루틴이 추가되어 프로그램이 런타임 에러를 발생시키지 않는다는 것을 확인했다.
728x90'Excel > Excel 매크로' 카테고리의 다른 글
Excel 매크로 (VBA) - 021. 인풋박스 (InputBox) 사용 방법 (0) 2022.09.14 Excel 매크로 (VBA) - 020. 런타임 에러 처리 (2) (0) 2022.09.13 Excel 매크로 (VBA) - 018. Vlookup으로 데이터 조회하기 (주식 종목 코드 조회) (4) 2022.09.11 Excel 매크로 (VBA) - 017. 텍스트 나누기 (공백, 특수문자) (1) 2022.09.08 Excel 매크로 (VBA) - 016. 중복 데이터 제거하기 (0) 2022.09.07