In the sections that follow, I'll introduce the basic features of VBScript. Later in the chapter, I'll introduce more advanced features (including some of those provided in the new version 5 scripting engines).
VBScript is a subset of Microsoft Visual Basic for Applications (VBA), the language provided with Microsoft Office and Visual Basic. Microsoft used several language constructs from VBA to define the VBScript syntax. If you've programmed in Visual Basic or Office, VBScript programming shouldn't be difficult for you.
You must enter statements using the syntax rules defined for VBScript. The following lines contain valid VBScript statements:
Value1 = 10 Value1 = Value1 + 10 If Value1 > 100 Then Value1 = 100 Tax = 0.1 : Price = Net * Tax
You can enter several statements on one line if you separate them with a colon (:), as in the last line of the preceding code. However, you should use this syntax sparingly to keep your programs more readable.
VBScript statements and keywords are not case sensitive, as they are in JScript.
Very long statements make your scripts less readable. The following statement, which shows a message box, is longer than the current page width:
WScript.Echo "You have entered a wrong name in the text box on the previous form. Please reenter the value in the text box."
If a program contains many long lines, you waste time scrolling horizontally to edit the lines. A better approach is to append a blank and an underscore (_) at the end of a line and continue the statement on the next line, as shown here:
WScript.Echo "You have entered a wrong name in the text box " & _ "on the previous form. Please reenter the value in the " & _ "text box."
When the language engine detects a line that ends with an underscore, it assumes a continued line and treats the next line as part of the current statement.
The last line of a continued statement can't have an appended underscore. Also, you can't append comments to a line that contains an underscore. If you want to use a long string in continued lines, split the string into several substrings and terminate each substring with a double quote ("). Then you can insert an underscore to divide the statement into several lines. You can concatenate (join together) the substrings using the & operator or the + operator. I used this structure in the preceding statement.
As I mentioned in Chapter 1, if you want to tell VBScript not to interpret a line or a part of a statement, you can simply write the statement as a comment. In VBScript, you use a single quote (') or the REM statement to mark a comment. If the VBScript interpreter detects this character in a statement, it ignores the rest of the line. Both of the following lines contain comments:
' This is a whole line containing a comment. Value1 = Net * Factor ' Comment at line end
The second line has a comment after the statement. VBScript executes the statement and ignores the trailing comment.
A VBScript program can consist of comments and statements. The script files used in this book follow the structure of Listing 4-1. (This file and the other samples used in this chapter are in the \WSHDevGuide\Chapter04 folder on the companion CD.)
Listing 4-1 WSHDemo.vbs
'************************************************ ' File: WSHDemo.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using WSH to show a simple dialog box '************************************************ Option Explicit Dim Message ' Initialize variable. Message = "Hurray, it works!" WScript.Echo Message '*** End
As I mentioned in the previous chapters, it's good practice to add comments to your scripts. If you receive a script from another programmer, you'll definitely be grateful if the author noted the purpose of the script and other information in the program's header.
You can also use VBScript programs within HTML documents and execute them in Microsoft Internet Explorer. Although Internet Explorer and Microsoft Windows Script Host (WSH) use the same language engine, they don't expose the same objects (or more precisely, the same object model). For example, the event handling provided with Internet Explorer is useless in the WSH environment. Therefore, it's helpful to have information in the header about the language, its version, and the environment the script is designed for.
In VBScript, you can use constants and variables to store values. The following sections discuss how to define constants and variables.
You'll definitely use constants in your scripts. You can use them directly in VBScript statements. The following code defines a constant:
result = price + 100.0
The formula takes the value of the variable price, adds 100.0, and assigns the result to a variable, result. The value 100.0 is a constant. This technique is common, and it's easy to read. However, it has a big disadvantage. Let's say that your script contains several hundred lines, and the value 100.0 appears on many lines. What happens if you have to change 100.0 to 110.0? You have to edit every line in the source code that contains the constant. You can use the editor's search-and-replace function, but this can be time consuming and can lead to errors because the value 100.0 might be used for different purposes.
To avoid this problem, you can set a constant or an identifier in the VBScript program header. This constant is a meaningful name that takes the place of a number or a string and never changes. You must declare a constant explicitly. In the following line of code, the keyword Const invokes the constant declaration. It is followed by the constant's name and its value:
Const profit = 100.0
You can use a named constant in any other statement in the VBScript program, as in this example:
Price = NetPrice * Amount + profit
The advantage of named constants is that you can change the value of a constant within the declaration instead of changing the value on lines spread throughout the source code. You can also assign a meaningful name to a value, which simplifies code maintenance.
At first glance, it might seem that you can use a named constant like you use a variable. But the constant's value is protected from being changed by executing code. Therefore, you can use its name only on the right side of an assignment statement.
You can also define several constants on a single line:
Const VAT = 0.16, Profit = 10
Unlike Visual Basic and VBA, VBScript supports only the Variant data type. Named constants are declared as public by default. This means that a constant declared in the script's header is available within the entire script. If you declare a constant within a procedure, the scope is valid only within the procedure. You can overwrite this default scope using the Public and Private keywords (as described later in this chapter).
Numeric constants are usually written in base 10 (decimal). However, you can also use constants in the hexadecimal system using the format &Hxxxx, where xxxx stands for a hexadecimal number. For example, the value &H0C corresponds to the decimal number 12. Literal constants containing text must be enclosed in double quotes (as in "Hello, world"). Time and date constants must be enclosed in number signs (as in #6/1/2000#).
VBScript contains several predefined constants (also known as built-in or intrinsic constants) such as vbOKOnly. Take a look at this statement:
MsgBox "Hello", 0 + 64, "Test"
If you use named constants, the statement is much less cryptic:
MsgBox "Hello", vbOKOnly + vbInformation, "Test"
The only catch is that you must know the exact name of the intrinsic constant.
All intrinsic constants are listed in the VBScript Language Reference.
Variables are placeholders that refer to a location in memory where a program can store values. Unlike constants, variables can change their value during program operation. You can use a variable directly in a program, as shown here:
Price = 45 ' Set the price. Discount = 17
The first time a variable appears in the program, VBScript creates the variable in memory and assigns an initial value. VBScript supports only the Variant data type for a variable. This means that you can store different values, such as numbers and text, in a variable.
As I just mentioned, VBScript supports only the Variant data type, a special data type that can contain different kinds of information—strings, date values, logical values (True or False), integers, floating-point numbers, and so on. The format of a value stored in a Variant depends on the value. If you assign a number to a variable, it is stored in numeric format. A date value is stored in date format, text is stored in string format, and so on. The format of a value stored in a Variant is called its subtype.
Most operators in VBScript require values of a specific subtype and return a value of a specific subtype. For example, if you add the content of two variables that have numeric values, the result is also numeric. The following statement stores a numeric result in the variable Sum1:
Sum1 = Price + 15.0
Using the + operator, you can also concatenate two strings:
Message = "Thing1 and " + "Thing2"
But the following statement causes a problem:
Result = "Value " + Sum1
The first part of the expression on the right side of the assignment is a string, and the variable Sum1 contains a numeric value. The VBScript interpreter can't add a string and a number, so it generates an error message (as shown in Figure 4-1).
Figure 4-1 An error message resulting from a type mismatch
In this situation, you can convert the numeric subtype by using the following statement:
Result = "Value " + CStr(Sum1)
The VBScript function CStr converts the numeric value in the variable Sum1 to a Variant data type with the string format. This result can be concatenated with the second string, "Value ", and the result can be assigned to the variable Result.
Concatenating strings using the + operator isn't good programming practice (although I sometimes use it). The + operator adds two operands—when the operands are strings, the result is a concatenation operation. A better approach is to use the & operator for string concatenation (as in "Hello, " & "world"). When using the & operator to combine values that have different data formats, VBScript does the type conversion automatically, without using CStr.
You can also treat numbers as strings if they're defined as constants. You must enclose the constants in quotation marks. Look at the following statement:
Text = "15" + "30"
This statement doesn't produce the value 45. Instead, the variable Text contains the value "1530" after the statement is executed! According to my explanation given above, it is much more readable if you write the statement as
Text = "15" & "30"
This statement makes it clear what you intend (a string concatenation). You can use conversion functions to convert data from one subtype to another Variant subtype.
Unlike Visual Basic or VBA, VBScript doesn't allow you to predefine a subtype for a variable. VBScript assigns the subtypes automatically. But you can use conversion functions such as Asc, CBool, CByte, CCur, CDate, CDbl, Chr, CInt, CLng, CSng, CStr, Hex, and Oct to convert the data types. You can also use the VarType function to query the subtype. For a list of all Variant subtypes, see the VBScript Tutorial.
By default, VBScript allows implicit variable declarations, whereby a variable is created and used without first declaring it with a Dim, Private, Public, or ReDim statement. If you allow implicit variable declarations in your scripts, however, you run the risk of creating subtle programming errors. If you mistype a variable name, for example, the VBScript interpreter assumes that you're using an implicit declaration and creates a new variable. Let's say that you type Pris instead of Price in your source code, as in the following code snippet:
VAT = 16.0 Price = 0 Net = 115.00 Pris = Net * (1.0 + VAT/100) MsgBox Price, vbOKOnly, "Price"
This sequence won't work the way you intended. The typo in the assignment statement causes the calculated price to be stored in the (new) variable Pris instead of the variable Price. The message box will show the result 0 instead of 133.4.
To detect mistyped variable names, you can use the Option Explicit statement in the first line of your program. The Option Explicit statement tells the interpreter to allow only variables that are declared explicitly within your script using a Dim, Private, Public, or ReDim statement. If you forget to declare your variables explicitly, WSH reports each implicitly declared variable in an error dialog box. This WSH feature also uncovers mistyped variable names. Listing 4-2 contains such a mistyped variable name.
Listing 4-2 ErrorTest2.vbs
'************************************************** ' File: ErrorTest2.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using an undeclared (mistyped) variable to ' demonstrate the Option Explicit statement '************************************************** Option Explicit ' Declare variables. Dim Message Dim Title ' Initialize variables. Message = "Hello, world" Titel = "WSH sample " ' This name isn't declared!! ' Show a message. MsgBox Message, vbInformation + vbOKOnly, Title '*** End
The script in Listing 4-2 contains a mistyped variable, Titel. If the interpreter reaches the line with the string assignment to the variable Titel, an error message appears (as shown in Figure 4-2).
Figure 4-2 An error message indicating an undefined variable
If you use the On Error Resume Next statement within a script, undeclared variable names are no longer reported, even if the script contains an Option Explicit statement.
You can use the keyword Dim to explicitly define a variable at the procedure, function, or script level or to define an array variable. If you use the Option Explicit statement, you must declare all variables by using the Dim keyword (in the script header or in a procedure or function), as shown here:
Dim text Dim x Dim Price, Vat
When you declare a variable, its value is automatically initialized. Numeric variables receive the value 0, and strings are set to an empty string ("").
In addition to the Dim statement, VBScript has two other keywords that allow you to declare variables at the script level: Public and Private. You use Public to extend and Private to limit the scope of script-level variables.
Public Test Private Price, Vat
The Private keyword restricts the scope of a declared variable to the script. If you use the Public keyword, the variable is visible to all scripts and procedures within the current file.
In a .vbs file, Private and Public have exactly the same effect as the Dim statement, so you might wonder why you'd ever use them. The answer is that Private and Public do matter in .wsf and .htm files. VBScript was originally developed for HTML documents, which can contain several scripts within <script> tags in the HTML code. Using the keyword Public, you can declare a variable that is also valid outside the local script (in other scripts in the same document).
The Public and Private keywords are illegal inside procedures and functions and cause a syntax error. However, you can use Public and Private as part of a procedure or function declaration to set the scope of the procedure or function explicitly. (For more information on procedure and function declarations, see the "Functions and Procedures" section later in this chapter.)
VBScript supports arrays, which you must declare and access in the following order:
Dim value(10) value(0) = 11
The first line of code defines an array with 11 items. (The index always starts with 0.) You can access the first array element using value(0). The second line of code assigns the value 11 to the first array element.
The Dim statement also allows you to declare multidimensional arrays. The following statement declares a two-dimensional array:
Dim value(10, 10)
Value(0, 0) is the first element in row 0 and column 0. VBScript allows up to 60 dimensions for arrays. The lower bound for arrays is always set to 0; you can set only the upper bound of an array in the Dim declaration.
You must use the Dim statement with empty parentheses—as in Dim value()—to define dynamic arrays. You can redefine the dimension of a dynamic array using the ReDim statement.
A variable name can have up to 255 characters. You can choose any variable name as long as it follows these rules:
The Set statement has a special meaning in VBScript. To access an object, you must assign a reference to it using Set, as in the following statement:
Set objAdr = WScript.Arguments
This statement assigns an object reference to the variable objAdr, which points to the Arguments property of the WScript object. The variable uses the Variant data type, but the subtype is set to Object. After assigning an object variable, you can use the reference in a statement, as shown here:
This statement shows the first argument passed to the script in a message box.
Generally, when you use Set to assign an object to a variable, no copy of the object is created for that variable. Instead, a reference to the object is created. More than one object variable can refer to the same object. Because these variables are references to (rather than copies of) the object, any change in the object is reflected in all variables that refer to it.
The names of objects, methods, and properties in a statement are separated by a dot—as in objAdr.Item, where objAdr is the object reference and Item is a property. (See Chapter 3 for more information about programming with objects.)
VBScript supports several types of operators: arithmetic operators, logical operators, comparison operators, and operators for concatenation.
Table 4-1 describes the arithmetic operators available in VBScript.
Table 4-1 Arithmetic Operators
|^||Exponentiation||x = y^Exponent|
|+||Addition||x = a + b|
|-||Subtraction or negative sign||x = -10 or x = a - 100|
|*||Multiplication||x = b * 30|
|/||Division||x = a / b|
|\||Integer-Division||x = a \ b|
|Mod||Modulo||x = a Mod b|
If you use the + operator for concatenation and one of the operands contains the value Null, the result is also Null. For more information, see the VBScript Language Reference.
VBScript supports a few logical operators to evaluate expressions. Table 4-2 describes them.
Table 4-2 Logical Operators
|Not||Negation||x = Not y|
|And||And||x = a And b|
|Or||Or||x = a Or b|
|Xor||Exclusive Or||x = a Xor b|
|Eqv||Equivalence||x = a Eqv b|
|Imp||Implication||x = a Imp b|
Logical operators are often used in branches. The following statement tests two conditions:
If a > 100 And a < 1000 Then
Both conditions (a > 100 and a < 1000) deliver a logical value of True or False, and the values are compared using And. If both conditions are True, the If branch is executed.
You can use the operators Not, And, Or, and Xor for logical expressions and also for bit operations on byte and integer values. Table 4-3 is the truth table for the logical Not operator.
Table 4-3 The Logical Not Operator
|Expression A||Not A|
As you can see from Table 4-3, the logical Not operator returns the opposite of a True or False expression. The bitwise Not operator uses the truth table in Table 4-4.
Table 4-4 The Bitwise Not Operator
The bitwise Not operator reads the bit and inverts its value. A 0 is converted to a 1, and vice versa. Such operations are best demonstrated in the binary or hexadecimal system. A decimal number 3 can be written in the binary system as 0011 (if you're using four digits for the representation). Using the bitwise Not operator yields a result of 1100. This binary number is equivalent to the hexadecimal value 0CH or decimal 12.
The logical And operator compares two expressions and returns a value of True only if both expressions are True. Table 4-5 summarizes the effect of the logical And operator.
Table 4-5 The Logical And Operator
|Expression A||Expression B||A And B|
The bitwise And operator compares two bits. If both bits are 1, the result is also 1, as shown in Table 4-6. The input values are in the Bit columns and the result is in the And column.
Table 4-6 The Bitwise And Operator
The following statement uses the bitwise And operator:
MsgBox (3 And 7)
The result, 3, is shown in a message box. The statement in parentheses does a bitwise operation using And. (For novices: a decimal 3 can be represented as the binary value 0011, and decimal 7 is equivalent to the binary value 0111, so the result of the And operator is 0011, which is equivalent to decimal 3.)
The logical Or operator compares two expressions and returns True if either expression is True. Table 4-7 enumerates the possible inputs and the results of combining them with the logical Or operator.
Table 4-7 The Logical Or Operator
|Expression A||Expression B||A Or B|
The bitwise Or operator compares two bits. If one bit is 1, the result is also 1. Table 4-8 shows the possible results of the bitwise Or operator.
Table 4-8 The Bitwise Or Operator
The result of the following bitwise Or operation appears in a message box:
MsgBox (3 Or 7)
The decimal value 3 is equivalent to 0011 decimal, and 7 decimal is 0111 binary. The result of the Or operator is 0111 binary, which is 7 decimal.
The logical Xor (exclusive Or) operator compares two expressions and returns True if the expressions are different but returns False if both expressions are the same. The results of the logical Xor operator are shown in Table 4-9.
Table 4-9 The Logical Xor Operator
|Expression A||Expression B||A Xor B|
The bitwise Xor operator yields a result of 1 if the two input values are different, as shown in Table 4-10.
Table 4-10 The Bitwise Xor Operator
You can use comparison operators to compare expressions (which can contain numbers, strings, and so on). Table 4-11 describes the comparison operators in VBScript.
Table 4-11 Comparison Operators
|<||Less than||a < b|
|>||Greater than||a > b|
|=||Equal to||a = b|
|<=||Less than or equal to||a <= b|
|>=||Greater than or equal to||a >= b|
|<>||Not equal to||a a <> b|
Comparison operators are used in branches and loops, as shown here:
Do While a < 10 ... Loop If a > 100 Then ... End If
When you use comparison operators, keep in mind that VBScript recognizes only Variant variables. If the two subtypes are of different data types, VBScript converts the data types automatically. As a result of this conversion, values that are not equal might be interpreted as equal.
The VBScript parser uses implicit operator precedence to evaluate expressions that use more than one operator. For example, to evaluate the expression
1 + 2 * 3 + 4
the parser first evaluates 2 * 3 because multiplication has a higher precedence than addition. Here's the order of precedence for arithmetic operators: exponentiation has the highest precedence, followed by negation, multiplication/division, integer division, modulo, addition/subtraction, and then concatenation. Comparison operators have equal precedence and are evaluated in left-to-right order. For logical operators, the Not operator has the highest precedence, followed by And, Or, Xor, Eqv, and Imp. If an expression combines different categories of operators, the arithmetic operators are evaluated first, comparison operators second, and logical operators third.
Parentheses can be used to override operator precedence; any part of an expression contained within parentheses is evaluated first.
VBScript supports the following control structures for controlling loops and branches.
You can use If…Then to implement a branch using a compare operation. The following statement resets the variable a to 100 if its value is greater than 100:
If a > 100 Then a = 100
This sequence also compares the variable a with 100:
If a > 100 Then a = 100 b = 20 End If
If the value is greater than 100, the statements between If…Then and End If are executed. If the value is less than or equal to 100, the program continues with the statement following the End If line.
You can use the If…Then…Else statement to create two branches. The following sequence tests the variable a:
If a > 100 Then a = 100 b = 20 Else a = a + 10 b = a \ 10 End If
If the value is greater than 100, the statements between If…Then and Else are executed. Otherwise, the statements between Else and End If are used.
If…Then…ElseIf allows nesting of several If blocks. The following sequence tests the variable a for different values:
If a = 1 Then b = 100 c = 20 ElseIf a = 2 Then b = 200 c = 40 ElseIf a = 3 Then b = 300 c = 60 End If
If a compare operation yields the result True, the statements between the compare operation and the next ElseIf or End If keyword are executed.
You can use the Select Case keyword to test a variable for several conditions. Depending on the variable's value, you can execute one of several blocks of code. The following sequence tests the variable a:
Select Case a Case 1 b = 100 c = 20 Case 2 b = 200 c = 40 Case 3 b = 300 c = 60 Case Else b = 0 c = 0 a = 1 End Select
The Case statements contain the value to be tested against the variable. If a condition is True, the statements within the Case block are executed. If none of the Case conditions is True, the (optional) Case Else block is used.
Loops are used to repeat a block of statements. The loop constructs available in VBScript are described as follows.
A Do While sequence creates a loop. The header of this loop contains a condition that must be True to execute the statements within the loop. If the condition is False, the interpreter continues execution with the first statement following the Loop keyword. The following code sequence uses a Do While loop:
a = 1 Do While a < 10 a = a + 1 Loop
The condition a < 10 is tested before the loop is entered. If the condition is True, the interpreter executes the statements until the Loop keyword is reached. The condition in the loop's header is tested repeatedly until the condition becomes False. Then the interpreter continues with the statement following the Loop keyword. Thus, the condition in the loop's header must yield the value True or False to execute or terminate the loop.
The Do Until statement creates a loop that is tested at the entrance of the loop. If the condition is False, the loop is executed. The loop terminates once the condition becomes True. The following sequence uses the Do Until statement:
a = 1 Do Until a > 10 a = a + 1 Loop
Within the loop, the condition a > 10 is tested. If the condition isn't True, the statements within the loop are executed. Once the condition within the loop's header becomes True, the program continues with the statement following the Loop keyword.
You can use the Do...Loop While statement to create a loop containing the condition test at the end of the loop. If the condition at the end of the loop is True, the loop is executed repeatedly. The loop terminates if the condition becomes False. The following code uses Do...Loop While:
a = 1 Do a = a + 1 Loop While a < 10
This loop tests the condition a < 10 at the end of the block. If the condition is True, the statements between Do and Loop While are processed again. If the condition becomes False, the statement following the loop is executed.
You can use Do…Loop Until to create a loop that is tested at the end of the block. If the condition is False, the loop statements are processed again. If the condition becomes True, the loop terminates and the statement following the loop is executed, as shown here:
a = 1 Do a = a + 1 Loop Until a > 10
This code tests the condition a > 10 at the loop's end. The loop is processed until the condition becomes True.
You can use the Exit Do statement within Do loops to terminate the loop. If the interpreter encounters this statement, the loop is terminated and execution resumes with the statement following the loop.
You can use a For loop to process a predefined number of steps. All statements within the For…Next block are processed during each step. The following sequence uses a For statement in VBScript:
For i = 1 To 10 a = a + 1 Next
The loop is repeated 10 times. The value i contains the loop index. The step width of a For loop determines how much the loop index is incremented each time through the loop and is set to 1 by default. However, you can use the For i = start To end Step x construction to set the step width to the value x.
Another important construction is the For Each sequence, which you can use to create a loop to process all elements in a collection or an array. The loop is repeated for each item in the collection or array. The following lines use such a loop:
For Each x In Worksheets ... Next
You can use the Exit For statement to terminate a For loop. If the interpreter encounters this statement, the execution continues with the line following the loop.
You can use a While…Wend loop to process a code sequence several times. The loop terminates if the condition in the line containing the While statement becomes False. The following code uses this kind of loop:
Dim value value = 1 While value < 10 value = value + 1 Wend
The loop is repeated until value becomes 10.
While…Wend pretty much has been superseded by Do…Loop, which is a much more structured and flexible looping construct.
In VBScript, you can use built-in functions and procedures or define your own. The following sections explain the basics of creating and calling user-defined functions and procedures in VBScript.
You use a function when only one result (which can be a variable or an array) is returned to the calling program. You declare a function using the following statements:
Function Name(Parameters) ... Name = result End Function
The return value must be assigned to the function name within the function body. In the preceding sequence, the Name = result statement is used. VBScript always uses a Variant data type for the return value. The first line defining a function must contain the keyword Function, followed by the function name (GetValue, for instance), followed by parentheses. Within the parentheses, you can declare parameters that are required for the function call. Listing 4-3 uses a function in VBScript.
Listing 4-3 Function.vbs
'************************************************ ' File: Function.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using a function '************************************************ Option Explicit Dim i, j j = 0 For i = 1 to 10 ' Loop 10 times. j = addx(i, j) ' Add values using function addx. Next WScript.Echo "Result: ", j Function addx(val1, val2) addx = val1 + val2 End Function '*** End
This sample uses the function addx with two parameters, val1 and val2, to add these two values. The result is returned as a function value in the following statement:
addx = val1 + val2
The function name addx is built into the function header. The result, val1 + val2, is assigned to this function name. The function block ends with the statement End Function, which terminates the function and returns control to the calling program.
VBScript also supports the optional Exit Function statement. If this statement is executed within a function, the function terminates and control is returned to the calling module.
You can use a user-defined function in the same way that you use a built-in VBScript function: insert the function name and the requested parameters (in parentheses) on the right side of an assignment statement. In Listing 4-3, the function is called using the statement
j = addx(i, j)
You can also use user-defined functions to extend VBScript. Let's say you need to calculate the sales price of several products, which will include a value-added tax (VAT). You can define a function named GetPrice using the following code:
Function GetPrice(Net, VAT) ' Get the price, including tax. GetPrice = Net * (1.0 + VAT/100.0) End Function
The VAT value can be passed (as a percentage value) to the function. Using this function in a script requires only the function name and the parameters, as shown here:
Net = 10.0 Vat = 16.0 Price = GetPrice(Net, Vat) Price1 = GetPrice(100.0, 16.0)
These statements show that you can use variables or constants as function parameters.
You can't define a function inside another function or procedure. The code of a function must be declared at the script level. Also, local variables declared in the function body are valid only during the function call.
VBScript provides a collection of built-in (intrinsic) functions, which you can use in the same way that you use user-defined functions. The following statement assigns the ANSI code of the character A to the variable i:
i = Asc("A")
The conversion is done using the intrinsic function Asc, which takes the character as a parameter.
For more information on user-defined functions and built-in functions, see the VBScript Language Reference.
You declare a procedure using this syntax:
Sub Name(Parameter) ... End Sub
Unlike a function, a procedure delivers no return value. To pass a variable to a procedure, you can use one of these approaches:
Listing 4-4 uses a procedure to calculate a price (including the VAT).
Listing 4-4 Procedure.vbs
'************************************************ ' File: Procedure.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using a procedure '************************************************ Option Explicit Dim Price, Net, Tax Tax = 16.0 Net = 100.0 GetPrice Net, Tax ' Calculate value. WScript.Echo "Result: ", Price Sub GetPrice(net1, tax1) Price = net1 * (1.0 + (tax1/100.0)) End Sub '*** End
The sample in Listing 4-4 uses several techniques to exchange information with a procedure. On the script level, I defined several global variables. The variable Price is global and can be accessed within the procedure. The code uses this global variable to return the result to the calling program. The procedure itself requires two parameters during the call. Notice the syntax of the procedure call. You must specify the procedure name followed by the parameters. The parameters are separated with commas.
The Call keyword isn't required in a procedure call. If you use it, however, you must enclose the parameters in parentheses. For example, the statement Call GetPrice(100.0, 0.16) is equivalent to GetPrice 100.0, 0.16.
In a function or procedure declaration, you can place the ByVal or ByRef keyword in front of a parameter to denote that the parameter is passed to the routine using call by value or call by reference, respectively. In call by value, a copy of the parameter (the value of a constant or variable) is passed to the routine. The routine can change the value of the copy without affecting the original constant or variable. In call by reference, the address of the parameter's value (the address of a constant or a variable) is passed to the routine. Passing a parameter by reference allows the called function or procedure to change the value of a parameter. If you don't specify either ByVal or ByRef for a parameter, VBScript defaults to ByRef.
The Procedure1.vbs sample in Listing 4-4 declares a variable Price at the script level to allow a procedure to return the result. Writing a procedure that returns values in global variables isn't good programming style, however, because such procedures can't be used without restrictions. You have to know the name of the global variable that is changed within the procedure. If you mistype the variable name, the script won't work. It's better to pass the values as parameters to the procedure and use call by reference to get the results back through parameters. The modified code in Listing 4-5 shows that you don't need to use global variables to return a result from a procedure.
Listing 4-5 Procedure1.vbs
'************************************************** ' File: Procedure1.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using a procedure '************************************************** Option Explicit Dim Price, Net, Tax Tax = 16.0 Net = 100.0 Call GetPrice(Price, Net, Tax) ' Calculate value. WScript.Echo "Result: ", Price Sub GetPrice(pris, net, tax) pris = net * (1.0 + (tax/100.0)) End Sub '*** End
Notice in Listing 4-5 that the new procedure call requires a third parameter, Price, which is used to return the result from the procedure. This parameter is declared as pris in the GetPrice procedure declaration and is ByRef by default. If the value of pris changes in the GetPrice procedure, this change is also reflected in the variable Price, so your program can use the result calculated in the procedure without using a global variable to exchange values. (Just for demonstration purposes, I used the Call statement in this sample to call the GetPrice procedure. The Call statement doesn't affect how the procedure works.)
In certain cases, a procedure can't change the values in the calling program. For example, consider a program that defines a variable named tax, which is set once to 16.0 and is used in several procedure calls. If a procedure changes this value accidentally, this action could be deadly because the calling program still needs the original value for further processing. The variables Net and Tax in Listing 4-5 must remain unchanged after the procedure call. To prevent modification of parameters within the procedure from changing variables in the calling program, you can declare that a parameter must be passed using call by value, as shown in Listing 4-6.
Listing 4-6 Procedure2.vbs
'************************************************** ' File: Procedure2.vbs (WSH sample in VBScript) ' Author: (c) G. Born ' ' Using the call by value feature '************************************************** Option Explicit Dim Price, Net, VAT VAT = 16.0 Net = 100.0 Call GetPrice(Price, Net, VAT) ' Calculate value. WScript.Echo "Result: ", Price, " VAT: ", VAT Sub GetPrice(ByRef pris, ByVal net, ByVal tax) pris = net * (1.0 + (tax/100.0)) tax = 17.0 End Sub '*** End
The procedure declaration indicates whether each parameter should be passed ByVal or ByRef. Pris is passed by reference (because we must return the result to the calling module), and net and tax are passed by value. If the parameter net or tax is changed in the procedure, the change has no effect on the value of Net or VAT in the script.