8

For example, the following function is used for checking whether a workbook is open:

Function BookOpen(Bk As String) As Boolean
    Dim T As Excel.Workbook 

    Err.Clear
    On Error Resume Next
    Set T = Application.Workbooks(Bk)
    BookOpen = Not T Is Nothing 
    Err.Clear 
    On Error GoTo 0 
End Function

Are these two Err.Clear statements necessary?

4

1 回答 1

17

在这个例子中

Function BookOpen(Bk As String) As Boolean
  Dim T As Excel.Workbook 
  Err.Clear
  On Error Resume Next
  Set T = Application.Workbooks(Bk)
  BookOpen = Not T Is Nothing 
  Err.Clear 
  On Error GoTo 0 
End Function

没有一个用途是合适的,因为On Error重置了最后一个错误,所以Err.Clear是多余的。

在实际处理失败的语句之后是合适的。

Function BookOpen(Bk As String) As Boolean
  Dim T As Excel.Workbook 

  On Error Resume Next
  Set T = Application.Workbooks(Bk)  ' this can fail...

  ' so handle a possible failure
  If Err.Number <> 0 Then
      MsgBox "The workbook named """ & Bk & """ does not exist."
      Err.Clear
  End If

  BookOpen = Not T Is Nothing 
End Function

如果您已经On Error Resume Next生效,程序将在出现错误后继续执行,就好像什么都没发生一样。没有抛出异常,没有警告,这不是结构化的错误处理(即它不像try/catch块)。如果您不进行严格的错误检查,您的程序最终可能会处于非常奇怪的状态。

这意味着您必须在之后检查错误。每一个。陈述。那。能够。失败。准备写很多If Err.Number <> 0 Then支票。请注意,这比看起来更难做到。

更好的是:避免On Error Resume Next像瘟疫一样有效的长代码段。将操作分解为只做一件事的较小的函数/子函数,而不是编写一个可以完成所有任务但可能中途失败的大函数。

简而言之:使您的程序在块Err.Clear中的语句失败后表现出可预测的行为。On Error Resume Next它将错误标记为已处理。这就是它的目的。


当然,在您的示例中,通过使用普遍接受的检查工作簿(即集合的成员)是否存在的方法很容易避免错误处理。

Function BookOpen(Bk As String) As Boolean
  Dim wb As Variant 

  BookOpen = False ' not really necessary, VB inits Booleans to False anyway

  For Each wb In Application.Workbooks
    If LCase(wb.Name) = LCase(Bk) Then
      BookOpen = True
      Exit For
    End If 
  Next
End Function
于 2013-10-20T12:53:11.283 回答