VBA - 从Property Get返回数组

时间:2011-04-10 17:43:16

标签: arrays class vba return-value byref

如果通过引用返回数组,为什么不能执行以下操作:

'Class1 class module
Private v() As Double
Public Property Get Vec() As Double()
    Vec = v()
End Property
Private Sub Class_Initialize()
    ReDim v(0 To 3)
End Sub
' end class module

Sub Test1()
    Dim c As Class1
    Set c = New Class1
    Debug.Print c.Vec()(1) ' prints 0 as expected
    c.Vec()(1) = 5.6
    Debug.Print c.Vec()(1) ' still prints 0
End Sub

4 个答案:

答案 0 :(得分:25)

您没有let属性。此外,get属性返回整个数组,而不仅仅是有问题的元素。将属性Get的返回类型从Double()更改为plain Double。添加属性让。请注意,它需要两个输入,但只传递一个输入。假设最后一个变量(在本例中为MyValue)从=符号后面的任何值获取它的值。在Test1()的早期某处放置一个断点,看看这些值在Locals窗口中是如何受到影响的。比较原始代码与我的代码创建的变量:

'Class1 class module
Private v() As Double
Public Property Get Vec(index As Long) As Double
    Vec = v(index)
End Property
Public Property Let Vec(index As Long, MyValue As Double)
    v(index) = MyValue
End Property
Private Sub Class_Initialize()
    ReDim v(0 To 3)
End Sub
' end class module

'Begin module
Sub Test1()
    Dim c As Class1
    Set c = New Class1
    Debug.Print c.Vec(1) ' prints 0 as expected
    c.Vec(1) = 5.6
    Debug.Print c.Vec(1) ' prints 5.6
End Sub
'End module  

答案 1 :(得分:11)

在VBA中,除非通过ByRef参数返回数组,否则永远不会通过引用返回数组。此外,每当你使用=为一个变量赋一个数组时,你就已经创建了一个数组的新副本,即使你将它分配给一个过程中的ByRef参数,所以你很漂亮试图让这项工作变得非常幸运。

一些替代方案是......

  • 使用VBA.Collection而不是数组。
  • 创建自己的类,封装数组并公开用于间接访问和操作内部数组的过程。

答案 2 :(得分:0)

我想建议另一种使用 Collectionstatic Property的好方法,而无需使用 class :< / p>

想象您想将xlCVError枚举作为数组(或集合),例如遍历错误并根据实际错误进行处理。

以下内容在访问时初始化一次:

'from https://stackoverflow.com/a/56646199/1915920
Static Property Get XlCVErrorColl() As Collection
    Dim c As Collection  'will be already initalized after 1st access
                         'because of "Static Property" above!
    Set XlCVErrorColl = c
    If Not c Is Nothing Then Exit Property

   'initialize once:

    Set c = New Collection
    c.Add XlCVError.xlErrDiv0
    c.Add XlCVError.xlErrNA
    c.Add XlCVError.xlErrName
    c.Add XlCVError.xlErrNull
    c.Add XlCVError.xlErrNum
    c.Add XlCVError.xlErrRef
    c.Add XlCVError.xlErrValue
    Set XlCVErrorColl = c
End Property

将其转换为数组或将其实现为数组很简单,但是集合对我来说似乎更有用,缺点是它们的元素没有隐式地类型化/(编译时)类型检查。 /> 因此,例如将其转换为(只读)数组(其他答案/评论中提到了in-mem-copy-disadvantage):

'from https://stackoverflow.com/a/56646199/1915920
Static Property Get XlCVErrorArr() As XlCVError()
   Dim a() As XlCVError
   XlCVErrorArr = a
   If UBound( a ) > 0 Then Exit Property

   'initialize once:

   Dim c As Collection:  Set c = XlCVErrorColl
   ReDim a(c.Count)
   Dim i As Integer:  For i = 1 To c.Count 
       a(i) = c(i)
   Next i
   XlCVErrorArr = a
End Function

因此,使用一些数组将示例从Clayton Ss answer转换为静态的,可修改的模块属性,它将是:

'module (no class required)
'from https://stackoverflow.com/a/56646199/1915920

Private v() As Double

Static Property Get Vec(index As Long) As Double
    If UBound(v) < 3 Then  'initialize once:
      ReDim v(0 To 3)  'one could initialize it with anyting after here too
    end if

    Vec = v(index)
End Property

Public Property Let Vec(index As Long, MyValue As Double)
    v(index) = MyValue
End Property

答案 3 :(得分:0)

Vec(索引为长,MyValue为双)

index关键字在这里做什么? 请引导我到一个网页,在这里我可以了解与数组相关的索引。