Home » excel » excel – Variable names don't match but still works

excel – Variable names don't match but still works

Posted by: admin April 23, 2020 Leave a comment

Questions:

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?

How to&Answers:

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

Answer:

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

So xFoo and 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:

  1. 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 xBlah variables passed

  2. The routine is exploiting the default ByRef passing of arguments, and is in fact designed to overwrite all those variables in place (the reason why x is 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 ...)