Relevant Codes (by Anshoo Arora)

A Test Development Resource for HP QuickTest Professional.

Passing Parameters ByRef & ByVal (Revised)

by Anshoo Arora on August 10, 2009

In VBScript, there are two ways values can be passed: ByVal and ByRef. Using ByVal, we can pass arguments as values whereas with the use of ByRef, we can pass arguments are references. This is the obvious bit, but, how do these 2 differ in practice?

Let’s find out!

Passing Parameters By Value
Consider the following code snippet:

Function GetValue( ByVal varVariable )
   varVariable = varVariable + 1
End Function
 
Dim x: x = 5
 
'Pass the variable x to the GetValue function ByVal
GetValue x
 
MsgBox "x = " & x

When you run the block of code above, you will get the following output:

Passing Parameter By Value

Passing Parameter By Value

In other words, when we passed the variable ‘x’ (ByVal) to the function ‘GetValue’, we were simply passing a copy of the variable ‘x’. When GetValue executes, ‘varVariable’ stores a copy of the variable ‘x’ and increments itself by 1. Therefore, because what we are passing to GetValue is a copy of ‘x’, it cannot be modified.

Now, let’s look at another way of passing variables: By Reference.

Passing Parameters By Reference
Consider the following code snippet that takes arguments ByReference:

Function GetReference( ByRef varVariable )
   varVariable = varVariable + 1
End Function
 
Dim x: x = 5
 
'Pass the variable x to the GetReference function ByRef
GetReference x
 
MsgBox x

I think you must already be aware what’s going to happen when the above code is executed. Let’s see the snapshot:

Passing Parameter By Reference

Passing Parameter By Reference

Yes, variable ‘x’ was increment by 1. But why was ‘x’ incremented? Only ‘varVariable’ must have incremented by 1, and not ‘x’? Well, that is the core concept behind passing variables by reference.

When the function ‘getReference’ executes, ‘varVariable’ becomes a reference of ‘x’, and therefore, any changes made to ‘varVariable’ would impact ‘x’. So if varVariable increments itself by 1, so would x. If varVariable becomes 0 (zero), so would x.

Let’s see another example:

Function GetReference( ByRef arrArray )
   ReDim Preserve arrArray(UBound(arrArray)+1)
   arrArray(UBound(arrArray)) = 2
End Function
 
Dim newArray: newArray = Array(0, 1)
GetReference newArray

Will the size of ‘newArray’ increase? Let’s see:

' new size: 2
MsgBox UBound(newArray)
 
' new elements: 0, 1, 2
For x = LBound(newArray) To UBound(newArray)
   MsgBox newArray(x)
Next

Since ‘newArray’ was passed as a reference to the GetReference function, the change made to ‘arrArray’ was reflected upon ‘newArray’ as well. Thus, sizes of both arrays incremented by 1.

Is there a way to pass variables byRef and still avoid this? Yes, there is. The answer lies in passing temporary variables (see footnotes below).

ByRef & Temporary Variables
The advantage of using this approach is that you can pass temporary variables to n number of functions accepting arguments as reference, without having the base (original) variables modified. This is a good (and recommended) approach, since your original variables stay intact and you do not lose track of them when working with extensive function libraries. Please see a simple demonstration of this approach below:

Function GetReference( ByRef varVariable )
 varVariable = varVariable + 1
End Function
 
Dim x: x = 5
Dim y: y = x
GetReference y
 
MsgBox x   'Returns 5 (x remains unchanged)
MsgBox y   'Returns 6

Above, you will notice that as y became a temporary variable and was passed to GetReference, only it was modified. The variable x was unchanged. Thus, it’s recommended to use temporary variables when passing variables as reference.

Summary

  • (ByVal) Arguments do not change when passed by value.
  • (ByRef) If the function parameter is modified, it will have the same impact on the parameter that was passed by reference.
  • (ByRef) Because the passed parameters can be changed, we can pass multiple values from functions.
  • (ByRef) In a huge function library, it can be hard to tell where the value was changed and what function the variable was supposed to perform.

* Credits go to Christopher J. Schärer for pointing out the error in this statement.
** This section has been modified and updated. Previously, it was “Constants and ByReference”, which is a valid technique, but as Christopher J. Schärer pointed out, a better approach is to pass temporary variables as ByRef arguments.

If you have any questions, please ask them in the comments section. If your query is confidential, please use the Contact Form to send me an e-mail instead.

{ 15 comments… read them below or add one }

1 nidhi November 5, 2009 at 3:52 pm

wow ! very neatly put. I am a newbie and i got a very clear idea. your examples are great !

Reply

2 Anshoo Arora November 5, 2009 at 5:41 pm

Thank you, Nidhi. If you have any question with any of the material here, please feel free to ask. :)

3 Tarun Lalwani December 15, 2009 at 7:27 am

You can also add about the forcing of passing by value for byRef params as explained in my comment in below article

http://www.sqaforums.com/showflat.php?Number=606036

Reply

4 Anshoo Arora December 16, 2009 at 10:09 am

Thanks for the link Tarun. I read the thread and will update the post soon. I have updated the article on RegisterUserFuncX, which its limitations. Thanks :)

5 Puneet February 5, 2010 at 3:45 am

Hi Anshoo,

