I’m looking at a file that someone in my work created, it has the below:
Sub Inputs(zDOB As Date, zRetAge As Double, zRetDate As Date, zDOJ As Date, zEmployer As Double, zEmployee As Double, _ zSalary() As Double, zInflation As Double, zFund As Double, zAVCRate As Double, zEvalDate As Date, zAVCFund As Double, _ zCharge As Double, zFund2 As Double, zAVCFund2 As Double) zDOB = Range("B1") zRetAge = Range("B7") zRetDate = Range("B8") zDOJ = Range("B11") zEmployer = Range("B15") zEmployee = Range("B16") zSalary(0) = Range("B14") zInflation = Range("B19") zFund = Range("B20") zFund2 = Range("B20") zAVCRate = Range("B24") zAVCFund = Range("B27") zAVCFund2 = Range("B27") zEvalDate = Range("B6") zCharge = Range("J7") End Sub
Fair enough, this is setting up the inputs to be used later.
My problem is when this sub is called again:
Call Module3.Inputs(xDOfB, xRetirementAge, xDateRetire, xDOJ, xEmployer, xEmployee, xSalary, _ xInflation, xFund, xAVC, xEvalDate, xAVCFund, xCharge, xFund2, xAVCFund2)
The z is now x, does this make a difference? How does this work?
You may want to use public variables if you will use them across subscripts.
Public zDOB As Variant Public zRetAte As Variant Sub textSub() Call Inputs End Sub Sub Inputs() zDOB = Range("B1") zRetAge = Range("B7") End Sub
When you call a Function/Sub in VBA, you can pass values to it, normally referred to as arguments. The names of arguments and their types are defined in the routine’s signature like you have here:
Sub Inputs(zDOB As Date, zRetAge As Double, zRetDate As Date, ...)
To call a routine with certain arguments, you can pass them from the calling code as raw values:
Inputs 1, 2, 4 ... 'equiv to the obsolete Call Inputs(1, 2, 4 ...)
OR, the values you supply when you call a routine can be stored in variables. So I can have a variable being passed as an argument:
Dim x as Date 'here I 'declare' x, you don't generally have to do this but it's advised x = CDate(Range("A1")) 'here I assign a Value (the date in A1) to a variable (x) Inputs x, 3, 4, ... 'and call Inputs passing a variable (x) and some values(3,4) as argments
or equivalently for your code:
Dim xDOfB, xRetirementAge, xDateRetire ... 'xDofB = blah 'we could initialise values here 'xRetirementAge = foo Inputs xDOfB, xRetirementAge, xDateRetire, ... 'call a function with these variables as arguments
zFoo are just variables held by different procedures, the calling code and the Inputs routine respectively
Now what’s weird is what the
Inputs routine actually does. It takes a load of arguments, which normally would contain values you want to use in the routine. However they are all immediately overwritten. It’s a bit like the following:
Option Explicit Sub Test() Dim x As Long x = 5 Debug.Print x 'prints 5; the value initially stored in x Foo x 'call Foo, passing the variable x which contains the value 5 Debug.Print x 'Actually prints 2! (see below) End Sub Sub Foo(arg1 As Long) arg1 = 2 Debug.Print arg1 'prints 2, the 5 we passed is gone End Sub
Why would you ever want to do that?
I suspect 2 possible reasons:
The routine declares a load of arguments, when the intention was actually just to declare a load of variables, in which case the code should in fact be:
Sub Inputs() Dim zDOB As Date Dim zRetAge As Double Dim zRetDate As Date ... zDOB = Range("B1") zRetAge = Range("B7") zRetDate = Range("B8") ... End Sub
And can be called without any
The routine is exploiting the default
ByRefpassing of arguments, and is in fact designed to overwrite all those variables in place (the reason why
xis assigned 2 even though it is declared outside the function)
In that case the signature should be made explicit:
Sub Inputs(ByRef zDOB As Date, ByRef zRetAge As Double, ByRef zRetDate As Date ...)