bestsource

VBA(Excel) 오류의 적절한 처리

bestsource 2023. 4. 9. 21:48
반응형

VBA(Excel) 오류의 적절한 처리

저는 VBA와 꽤 오랫동안 일해 왔지만, 여전히 오류 처리에 대해 잘 모르겠습니다.

좋은 기사는 CPearson.com의 기사입니다.

그러나 지금까지의 에러 처리 방법이 완전히 잘못된 것은 아닌지 아직 의문입니다.블록 1

On Error Goto ErrCatcher
   If UBound(.sortedDates) > 0 Then

       // Code

   Else
ErrCatcher:
       // Code

   End If

if 구가 true일 경우 실행되며, 실패 시 Goto가 Else 파트로 들어갑니다.어레이의 Ubound가 0 이하가 되어서는 안 되기 때문에 오류 없이 이 방법은 지금까지 매우 잘 작동했습니다.

제가 제대로 이해했다면 다음과 같습니다.

블록 2

On Error Goto ErrCatcher
    If Ubound(.sortedDates) > 0 Then

       // Code
    End If

    Goto hereX

ErrCatcher:
       //Code
    Resume / Resume Next / Resume hereX

hereX:

또는 이렇게도 할 수 있습니다.블록 3

On Error Goto ErrCatcher
    If Ubound(.sortedDates) > 0 Then

       // Code
    End If

ErrCatcher:
    If Err.Number <> 0 then
       //Code
    End If

가장 일반적인 것은 에러 「캐처」는 서브의 끝에 있고, 서브는 실제로 「종료 서브」로 끝나는 것입니다만, 코드를 읽기 위해서 반대로 점프하면, 서브가 큰 것은 조금 혼란스럽지 않습니까?

블록 4

코드 출처: CPearson.com

  On Error Goto ErrHandler:
   N = 1 / 0    ' cause an error
   '
   ' more code
   '
  Exit Sub

  ErrHandler:

   ' error handling code'

   Resume Next

End Sub 

블록 3처럼 해야 하나요?

ray023에서 정말 훌륭한 답변을 받았습니다만, 과잉 살상이라고 하는 코멘트는 적절합니다.'더 가벼운' 버전의 경우...

블록 1은 IMHO, 나쁜 관행입니다.osknows에서 이미 지적했듯이 오류 처리와 일반 경로 코드를 혼합하는 것은 좋지 않습니다.예를 들어, 에러 상태가 실제로 존재하는 동안 새로운 에러가 발생했을 경우, 그 에러를 처리할 기회가 없습니다(실행이 「버블 업」되는 에러 핸들러가 있는 루틴으로부터 호출하지 않는 한).

블록 2는 Try/Catch 블록을 모방한 것 같습니다.괜찮을 것 같은데 VBA Way가 아니에요.블록 3은 블록 2의 변형입니다.

블록 4는 VBA Way의 베어본 버전입니다.코드를 계승하는 다른 VBA 프로그래머가 기대하는 것이기 때문에, 그것을 사용하는 것을 강력히 추천합니다.자, 이제 작은 확장을 설명하겠습니다.

Private Sub DoSomething()
On Error GoTo ErrHandler

'Dim as required

'functional code that might throw errors

ExitSub:
    'any always-execute (cleanup?) code goes here -- analagous to a Finally block.
    'don't forget to do this -- you don't want to fall into error handling when there's no error
    Exit Sub

ErrHandler:
    'can Select Case on Err.Number if there are any you want to handle specially

    'display to user
    MsgBox "Something's wrong: " & vbCrLf & Err.Description

    'or use a central DisplayErr routine, written Public in a Module
    DisplayErr Err.Number, Err.Description

    Resume ExitSub
    Resume
End Sub