Below is a code I am working on which i cannot seem get one thing right within the code. When a user selects a username it should check to see if the message box appears and if it does then it should go to the datatable and select a different username. Right now the script is running and only detecting SSN and changing the SSN regardless of me duplicate username.

NewUser ‘Selecting a new user from the functional library
‘Adding the profile
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).SwfComboBox(“cboUserType”).Select “PROVIDER”
SwfWindow(“DHA – You are currently”).SwfWindow(“Add User”).SwfEdit(“txtLname”).Set “One”
SwfWindow(“DHA – You are currently”).SwfWindow(“Add User”).SwfEdit(“txtFname”).Set “Provider”
username = SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).SwfEdit(“txtUsername”).GetROProperty(“text”)

‘If the SSN is duplicate then select the next one in the datatable
For i = 1 to 10
datatable.SetCurrerntRow(i)
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).SwfEdit(“txtSSN”).Set DataTable(“SSN”, dtLocalSheet)
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).SwfComboBox(“cmbCountry”).Select “US”
SwfWindow(“DHA – You are currently”).SwfWindow(“Add User”).SwfButton(“btnAddUser”).Click

If SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Static(“User with same SSN already”).Exist Then
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Static(“User with same SSN already”).Check CheckPoint(“User with same SSN already exists in the database.”)
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Activate
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).WinButton(“OK”).Click
Exit For

Elseif SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Static(“Another record with the”).Exist Then
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Static(“Another record with the”).Check CheckPoint(“Another record with the same user name already exists in the database.”)
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).Activate
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Alert]“).WinButton(“OK”).Click
‘Reporter.ReportEvent micFail, “Verify the user has been added”, “The” &username& “already exist”

If SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Acknowledgement]“).Exist Then
Reporter.ReportEvent micPass, “<Verify the user has been added;&gt”, “The ” &username& ” successfully has been added”
SwfWindow(“HA – You are currently”).SwfWindow(“Add User”).Dialog(“HA – [Acknowledgement]“).WinButton(“OK”).Click
end if
end if
next

Reply

6 Anshoo Arora February 10, 2010 at 2:15 pm

Hi Puneet,

Which part of the code is causing this issue? I think you would need to branch your code so that it does one complete iteration with the help of conditional statements. For example, if the userName is still the same as the previous, re-run the code and loop the code until the userName is different..

7 VK July 3, 2010 at 5:01 pm

Ankur- You talked about two ways values can be passed: ByVal and ByRef.
What is the default way through which values are passed? I mean if I don’t specify Byval or Byref with the parameters, does it pass by reference?

Reply

8 Tarun Lalwani July 4, 2010 at 1:44 am

I hope you meant Anshoo and not Ankur?

By default it is ByRef

Reply

9 VK July 4, 2010 at 3:52 pm

oops..sorry. I meant Anshoo :(
thanks for the prompt reply.

10 Kevin Abel November 4, 2010 at 1:16 pm

I have used byRef in previous versions of QTP and many other languages. For some reason it is not working in QTP 10.0. I am also using QTP patch QTP_00626 in case this matters.

I call like this:

do_it(parm1) ‘ Parm 1 is undefined at the end of run.
x = 1 ‘ used as a breakpoint line.
The function looks like

Function do_it(by Ref parm1)
parm1 = “hello”
End Function

What is wrong?

Reply

11 Anshoo Arora November 14, 2010 at 5:29 pm

Kevin,

Does this work for you?

Dim var : var = ""

Function do_It(ByRef arg)
	arg = "hello"
End Function

do_It var

MsgBox var

I have tried this code with QTP 10 and it works as expected. Also tried it on QTP 11 and the same result..

12 Tarun November 4, 2010 at 3:50 pm

The problem is in your call. It should be

call do_it(parm1)

and NOT

do_it(parm1)

In the later the brackets enforce pass by value instead of reference

Reply

13 Anshoo Arora November 14, 2010 at 5:30 pm

Woops. Didn’t see Tarun’s reply there..

14 Kevin Abel November 14, 2010 at 7:13 pm

I did know how QTP and VBScript is supposed to work with ByRef and ByVal. For some unknown reason ByRef did not work either in the default mode or when parameters are specified to be ByRef in the called function. The values going into the funciton calls, but were not returning with the new values.

At first I thought I may be doing something wrong so I showed my finding to a VB programmer and said I was not making a mistake. I tried it on a second machine with another QTP 10.00 developer and we ran into the same issue.

The solution was to put a CALL in front of the funciton call. Then the functions did pass by reference. I did see another article on line where the variable did not get sent back to the calling function and they also used the CALL statement. The article was talking about dictionary objects being passed by reference and how the CALL statement made the ByRef work differenty that gave me the idea of trying:
CALL DoSomething param1
and it did return the updated value through param1

I take away the CALL and the ByRef value did not return anything and the value became undefined which is even a step worse than by val because it lost the original value.

I do not know why the parameters pass on some PCs and not others.

Thanks,

Kevin

Reply

15 Anshoo Arora December 5, 2010 at 9:35 pm

I have a friend who was searching for some information on this topic and landed on this page + read your comments. Thanks for sharing such wonderful information with us, Kevin.

Leave a Comment

{ 2 trackbacks }

Previous post:

Next post: