尽管您可以使用CopyMemory
and FillMemory
,但我强烈建议您永远不要将这些引用保留太久。作为一个例子,我stdRefArray
根据这个确切的原则制作课程,不要使用这个代码!继续阅读以找出原因...:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "stdRefArray"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'I STRONGLY RECOMMEND AGAINST USING THIS CLASS. SEE WHY HERE:
'https://stackoverflow.com/a/63838676/6302131
'Status WIP
'High level wrapper around 2d array.
#Const DEBUG_PERF = False
'Variables for pData
Private Declare PtrSafe Sub FillMemory Lib "kernel32" Alias "RtlFillMemory" (Destination As Any, ByVal Length As Long, ByVal Fill As Byte)
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cbCopy As Long)
Public Data As Variant
Private Const VARIANT_SIZE As Long = 16
Public Function Create(ByRef Data As Variant) As stdRefArray
Set Create = New stdRefArray
Call Create.Init(Data)
End Function
Public Sub Init(ByRef DataIn As Variant)
'Create direct reference to array:
CopyMemory Data, DataIn, VARIANT_SIZE
End Sub
Private Sub Class_Terminate()
'Clean up array reference
FillMemory Data, VARIANT_SIZE, 0
End Sub
Public Function GetData(ByVal iRow as long, ByVal iCol as long) as Variant
Attribute GetData.VB_UserMemID=0
GetData = GetData(iRow,iCol)
End Function
我最初使用此类的想法是执行以下操作:
Cars.FindCar(...).GetDoor(1).Color = Rgb(255,0,0)
其中 Car 类具有对 Cars 数组的引用,并且与 Door 类类似地存储对 Cars 数组的引用,从而允许“即时”设置器直接访问初始数据的源。
这很好用!但...
我在调试时遇到了很多问题。如果您处于调试模式,在 Door 类中,在颜色设置器中,如果您对需要重新编译的结构进行更改 IE 更改dim
ed 变量的名称,更改方法/属性的名称,或更改他们的类型,Excel会立即崩溃。当您单击 VBA 停止(方形)按钮时,也会发生类似的事情。不仅如此,从 Excel 中调试这些即时崩溃也非常令人讨厌……
这使得上述代码确保您的代码库的其余部分也难以维护。这将增加修复的时间,导致很多挫折和制造。在运行时节省的时间并不能证明解决问题所花费的时间是合理的。
如果您确实制作了这些数组引用,请确保您将它们的生命保持得非常短,并在调试问题之间充分评论。
注意:如果有人可以找到解决此崩溃问题的方法(即在 VBA 崩溃之前正确清理堆栈,我会非常感兴趣!)
相反,我强烈建议您使用这样的简单类:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "stdRefArray"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
'Status WIP
'High level wrapper around arrays
Public Event Changed(ByVal iRow As Long, ByVal iCol As Long, ByVal Value As Variant)
Public vData As Variant
Public Function Create(ByRef Data As Variant) As stdRefArray
Set Create = New stdRefArray
Call Create.Init(Data)
End Function
Public Sub Init(ByRef Data As Variant)
'Slow, but a stable reference
vData = Data
End Sub
Public Property Get Data(Optional ByVal iRow As Long = -1, Optional ByVal iCol As Long = -1) As Variant
Attribute Data.VB_UserMemId = 0
If iRow = -1 And iCol = -1 Then
CopyVariant Data, vData
ElseIf iRow <> -1 And iCol <> -1 Then
CopyVariant Data, vData(iRow, iCol)
Else
stdError.Raise "stdRefArray::Data() - Invalid use of Data", vbCritical
End If
End Property
Public Property Let Data(ByVal iRow As Long, ByVal iCol As Long, Value As Variant)
vData(iRow, iCol) = Value
RaiseEvent Changed(iRow, iCol, Value)
End Property
Public Property Set Data(ByVal iRow As Long, ByVal iCol As Long, Value As Object)
Set vData(iRow, iCol) = Value
RaiseEvent Changed(iRow, iCol, Value)
End Property
Public Property Get BoundLower(ByVal iDimension As Long) As Long
BoundLower = LBound(vData, iDimension)
End Property
Public Property Get BoundUpper(ByVal iDimension As Long) As Long
BoundUpper = UBound(vData, iDimension)
End Property
Private Function CopyVariant(ByRef dest As Variant, ByVal src As Variant)
If IsObject(src) Then
Set dest = src
Else
dest = src
End If
End Function
我添加了一些额外的步骤来帮助绑定。你仍然会失去很多原生行为,但是这是最安全的赌注,也是最容易维护的赌注。这也是在不使用集合的情况下获得类似集合功能的最快方法。
用法,Car.cls
:
Private WithEvents pInventory as stdRefArray
Public Function Create(ByRef arrInventory as variant)
Set Create = new Car
Set Create.pInventory = stdRefArray.Create(arrInventory)
End Function
Public Function GetDoor(ByVal iRow as long) as Door
Set GetDoor = new Door
GetDoor.init(pInventory,iRow)
End Function
Door.cls
Private pArray as stdRefArray
Private pRow as long
Private Const iColorColumn = 10
Sub Init(ByVal array as stdRefArray, ByVal iRow as long)
set pArray = array
pRow = iRow
End Sub
Public Property Get Color() as long
Color = pArray(pRow,iColorColumn)
End Property
Public Property Let Color(ByVal iNewColor as long)
pArray(pRow,iColorColumn) = iNewColor
End Property
这个例子可能不太好,哈哈,但希望你能明白。