error handling程序后,Excel VBA仍然中断

我有一个非常简单的代码循环通过一列数据,并添加到集合的唯一值。

它是VBA,所以当然Collection没有Exists函数(谁会想要这个函数?),我宁愿避免遍历列中每个单元格的整个集合,我决定采用error handling方法 -尝试从集合中检索项目,捕获不存在的错误并添加它:

 '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.Break on Unhandled Errors.

任何想法为什么发生这种情况?

你可以使用On Error Resume Next,但是你最好把error handling封装在它自己的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文档中描述了您的问题的原因:

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

在第一个错误之后,您还没有调用Resume或退出过程,所以error handling程序无法处理后续错误。

UPDATE

来自评论:

我讨厌推广使用On Error Resume Next …的想法

我可以同情这个POV,但是在VBA中有一些东西(比如检查一个集合中是否存在一个键),你只能通过处理一个错误来做。 如果你在一个专门的辅助方法(Sub / Function)中这样做,这是一个合理的方法。 当然,你也可以使用On Error Goto来替代,例如像下面这样的东西(上面的一个变种,它testing一个集合是否包含一个给定的键):

 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 

使用一个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 

这里还有更多的例子