【问题标题】:Error handling VBA (if Err raise skip this block)错误处理 VBA(如果 Err 引发跳过此块)
【发布时间】:2018-06-02 23:36:00
【问题描述】:

我是一名初学者 python 程序员,但最近我在 access 和 excel 中使用 VBA 进行了一些编码。

我正在编写从两个不同查询(从访问 Excel 工作簿)导出一些数据的代码。然后,我继续从 excel 中对数据进行更多处理,以便进行一些销售分析。

问题是,有时,查询之一(或两者)可能为空,这会引发

错误“3021”

我想做的是,如果一个

错误“3021”

发生在特定的块中,跳转到特定的行并继续执行。

我会在 python 中放置那个代码块——我知道它可以提高

错误“3021”

在“尝试”内避免执行

#code here
Try:
    #code that may raise error
Except Exception as '3021':
    pass
#code here....

在 VBA 中我能够处理

错误“3021”

但不是我想要的。一旦我“管理”了

错误“3021”

如果在其余代码中引发另一个错误,则最后一个错误处理程序始终处于活动状态(隐藏我想引发以进行调试的其他错误引发。代码摘录如下:

On Error GoTo Err1Handler
'here starts the code that may raise the error '3021'
consulta16.MoveFirst
Datos16.Range("A2").CopyFromRecordset consulta16

With APIExcel.ActiveSheet.Cells
.Select
.EntireColumn.AutoFit
.Range("A1").Select
End With
'From here I know there wont be an error '3021'
NoData16:
columnas = consulta17.Fields.Count
For i = 0 To columnas - 1
    Datos17.Cells(1, i + 1) = consulta17.Fields(i).Name
Next i
'Now comes the second query that may raise same 

错误“3021”

所以我又犯了一个错误异常

 On Error GoTo Err2Handler
 consulta17.MoveFirst

Datos17.Range("A2").CopyFromRecordset consulta17
    With APIExcel.ActiveSheet.Cells
    .Select
    .EntireColumn.AutoFit
    .Range("A1").Select
End With
'#more code.......
Err1Handler:
If Err.Number = 3021 Then
    'MsgBox ("Sin datos del 16")
    Resume NoData16
End If
Err2Handler:
If Err.Number = 3021 Then
        'MsgBox ("Sin datos del 17")
        Resume NoData17
End If

我读过here This documentation about error handling in Vba 但我不知道如何在不影响整个脚本的情况下处理特定错误。我想我正试图将 vba 错误处理作为 python 中的编码来处理......如果有人能帮助我理解如何在不影响整个脚本的情况下隔离错误处理程序中的代码块,我将不胜感激(尝试/捕获/最终方式? )

【问题讨论】:

  • 如果这个问题与python无关,你应该删除python代码和标签并专注于你遇到的vba问题。

标签: vba excel error-handling


【解决方案1】:

您应该能够使用一个主要的错误处理程序并捕获其中的不同代码和操作,并在适当处理后使用 Err.Clear 重置错误编号。然后是关于返回到哪里的说明。

'Other code
Exit Sub

Err1Handler:

If Err.Number = 3021 Then

    'MsgBox ("Sin datos del 16")
    Err.Clear
    Resume NoData16

ElseIf Err.Number = X Then
    MsgBox "The workbook named """ & Bk & """ does not exist."
    Err.Clear
    'Resume Next  ''Example. Instruction on what to do next; where to go
End If

End Sub

或使用相同的想法,但使用

Select Case Err.Number
            Case 0

【讨论】:

  • 这段代码应该在过程/函数的主体之外。即Exit Function/Sub,后跟错误处理,然后是End Function/Sub。例如。 - 使用@Vityata 答案中的代码 - 注释掉Exit Sub,在End Sub 上方添加Resume Next,最后一个错误(错误6)将出现两次并抛出Resume without error 错误。
  • 是的,这些变化很好。 :)
【解决方案2】:

我会这样做:

选项显式

Public Sub TestMe()

    Dim a As Long
    Dim b As Long

    On Error GoTo TestMe_Error

    a = 1: b = 0
    Debug.Print a / b   'Error 11
    Debug.Print "Some more stuff..."
    Debug.Print a / b   'Error 11
    Debug.Print "Some other stuff..."        
    a = 0
    Debug.Print a / b   'Error 6

    On Error GoTo 0
    Exit Sub

TestMe_Error:
    If Err.Number = 11 Then
        Resume Next
    Else
        MsgBox Err.Number & " " & Err.Description
    End If
End Sub

因此,如果您查找错误 11,它将忽略它并继续,并且将捕获所有其他错误(例如捕获错误 6)。


这是如何找到该行,导致错误:

Public Sub TestMe()

    On Error GoTo TestMe_Error

    Debug.Print 3 / 4
    Debug.Print 4 / 0
    Debug.Print 6 / 1

    On Error GoTo 0
    Exit Sub

TestMe_Error:
    Stop
    Resume
End Sub

代码在Stop 行停止后,如果按两次F8,则会转到错误行。

【讨论】:

  • 那么在 VBA 中处理不同错误的一种方法是使用单个 On Error,并在内部使用 if 语句来检查错误并采取一些措施?
  • 有什么方法可以知道 Else 语句中引发的错误发生在哪一行代码中?
  • @DLA - 如果您在错误处理程序上只写Stop : Resume,那么它将在错误处停止并在发生错误的确切行处恢复。这样你就知道了。
  • @DLA 您可以添加行号并使用erl 在错误处理程序中返回行号。我最后一次使用行号是八十年代的 Sinclair Basic,现代语言不使用行号。一旦处理了错误,我的大多数错误处理程序都有Resume Next - 我在错误处理程序中放置了一个断点,注释掉Next,正如Vityata所说 - 它带你回到导致错误的行。 stackoverflow.com/questions/41001047/…
  • @Vityata 我几乎明白了。现在我可以用 stop 识别除 3021 之外的任何其他错误:Resume 但是你在我的代码中怎么样,我需要处理两次相同的错误,但在每种情况下处理它的方式都不同(跳过不同的代码块)。我需要使用两个不同的错误处理程序吗?
【解决方案3】:

我会以不同的方式处理这个问题。我的查询知识相当薄弱,但我相信同样的原则也适用:

If (Test for a record) then
'Code here
Else
'Error Handling here
End if

这会得到相同的结果,而无需处理 onerror - 因为如果您有更多的代码,并且您忘记将其关闭/更改它,您可能会毫无意义地循环回到它。我已经处理了足够多的意大利面条代码,以便在我可以使用布尔值代替时避免出现错误。

当然,所有这些都假设您可以在运行查询之前测试记录是否存在。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-21
    • 2020-05-31
    • 1970-01-01
    • 2022-01-18
    • 2014-08-12
    • 1970-01-01
    • 2021-06-06
    • 2022-11-10
    相关资源
    最近更新 更多