处理VBA时出错(如果Err raise跳过此块)

处理VBA时出错(如果Err raise跳过此块),vba,excel,error-handling,Vba,Excel,Error Handling,我是一名初级python程序员,但最近我在access和excel中使用VBA编写了一些代码 我使用的代码从两个不同的查询(从excel工作簿访问)导出一些数据。然后在excel中,我继续使用数据进行更多的处理,以便进行一些销售分析 问题是,有时查询中的一个(或两个)可能为空,这会引发错误 错误“3021” 我想做的是,如果 错误“3021” 发生在特定的块中,跳转到特定的行并继续执行 在python中,我会把代码块放进去,我知道它可以提高 错误“3021” 在一次“尝试”中避免执行 #code

我是一名初级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

我读
本文档介绍Vba中的错误处理,但我不知道如何在不影响整个脚本的情况下处理特定错误。我想我正在尝试将Vba错误处理作为python编码来面对……如果有人能帮助我理解如何在不影响整个脚本的情况下隔离错误处理程序中的代码块,我将不胜感激(Try/Catch/Finally way?

您应该能够使用一个主错误处理程序,捕获其中的不同代码和操作,并使用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

我会这样做:

选项显式

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,您将转到错误行。

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

If (Test for a record) then
'Code here
Else
'Error Handling here
End if
这得到了相同的结果,没有处理onerror-因为如果您有更多的代码,并且忘记关闭/更改它,您可以毫无意义地返回到其中。我已经处理了足够多的意大利面代码,希望在使用布尔值时避免onerror


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

如果这个问题与python无关,您应该删除python代码和标记,并关注vba的问题。这些代码应该在过程/函数的主体之外。即
退出函数/Sub
之后是错误处理,接着是
结束功能/Sub
。例如,使用@Vityata answer中的代码-注释掉
退出Sub
,在
结束Sub
和最后一个错误(错误6)上方添加一个
继续下一步
将出现两次,并抛出一个无错误的
恢复。
错误。是的,这些更改很好。:)因此,在VBA中处理不同错误的一种方法是使用一个On Error,内部有一个if语句来检查错误并采取一些措施?有没有办法知道Else语句中引发的错误发生在哪一行代码中?@DLA-如果您只在错误处理程序上写入
Stop:Resume
,那么它将在错误时停止,并执行以下操作:我将在错误发生的准确行上继续。这样,您就知道了。@DLA您可以添加行号并使用
erl
在错误处理程序中返回行号。我上次使用行号是在80年代的Sinclair Basic,现代语言不使用行号。我的大多数错误处理程序都有
resume Next
一旦错误得到处理-我在错误处理程序中放了一个断点,注释掉
Next
,正如Vityata所说-它会把你带回到导致错误的那一行。@Vityata我几乎明白了。现在我可以用stop:Resume识别除3021之外的任何其他错误,但你觉得我的代码怎么样,我需要处理两次同一个错误,但处理它的方式在每种情况下都不同(跳过不同的代码块)。我需要使用两个不同的错误处理程序吗?
If (Test for a record) then
'Code here
Else
'Error Handling here
End if