Found this on the web, hope it helps:
Lets' look at what happens with a regular function.
Start with a string.
Code:
Dim varDef As String, varRef As String, varVal As String
varRef = "ref"
varVal = "val"
varDef = "default"
testVar varDef, varRef, varVal
Debug.Print varDef, varRef, varVal
being passed to this function as a variant...
Code:
Private Function testVar(varDef As Variant, ByRef varRef As Variant, ByVal varVal As Variant)
varDef = "overwrote default"
varRef = "overwrote ref"
varVal = "overwrote val"
End Function
If the string was passed by reference, then it will be changed. If by value it will remain unchanged.. the result is...
overwrote default overwrote ref val
which proves that default & by reference are the same,
So let's do the same thing with arrays...
Code:
Dim arrDef(1 To 1) As String
arrDef(1) = "arr string default"
Dim arrRef(1 To 1) As String
arrRef(1) = "arr string ref"
Dim arrVal(1 To 1) As String
arrVal(1) = "arr string val"
testArray arrDef, arrRef, arrVal
Debug.Print arrDef(1), arrRef(1), arrVal(1)
Private Function testArray(varDef As Variant, ByRef varRef As Variant, ByVal varVal As Variant)
varDef(1) = "overwrote string default"
varRef(1) = "overwrote string ref"
varVal(1) = "overwrote string val"
End Function
the result is...
overwrote string default overwrote string ref arr string val
which means that arrays behave the same as regular args..
So what happens when we pass an array to something that's expecting a string. We can do this by calling the first test function with arrays as arguments..
Code:
testVar arrDef, arrRef, arrVal
when i try to assign a string to the first two, which are passed by reference, I get a VBA error. The 3rd argument, which is by Value, happily assigns a string value - but back in the calling procedure, arrVal retains its original value - which proves that by value activity is confined to the calling stack for an array.
But all this doesn't matter - because lets see what happens in a class when we assign an array in each of the 3 different ways...
Code:
Option Explicit
Private pArrVal As Variant
Private pArrRef As Variant
Private pArrDef As Variant
Public Property Let arrVal(ByVal anArray As Variant)
pArrVal = anArray
End Property
Public Property Let arrRef(ByRef anArray As Variant)
pArrRef = anArray
End Property
Public Property Let arrDef(anArray As Variant)
pArrDef = anArray
End Property
Public Property Get arrVal()
arrVal = pArrVal
End Property
Public Property Get arrRef()
arrRef = pArrRef
End Property
Public Property Get arrDef()
arrDef = pArrDef
End Property
Private Function classRef()
Dim ValRef As New cValRef
Dim arr(1 To 2) As String
arr(1) = "a1"
arr(2) = "a2"
ValRef.arrDef = arr
ValRef.arrRef = arr
ValRef.arrVal = arr
Debug.Print ValRef.arrDef(2), ValRef.arrRef(2), ValRef.arrVal(2)
arr(2) = "changed"
Debug.Print ValRef.arrDef(2), ValRef.arrRef(2), ValRef.arrVal(2)
End Function
the result
a2 a2 a2
a2 a2 a2
So this proves that if I change the contents of an array after it's been assigned to an instance of a class - it doesn't matter whether it was assigned by value or reference in the let property, since it is a copy of the original.
If you assigned an object with property Set (as opposed to Let), then the address of the object is stored - not the contents itself. The key point here is that an array in VBA is not an object, as it is in some other languages such as JavaScript.
You'll find more about all this here -
Getting Started with argument passing - Desktop Liberation
Property let only has one argument .. That's because it's used like this.
X is the argument that arrives as an argument.
A Let is always by value, so if pass an array and assign to a property of a class, it will be a copy of the array. This means that if you change an array element of a class, the original array that was assigned remains unchanged.
Each instance of a class will have a copy of the array at the time it was assigned,
This is in contrast to the set property which would store the address of an object, and changes made would reflect in the original object.
Unlike some other languages, an array in vba is not an object, which is why you use let.
So
A.. By ref should be avoided in any case. A function should not update its own arguments as a general principle, and in any case, it doesn't apply with property let.
B. An array in an object can simply be updated by a.prop(1) = y
In general arguments should be passed by ref - the default. You would need to be doing something special to want to change that. So in principle - leave it alone. The main reason for byVal is so that VBA can call windows APIs and other special things in other languages that are expecting the value of a variable rather than its address on the call stack.
My comment about by ref should be avoided meant ---> updating arguments passed by ref should be avoided - a function should not be designed to create side effects like this (although some of the older built in functions in VBA, like the ones that access the IDE code itself, actually do this) - so never, ever do it.
THOUGH I'M NOT SURE ABOUT THIS STATEMENT:
Code:
The concept of multiple arguments to a let property doesn't make sense, since the syntax of using it is
A property let will store the value of theArgument in the given property via the Property Let definition, (even if theArgument is an array).
A property set will store the address of theArgument .. which will be an object
In other words forget about byref and byvalue when dealing with property let.
If you need to provide multiple values, use a function instead
Code:
Public function DataArrayItem(RowIndex As Integer, ColIndex As Integer, Item As Variant)
pDataArray(RowIndex, ColIndex) = Item
End function