我们需要为每个子例程创建一个错误处理程序吗?

lam*_*988 5 error-handling vba program-flow

我从SO复制一段代码作为例子.子例程包含错误处理程序.是否应该为所有Subs制作错误处理程序?

Public Sub SubA()
  On Error Goto ProcError

  Connection.Open
  Open File for Writing
  SomePreciousResource.GrabIt

ProcExit:  
  Connection.Close
  Connection = Nothing
  Close File
  SomePreciousResource.Release

  Exit Sub

ProcError:  
  MsgBox Err.Description  
  Resume ProcExit
End Sub
Run Code Online (Sandbox Code Playgroud)

顺便说一下,如何做一个子程序内部的控制流时,代码执行遇到Exit Sub,End SubResume?当它遇到诸如ProcError:执行期间的标签时,它是执行它还是跳过它?

Jea*_*ett 9

简短的回答是:不,你不仅不需要在每个过程中都有一个错误处理程序,但实际上你通常不希望在每个过程中都有一个错误处理程序.

您将需要在最有意义的情况下执行错误处理.通常,您只需要在最高级别的过程中使用错误处理程序,即调用所有其他过程的错误处理程序; 较低级别的程序应该将问题解决到楼上,让错误"冒泡"到更高级别的程序.有时您会希望在较低级别的过程中进行一些错误处理.

更多信息,请参阅@jtolle的这两个优秀答案:

此外,互联网搜索将揭示网上有关于错误处理的整个文献.在我看来,有些是非常错误的!但如果它坚持我在前两段写的内容,那么值得考虑.

Exit Sub并且End Sub相当直观:前者停止当前Sub的执行并将控制返回到调用它的过程(或者如果该过程未被另一个过程调用则完全停止执行).后者只是对编译器的一个指示,即这个特定Sub的代码结束 - 如果执行,则End Sub表现得像Exit Sub.

Resume指定错误处理例程完成后应该发生的事情.Plain Resume返回导致错误的同一语句并尝试再次执行它.Resume Next跳过导致错误的语句,而是转到紧跟其后的语句.Resume mylabel去标签mylabel:.

如果ProcError:在执行过程中遇到像你这样的标签,那么没有什么特别的事情会发生,并且执行会转移到标签之后的下一个语句.当然在你的例子中,ProcError:永远不会直接执行(即除非出现错误),因为Exit Sub它就在它之前.


顺便说一下,ProcExit:块可能应该从一开始On Error Resume Next(即继续关闭所有内容并退出而不管任何错误),或者正如@Phydaux指出的那样On Error Goto 0(出错,停止执行),否则如果其中的某些内容触发了错误,您可能会在错误处理程序和ProcExit:代码之间进入无限的乒乓循环.

ProcExit:
   On Error Resume Next ' or, alternatively, On Error Goto 0
   Connection.Close
   Connection = Nothing
   Close File
   SomePreciousResource.Release
Exit Sub
Run Code Online (Sandbox Code Playgroud)


pin*_*txo 2

Exit Sub会像Java中的return一样立即退出子程序

End Sub 只是子例程块结束的标记,如 Java 中的 }

标签只是代码中的一个标记,用于定义跳转目的地。如果您没有跳转到标签,而是“定期”到达那里,则标签本身将被忽略,但标签后面的代码将像没有标签一样执行,示例中的代码将一直执行到只要不发生错误就退出Sub语句。如果发生它会跳转到 ProcError

在这种情况下,Resume 将执行 ProcExit 请参阅此处