VBScript has a few rules for what names you can give to a variable. The rules are pretty simple, and leave you plenty of room to come up with clear, useful, understandable variable
Rule Number 1: VBScript variable names must begin with an alpha character.
is any character between 'a' and 'z' (capital or lowercase). Non-alpha
And these are illegal variable names:
Rule Number 2: Numbers and the
VBScript does not like variable names that contain characters that are anything but numbers and
And these are illegal variable names:
str & Name
Rule Number 3: VBScript variable names cannot exceed 255 characters.
Hopefully, your variable names will not exceed 20 characters or so, but VBScript allows them to be as long as 255 characters.
These rules for variable naming should be pretty easy to follow, but it is important to make a distinction between coming up with variable names that are legal, and coming up with variable names that are clear, useful, and understandable. The fact that VBScript will
you to use a variable name such as
A variable name should make the purpose of the variable clear. If you're going to store the
Another principle that a large percentage of programmers have found useful is the 'Hungarian naming convention,' which we have mentioned a couple times before, and which we have been using throughout this and the
For example, the variable name strUserName indicates not only that the variable should hold the user's name, but also that the subtype of the variable should be String . Similarly, the variable name lngFileCount indicates not only that the variable should hold a count of the number of files, but also that the subtype of the variable should be Long .
Appendix B of this book contains additional guidelines for naming variables, including a list of suggested data type prefixes.
At this point we will introduce the concept of procedures and functions, which are essential building blocks for more complex scripts. Procedures and functions allow you to
Sometimes the word
is used in the generic sense to refer to either a procedure or a function, but we will do our best in this chapter to use the
A named block of code
: When we use the term block of code, we are referring to a grouping of lines of code that are
: When we say 'the calling code' we mean the code that
a procedure or function. One of the primary purposes of naming a block of code is that other code can invoke that block of a code using the name. Throughout the
Returning a value
: Some named blocks of code can return a value to the calling code. A procedure does not return a value, whereas a function does. Sometimes you need a value to be returned by a block of code, and sometimes you do not. As we have been using it, the
procedure does not return a value (though it can if you ask it to-
is interesting as it can be used as either a procedure or a function). We just pass
a value to display, it displays the value to the user, and when the
lngCount = CLng("12")
A procedure is declared with the following syntax.
[PublicPrivate] Sub Name ([Argument1],[ArgumentN]) [code inside the procedure] End Sub
A named block of code that is a procedure is identified with
keyword. ('Sub' is short for 'subprocedure,' which is another way of saying 'procedure.') You can
In a normal script file (that is, one that is not a class or a Windows Script Component), the keywords
do not really do anything for you since no procedures, functions, or
The ending boundary of the procedure must be defined with the keywords End Sub . Between the Sub and End Sub boundaries, normal VBScript syntax rules apply.
The rules for naming a procedure are the same as those for naming variables (see earlier). It is a good idea, however, to use clear, purposeful
(also known as
) are optional for a procedure, and you can use as many arguments as you would practically need (though a procedure with too many arguments is a sure sign of a poorly designed procedure that is doing too much; see under section
Design Strategies for Procedures and Functions
). An argument is a value that you wish to 'pass into' the procedure so that the code inside the procedure will have access to it. The argument list must be
Here is a bare-bones procedure that does not use any arguments ( PROCEDURE_SIMPLE.VBS ).
Option Explicit SayHelloToBill Sub SayHelloToBill MsgBox "Hello, Bill. Welcome to our script." End Sub
The first line in this example is not part of the procedure definition, but rather is the calling code that invokes the procedure. A procedure just sits there doing nothing unless there is some other code to call it.
Notice that we have omitted the Public / Private keywords and that there are no parentheses after the procedure name since it does not take any arguments. Also notice that the code inside of the procedure is indented; this is not required, but is a common convention since it makes the code easier to read. The indentation suggests the hierarchical relationship between the procedure and the code within it.
Here is a similar procedure that takes one argument (PROCEDURE_ARGUMENT.VBS ).
Option Explicit GreetUser "Bill" Sub GreetUser(strUserName) MsgBox "Hello, " & strUserName &_ ". Welcome to our script." End Sub
Notice how the addition of the
argument, along with an adjustment to the procedure name, allows us to make the procedure more generic, which in
The syntax for a function is identical to that of a procedure, except that you change the keyword Sub to the keyword Function .
[PublicPrivate] Function Name ([Argument1],[ArgumentN]) [code inside the function] End Function
The rules for naming, Public / Private , and the declaration of arguments are the same as for procedures. As we've said, the distinction between a function and a procedure is that a function returns a value. Here is an example that illustrates the syntax for a function and how the code within a function sets the return value for the function ( FUNCTION_SIMPLE.VBS ).
Option Explicit Dim lngFirst Dim lngSecond lngFirst = 10 lngSecond = 20 MsgBox "The sum is: "& AddNumbers(lngFirst, lngSecond) Function AddNumbers(lngFirstNumber, lngSecondNumber) AddNumbers = lngFirstNumber + lngSecondNumber End Function
may not be the most useful function in the world, but it serves well to
AddNumbers = lngFirstNumber + lngSecondNumber
It's as if there is a nondeclared variable inside of the function that has the same exact name as the function itself. To set the return value of the function, you set the value of this invisible variable. You can do this from
Let's join together a procedure and a function in order to
Option Explicit GreetUser Sub GreetUser MsgBox "Hello, "& GetUserName & _ ". Welcome to our script." End Sub Function GetUserName GetUserName = InputBox("Please enter your name.") End Function
Notice how the GreetUser procedure calls the GetUserName function. Functions and procedures can work together in this way, which is how programs are built. Break your code up into specific modular building blocks of procedures and functions that do very specific things and then string the building blocks together in a logical manner.
Some amount of 'coupling' amongst code modules is necessary and good, but coupling is also something that you want to avoid if you don't need it. The more couplings in your program, the more complex it is. Some complexity is inevitable, but you want to reduce complexity as much as possible. When functions and procedures are
Here's a different version of the same script that eliminates the unnecessary coupling.
Option Explicit GreetUser GetUserName Sub GreetUser(strUserName) MsgBox "Hello, " & strUserName & _ ". Welcome to our script." End Sub Function GetUserName GetUserName = InputBox("Please enter your name.") End Function
The logic of the program is the same, but now we have decoupled GreetUser and GetUserName . We did this by restoring the strUserName argument to GreetUser and instead using the code at the top of the script to put the two functions together without either function 'knowing about' the other. Here is the interesting line of code in this script.
The return value from the GetUserName function is fed as the strUserName argument of the GreetUser function.
One final note about function syntax: programmers familiar with other languages may have noticed that there is no way to declare the data type of a function's return value. This makes sense if you remember that VBScript supports only one data type-the Variant . Since all variables are Variant s, there is no need for syntax that specifies the data type of a function.
One way that many VBScript programmers choose to help with code clarity in this regard is to use the same Hungarian type prefixes in front of their function names as they do for their variable names. For example,
In the preceding examples of procedures and functions, you may have noticed some differences in the syntax for calling a procedure as opposed to a function. There are indeed differences, and the VBScript compiler is very particular about them.
Here is one way to call a procedure.
Here is another.
These two conventions are functionally equivalent, and whichever you choose is largely a matter of taste. Some would argue that the second convention (using the Call keyword) is more clear, but both conventions are equally common and Visual Basic and VBScript programmers over time become very accustomed to one or the other.
Likewise, this example is also illegal for calling a procedure.
Call GreetUser "Bill"
When calling a procedure (as opposed to a function), if you choose not to use the Call keyword, then you cannot use parentheses around the argument value you are passing to the procedure. Conversely, if you do wish to use the Call keyword, then the parentheses are required.
The rules for calling functions are a bit different. If you want to receive the return value from a function, then you must not use the Call keyword and you must use parentheses around the argument list, like so:
lngSum = AddNumbers(10,20)
This syntax is illegal because it omits the parentheses.
lngSum = AddNumbers 10,20
And this is illegal as well because you cannot use the Call keyword when receiving the return value.
lngSum = Call AddNumbers(10,20)
You can, however, use the Call keyword if you do not wish to receive the return value of the function, but you have to use the parentheses.
You could also omit the Call keyword and still ignore the return value, but you must omit the parentheses in that case.
This begs the question: why would you ever want to call a function if you did not want the return value? The code in the preceding two examples might compile, but it looks awfully silly.
However, there are cases where it makes sense to ignore the return value and call a function as if it were a procedure. The way we have been using MsgBox is a good example of this. MsgBox can be used as either a procedure or a function, depending on why you need it. MsgBox has dual purpose. It can just display a message for you, which is how we've been using it, or you can use it as a function to find out which button a user clicked on the dialog box. Here is a script that illustrates the two ways of using MsgBox ( MSGBOX_DUAL.VBS ).
Option Explicit Dim lngResponse Dim strUserName lngResponse = MsgBox("Would you like a greeting?", vbYesNo) If lngResponse = vbYes Then strUserName = GetUserName GreetUser strUserName End If Sub GreetUser(strUserName) MsgBox "Hello, " & strUserName & _ ". Welcome to our script." End Sub Function GetUserName GetUserName = InputBox("Please enter your name.") End Function
In this line of code we are using MsgBox as a function.
lngResponse = MsgBox("Would you like a greeting?", vbYesNo)
has some optional arguments, one of which is the second argument that allows you to specify if you want the dialog box to offer more
If the user clicks the Yes button, the MsgBox function will return a certain value (defined as vbYes in this example). If the user clicked Yes , then the familiar GreetUser procedure will eventually be called, in which you can see how we can call MsgBox as a procedure instead of as a function.
vbYesNo and vbYes from the example are built-in VBScript 'named constants,' which are like variables with fixed, unchangeable values. (We will cover named constants later in this chapter.)
As we just saw with the MsgBox function in the previous section, procedures and functions can have optional arguments. If an argument is optional, then you don't have to pass anything to it. Generally, an optional argument will have a default value if you don't pass anything. Optional arguments will always appear at the end of the argument list; mandatory arguments must come first, followed by any optional arguments.
However, the procedures and functions you write yourself using VBScript cannot have optional arguments. The built-in VBScript procedures you call (such as
) can have optional arguments, but your own VBScript procedures cannot. If you need to, you can get around this by defining mandatory arguments and interpreting a certain value (such as Null) to
A procedure or function will exit naturally when the last line of code inside of it is done executing. However, sometimes you want to terminate a procedure sooner than that. In this case, you can use either of the statements Exit Sub (for procedures) or Exit Function (for functions). The code will stop executing wherever the Exit statement appears and the flow of the code will return to the caller.
With the simple functions we have been using as examples, there has not been an obvious place where you would want to use Exit Sub or Exit Function . Usually these statements are used inside of more complex code in situations where you have reached a logical stopping point or dead end in the logic. That said, many programmers discourage the use of these statements in favor of using a code structure that does not require them. Take this code, for example ( EXIT_SUB.VBS ).
Option Explicit GreetUser InputBox("Please enter your name.") Sub GreetUser(strUserName) If IsNumeric(strUserName) or IsDate(strUserName) Then MsgBox "That is not a legal name." Exit Sub End If MsgBox "Hello, "& strUserName & _ ". Welcome to our script." End Sub
procedure. We have added some logic that tests to make sure the name is not a number or date, and if it is, we
Option Explicit GreetUser InputBox("Please enter your name.") Sub GreetUser(strUserName) If IsNumeric(strUserName) or IsDate(strUserName) Then MsgBox "That is not a legal name." Else MsgBox "Hello, "& strUserName & _ ". Welcome to our script." End If End Sub
Notice that instead of using
we have used an
clause. The principle at work here is to design the procedure to have only one exit point, that being the implicit exit point at the end of the procedure. By definition, procedure or function with an
statement has more than one exit point, which some programmers would argue is poor design. The logic behind this principle is that procedures with multiple exit points are more prone to