배움터  
  HOME > 배움터 > Daily Tip
Daily Tip

제품:   Excel 버전:   공통
검색어:   try, C#
제목:   에러핸들러 권하는 사회 : Try-Catch-Finally 만들기
     
 

New Page 2
  STEP> 따라하기


에러 처리를 하는 경우 VBA에서 종종 On Error Resume Next라는 구문을 사용합니다. 에러가 나면 무시하고 다음으로 넘어가라는 뜻입니다. 이것은 에러를 이용하여 개체가 존재하는 지 여부를 검사하는 경우 등등 상황에 따라 유용하게 활용되는 구문입니다.

몇 년전에 필자도 에러가 날 여지는 없지만 에러를 무시하고 실행해도 상관없을 듯하여 이 구문을 사용한 적이 있습니다. 그런데 며칠 후 계산의 결과가 틀렸다는 것을 뒤늦게 알았습니다. On Error Resume Next 때문에 몰랐던 겁니다.

On Error Resume Next 를 사용하는 것은 아픈 관절에 파스만 붙이고 다니는 것과 비슷합니다. 파스는 잠시 고통만 줄여줄 뿐 치료를 해주는 것은 아닙니다. 그래서 파스만 계속 붙이게 되면 결국에는 수술로 치료하는 것이 늦어져 다리를 못쓰게 됩니다. 에러가 나면 원인을 찾아 해결하는 것이 좋습니다. 여러분도 반갑게 에러를 맞아주시길 바랍니다.

서론이 길었습니다. 자바나 C# 과 같은 언어를 보면 try-catch-finally라는 에러 핸들러를 사용합니다. 엄밀하게 따지면 try-catch-finally가 VB/VBA의 에러핸들러와 같은 것은 아니지만 VB/VBA입장에선 에러핸들러같은 역할을 한다고 봅니다.

try-catch-finally 블럭은 매력적인 흐름처리구조입니다. try블럭에서 실행해보고 catch블럭에서 에러를 잡아 finally 블럭에서 최종적인 처리를 하는 구조입니다. 상당히 논리적이고 직관적인 구조입니다. 다음은 MSDN에서 가져온 try-catch-finally 블럭 사용 예입니다.
 

 // try-catch-finally
 using System;
 public class EHClass {
   public static void Main () {
      try {
         Console.WriteLine("Executing the try statement.");
         throw new NullReferenceException();
      }

      catch(NullReferenceException e) {
         Console.WriteLine("{0} Caught exception #1.", e);
      }

      catch {
         Console.WriteLine("Caught exception #2.");
      }

      finally {
         Console.WriteLine("Executing finally block.");

      }

   }
}

위의 C#코드가 뭐하는 건지 모르셔도 됩니다. 그러나 try-catch-finally 블럭과 같이 에러 처리를 하는 방법도 있다는 것만 아셔도 됩니다.

이번에는 VBA를 가지고 C#을 흉내내어 try-catch-finally를 만들어 본 코드를 보여드리겠습니다 (남들 하는 건 다 해봐야 겠죠)
 
Function ErrorSample() As Variant
    Dim CntError As Integer

    CntError=1
Try:

   On Error GoTo Catch
    작업실행
   GoTo Finally
Catch:

   If Err.Number <> 0 Then

      If (CntError=1 And Err.Number = 91) Then
          처리가능한 에러 처리, 여기에선 91번 에러
        CntError=CntError+1
        GoTo Try
       End If

      ErrorSample= "#VBA Error: " & Err.Description
    End If

Finally:
End Function

이번에는 위의 주요한 코드를 하나 하나 설명을 드리겠습니다.
 
Function ErrorSample() As Variant
    Dim CntError As Integer

‘// 단 1회의 에러처리만 하기 위한 변수.
‘// 에러를 처리하지 못하는 경우 처리를 시도하면서
‘// 무한루프를 돌 수 있다. 그러므로 1회의 시도만 하기 위해
‘// CntError변수를 사용한다.
‘// 아래의 If문에서 이를 판단한다
     CntError=1
Try:

‘// Try 레이블 아래에 작업하려는 코드를 두게 된다
‘// 에러가 나면 Catch 레이블로 이동한다
    On Error GoTo Catch

              작업실행코드(do something)

‘// 에러없이 위의 작업이 실행되었다면 Finally로 가서 프로시져를 종료한다
        GoTo Finally

Catch:

‘// 그러나 에러가 발생하면 Err.Number는 0이 아닌 에러번호를 가질 것이다.
‘// 그리고 Catch레이블 이하로 프로세스 흐름이 분기된다.

    If Err.Number <> 0 Then

‘// 에러의 횟수가 1회이고 처리가능한 에러라면
‘// 여기에선 91번 에러를 처리가능하다고 보고 에러처리를 준비한다.
        If (CntError=1 And Err.Number = 91) Then

‘// 에러를 처리한다. 그러나 에러가 반드시 처리된다는 보장은 없다.
‘// 또 91번 에러가 여전히 발생할 수 있다.
‘// 그런 경우 에러처리가 무한정 반복될 수 있다.
‘// 그러므로 CntError 변수값을 위의 If문에서 ‘1’인가 검사하는 것이다.
‘// 91번에러에 대해 단 1회의 에러처리만을 하기 위해서
‘// CntError 변수값을 증가시킨다.
                91번 에러 처리
                CntError=CntError+1

                GoTo Try
          End If

‘// 91번 에러가 아니거나 1회 이상의 에러처리를 시도한 91번에러인 경우
‘// 결과 값대신 에러에 대한 설명을 내보낸다.
         ErrorSample= "#VBA Error: " & Err.Description

        End If

‘// 최종
Finally:
End Function