번째 " " " "는 주의해 주세요.Resume이것은 최근에 배운 요령입니다.일반 처리에서는 실행되지 않습니다.Resume <label>스테이트먼트를 지정하면 실행이 다른 곳으로 전송됩니다.하지만 디버깅을 위한 신의 선물일 수도 있습니다.[디버깅] [디버깅] ( [ Ctl - Break ] 、 [ Execution was interrupted ][ Debug ]를( 。 표시은 ''입니다.MsgBox또는 다음 문구를 참조하십시오. Statement하여 "Set Next Statement"(Ctl-F9)를 강조 합니다.ResumeF8 키를 누릅니다.그러면 오류가 발생한 위치가 정확히 표시됩니다.

이 포맷의 「점핑 어라운드」에 대한 당신의 반대에 대해서는, A)앞에서 설명한 바와 같이 VBA 프로그래머가 기대하는 것과 B) 당신의 루틴은 점프할 수 있을 정도로 짧아야 합니다.

에러 처리의 주된 목적은 다음과 같습니다.

  1. 예측은 가능하지만 사용자가 실행하지 않도록 제어할 수 없는 트랩 오류(예를 들어, 썸 드라이브가 제거되었을 때 파일을 썸 드라이브에 저장)
  2. 예기치 않은 오류의 경우 사용자에게 문제가 무엇인지 알려주는 양식을 제공합니다.이렇게 하면 메시지를 전달할 수 있으며 수정 작업을 수행하는 동안 해결 방법을 제공할 수 있습니다.

그럼 어떻게 할 건데?

먼저 예기치 않은 오류가 발생했을 때 표시할 오류 양식을 만듭니다.

frmErrors를 사용하다 회사 오류 양식

다음 라벨에 주의해 주세요.

  • lbl 표제
  • lbl 소스
  • lbl 문제
  • lbl Response(응답)

또한 표준 명령 버튼은 다음과 같습니다.

  • 무시
  • 재시도
  • 취소

이 폼의 코드에는 화려한 것이 없습니다.

Option Explicit

Private Sub cmdCancel_Click()
  Me.Tag = CMD_CANCEL
  Me.Hide
End Sub

Private Sub cmdIgnore_Click()
  Me.Tag = CMD_IGNORE
  Me.Hide
End Sub

Private Sub cmdRetry_Click()
  Me.Tag = CMD_RETRY
  Me.Hide
End Sub

Private Sub UserForm_Initialize()
  Me.lblErrorTitle.Caption = "Custom Error Title Caption String"
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
  'Prevent user from closing with the Close box in the title bar.
    If CloseMode <> 1 Then
      cmdCancel_Click
    End If
End Sub

기본적으로 폼이 닫힐 때 사용자가 어떤 버튼을 눌렀는지 알아야 합니다.

다음으로 VBA 앱 전체에서 사용되는 오류 핸들러 모듈을 만듭니다.

'****************************************************************
'    MODULE: ErrorHandler
'
'   PURPOSE: A VBA Error Handling routine to handle
'             any unexpected errors
'
'     Date:    Name:           Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/22/2010    Ray      Initial Creation
'****************************************************************
Option Explicit

Global Const CMD_RETRY = 0
Global Const CMD_IGNORE = 1
Global Const CMD_CANCEL = 2
Global Const CMD_CONTINUE = 3

Type ErrorType
    iErrNum As Long
    sHeadline As String
    sProblemMsg As String
    sResponseMsg As String
    sErrorSource As String
    sErrorDescription As String
    iBtnCap(3) As Integer
    iBitmap As Integer
End Type

Global gEStruc As ErrorType
Sub EmptyErrStruc_S(utEStruc As ErrorType)
  Dim i As Integer
    
  utEStruc.iErrNum = 0
  utEStruc.sHeadline = ""
  utEStruc.sProblemMsg = ""
  utEStruc.sResponseMsg = ""
  utEStruc.sErrorSource = ""
  For i = 0 To 2
    utEStruc.iBtnCap(i) = -1
  Next
  utEStruc.iBitmap = 1

