我在Access 2013中使用VBA。
在常规模块中,有2个程序,RunProc()
和PopulateCollection()
执行RunProc
时,会调用PopulateCollection
传递的参数是名为MyCol
的集合实例。
PopulateCollection
添加3个项目,然后RunProc
继续迭代集合。
我的问题是:
我希望MyCol
中的参数RunProc
不会被PopulateCollection
填充。实现这个目标的正确方法是什么?
为什么PopulateCollection
会填充参数和参数?
' --------Module1------------------
Option Compare Database
Option Explicit
Dim i As Integer
Dim MyCol As VBA.Collection
Sub RunProc()
Set MyCol = New VBA.Collection
PopulateCollection MyCol
For i = 1 To MyCol.Count
Debug.Print MyCol.Item(i)
Next i
End Sub
Function PopulateCollection(ByRef pMyCol As VBA.Collection)
For i = 1 To 3
pMyCol.Add "Item" & i
Next i
End Function
这是提出问题的另一种方式:
选项比较数据库 选项明确
Sub Proc1()
Dim myInt As Integer
myInt = 1
Proc2 myInt
Debug.Print myInt
myInt = 1
Proc3 myInt
Debug.Print myInt
End Sub
Sub Proc2(ByVal pmyInt)
pmyInt = pmyInt + 1
Debug.Print pmyInt
End Sub
Sub Proc3(ByRef pmyInt)
pmyInt = pmyInt + 1
Debug.Print pmyInt
End Sub
'考虑3个程序:Proc1,Proc2,Proc3
'Proc1调用Proc2和Proc3
'Proc2和Proc3之间的唯一区别是 '参数pmyInt的调用方式不同:ByVal vs ByRef
'Proc2不会更改参数myInt 'Proc3确实改变了参数myInt
'我的问题的根源是为什么同样的行为 '没有展示对象(VBA.Collection) '假设我想不要改变原来的Collection “我该怎么办?
答案 0 :(得分:6)
在VBA中,对象(例如集合)始终通过引用传递。传递对象ByRef时,会传递对象的地址,PopulateCollection可以更改引用。
当您传递ByVal时,会传递参考的副本。引用的副本仍指向原始Collection,但如果更改副本,则不会更改RunProc中的引用。
Sub RunProc()
Dim MyCol As Collection
Dim i As Long
Set MyCol = New Collection
PopCollByVal MyCol
'I changed what pMyCol points to but *after*
'I populated it when it still pointed to MyCol
'so this returns 3
Debug.Print "ByVal: " & MyCol.Count
PopCollByRef MyCol
'When I changed the reference pMyCol it changed
'MyCol so both became a new Collection. This
'return 0
Debug.Print "ByRef: " & MyCol.Count
End Sub
Function PopCollByVal(ByVal pMyCol As Collection)
Dim i As Long
'The pointer pMyCol is a copy of the reference
'to MyCol, but that copy still points to MyCol
For i = 1 To 3
'I'm changing the object that is pointed to
'by both MyCol and pMyCol
pMyCol.Add "Item" & i
Next i
'I can change what pMyCol points to, but I've
'already populated MyCol because that's what
'pMyCol pointed to when I populated it.
Set pMyCol = New Collection
End Function
Function PopCollByRef(ByRef pMyCol As Collection)
Dim i As Long
'The pointer pMyCol is the actual reference
'to MyCol
For i = 1 To 3
pMyCol.Add "Item" & i
Next i
'When I change what pMyCol points to, I also
'change what MyCol points to because I passed
'the pointer ByRef. Now MyCol is a new collection
Set pMyCol = New Collection
End Function