Post for reference from a few other places, such as
https://eileenslounge.com/viewtopic....322751#p322751
https://www.excelfox.com/forum/showt...php/2824/page2
ByRef ByVal and winapi
VBA variable basics
Variables, ByRef ByVal, "pointers" (Addresses)
The idea of this and the over next posts is to just very slightly extend the simplest typical explanation of ByRef and ByVal in VBA. This slightly extended explanation in the next post including an equally very slightly extended explanation of some VBA variables can, IMO, go a long way to help understand other issues later on when learning VBA: It is worth the effort in almost all cases, since the over simplified explanations can make further learning unnecessarily complicated.
The slightly fuller explanations can be particularly helpful in API work, and indeed these postings arise from my attempts to get a better understanding to the issues in this post: https://eileenslounge.com/viewtopic.php?f=30&t=41659
This first post revises the typical beginner explanation
ByRef ByVal
Review of typical explanation VBA ByRef ByVal
This is a typical simple explanation, and I will assume you know this. If you don’t then best learn it before you go any further
The TLDR:
ByRef and ByVal are instructions to VBA. They instruct whether to take the value (ByVal ), of a given variable ( "the original text" of/in the variable StrBuffa in this example ) or whether to refer to the variable, - crudely in this latter case, in Layman terms ByRef instructs to take the variable itself, rather than the value in it..
Simple sample coding
Code:
Sub MainRoutine_ByValByRefSimpleVBAFunctionsExample() ' https://www.excelfox.com/forum/showthread.php/2404/page3#post11880
Dim StrBuffa As String
Let StrBuffa = "the original text" '
Call TakeValue(StrBuffa) ' Take the value in StrBuffa into Sub TakeValue(ByVal Tecst As String)
Debug.Print StrBuffa ' : MsgBox StrBuffa
Debug.Print
Call TakeVariable(StrBuffa) ' A bit like Taking the variable, StrBuffa, into Sub TakeVariable(ByRef Tecst As String)
Debug.Print StrBuffa ' : MsgBox StrBuffa
End Sub
Sub TakeValue(ByVal Tecst As String)
Let Tecst = "a new value" ' This only does anything within this routine, so it has no effect, for example, on anything in the main routune
End Sub
Sub TakeVariable(ByRef Tecst As String)
Let Tecst = "a new value" ' This has the effect of changing the value of StrBuffa in ther main routine
End Sub
If you run the first, main routine above, Sub MainRoutine_ByValByRefSimpleVBAFunctions() , then this should be the output:
the original text
a new value
The first output ,
the original text
, received after the first Call, Call TakeValue(StrBuffa) , tells you that you (still) have the original text in a string variable, StrBuffa, which is at the start of the main routing , Sub MainRoutine_ByValByRefSimpleVBAFunctions()
, and the second output ,
a new value
, received after the second Call , Call TakeVariable(StrBuffa) , tells you that you have a new value in that original string variable. In other words in this latter case you changed the value in the original main coding variable, StrBuffa,
Simple layman Explanation
A simple laymen explanation is that in the first Call, Call TakeValue(StrBuffa), I put a value in a local variable, Tecst, in the second routine, Sub TakeValue[( … ). That’s it. There is no way inside that second subroutine to change the value in the original variable StrBuffa , of the main routine, Sub MainRoutine_ByValByRefSimpleVBAFunctions()
In the second Call , Call TakeVariable(StrBuffa) , I am arranging that I am referring to the variable StrBuffa, (from the main routine ), when in the third and final routine , Sub TakeVariable( …. ). So I can, and do, change its value, which is then what the second output tells me. - Inside Sub TakeVariable( …. ), any reference to Tecst is effectively referring to the original variable StrBuffa , from the main routine.
In other words, within the third and final routine , Sub TakeVariable, the variable Tecst can be thought of as not a local variable, but effectively the variable StrBuffa within the main routine, Sub MainRoutine_ByValByRefSimpleVBAFunctions()
Another simple layman way to think of that is that in the third and final routine, Sub TakeVariable( .. ), I take the variable from the main routine, StrBuffa, itself , into the third and final routine , not just the value inside it. In the second routine, Sub TakeValue( ..) , I just take the value.
I realise that all the above is not technically so correct. - Indeed the purpose of this and the next post is to give a slightly more technically correct explanation, but one that is still understandable by a beginner
ByRef and ByVal are instructions to VBA. They instruct whether to take the value (ByVal ), of a given variable ( StrBuffa in this example ) or whether to refer to the variable, - crudely in this latter case, in Layman terms ByRef instructs to take the variable itself.
(In these sort of coding arrangements, we may refer to the main routine as the Calling routine, and the others as the Called routines )
A useful consequence of the above: Use ByRef instead of function return value
This is also worth reviewing , while we are here.
Some of us will know that this latter ByRef way of taking a variable, is a way to effectively get values returned from a routine, or function, since variables like StrBuffa can be thought of as a Buffer ( Buffer = box, variable, place, shelf, pigeon hole etc), to take and hold values assigned within the Called routine.
In other words, it can be thought of as a trick to make a Called routine or Function work as if it was a function that can return more than one value**.
( ** A Function in VBA and other languages is generally regarded as something that can return a single value, we talk of "The function return value", which if x is the "The function return value", then it would typically be seen in coding as x = MyFunction( ….. ) )
Examples in the next post
Bookmarks