将VBA集合转换为数组

时间:2018-01-08 15:34:26

标签: excel vba excel-vba

我正在尝试创建一个数组,其中包含工作簿中包含“模板”一词的所有工作表名称。我认为最简单的方法是首先创建一个集合,然后将其转换为数组,但我遇到了麻烦。现在我得到的错误是

collectionToArray (col)

线。我收到了

  

参数不可选错误

相当困难,任何帮助都非常感激。谢谢!

Public col As New Collection
Public Sub Test()
For Each ws In ThisWorkbook.Worksheets
    If InStr(ws.Name, "Template") <> 0 Then
        col.Add ws.Name
    End If
Next ws

collectionToArray (col)
End Sub

Function collectionToArray(c As Collection) As Variant()
    Dim a() As Variant: ReDim a(0 To c.Count - 1)
    Dim i As Integer
    For i = 1 To c.Count
        a(i - 1) = c.Item(i)
    Next
    collectionToArray = a
End Function

3 个答案:

答案 0 :(得分:7)

一切都在那里,你只是没有使用函数作为一个函数。您需要将结果存储在某些内容中,例如&#39; NewArray&#39; ..?

Public col As New Collection
Public Sub Test()
For Each ws In ThisWorkbook.Worksheets
    If InStr(ws.Name, "Template") <> 0 Then
        col.Add ws.Name
    End If
Next ws


' Tweaked as per Vityata's comment

If col.Count > 0 Then 
    newarray = collectionToArray(col)
Else
    ' Do something else
End If

End Sub

Function collectionToArray(c As Collection) As Variant()
    Dim a() As Variant: ReDim a(0 To c.Count - 1)
    Dim i As Integer
    For i = 1 To c.Count
        a(i - 1) = c.Item(i)
    Next
    collectionToArray = a
End Function

答案 1 :(得分:6)

collectionToArray (col)

请注意函数名称和参数列表之间的空格?这就是VBE告诉你的事情:

我将接受该论点,将其评估为值,然后将其ByVal传递给您正在调用的过程,即使该过程的签名为ByRef,明确与否。

这种“无关的括号”习惯不可避免地会让你在某个时刻碰到奇怪的“对象必需”运行时错误:失去它。

Function过度使用IMO:Variant可以很好地包装数组,因此我会更改其签名以返回Variant而不是Variant()

Integer是一个16位有符号整数类型(在某些其他语言中为short),使用Long代替(32位有符号整数)可能更好一点,即int在其他一些语言中) - 这样当你需要处理超过32,767个值时,你就会避免遇到“溢出”问题(如果涉及到工作表,这种情况尤其常见)。

Public col As New Collection

这会使col成为自动实例化的对象变量,并且它可能会产生令人惊讶的副作用。请考虑以下代码:

Dim c As New Collection
c.Add 42
Set c = Nothing
c.Add 42
Debug.Print c.Count

您希望此代码能做什么?如果你认为“错误91,因为对象引用是Nothing”,你就会被自动实例化所困扰。最好避免它,并将声明和作业保持为单独的指令。

除此之外,CLR's answer还有您的解决方案:Function应该返回一个值,调用代码应该使用该值。

result = MyFunction(args)

你会注意到VBE清除了你可能想要在MyFunction(args)之间添加的任何空格:这是VBE告诉你的:

我将接受该论点,将其传递给MyFunction,并将函数的返回值分配给result

答案 2 :(得分:3)

这是我的collectionToArray功能:

Public Function CollectionToArray(myCol As Collection) As Variant

    Dim result  As Variant
    Dim cnt     As Long

    ReDim result(myCol.Count)
    For cnt = 0 To myCol.Count - 1
        result(cnt) = myCol(cnt + 1)
    Next cnt
    CollectionToArray = result

End Function

它比您正在使用的更好,因为如果集合为空,它不会给出错误。 为了避免在您的案例中出现空集合的错误,您可以考虑添加如下检查:

If col.Count > 0 Then k = CollectionToArray(col)