End Sub
Function FillErrorStruct_F(EStruc As ErrorType) As Boolean
  'Must save error text before starting new error handler
  'in case we need it later
  EStruc.sProblemMsg = Error(EStruc.iErrNum)
  On Error GoTo vbDefaultFill

  EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum)
  EStruc.sProblemMsg = EStruc.sErrorDescription
  EStruc.sErrorSource = EStruc.sErrorSource
  EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum) & ". You should write down the program function you were using, the record you were working with, and what you were doing."
  
   Select Case EStruc.iErrNum
       'Case Error number here
       'not sure what numeric errors user will ecounter, but can be implemented here
       'e.g.
       'EStruc.sHeadline = "Error 3265"
       'EStruc.sResponseMsg = "Contact tech support. Tell them what you were doing in the program."

     Case Else
       
       EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": " & EStruc.sErrorDescription
       EStruc.sProblemMsg = EStruc.sErrorDescription
      
   End Select
   
   GoTo FillStrucEnd
   
vbDefaultFill:

  'Error Not on file
  EStruc.sHeadline = "Error " & Format$(EStruc.iErrNum) & ": Contact Tech Support"
  EStruc.sResponseMsg = "Contact the Company and tell them you received Error # " & Str$(EStruc.iErrNum)
FillStrucEnd:

  Exit Function

End Function
Function iErrorHandler_F(utEStruc As ErrorType) As Integer
  Static sCaption(3) As String
  Dim i As Integer
  Dim iMCursor As Integer
  
  Beep

  'Setup static array
  If Len(sCaption(0)) < 1 Then
    sCaption(CMD_IGNORE) = "&Ignore"
    sCaption(CMD_RETRY) = "&Retry"
    sCaption(CMD_CANCEL) = "&Cancel"
    sCaption(CMD_CONTINUE) = "Continue"
  End If

  Load frmErrors
  
  'Did caller pass error info?  If not fill struc with the needed info
  If Len(utEStruc.sHeadline) < 1 Then
    i = FillErrorStruct_F(utEStruc)
  End If

  frmErrors!lblHeadline.Caption = utEStruc.sHeadline
  frmErrors!lblProblem.Caption = utEStruc.sProblemMsg
  frmErrors!lblSource.Caption = utEStruc.sErrorSource
  frmErrors!lblResponse.Caption = utEStruc.sResponseMsg
  
  frmErrors.Show
  iErrorHandler_F = frmErrors.Tag   ' Save user response
  Unload frmErrors                  ' Unload and release form

  EmptyErrStruc_S utEStruc          ' Release memory

End Function

