Passing Variables By Reference And By Value This page describes the difference between passing parameters ByRef and ByVal. Many, if not most, procedures accept input parameters that are used to calculate the result of a function or otherwise direct the action of a procedure. These parameters may be passed By Reference (ByRef) or By Value TERMINOLOGY NOTE: Strictly speaking, the term argument refers to passed values from the perspective of the passing-fromFor example, the calling procedure CallingSub passes arguments Arg1 and Arg2 to the procedureThe term parameter refers to values passed into a called procedure, from the perspective of the called procedure. For example, the procedure CalledSub accepts parameters X and Y fromHowever, these terms are used interchangably in most documentation and will be used interchangably on this site. The meaning will be clear from the context provided by the narrative text. Passing ByRef or ByVal indicates whether the actual value of an argument is
passed to the CalledProcedure by the CallingProcedure, or whether a reference (called a pointer in some other languages) is passed to to the CalledProcedure. argument is passed ByRef, the memory address of the argument is passed to the CalledProcedure and any modification to that parameter by the CalledProcedure is made to the value in the CallingProcedure. If an argument is passed ByVal, the actual value, not a reference to the variable, is passed to the CalledProcedure. A simple example will illustrate this clearly: In the the variables A and B are assigned the values 123 and 456, respectively. These values are confirmed with the firstThen, the is called passing arguments A and B. Within the parameters X and Y are assigned the values 321 and 654 respectively, and control is returned back to the procedureSince the parameter X was declared with , a reference or pointer to A was passed to and any modification to the X parameter in affects the variable
The parameter Y was declared with , so only the actual value of B was passed toChanges made to the parameter Y are not made to the variable B. This is illustrated by the second statement. A was modified by but that B was not changed. Objects are always passed by reference. The ByRef and ByVal modifers indicate how the reference is passed to the called procedure. When you pass an object type variable to a procedure, the reference or address to the object is passed -- you never really pass the object itself. When you pass an object ByRef, the reference is passed by reference and the called procedure can change the object to which that reference refers to. When an object is passed ByVal an copy of the reference (address) of the As is so often the case, an example will serve well to illustrate this: In the CallingProcedure, the variable is set to and the variable is set to . is called, passing and . sets the values of these ranges to new values and then changes the ranges to which
, the can change the cell to whichAs is confirmed by the second group of statements, the variable now refers to (points to) passed , the cannot change the range to which refers to in . The rules for passing your own custom classes are the same for passing object type variables. Throughout this article, we have discussed that you cannot change the value of a variable in the calling procedure if a parameter referring to that variable was passed ByVal. It is worth noting, for clarity, though, that you can certainly change the value of a parameter variable regardless of whether is was passed by ByRef orThese declarations refer to only if the variable in the calling procedure can be changed. You can always change the value of a parameter in the called procedure. In this code, the is free to change the values of its parameters X and Y, and indeed this is often quite useful. and declaration affect only whether changes to parameters affect the variables in the .
This same rule applies to object This code clearly illustrates that the object parameters and can be changed within the scope of the procedure. determine only if the changes to the parameters make their way back to the calling procedure. Even if a called procedure has declared its parameters as ByRef, you can force those to be ByVal by enclosing each argument within parentheses. First, examine the following code. quite familiar as we have used it before: The changes the values of its parameters to 321 and 654 respectively. the situation in which you do want to call on the functionality of but you don't want that procedure to modify the input parameters. The difficult way would be to save the original copies of A and B and restore the values after returns, or to even rewriteHowever, VB/VBA gives you a much simpler method: just enclose the arguments individually in parentheses. Here, the second statement illustrates that the values of A and
B have not had their values changed. However, there are a few caveats to using this approach: You cannot use named arguments in the call to the . You (generally) cannot pass Object type parameters in this manner. In the circumstances in which you can use object type variable (when the object has a default property and the parameter as declared as Variants), you may very well get incorrect results or a run time error because the By default, all parameters are passed by reference, so it is not necessary to include theHowever, I have over my 20 years as a professional programmer found that it is good practice to include the declaration if you are going to change the value of the parameter. It makes no difference to how the code runs -- in makes the code neither faster nor slower -- but it serves as documentation that the variable in the calling procedure is going to be modified by the called procedure. It helps make the code self-documenting. You may or may not agree.