Tải bản đầy đủ - 0 (trang)
Figure 5-2. Examples of variable scope

Figure 5-2. Examples of variable scope

Tải bản đầy đủ - 0trang

One of the advantages of local variables is that we can use the same name in different procedures

without conflict, since each variable is visible only to its own procedure.

5.4.11.2 Module-level variables

A module-level variable (or constant) is one that is declared in the declarations section of a code

module (standard, class, or UserForm). Module-level variables and constants come in two flavors:

private and public.

Simply put, a module-level public variable (or constant) is available to all procedures in all of the

modules in the project, not just the module in which it is declared, whereas a module-level private

variable (or constant) is available only to the procedures in the module in which it was declared.

Public variables and constants are declared using the Public keyword, as in:

Public APubInt As Integer

Public Const APubConst = 7



53



Private variables and constants are declared using the Private keyword, as in:

Private APrivateInt As Integer

Private Const APrivateConst = 7



The Dim keyword, when used at the module level, has the same scope as Private, but is not as

clear, so it should be avoided.

Public variables are also referred to as global variables, but this descriptive term is not de rigueur.



5.4.12 Variable Lifetime

Variables also have a lifetime. The difference between lifetime and scope is quite simple: lifetime

refers to how long (or when) the variable is valid (that is, retains a value) whereas scope refers to

where the variable is accessible or visible.

To illustrate the difference, consider the following procedure:

Sub ProcedureA()

Dim LocalVar As Integer

LocalVar = 0

Call ProcedureB

LocalVar = 1

End Sub



Note that LocalVar is a local variable. When the line:

Call ProcedureB



is executed, execution switches to ProcedureB. While the lines of ProcedureB are being

executed, the variable LocalVar is out of scope, since it is local to ProcedureA. But it is still

valid. In other words, the variable still exists and has a value, but it is simply not accessible to the

code in ProcedureB. In fact, ProcedureB could also have a local variable named LocalVar,

which would have nothing to do with the variable of the same name in ProcedureA.

Once ProcedureB has completed, execution continues in ProcedureA with the line:

LocalVar = 1



This is a valid instruction, since the variable LocalVar is back in scope.

Thus, the lifetime of the local variable LocalVar extends from the moment that ProcedureA is

entered to the moment that it is terminated, including the period during which ProcedureB is

being executed as a result of the call to this procedure, even though during that period, LocalVar

is out of scope.

Incidentally, you may notice that the Microsoft help files occasionally get the notions of scope and

visibility mixed up a bit. The creators of the files seem to understand the difference, but they don't

always use the terms correctly.

5.4.12.1 Static variables

To repeat, a variable may go in and out of scope and yet remain valid during that time—that is,

retain a value during that time. However, once the lifetime of a variable expires, the variable is



54



destroyed and its value is lost. It is the lifetime that determines the existence of a variable; its

scope determines its visibility.

Thus, consider the following procedures:

Sub ProcedureA()

Call ProcedureB

Call ProcedureB

Call ProcedureB

Call ProcedureB

Call ProcedureB

End Sub

Sub ProcedureB()

Dim x As Integer

x = 5

. . .

End Sub



When ProcedureA is executed, it simply calls ProcedureB five times. Each time

ProcedureB is called, the local variable x is created anew and destroyed at the end of that call.

Thus, x is created and destroyed five times.

Normally, this is just want we want. However, there are times when we would like the lifetime of

a local variable to persist longer than the lifetime of the procedure in which it is declared. As an

example, we may want a procedure to do something special the first time it is called, but not

subsequent times. For instance, the following one-line macro changes the font of the selected cells

to Comic Sans:

Sub ToComic()

Selection.Font.Name = "Comic Sans"

End Sub



Suppose, however, that we wish to warn the user that Comic Sans is a bit informal and ask if he or

she really wants to make this change. We don't want to make a pest of ourselves by asking every

time the user invokes this macro. What we need is a local variable with a "memory" that will

allow it to keep track of whether or not a particular call to ToComic is the first call or not. This is

done with a static variable.

A static variable is a local variable whose lifetime is the lifetime of the entire module, not just the

procedure in which it was declared. In fact, a static variable retains its value as long as the

document or template containing the code module is active (even if no code is running).

Thus, a static variable has the scope of a local variable, but the lifetime of a module-level variable.

C'est tout dire !

Consider now the modification of the preceding macro, which is shown in Example 5-2. The code

first declares a static Boolean variable called NotFirstTime. It may seem simpler to use a

variable called FirstTime, but there is a problem. Namely, Boolean variables are automatically

initialized as False, so the first time that the ToComic macro is run, FirstTime would be False,

which is not want we want. (We will discuss variable initialization a bit later.)

Example 5-2. ToComic() Modified to Use a Static Variable

Sub ToComic()

' Declare static Boolean variable



55



Static NotFirstTime As Boolean

' If first time, then ask for permission

If NotFirstTime = False Then

If MsgBox("Comic Sans is a bit informal. Proceed?", _

vbYesNo) = vbYes Then

' Make the change

Selection.Font.Name = "Comic Sans MS"

End If

' No longer the first time

NotFirstTime = True

Else

' If not the first time, just make the change

Selection.Font.Name = "Comic Sans MS"

End If

End Sub



The If statement checks to see if the value of NotFirstTime is False, as it will be the first time

the procedure is called. In this case, a message box is displayed, as shown in Figure 5-3. If the

user chooses the Yes button, the font is changed. In either case, the static Boolean variable

NotFirstTime is set to True. Precisely because NotFirstTime is static, this value will be

retained even after the macro ends (but not if the document is closed).

Figure 5-3. Dialog that appears if the static NotFirstTime is false



The next time the macro is executed, the variable NotFirstTime will be True, and so the If

condition:

If NotFirstTime = False Then



will be False and the MsgBox function will not be executed. Instead, the Else code will execute.

This code just changes the font, without bothering the user with a message box.

Static variables are not used very often, but they can be quite useful at times.

It may have occurred to you that we could accomplish the same effect by using a module-level

private variable to keep a record of whether or not the macro has been called, instead of a static

local variable. However, it is considered better programming style to use the most restrictive scope

possible which, in this case, is a local variable with an "extended" lifetime. This helps prevent

accidental alteration of the variable in other portions of the code. (Remember that this code may

be part of a much larger code module, with a lot of things going on. It is better to hide the

NotFirstTime variable from this other code.)



5.4.13 Variable Initialization

When a procedure begins execution, all of its local variables are automatically initialized, that is,

given initial values. In general, however, it is not good programming practice to rely on this



56



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Figure 5-2. Examples of variable scope

Tải bản đầy đủ ngay(0 tr)

×