Localizing Variables

atclaus

New Member
Joined
Sep 19, 2014
Messages
2
I am stuck on local vs global variables. If you call a variable within a sub as "sub test(a as Integer)" is a now a global variable?

I have simplified a lot of code to the below to demonstrate the issue. Right now I have put in another IF statement using the tmp variable to flip cl_min and cl_max back, but would not have thought it would work this way. At first I was using cl_min instead of c_min in create_diagonal so thought a name change would help, but it changes it anyway. Any advice on how to better code this would be appreciated. Thanks!

Code:
Option Explicit

Sub Setup_Test_Document()
    Dim rack_sample_pattern As String
    Dim rw_min As Integer, rw_max As Integer, cl_min As Integer, cl_max As Integer

    rack_sample_pattern = "x"
    cl_min = 2
    cl_max = 11
    rw_min = 5
    rw_max = 12
    MsgBox ("cl_min= " & cl_min & Chr(10) & "cl_max= " & cl_max)
    Call rack_sampling(rack_sample_pattern, rw_min, rw_max, cl_min, cl_max)
    MsgBox ("cl_min= " & cl_min & Chr(10) & "cl_max= " & cl_max)
End Sub

Sub rack_sampling(rack_sample_pattern, rw_min As Integer, rw_max As Integer, cl_min As Integer, cl_max As Integer)
    Call create_x(cl_min, cl_max, rw_min, rw_max)
End Sub

Sub create_x(cl_min As Integer, cl_max As Integer, rw_min As Integer, rw_max As Integer)
    Call create_diagonal(True, cl_min, cl_max, rw_min, rw_max)
    Call create_diagonal(False, cl_min, cl_max, rw_min, rw_max)
End Sub

Sub create_diagonal(top_left As Boolean, c_min As Integer, c_max As Integer, r_min As Integer, r_max As Integer)
    Dim rw, cl, cl_step, tmp As Integer
    Dim double_here As Boolean
    
    If top_left Then
        cl_step = 1
    Else
        cl_step = -1
        tmp = c_min
        c_min = c_max
        c_max = tmp
    End If
    'do work
End Sub
 

Some videos you may like

Excel Facts

How to fill five years of quarters?
Type 1Q-2023 in a cell. Grab the fill handle and drag down or right. After 4Q-2023, Excel will jump to 1Q-2024. Dash can be any character.

joeu2004

Well-known Member
Joined
Mar 2, 2014
Messages
2,809
Office Version
  1. 2010
Platform
  1. Windows
I am stuck on local vs global variables. If you call a variable within a sub as "sub test(a as Integer)" is a now a global variable?

No, "a" is a local variable.

A global variable is one that is declared outside of any procedure (and class). You would declare them before the first Sub or Function in a module.

Global variables can be Private or Public. A Private global variable can be referenced only by procedures (Subs and Functions) in the same module. Public global variables can be referenced in other modules.

As a programming principle, it is better to make the "locality" of a variable as limited as possible. Local variables are best. Private global variables are better than Public global variables. Usually, it is better to pass a value (or variable By Ref) as a parameter than to declare a global variable.

But when I say "better", again, I am speaking about principles. It is "better" to always drive the speed limit. Yeah, like that's gonna happen. (wink)

OTOH, I cannot remember the last time that I used a global variable.
 

joeu2004

Well-known Member
Joined
Mar 2, 2014
Messages
2,809
Office Version
  1. 2010
Platform
  1. Windows
Regarding your code....

First, an aside.... It is better to use type Long instead of Integer. And for the future, it is better to use type Double instead of Single.

There is no point in using variables in Setup_Test_Document, unless you intend to pass them By Ref, which you did not. Simply write the call as follows:

Call rack_sampling("x", 5, 12, 2, 11)

There is no need to swap c_min and c_max within create_diagonal. You can do it in the call, to wit:

Call create_diagonal(cl_min, cl_max, rw_min, rw_max, 1)
Call create_diagonal(cl_max, cl_min, rw_min, rw_max, -1)

where create_diagonal is declared as:

Sub create_diagonal(c_min As Long, c_max As Long, r_min As Long, r_max As Long, cl_step As Long)

Note that I added cl_step as a parameter. Remove it from the Dim statement inside the procedure.

Aside.... You might want to change the names cl_min and cl_max, if they are not really "min" and "max" of something. OTOH, I cannot think of better names; then again, I have never been with choosing variable names. (sigh)
 
Last edited:

joeu2004

Well-known Member
Joined
Mar 2, 2014
Messages
2,809
Office Version
  1. 2010
Platform
  1. Windows
There is no point in using variables in Setup_Test_Document, unless you intend to pass them By Ref, which you did not.

My bad! I forgot that ByRef is the default in VBA.

So yes, when you swap c_min and c_max in create_diagonal, you effectively modify cl_min and cl_max in setup_test_document.

But not because they became global variables. (They did not.)

And not because of the similarity of local (or parameter) variable names.

(You can use the same local variable names in each procedure.)

It is because when you pass a variable in VBA, you are, by default, passing its location (ByRef), not just its value.

It appears that that is not your intent, since you mention adding ``another IF statement using the tmp variable to flip cl_min and cl_max back``.

(I don't see that in your code snippet.)

You can avoid that in several ways:


1. Passing constants in setup_test_document, as I mentioned before. However, rack_sampling and create_x are still affected.


2. Put parentheses around each variable name in the call. For example:

Call rack_sampling( (rack_sample_pattern), (rw_min), (rw_max), (cl_min), (cl_max) )


3. Change the procedure declarations, adding ByVal before each parameter name. For example:

Sub rack_sampling(ByVal rack_sample_pattern, ByVal rw_min As Integer, ByVal rw_max As Integer, ByVal cl_min As Integer, ByVal cl_max As Integer)


#3 is probably the best way.

Whicheverr solution that you choose, apply it to all procedures or calls.

And don't forget to also consider the other improvements that I mentioned previously: Long instead of Integer; and avoiding the swap altogether.
 
Last edited:

Watch MrExcel Video

Forum statistics

Threads
1,108,954
Messages
5,525,879
Members
409,669
Latest member
JDCupps

This Week's Hot Topics

Top