2014-06-30 61 views
2

我有一个整洁的例子,我需要帮助。我试图找到一种方法来处理我的错误,但保持我的子功能模块化(不需要知道我的代码的其余部分是否正常工作)VBA子功能错误处理

在Excel VBA中,没有Try/Catch功能。 VBA中有原生函数,如果它们失败会返回错误。我期待,使下面的例子整齐

Function wrapperForFunction(input As Variant) As Boolean 
    On Error goto returnTrue 
    fancyFunctionThatReturnsError(input As Variant) 
    wrapperForFunction = False 
    LINE OF CODE THAT SETS ERROR BACK TO WHAT IT WAS BEFORE CHANGING IT TO returnTrue 
    Return 
returnTrue: 
    wrapperForFunction = True 
    LINE OF CODE THAT SETS ERROR BACK TO WHAT IT WAS BEFORE CHANGING IT TO returnTrue 
End Function 

Sub MainProgram() 
    On Error goto errorHandlerMain 
    '' do stuff 
    if wrapperForFunction(input) then 'do stuff 
    '' do morestuff 
    if wrapperForFunction(input) then 'do stuff 
errorHandlerMain: 
    'non-erroring cleanup code 
End Sub 

Sub NestedSub() 
    On Error goto errorHandlerNestedSub 
    '' do stuff 
    if wrapperForFunction(input) then 'do stuff 
errorHandlerNestedSub: 
    'non-erroring cleanup code  
End Sub 

我试图避免为这种解决方案

Function wrapperForFunction(input As Variant) As Boolean 
    On Error goto returnTrue 
    fancyFunctionThatReturnsError(input As Variant) 
    wrapperForFunction = False 
    Return 
returnTrue: 
    wrapperForFunction = True 
End Function 

Sub MainProgram() 
    On Error goto errorHandlerMain 
    '' do stuff 
    tmp = wrapperForFunction(input) ' <------------ THIS LINE WAS ADDED 
    On Error goto errorHandlerMain ' <------------ THIS LINE WAS ADDED 
    if tmp then 'do stuff 
    '' do morestuff 
    tmp = wrapperForFunction(input) ' <------------ THIS LINE WAS ADDED 
    On Error goto errorHandlerMain ' <------------ THIS LINE WAS ADDED 
    if tmp then 'do stuff 
errorHandlerMain: 
    'non-erroring cleanup code 
End Sub 

Sub NestedSub() 
    On Error goto errorHandlerNestedSub 
    '' do stuff 
    tmp = wrapperForFunction(input) ' <------------ THIS LINE WAS ADDED 
    On Error goto errorHandlerNestedSub ' <------------ THIS LINE WAS ADDED 
    if tmp then 'do stuff 
errorHandlerNestedSub: 
    'non-erroring cleanup code 
End Sub 

任何建议?有没有办法找到当前的“On Error goto x”状态,并将其重置为在更改之前的状态? 像

Function foobar() 
    Dim errorLine As Long: errorLine = CURRENT_ERROR_LINE 
    On Error goto 40 
    'do stuff 
    On Error goto errorLine 
    Return 
40'cleanup code 

End Function 
+0

可以在VBA模拟try catch块请看这里 http://stackoverflow.com/q/30991653/4413676 – HarveyFrench

回答

1

几个点需要注意的VBA错误处理:

  • On Error Goto <x>声明的范围是该声明所包含的步骤,从内调用的任何过程程序。
  • 作为前一点的扩展:如果发生错误,它将'调出堆栈直到它到达定义了错误处理的过程,如果堆栈上没有过程定义了错误处理,它将显示通用消息框。

通过以上行为记,没有必要每次调用程序后重新状态On Error Goto <x>任何改变被叫过程使得它的错误处理将其已完成的时间已经超出范围。

与下面的示例工作:

Public Sub Subroutine1() 
    Dim a As Double, b As Double, c As Double 

    On Error GoTo Err_Subroutine 
    a = 10 
    b = 2 

    c = Divide(a, b) 
    c = c/0   

Exit_Subroutine: 
    Exit Sub 

Err_Subroutine: 
    Select Case Err.Number 
     Case 11 'DIV/0 
      MsgBox "DIV/0 error in Sub Subroutine1()" 
      Resume Exit_Subroutine 
     Case Else 
      MsgBox "Unhandled error in Subroutine1()" 
      Resume Exit_Subroutine 
    End Select 
End Sub 

'Returns a/b or 0 if an error occurs 
Public Function Divide(a, b) 
    On Error GoTo Err_Divide 

    Divide = a/b 

Exit_Divide: 
    Exit Function 

Err_Divide: 
    Select Case Err.Number 
     Case 11 'DIV/0 
      MsgBox "DIV/0 error in Function Divide()" 
      Divide = 0 
      Resume Exit_Divide 
     Case Else 
      MsgBox "Unhandled error in Function Divide()" 
      Divide = 0 
      Resume Exit_Divide 
    End Select 
End Function 

尽管Divide已调用和执行该语句On Error GoTo Err_Divide,当在下一行出现DIV/0错误的错误仍然会被引导到Err_Subroutine

+0

也可能是值得注意的是,'对错误转到0'返回错误处理到其默认状态即在当前范围内未处理。 – Aiken