어플리케이션에만 커스텀되는 에러가 발생할 수 있습니다.이것은 통상, 사용의 애플리케이션 전용의 에러의 짧은 리스트입니다.상수 모듈이 아직 없는 경우 사용자 지정 오류의 ENUM을 포함하는 모듈을 만듭니다(참고: Office '97은 ENUMS를 지원하지 않습니다).ENUM은 다음과 같습니다.

Public Enum CustomErrorName
  MaskedFilterNotSupported
  InvalidMonthNumber
End Enum

커스텀 에러를 발생시키는 모듈을 작성합니다.

'********************************************************************************************************************************
'    MODULE: CustomErrorList
'
'   PURPOSE: For trapping custom errors applicable to this application
'
'INSTRUCTIONS:  To use this module to create your own custom error:
'               1.  Add the Name of the Error to the CustomErrorName Enum
'               2.  Add a Case Statement to the raiseCustomError Sub
'               3.  Call the raiseCustomError Sub in the routine you may see the custom error
'               4.  Make sure the routine you call the raiseCustomError has error handling in it
'
'
'     Date:    Name:           Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010    Ray       Initial Creation
'********************************************************************************************************************************
Option Explicit
Const MICROSOFT_OFFSET = 512 'Microsoft reserves error values between vbObjectError and vbObjectError + 512
'************************************************************************************************
'  FUNCTION:  raiseCustomError
'
'   PURPOSE:  Raises a custom error based on the information passed
'
'PARAMETERS:  customError - An integer of type CustomErrorName Enum that defines the custom error
'             errorSource - The place the error came from
'
'   Returns:  The ASCII vaule that should be used for the Keypress
'
'     Date:    Name:           Description:
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'03/26/2010    Ray       Initial Creation
'************************************************************************************************
Public Sub raiseCustomError(customError As Integer, Optional errorSource As String = "")
  Dim errorLong As Long
  Dim errorDescription As String
  
  errorLong = vbObjectError + MICROSOFT_OFFSET + customError
  
  Select Case customError
  
    Case CustomErrorName.MaskedFilterNotSupported
      errorDescription = "The mask filter passed is not supported"
      
    Case CustomErrorName.InvalidMonthNumber
      errorDescription = "Invalid Month Number Passed"
      
    Case Else
      errorDescription = "The custom error raised is unknown."
      
  End Select
  
  Err.Raise errorLong, errorSource, errorDescription
  
End Sub

이것으로, 프로그램의 에러를 트랩 할 수 있게 되었습니다.서브(또는 기능)는 다음과 같습니다.

Public Sub MySub(monthNumber as Integer)
  On Error GoTo eh  
  
  Dim sheetWorkSheet As Worksheet
  
  'Run Some code here
  
  '************************************************
  '*   OPTIONAL BLOCK 1:  Look for a specific error
  '************************************************
  'Temporarily Turn off Error Handling so that you can check for specific error
  On Error Resume Next
  'Do some code where you might expect an error.  Example below:
  Const ERR_SHEET_NOT_FOUND = 9 'This error number is actually subscript out of range, but for this example means the worksheet was not found
  
  Set sheetWorkSheet = Sheets("January")
  
  'Now see if the expected error exists
  
  If Err.Number = ERR_SHEET_NOT_FOUND Then
    MsgBox "Hey!  The January worksheet is missing.  You need to recreate it."
    Exit Sub
  ElseIf Err.Number <> 0 Then
    'Uh oh...there was an error we did not expect so just run basic error handling 
    GoTo eh
  End If
  
  'Finished with predictable errors, turn basic error handling back on:
  On Error GoTo eh
  
  '**********************************************************************************
  '*   End of OPTIONAL BLOCK 1
  '**********************************************************************************
  
  '**********************************************************************************
  '*   OPTIONAL BLOCK 2:  Raise (a.k.a. "Throw") a Custom Error if applicable
  '**********************************************************************************
  If not (monthNumber >=1 and monthnumber <=12) then
    raiseCustomError CustomErrorName.InvalidMonthNumber, "My Sub"
  end if
  '**********************************************************************************
  '*   End of OPTIONAL BLOCK 2
  '**********************************************************************************
  
  'Rest of code in your sub
  
  goto sub_exit

eh:
  gEStruc.iErrNum = Err.Number
  gEStruc.sErrorDescription = Err.Description
  gEStruc.sErrorSource = Err.Source
  m_rc = iErrorHandler_F(gEStruc)
  
  If m_rc = CMD_RETRY Then
    Resume
  End If

sub_exit:
  'Any final processing you want to do.
  'Be careful with what you put here because if it errors out, the error rolls up.  This can be difficult to debug; especially if calling routine has no error handling.
  
  Exit Sub 'I was told a long time ago (10+ years) that exit sub was better than end sub...I can't tell you why, so you may not want to put in this line of code.  It's habit I can't break :P
End Sub

위의 코드를 복사/붙여넣으면 바로 사용할 수 없지만, 반드시 요점을 알려드립니다.

저는 Block1을 절대 안 써요.Errors와 무관한 IF 문에 Error 블록을 두는 것은 옳지 않은 것 같습니다.

블록 2, 3, 4는 테마의 변형인 것 같아요.GOTO 스테이트먼트를 싫어하기 때문에 Block 3 & 4를 2보다 사용하는 것을 선호합니다.일반적으로 Block 4 방식을 사용합니다.이것은 Microsoft ActiveX Data Objects 2.8 라이브러리가 추가되었는지, 추가되지 않은 경우 2.8이 없는 경우 이전 버전을 추가하거나 사용하기 위해 사용하는 코드의 예입니다.

Option Explicit
Public booRefAdded As Boolean 'one time check for references

Public Sub Add_References()
Dim lngDLLmsadoFIND As Long

If Not booRefAdded Then
    lngDLLmsadoFIND = 28 ' load msado28.tlb, if cannot find step down versions until found

        On Error GoTo RefErr:
            'Add Microsoft ActiveX Data Objects 2.8
            Application.VBE.ActiveVBProject.references.AddFromFile _
            Environ("CommonProgramFiles") + "\System\ado\msado" & lngDLLmsadoFIND & ".tlb"

        On Error GoTo 0

    Exit Sub

RefErr:
        Select Case Err.Number
            Case 0
                'no error
            Case 1004
                 'Enable Trust Centre Settings
                 MsgBox ("Certain VBA References are not available, to allow access follow these steps" & Chr(10) & _
                 "Goto Excel Options/Trust Centre/Trust Centre Security/Macro Settings" & Chr(10) & _
                 "1. Tick - 'Disable all macros with notification'" & Chr(10) & _
                 "2. Tick - 'Trust access to the VBA project objects model'")
                 End
            Case 32813
                 'Err.Number 32813 means reference already added
            Case 48
                 'Reference doesn't exist
                 If lngDLLmsadoFIND = 0 Then
                    MsgBox ("Cannot Find Required Reference")
                    End
                Else
                    For lngDLLmsadoFIND = lngDLLmsadoFIND - 1 To 0 Step -1
                           Resume
                    Next lngDLLmsadoFIND
                End If

            Case Else
                 MsgBox Err.Number & vbCrLf & Err.Description, vbCritical, "Error!"
                End
        End Select

        On Error GoTo 0
End If
booRefAdded = TRUE
End Sub

나는 일을 단순하게 한다.
모듈 레벨에서 2개의 변수를 정의하고 1개의 변수를 모듈 이름으로 설정합니다.

    Private Const ThisModuleName            As String = "mod_Custom_Functions"
    Public sLocalErrorMsg                   As String

모듈의 각 하위/기능 내에서 로컬 변수를 정의합니다.

    Dim ThisRoutineName                     As String

ThisRoutineName을 서브 또는 함수의 이름으로 설정했습니다.

' Housekeeping
    On Error Goto ERR_RTN
    ThisRoutineName = "CopyWorksheet"

그런 다음 모든 오류를 ERR_로 보냅니다.RTN: 발생 시 먼저 sLocalErrorMsg를 설정하여 실제 오류를 정의하고 디버깅 정보를 제공합니다.

    If Len(Trim(FromWorksheetName)) < 1 Then
        sLocalErrorMsg = "Parameter 'FromWorksheetName' Is Missing."
        GoTo ERR_RTN
    End If

각 하위/함수의 하단에서 다음과 같이 논리 흐름을 지시합니다.

    '
    ' The "normal" logic goes here for what the routine does
    '
    GoTo EXIT_RTN

    ERR_RTN:

        On Error Resume Next

    ' Call error handler if we went this far.
        ErrorHandler ThisModuleName, ThisRoutineName, sLocalErrorMsg, Err.Description, Err.Number, False

    EXIT_RTN:

        On Error Resume Next
     '
     ' Some closing logic
     '
    End If

다음으로 "mod_Error_Handler"라고 하는 다른 모듈을 모든 프로젝트에 투입합니다.

    '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' Subroutine Name:     ErrorHandler                                                     '
    '                                                                                       '
    ' Description:                                                                          '
    '   This module will handle the common error alerts.                                    '
    '                                                                                       '
    ' Inputs:                                                                               '
    '   ModuleName                String    'The name of the module error is in.            '
    '   RoutineName               String    'The name of the routine error in in.           '
    '   LocalErrorMsg             String    'A local message to assist with troubleshooting.'
    '   ERRDescription            String    'The Windows Error Description.                 '
    '   ERRCode                   Long      'The Windows Error Code.                        '
    '   Terminate                 Boolean   'End program if error encountered?              '
    '                                                                                       '
    ' Revision History:                                                                     '
    ' Date (YYYYMMDD) Author                Change                                          '
    ' =============== ===================== =============================================== '
    ' 20140529        XXXXX X. XXXXX        Original                                        '
    '                                                                                       '
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    '
    Public Sub ErrorHandler(ModuleName As String, RoutineName As String, LocalErrorMsg As String, ERRDescription As String, ERRCode As Long, Terminate As Boolean)
        Dim sBuildErrorMsg                 As String

    ' Build Error Message To Display
        sBuildErrorMsg = "Error Information:" & vbCrLf & vbCrLf

        If Len(Trim(ModuleName)) < 1 Then
            ModuleName = "Unknown"
        End If

        If Len(Trim(RoutineName)) < 1 Then
           RoutineName = "Unknown"
        End If

        sBuildErrorMsg = sBuildErrorMsg & "Module Name:        " & ModuleName & vbCrLf & vbCrLf
        sBuildErrorMsg = sBuildErrorMsg & "Routine Name:       " & RoutineName & vbCrLf & vbCrLf

        If Len(Trim(LocalErrorMsg)) > 0 Then
            sBuildErrorMsg = sBuildErrorMsg & "Local Error Msg:    " & LocalErrorMsg & vbCrLf & vbCrLf
        End If

        If Len(Trim(ERRDescription)) > 0 Then
            sBuildErrorMsg = sBuildErrorMsg & "Program Error Msg:  " & ERRDescription & vbCrLf & vbCrLf
            If IsNumeric(ERRCode) Then
                sBuildErrorMsg = sBuildErrorMsg & "Program Error Code: " & Trim(Str(ERRCode)) & vbCrLf & vbCrLf
            End If
        End If

        MsgBox sBuildErrorMsg, vbOKOnly + vbExclamation, "Error Detected!"

        If Terminate Then
            End
        End If

    End Sub

최종 결과는 팝업에러 메시지입니다.이 메시지는 어떤 모듈에서 어떤 soubroutine에서 구체적으로 어떤 에러 메시지였는지를 나타냅니다.또, Windows 에러 메세지와 코드도 삽입합니다.

블록 2는 에러 핸들러를 리셋 하지 않기 때문에 기능하지 않습니다.그 때문에, 무한 루프가 발생할 가능성이 있습니다.에러 처리를 VBA에서 올바르게 동작시키려면 , 다음의 조작이 필요합니다.Resume에러 핸들러를 클리어하기 위한 스테이트먼트입니다.Resume는 이전의 에러 핸들러도 재활성화합니다.새로운 에러가 이전의 에러 핸들러로 돌아와 무한 루프가 발생하기 때문에 블록2가 실패합니다.

블록 3이 없기 때문에 실패한다.Resume그 후 오류 처리를 시도하면 실패합니다.

모든 오류 핸들러는 절차를 종료하거나Resume진술.에러 핸들러에 대해서 통상의 실행을 라우팅 하는 것은 혼란스럽습니다.그렇기 때문에 보통 에러 핸들러는 맨 아래에 있습니다.

그러나 VBA의 오류를 처리하는 다른 방법이 있습니다.VB.net의 Try/Catch와 같은 인라인 방식으로 오류를 처리합니다.몇 가지 함정이 있지만 적절하게 관리하면 상당히 잘 작동합니다.

Sub InLineErrorHandling()

    'code without error handling

BeginTry1:

    'activate inline error handler
    On Error GoTo ErrHandler1

        'code block that may result in an error
        Dim a As String: a = "Abc"
        Dim c As Integer: c = a 'type mismatch

ErrHandler1:

    'handle the error
    If Err.Number <> 0 Then

        'the error handler has deactivated the previous error handler

        MsgBox (Err.Description)

        'Resume (or exit procedure) is the only way to get out of an error handling block
        'otherwise the following On Error statements will have no effect
        'CAUTION: it also reactivates the previous error handler
        Resume EndTry1
    End If

EndTry1:
    'CAUTION: since the Resume statement reactivates the previous error handler
    'you must ALWAYS use an On Error GoTo statement here
    'because another error here would cause an endless loop
    'use On Error GoTo 0 or On Error GoTo <Label>
    On Error GoTo 0

    'more code with or without error handling

End Sub

출처:

이 작업을 수행하기 위한 열쇠는Resume바로 뒤에 이어지는 성명On Error진술.Resume에러 핸들러내에 있어, 코드를 로 변환합니다.EndTry1라벨. 즉시 다른 라벨을 설정해야 합니다.On Error이전 에러 핸들러가 「실패」하기 때문에, 문제를 회피하는 스테이트먼트입니다.즉, 활성화되어 다른 오류를 처리할 준비가 됩니다.이로 인해 오류가 반복되어 무한 루프 상태가 될 수 있습니다.

핸들러를 , 「 」를 설정할 .On Error 「」를 사용합니다.On Error Goto 0모든 오류 처리를 취소합니다.

이것이 내일 학생들에게 가르칠 내용입니다.몇 년 동안 이걸 보고...즉, http://www.cpearson.com/excel/errorhandling.htm 위의 모든 문서는 뛰어난 것으로 생각됩니다.

다른 분들을 위해서 요약이 됐으면 좋겠어요. 게 있어요.Err또는 inactive) 。ErrorHandler둘 다 새로운 오류에 대처하고 리셋해야 합니다.

