【问题标题】:VBA Change error handling method during code executionVBA更改代码执行期间的错误处理方法
【发布时间】:2018-01-09 16:41:19
【问题描述】:

我有一个宏,部分代码涉及: 1)检测一列是否包含空单元格 - 如果是这样,用一些值填充它们 2) 检测列是否包含包含错误的单元格(例如 N/A),如果是,则用一些值填充它们

现在如果列中没有错误/空单元格,找到它们的行会给出“运行时错误 1004 未找到单元格”。

我使用错误处理来跳过 GoTo。

下面是代码 - 第一个错误处理 GoTo 完美运行,而第二个给出了预期的错误,虽然设置了错误处理 GoTo,但这似乎不起作用。带有 cmets 的代码:

On Error GoTo EErrorOne


'depending on file I get, below line will generate error and code successfully skips to ErrorOne label

Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).SpecialCells (xlCellTypeBlanks)

' code to be skipped

    Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).Select
    Selection.SpecialCells(xlCellTypeBlanks).Select
    Selection.Value = "Some Value"

' end of code to be skipped

EErrorOne:

' successfully skipped error line by now. Below line should set a new Error handling procedure.

On Error GoTo EErrorTwo



Workbooks(nazwawb).Sheets(szitnr).Columns(ktorepole).Select

' Below line generates an error but does not skip to EErrorTwo label as detailed in the current Error handling procedure

Selection.SpecialCells(xlCellTypeFormulas, 16).Select   

' code to be skipped


Selection.SpecialCells(xlCellTypeFormulas, 16).Select
    Selection.Value = "Some Value"

' end of code to be skipped


EErrorTwo:



' Below line should reset error handling procedure to normal for subsequent handling of other errors:
On Error GoTo 0

似乎忽略了错误处理过程(GoTo 特定标签),而是显示一条错误消息,好像错误处理已重置为 GoTo 0。如何跳过第二个错误?

【问题讨论】:

  • 最好创建不依赖错误处理程序来运行的代码。而是检查导致错误的条件并跳过您知道会导致错误的代码。
  • 你的代码做的事情太多了。每个过程一个处理程序。处理错误时无法处理新错误,需要先处理第一个错误On Error 在错误处理程序中毫无用处,您已经处于错误状态,您希望发生什么? FWIW 这将很快成为Rubberduck 检查。
  • braX,我尝试将相关单元格分配给一个范围,然后设置如果不是 rangename 什么都没有,但它仍然评估为错误消息。 Mat's Mug,我不是这方面的专家,虽然我怀疑我需要在重新开始之前退出错误处理,但我认为 On Error GoTo 0 会重置错误处理 - 结果应该是 On Error GoTo -1,正如我的问题已接受的答案中所指出的那样。无论如何,我没有在我应该有的地方重置错误处理,这是我的问题的解决方案。谢谢大家

标签: excel vba


【解决方案1】:

当错误发生时,您并没有清除错误,只是试图跳过它们,代码想知道错误发生了什么。

正如 Chip Pearson 在他的网站上所说:

当第一个错误出现时,执行转移到该行 以下 Err1:.当第二个错误处理程序仍然处于活动状态 发生错误,因此第二个错误不会被 On 捕获 错误说明

然后继续

Resume 语句指示 VBA 在指定的位置恢复执行 点在代码中。您只能在错误处理中使用 Resume 堵塞;任何其他用途都会导致错误。此外,简历是唯一的 方式,除了退出过程,摆脱错误处理 堵塞。不要使用 Goto 语句来引导代码执行 一个错误处理块。这样做会导致奇怪的问题 错误处理程序。 http://www.cpearson.com/excel/errorhandling.htm

理想的方法是首先避免错误 - 在打开之前检查工作簿是否存在,在尝试引用之前检查工作簿中是否存在工作表,如果发生错误则跳出例程的主体,处理错误,然后再次跳转。

举个例子:

Sub Test()

    On Error GoTo ERR_HANDLE

    '.... code ....

FAST_EXIT:
    'Code to tidy up, clear references etc before finishing.

Exit Sub

ERR_HANDLE:
    Select Case Err.Number
        Case 1004
            'Code to resolve error
            '.
            '.
            'Resume - clear error, jump back to line that caused it.
            'Resume Next - clear error, jump to line after the one that caused error.
            'Resume FAST_EXIT - clear error and go to line label.

        Case 92 'Do something else to resolve error.

        Case Else
    End Select

End Sub

【讨论】:

  • 为了进一步澄清 Darren 的回答,错误处理程序处于活动状态,直到明确告知代码。标准错误处理使用On Error GoTo SomeLineLabel : Error Handling Code After Label : Resume or Resume Next。最后的语句本质上是清除错误。
  • @Brandon 说了什么。试图通过清除错误来解决这个问题,跳回导致它的行。。需要更明确地说明 清除错误 在每种情况下都很重要。
【解决方案2】:

在错误处理例程中,似乎定义新的错误处理例程不起作用,除非您清除先前设置的错误例程 (https://excelmacromastery.com/vba-error-handling/):

'...
EErrorOne:
On Error GoTo -1 'Clears error trap flag
On Error GoTo EErrorTwo 'Reset error handling
'...

接受后编辑:
正如 cmets 中所讨论的,On Error GoTo -1 清除错误陷阱标志,而 Err.Clear 仅清除错误。
下面的代码通过创建两个错误并尝试捕获它们来说明这一点。

On Error Goto -1 允许On Error GoTo NextLabel 行捕获第二个错误,当错误发生时代码跳转到标签。
Err.Clear 保持第一个错误有效,所以当第二个错误发生时显示错误消息而不是代码跳转到标签。

Sub ClearErr()

    Dim x As Long
    Dim y As Worksheet

    'Jump to label when "Division by 0" occurs.
    On Error GoTo ErrorLabel

    x = 1 / 0
    Debug.Print x

ErrorLabel:

    'On Error GoTo -1 'Next error is trapped.
    Err.Clear   'Untrapped error on y=Worksheets(1)

    'Jump to label when "Object Variable not set" occurs.
    On Error GoTo NextLabel

    y = Worksheets(1)
    Debug.Print y.Name

NextLabel:

End Sub

【讨论】:

  • @DarrenBartrup-Cook Err.Clearclears 错误,但不清除错误陷阱标志!试一试。
  • 不是吗?我得看看那个。我仍然建议跳出主程序来处理任何错误并使用RESUME
  • @DarrenBartrup-Cook 尝试。
  • 很公平 - 试过了。如果我用演示它的代码更新你的答案可以吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
  • 2019-11-30
  • 2012-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多