VBA Variant到某个对象?

时间:2017-03-24 06:29:42

标签: excel vba excel-vba

我开始在VBA(Excel AddIn - &gt; xlam)中使用Collection,但发现它很难使用。我无法检索任何我放入的东西,除了Variants。例如,在Java中,如果你创建一个Collection,你可以给它分配一个类型,比如Collection<MyPerfectObjectThatStoresSomeData>,所以当我预先知道它时,我知道我得到了我的对象并可以像这样使用它。当我想在VBA中做同样的事情时,我会回到Variant类型,我甚至无法将其转换为我的类型。

实施例。

我想说我希望得到Collection的最后一个条目,我填写如下:

Private Function FindTargets(sheet As Worksheet, target As String) As Collection
    Dim result As New Collection
    Dim aCell As range
    Dim i As Long
    For i = 1 To 10456
      Set aCell = sheet.Rows(i).Find(What:=target, LookIn:=xlValues, _
            LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
            MatchCase:=False, SearchFormat:=False)
        If Not aCell Is Nothing Then
             MsgBox "Value Found in Cell " & aCell.Address & _
            " and the Cell Column Number is " & aCell.Column
            result.Add aCell
        End If
    Next i

    Set FindTargets = result
End Function

之后,我想循环查看结果,但我无法在没有错误的情况下获取最后一个条目:

Dim targetCollection As Collection
Set targetCollection = FindTargets(targetSheet, "some text")
Dim target As range
target = targetCollection.Item(targetCollection.Count - 1)

我收到错误:

Run-time error '91':
Object variable or With block variable not set

如果我尝试

Set target = targetCollection.Item(targetCollection.Count - 1)

我明白了:

Run-time error '1004':
Application-defined or object defined error

我是否只能循环并将Collection的条目转换为Variant以外的类型?

编辑:更具体地说,此代码需要范围的坐标,但在Variant中,我得到了单元格的文本。我想创建一个新的类,比如CellProperties,其中包含文本和坐标属性,并将其放入Collection中,但同样,我无法从Collection中检索除Variant之外的任何内容。

2 个答案:

答案 0 :(得分:4)

看来您的错误是由假设Collection的项目从零开始,但Collection中的第一个项目的索引为1

以下是我用于测试的FindTargets的缩减版本,以及返回添加到Address的最后一个单元格的Collection的测试子例程:

Private Function FindTargets(sheet As Worksheet, target As String) As Collection
    Dim result As New Collection
    Dim i As Long
    For i = 1 To 100
        result.Add Cells(i, 1)
    Next i

    Set FindTargets = result
End Function

Sub test()
Dim targetCollection As Collection
Set targetCollection = FindTargets(Worksheets("Sheet1"), "some text")
Dim target As Range
Set target = targetCollection.Item(targetCollection.Count)
MsgBox target.Address 'will display $A$100
End Sub

答案 1 :(得分:1)

VBA-Collection是可以包含异构对象的数据结构。因此,与Collection Of MyPerfectObjectThatStoresSomeData不同,集合确保可以添加某些数据类型的对象,在VBA-Collection中我们可以在集合中存储任何内容,以便它可以同时包含异构对象类型。但在您的情况下,该集合实际上包含Variant\Object\Range类型的对象。这意味着它包含Variant类型和子类型Range的对象。可以枚举VBA-Collection并且它具有Item方法,该方法可用于访问第一个项目具有1索引的集合的项目。

在你的情况下你可以做到,例如这样:

targetCollection.Add "Banana"
targetCollection.Add ActiveSheet
targetCollection.Add Excel.Application

Dim itm As Variant
For Each itm In targetCollection
    If TypeName(itm) = "Range" Then _
        Debug.Print itm.Address
Next itm

安全地获取最后一个元素(如果最后一个元素是Range类型):

Dim lastElement As Range
If targetCollection.Count > 0 Then _
    Set lastElement = targetCollection.Item(targetCollection.Count)

作为旁注:为什么不使用Dim As New