使用VBA中的Application.Match检查项目是否存在于集合中

时间:2017-05-18 18:34:34

标签: excel vba excel-vba

我的宏代码有问题我正在为Excel写作。

它特别涉及方法Application.MatchApplication.WorksheetFunction.Match

我有一个字符串数组,我将所有公司的名称存储在列表中

Dim CompanyID() As String
ReDim CompanyID(NumCO)


For i = 1 To NumCO
    CompanyID(i) = Worksheets("Sheet1").Cells(i, 1).Value
Next i

然后我创建了一个仅包含所有不同公司的集合

Dim DifCO As New Collection, a

On Error Resume Next
For Each a In CompanyID
    DifCO.Add a, a
Next

稍后在我的代码中,我再次浏览公司,将它们与某些属性相关联,为此我需要在集合DifCO中保存公司的位置索引。但是,我无法通过Application.Match

获得它

我的程序似乎没有在该行中执行任何操作并证明我已尝试在MsgBox中打印索引,但MsgBox没有显示,并且它没有&#39 ; t甚至发送错误信息。

For i to NumCO
    MsgBox (Application.WorksheetFunction.Match(CompanyID(i), DifCO, 0))
Next i

我尝试过使用Application.Match并将Collection的元素移动到另一个字符串的数组,但结果是相同的。

我知道代码循环正确,因为我已经在逐步调试选项中观察到它。但是我已经没有关于可能出现问题的想法,所以我在这里问这个社区。

1 个答案:

答案 0 :(得分:3)

正如Mat在对OP的评论中所表示的那样,看起来您已使用On Error Resume Next而没有On Error GoTo 0,因此处理程序正在吞下错误并且您没有看到它,并且MsgBox是没有显示。

调试时,Break on All Errors有一个选项可能很有用,虽然在非常复杂的应用程序中它很麻烦,对于这样的事情,它会立即为你标记问题。在VBE下的工具>选项>一般:

enter image description here

一般情况下,除了非常小且有目的的错误陷阱之外,您要避免使用Resume Next。让它像这样打开必然会导致代码中的错误,这些错误很难排除故障(正如您所注意到的那样!)。

对于您的解决方案,您可以使用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

然后,通过使用ArrayList方法将ToArray转储到变量数组来获取索引,然后使用Application.Match对其进行测试:

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