【问题标题】:Excel VBA still breaks after On Error handler错误处理程序后 Excel VBA 仍然中断
【发布时间】:2014-11-18 13:27:48
【问题描述】:

我有一段非常简单的代码,它遍历一列数据并向集合添加唯一值。

它是 VBA,所以 Collection 当然缺少 Exists 函数(谁想要那个?),我宁愿避免为列中的每个单元格遍历整个集合,我决定去对于错误处理方法 - 尝试从集合中检索项目,如果它不存在则捕获发生的错误并添加它:

'Trucated the code slightly, I know I should be checking the actual error code, but omitted that for brevity

Dim r As Range
Set r = MySheet.Range("B2") 'First cell in column

Dim uniqueValues As New Collection
Do While r.Value <> ""
    On Error GoTo ItemExists
    'If r.Value doesn't exist in the collection, throws an error
    uniqueValues.Add(Item:=r.Value, Key:=r.Value) 
ItemExists:
    r.Offset(1)
Loop

问题? Excel 似乎完全忽略了On Error 行,破坏了代码并抛出了Continue/End/Debug 对话框不管

我检查了 VBA 中的选项,它正确设置为Break on Unhandled Errors.

知道为什么会这样吗?

【问题讨论】:

  • 使用Dictionary 而不是Collection
  • 我在哪里可以找到字典?它似乎不是标准库的一部分。
  • 添加对Microsoft Scripting RuntimeCreateObject("Scirpting.Dictionary")的引用
  • 您可能对this attempt at building a better collection 感兴趣。现在可以在Github 上找到整个项目。 (哦,请不要使用On Error Resume Next,除非您真的了解它的作用。)
  • @bp_ 在这种情况下,OERN 绝对没有问题。它可能经常被滥用,但这并不意味着它没有地方! ;)

标签: vba excel


【解决方案1】:

您可以使用 On Error Resume Next,但最好将错误处理封装在它自己的 Sub 或 Function 中。例如。类似:

Private Sub AddIfNotPresent(Coll As Collection, Value As Variant, Key As Variant)
    On Error Resume Next
    Coll.Add Item:=Value, Key:=Key
End Sub

您可以按如下方式使用:

Do While r.Value <> ""
    AddIfNotPresent uniqueValues, r.Value, r.Value
    r = r.Offset(1)
Loop

On Error 的 VBA 文档中描述了问题的原因:

“启用”错误处理程序是由 On Error 语句打开的错误处理程序; “活动”错误处理程序是正在处理错误的已启用处理程序。如果在错误处理程序处于活动状态时发生错误(在错误发生和 Resume、Exit Sub、Exit Function 或 Exit Property 语句之间),则当前过程的错误处理程序无法处理该错误

第一个错误后你还没有调用 Resume 或退出过程,因此错误处理程序无法处理后续错误。

更新

来自 cmets:

我讨厌提倡使用 On Error Resume Next ...

我可以同情这个 POV,但是在 VBA 中有一些事情(例如检查集合中是否存在密钥),您只能通过处理错误来做到这一点。如果您在专用的辅助方法(子/函数)中执行此操作,这是一种合理的方法。当然,您可以改用 On Error Goto,例如类似于以下内容(上面的变体,用于测试集合是否包含给定键):

Public Function ContainsKey(Coll As Collection, Key As Variant) As Boolean
    On Error GoTo ErrHandler
    Dim v As Variant
    v = Coll(Key)
    ContainsKey = True
    Exit Function
ErrHandler:
    ContainsKey = False
    Exit Function
End Function

【讨论】:

  • 虽然我讨厌推广使用 On Error Resume Next 这个答案是正确的,因为 OP 在错误处理程序中没有 Resume。赞成这个让我很痛苦......
  • 只是为未来的 Google 员工添加信息;我最喜欢的错误处理来源之一:cpearson.com/excel/errorhandling.htm
  • 这或多或少是我最终做的事情(尽管后来改为@vba4all 建议使用字典来完全避免错误处理的事情)。干杯~
【解决方案2】:

使用 ArrayList 代替,它具有 .Contains 方法以及其他方便的方法,例如 .Sort 方法

With CreateObject("System.Collections.ArrayList")

    .Add "Item 1"
    .Add "Item 2"

If .Contains "Item 1" Then Msgbox "Found Item 1"
If .Contains "Item 3" Then Msgbox "Found Item 3"


End With

更多示例here

【讨论】:

    猜你喜欢
    • 2019-01-07
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 2015-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多