VBA Excel 简单错误处理

Posted

技术标签:

【中文标题】VBA Excel 简单错误处理【英文标题】:VBA Excel simple Error Handling 【发布时间】:2015-08-09 22:14:46 【问题描述】:

我已尽可能多地上网(Microsoft 支持网站除外,该网站由于某种原因在工作中被阻止)。我试图简单地跳过一个错误。我在此处编写的代码已简化,但应该以相同的方式工作。

我的代码应该做什么: 我的一个潜艇在循环中创建形状并命名它们(btn_1、btn_2 等)。但在创建它们之前,它会调用一个尝试删除它们的子程序,以免创建重复项。这个子循环遍历(btn_1、btn_2 等)并使用以下命令删除形状:

for i = 1 to (a certain number)
    Set shp = f_overview.Shapes("btn_" & i)
    shp.delete
next

当然,形状不能被删除,因为它根本不存在。我发现大多数时候,推荐的修复方法是在设置形状之前添加(下一个错误恢复),因为我收到一个错误说它不存在。我已经在循环内、循环之前等尝试过,如下所示:

for i = 1 to (a certain number)
    On Error Resume Next
    Set shp = f_overview.Shapes("btn_" & i)
    shp.delete
next

据我所知,如果形状不存在,它应该直接循环,但无论我是否添加下一个错误恢复,我仍然会遇到相同的错误!我做错了什么?

编辑:当形状确实存在时没有错误。

【问题讨论】:

【参考方案1】:

试试:

On Error Resume Next

for i = 1 to (a certain number)
    Set shp = f_overview.Shapes("btn_" & i)
    if err<>0 then err.clear else shp.delete
next

on Error Goto 0

【讨论】:

【参考方案2】:

听起来您设置了错误的错误捕获选项。在 VBA 编辑器中,选择 Tools -&gt; Options。在打开的窗口中,选择General tab,然后选择Break on Unhandled Errors 单选按钮。这应该允许 Excel 正确处理 On Error Resume Next 命令。

我怀疑你选择了Break on All Errors

【讨论】:

谢谢!我一直在尝试其他回答者的建议,但都失败了。这就是为什么尽管他们也提供了有价值的信息! @DavidGrand'Maison 我同意在其他答案中进行的错误处理更干净、更好。但是您的原始代码应该可以工作。【参考方案3】:

与其尝试盲目地删除形状和跳过错误,不如遍历已知形状列表并删除它们。那么您就不必担心On Error Resume Next经常最终被滥用。

Sub Test(TheSheet As Worksheet)

Dim Shp as Shape

For Each Shp in TheSheet.Shapes
  If left(Shp.Name, 4) = "btn_" Then
    Shp.Delete
  End if
Next

End Sub

如果要删除所有形状,请删除 If 语句。如果要删除多个不同命名的形状,请适当修改If 语句。

【讨论】:

太棒了!这是我将选择的方式。谢谢你的修复。 +1 回答,即使您没有解释如何使用错误处理:-) 您在缺少错误处理细节方面是正确的 - 这个循环不需要它,尤其是您的想法。 Mat's Mug 在一般的错误处理方面做得很好。 没关系,@FreeMan,3 个月后,有一个随机的路过投票! :)【参考方案4】:

我发现大多数时候,推荐的修复方法是在设置形状之前添加(下一个错误恢复),因为我收到一个错误说它不存在。

不!

处理运行时错误的推荐方法是将它们推到地毯下并继续执行,就像什么都没发生一样 - 这正是 On Error Resume Next 所做的。

避免运行时错误的最简单方法是检查错误条件,并避免执行导致 100% 失败率的代码,例如尝试在 Nothing 的对象引用上运行方法:

For i = 1 To (a certain number)
    Set shp = f_overview.Shapes("btn_" & i)
    If Not shp Is Nothing Then shp.Delete
Next

如果您无法检查错误情况并且必须处理错误,推荐的方法是处理它们:

Private Sub DoSomething()
    On Error GoTo CleanFail

    '...code...

CleanExit:
    'cleanup code here
    Exit Sub

CleanFail:
    If Err.Number = 9 Then 'subscript out of range
        Err.Clear
        Resume Next
    Else
        MsgBox Err.Description
        Resume CleanExit
    End If
End Sub

【讨论】:

++ 关于正确的错误处理:) @SiddharthRout 是的,除了我没有测试它,现在我越想它,我越相信这个作业会抛出一个 index out of range 错误,在这种情况下 FreeMan's answer 有一个更好的解决方案。 那;没问题 :) 编辑上面的代码。我的评论是您在帖子底部显示的正确错误处理。我确实在我的帖子中提到了这一点:) @SiddharthRout 已编辑,...没有窃取任何人的答案:) 无需在 Resume Next 之前明确地“Err.Clear”。至于 MS Docs “在错误处理例程中的 Exit Sub、Exit Function、Exit Property 或 Resume Next 语句之后,Err 对象的属性被重置为零或零长度字符串 ("")。使用任何形式的错误处理例程之外的 Resume 语句不会重置 Err 对象的属性。Clear 方法可用于显式重置 Err。"【参考方案5】:

只要您了解自己在做什么以及它将如何影响您的代码,使用 OERNOn Error Resume Next)没有任何错误。

在你的情况下,使用 OERN 是完全正常的

Dim shp As Shape

For i = 1 To (a certain number)
    On Error Resume Next
    Set shp = f_overview.Shapes("btn_" & i)
    shp.Delete
    On Error GoTo 0
Next

同时确保你不要做类似的事情

On Error Resume Next
<Your Entire Procedure>
On Error GoTo 0

这将抑制所有错误。使用 Matt 所示的正确错误处理

编辑

这是另一个关于如何使用 OERN 的漂亮示例。此函数检查特定工作表是否存在。

Function DoesWSExist(wsName As String) As Boolean
    Dim ws As Worksheet

    On Error Resume Next
    Set ws = ThisWorkbook.Sheets(wsName)
    On Error GoTo 0

    If Not ws Is Nothing Then DoesWSExist = True
End Function

如果您愿意,您还可以遍历所有工作表以检查工作表是否存在!

【讨论】:

感谢您的解释!但是,它失败的原因是我的设置错误(请参阅选择的答案)。 ++ 但不幸的是,大多数人不理解使用 OERN 的含义。我喜欢这个首字母缩写词。我留着。

以上是关于VBA Excel 简单错误处理的主要内容,如果未能解决你的问题,请参考以下文章

VBA_Excel_教程:Option,错误处理

Excel VBA入门: 代码调试/错误处理/代码优化

Excel VBA 自动过滤器然后更改字段值并填写错误处理空白单元格的可能性

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

VBA 在 Excel 2016 中以不同方式处理日期?有这方面的文件吗?

VBA Excel 错误对象变量或未设置块变量