使用VBA中的Application.Match检查项目是否存在于集合中
我有一个我为Excel编写的macros的代码有问题。
它具体涉及方法Application.Match
或者Application.WorksheetFunction.Match
我有一个string数组,我将所有公司的名称存储在列表中
Dim CompanyID() As String ReDim CompanyID(NumCO) For i = 1 To NumCO CompanyID(i) = Worksheets("Sheet1").Cells(i, 1).Value Next i
然后我创build一个collections只包含所有不同的公司
Dim DifCO As New Collection, a On Error Resume Next For Each a In CompanyID DifCO.Add a, a Next
后来在我的代码中,我再次通过这些公司,将它们与某些属性相关联,为此我需要在Collection DifCO
保存公司的索引。 但是,我一直无法得到它与Application.Match
我的程序似乎没有做任何事情,并certificate它我已经试图在MsgBox
打印索引,但MsgBox
不会出现,它甚至不会发送错误消息。
For i to NumCO MsgBox (Application.WorksheetFunction.Match(CompanyID(i), DifCO, 0)) Next i
我已经尝试了不同的事情,使用Application.Match
和将集合的元素移动到另一个string的数组,但结果是相同的。
我知道代码循环正确,因为我已经在逐步debugging选项中观察到它。 但是我已经想出了什么可能是问题的想法,所以我在这里问这个社区。
正如Mat在OP上的注释中所表示的那样,它看起来像是使用了On Error Resume Next
而没有On Error GoTo 0
,所以处理程序正在吞咽错误,并且没有看到它,并且不显示MsgBox。
在debugging的时候,有一个选项可以Break on All Errors
,尽pipe在非常复杂的应用程序中它是一个非常痛苦的事情,因为像这样的事情会立即为你标记问题。 在工具>选项>常规下的VBE中:
通常,您希望避免Resume Next
除非是非常小而有目的的错误陷阱。 让它像这样打开,势必会在你的代码中导致进一步的错误,这些错误很难排除(正如你注意到的那样)。
对于你的解决scheme,你可以使用一个ArrayList
Dim list as Object Set list = CreateObject("System.Collections.ArrayList") For Each a In CompanyID If Not list.Contains(a) Then list.Add(a) Next
然后,通过使用ToArray
方法将ArrayList
转储到variables数组,然后使用Application.Match
testing该数组:
Dim arr, foundAt arr = list.ToArray() For i = 1 To NumCO foundAt = Application.Match(CompanyID(i), arr, 0) If Not IsError(foundAt) Then MsgBox foundAt End If Next i
否则,从集合或数组获取索引的通常方法就是对项目进行粗暴的迭代,最好是分离一个ad-hoc函数来完成这些工作,而不是使用额外的循环混淆主要过程:
Sub collExample() Dim c As New Collection c.Add "9" c.Add "14" c.Add "3" c.Add "15" c.Add "4" c.Add "3" Debug.Print colItmExists(c, "5") '~~> False Debug.Print colItmExists(c, "10") '~~> True Debug.Print colItmFirstIndex(c, "3") '~~> 3 Debug.Print colItmFirstIndex(c, "17") '~~> -1 End Sub Function colItmExists(col As Collection, itm) As Boolean Dim i, ret As Boolean For i = 1 To col.Count If col(i) = itm Then ret = True Exit For End If Next colItmExists = ret End Function Function colItmFirstIndex(col As Collection, itm) As Long Dim ret As Long If Not colItmExists(col, itm) Then ret = -1 Else For i = 1 To col.Count If col(i) = itm Then ret = i Exit For End If Next End If colItmFirstIndex = ret End Function