ByVal ByRef

shamas21

Registered User.
Local time
Today, 08:25
Joined
May 27, 2008
Messages
162
Hi All

This is regarding ByVal ByRef

Its taken me over a year to try and understand this concept as I feel either I just dont get it or people are not explaining it to me very well.

Am I right in saying that ByVal and ByRef only matters if the called sub or Function changes the values of its own parameter variable. i.e.

Code:
Function Test(ByRef Param as Integer)
    Param = 5
End Sub

So ByVal would take a copy of the Param variable where as ByRef would directly modify the location in memory of Param. So despite Param equaling 5 - if its called ByRef then if the calling Sub changes Param then that is the value that would be used and vice versa for ByVal.

However, let say the code was written as below

Code:
Function Test(Param as Integer)
    'Some code here that doesnt change the value of Param
End Sub

Then it doesnt matter if its ByVal or ByRef because this is only used for when the Called Sub or Function changes its own Parameter variable.

But if this is the case then I cant ever see a live example of me ever wanting to use this in a real world example.

Any clarification would be greatly appreciated.

Thanks
 
Your understanding is essentially correct. I'm not sure if you think a ByVal parameter would be updated? (It wouldn't).

Here's an example for you:
Code:
Rem conditional compilation used to select the method below
#Const kMode = flase
Private Sub test()
Rem the value to be changed
Dim intTest As Integer
intTest = 0
#If kMode Then
Rem call a subroutine to change the value directly
newValue intTest
#Else
Rem call a subroutine to change the value indirectly
intTest = newValue(intTest)
#End If
MsgBox "New value is " & intTest
End Sub
#If kMode Then
Private Sub newValue(ByRef pField As Integer)
Rem increment the field in situ
pField = pField + 1
End Sub
#Else
Private Function newValue(ByVal pField As Integer) As Integer
Rem increment the value passed as a local copy, then retunr the result to caller
newValue = pField + 1
End Function
#End If
Put this in a command button Click event to try it out. Change the kMode value to True or False to see each method in action.

Real-life example might be a date calculation which is applied to many fields, so you would iterate the fields by calling the calculation with each field as a parameter.
 
In this context ByVal is a passed variable and ByRef returns a variable

Code:
Sub Test1(ByVal S as String)
    S='hello world'
End sub
 
Sub Test2(ByRef S as String)
    S='hello world'
End sub
 
Your calling code
Dim Str as String
...
....
Str="Goodbye"
Test1(Str)
Debug.Print Str ' will print 'Goodbye'
Test2(Str)
Debug.Print Str ' will print 'hello world'
...
....
In the above instance, Test2 could have been a function returning a string with ByVal S as a parameter but would then be written as

Str=Test2(Str)

So why would you want to use ByRef when function will do? One situation may be where you want more that one value returned - for example to scale up the height and width of an image control, you would have to otherwise use 2 functions, or call the same function twice. If done as a long type function you can return any error code - effectively passing error control back your calling code, e.g.

Code:
Function Scaleup(ByRef Hgt as long, by Ref Wdh as long) as long
On Error Goto ErrCtrl
...
...
Scaleup=0
Exit Function
 
ErrCtrl:
Scaleup=Err
End Function
 
Your calling code
...
....
if ScaleupTest1(myImagectrl.Height, myImagectrl.Width)<> 0 then
    msgBox myImageCtrl.Name & " could not be scaled"
End if
...
....
 
byval, byref

a variable is stored in an area of memory.
so say you declare a variable

dim myvar as long

VBA allocates a 4 byte area of memory for use as myvar.

Now if you want to use this value in another procedure, you can pass it as byref, or byval as an argument/parameter

byref is by reference - in which case the real address of the variable myvar gets passed to the called procedure, so changing the value of the passed argument actually changes the real value of the variable myvar

byval is by value - in which case the sub/function makes a copy of the real variable myvar for use in the sub/function. This way, changing the value of the passed
argument changes the temporary copy, and not the real variable myvar

if you are used to not changing passed in parameters then it makes little difference to be honest. Generally it is probably unusual to change a parameter. It is therefore a bit surprising that VBA chose to make byref the default - as byval is generally "safer", and it is the programmer's decision to actively make a parameter byref.


note that for some argument types, (eg an array) there is no difference between byval and byref. complex data types such as an array are always passed byref.


maybe a good example of a byref is something like this

function myfunc (byref returnvalue as string) as Boolean

you want a function to return true or false depending on whether it was successful. But if successful you also want a returnvalue to be set. So you can use a byref parameter to store the returnvalue, and only test it in the calling procedure, if the function was successful
 
Many thanks all - I greatly appreciated all your inputs. I makes sense now.
 

Users who are viewing this thread

Back
Top Bottom