워크북에 붙여넣고 F8을 사용하여 단계를 수행합니다.

Sub ErrorHandlingDemonstration()

    On Error GoTo ErrorHandler

    'this will error
    Debug.Print (1 / 0)

    'this will also error
    dummy = Application.WorksheetFunction.VLookup("not gonna find me", Range("A1:B2"), 2, True)

    'silly error
    Dummy2 = "string" * 50

    Exit Sub

zeroDivisionErrorBlock:
    maybeWe = "did some cleanup on variables that shouldnt have been divided!"
    ' moves the code execution to the line AFTER the one that errored
    Resume Next

vlookupFailedErrorBlock:
    maybeThisTime = "we made sure the value we were looking for was in the range!"
    ' moves the code execution to the line AFTER the one that errored
    Resume Next

catchAllUnhandledErrors:
    MsgBox(thisErrorsDescription)
    Exit Sub

ErrorHandler:
    thisErrorsNumberBeforeReset = Err.Number
    thisErrorsDescription = Err.Description
    'this will reset the error object and error handling
    On Error GoTo 0
    'this will tell vba where to go for new errors, ie the new ErrorHandler that was previous just reset!
    On Error GoTo ErrorHandler

    ' 11 is the err.number for division by 0
    If thisErrorsNumberBeforeReset = 11 Then
        GoTo zeroDivisionErrorBlock
    ' 1004 is the err.number for vlookup failing
    ElseIf thisErrorsNumberBeforeReset = 1004 Then
        GoTo vlookupFailedErrorBlock
    Else
        GoTo catchAllUnhandledErrors
    End If

End Sub

언급URL : https://stackoverflow.com/questions/6028288/properly-handling-errors-in-vba-excel

반응형