Procedures
In this chapter, you will see how VBScript procedures can be used to improve the overall organization and manageability of your scripts. You will learn about the two types of procedures supported by VBScript, subroutines and functions. This chapter will cover how to use procedures to control variable scope by defining local and global variables. You will also learn how to create event handlers that react to browser events and will examine the types of browser events to which VBScript can react. Finally, you will examine VBScript's complete collection of built-in functions.
Organizing VBScript into Procedures
VBScript procedures provide the basic building blocks of VBScript organization. Procedures allow you to create modular scripts that organize statements into logical groups that can be executed as a unit. VBScript supports two different types of procedures:
- Function. A type of procedure that can return a result back to its calling statement
- Subroutine. A type of procedure that does not return a result back to its calling statement
Procedures have two main benefits: First, they provide a means of organizing VBScripts into a more manageable format. Second, procedures allow you to create reusable code and reduce the overall size of scripts.
Enhanced Script Maintenance
Procedures allow you to create scripts that are easier to maintain by allowing you to group related statements together and to execute them as a unit. Therefore, as a general rule, you should use procedures as the primary organization construct for your VBScripts. By developing modular code using VBScript, you make your scripts easier to read and maintain. For example, by grouping related statements together in a procedure, you make them easier to find. You also make the script easier to update, allowing individual modules or procedures to be updated without having to make substantial changes to other parts of the script.
By making scripts easier to manage, procedures allow you to add more complexity without necessarily making them more difficult for you to work with or maintain. As suggested in Chapter 2, "Errors, Constants, and Variables," when developing scripts that will be run using the WSH, consider developing a VBScript template similar to that in the following example.
'************************************************************************* 'Script Name: ScriptName.vbs 'Author: Author Name 'Created: mm/dd/yyyy 'Description: Place a brief description of the script here '************************************************************************* 'Initialization Section 'Main Processing Section 'Procedure Section
Using this template, you would place all subroutines and functions in the Procedure section. This provides a consistent organization to your scripts by providing a predictable location for storing and finding procedures. The important thing is to group your procedures together where you can easily find them in your VBScripts. Most VBScript programmers choose to store their subroutines and procedures at the end of their scripts.
When developing VBScripts that are embedded inside HTML pages, most programmers generally locate their subroutines and functions in a VBScript placed in the HEAD section. This helps to ensure that all procedures have been initialized before being called upon by VBScripts or event handlers located in the HTML page's BODY section.
Reusable Code
Functions and subroutines help make for smaller scripts by allowing the creation of reusable modules of code that can be called upon as many times as necessary from any location within a script. Therefore, functions and subroutines should be used in any situation where a particular task needs to performed more than once within a script.
Procedures also make script maintenance easier because you only have to modify the code located in one procedure instead of making the same change over and over again to code that would otherwise be duplicated throughout a script.
Subroutines vs Functions
Subroutines and functions perform nearly identical roles within VBScripts. Both provide a means for grouping and executing collections of related statements. Both provide a means of limiting variable scope, which is discussed later in this chapter. They even share a similar syntax. Where they differ is in their ability to return data back to the statement that calls them. Functions provide this capability, whereas subroutines cannot return a result back to their calling statement.
Subroutines
Subroutines are used to execute a collection of statements without returning a result to a calling statement. Once executed, a subroutine returns processing control back to the statement that follows its calling statement.
Subroutines are created using the VBScript Sub statement. The Sub statement defines the name of the subroutine and any arguments that it expects to receive. The syntax for the Sub statement is shown below.
[Public | Private] Sub name [(arglist)] statements End Sub
Public and Private are optional keywords. The Public keyword specifies that the subroutine can be called upon by other procedures located within the script. The Private keyword specifies that the subroutine cannot be called upon by other procedures within the script. Name is the name assigned to the subroutine and must be unique within the script. Arglist is a list of comma delineated arguments that can be passed to the subroutine when it is called.
To call a subroutine, you type its name in the following format:
SubroutineName()
The closing parentheses characters () are required. You can call a subroutine and pass it arguments by specifying the arguments, separated by commas, within the parentheses, as demonstrated below.
SubroutineName(arg1, arg2, arg3, ... argn)
For example, the following VBScript statement defines a subroutine called AboutRoutine().
Sub AboutRoutine() MsgBox "UserAcctMgr.vbs" & vbCrLf & vbCrLf & _ "Copyright Jerry Ford 2003" & vbCrLf & vbCrLf & _ "For more information about UserAcctMgr.vbs please contact " & _ "jlf04@yahoo.com", ,"About Sample Script" End Sub
This subroutine might be included as part of a larger script to provide information about the script. When called, AboutRoutine() uses the MsgBox() function to display information about the script. This subroutine has not been designed to accept any arguments as input and can be called from anywhere in the script using the following statement.
AboutRoutine()
When executed, this subroutine displays the pop-up dialog box shown in Figure 4.1.
Figure 4.1: Using a subroutine to display information about a script
The following example demonstrates how to define a subroutine that accepts and processes one argument when called upon to execute.
Sub DisplayMsg(strMsgText) MsgBox strMsgText, , "VBScript Subroutine Demo" End Sub
This subroutine could be added to any VBScript to provide a generic message display procedure. It accepts a single argument, which in the case of this example would be a text string passed to it by its calling statement. For example, the following statement could be used to execute the DisplayMsg() subroutine, which results in displaying the pop-up dialog box shown in Figure 4.2.
Figure 4.2: Viewing a message displayed using a generic message display subroutine
DisplayMsg("This message will be displayed by a message display subroutine.")
Functions
Functions are similar to subroutines, except that they also provide the ability to return a result to their calling statements. The syntax for functions is outlined below.
[Public | Private] Function name [(arglist)] statements End Function
Public and Private are optional keywords. The Public keyword specifies that the function can be called upon by other procedures located within the script. The Private keyword specifies that the function cannot be called upon by other procedures within the script. Name is the name assigned to the function and must be unique within the script. Arglist is a list of comma delimitated arguments that can be passed to the function when it is called.
For example, the following function represents a rewrite of a previous subroutine that displays information about a script in a pop-up dialog box.
Function AboutRoutine() MsgBox "UserAcctMgr.vbs" & vbCrLf & vbCrLf & _ "Copyright Jerry Ford 2003" & vbCrLf & vbCrLf & _ "For more information about UserAcctMgr.vbs please contact " & _ "jlf04@yahoo.com", ,"About Sample Script" End Function
This function can be called using the following statement from anywhere within the script that defines it.
AboutRoutine()
When used in this manner, there is no advantage to using a function over a subroutine. The advantage of using a function in place of a subroutine is the function's ability to return a result to its calling statement. In order to return a result back to its calling statement, a function must define a variable with the same exact name as the function and then assign the result that is to be returned to that variable. When the function stops executing, the value is then returned to the calling statement. For example, the following function might be used to collect the name of a file from the user.
Function GetFileName() GetFileName = InputBox("Please type the name of the file you wish to open.") End Function
The name of the function is GetFileName(). It uses the VBScript InputBox() function to collect the name of a file from the user and assigns the file name typed by user to a variable named GetFileName. Note that the name of the variable is exactly the same as the name of the function (less the parentheses). To execute this procedure, the calling statement can reference it, as shown below.
strFileName = GetFileName()
In this example, the name of the file that is returned by the function is assigned to a variable name strFileName. Another way to call the function would be to include a reference to it within a VBScript statement, as shown below.
MsgBox "Click on OK to delete " & GetFileName()
In this example, the MsgBox() function includes a reference to the GetFile-Name() function and substitutes the results returned by that function into the message that it has been set up to display.
Functions can also accept arguments passed to them at run time, as demonstrated below.
Function DisplayMsg(strMsgText) MsgBox strMsgText, , "VBScript Subroutine Demo" End Function
Controlling Variable Scope
Procedures provide VBScript with the ability to localize or isolate variables. Any variable defined outside of a procedure is global in scope, meaning that it can be referenced from any location within the script. A variable with a local scope, on the other hand, is one that is defined within a procedure and can be accessed only from within that procedure. Local variables exist only as long as the procedure that defined them is executing.
By localizing variable values, you eliminate the possibility of accidentally modifying a variable outside of the procedure where it was created. As a programming technique, it is generally preferable to localize variables as much as possible. The following example demonstrates the differences between local and global variables.
'************************************************************************* 'Script Name: Script 4.1.vbs 'Author: Jerry Ford 'Created: 01/04/2003 'Description: This script demonstrates global and local variable scopes '************************************************************************* 'Initialization Section Option Explicit Dim X, Y 'Main Processing Section X = 10 GetNewNumber() MsgBox "X = " & X & " Y = " & Y 'Procedure Section Function GetNewNumber() Dim Y Y = 20 End Function
In this script, two variables are defined, X and Y. The X variable and its value are both defined in the script's Main Processing Section and are global in scope. Next, the script executes the GetNewNumber() function, which defines the Y variable and sets its value. Once the GetNewNumber() function is finished, processing control returns to the Main Processing Section, which then uses the VBScript MsgBox() function to try and display the values assigned to X and Y. However, only the value of X can be displayed because the Y variable no longer exists.
Figure 4.3 shows the output produced when this script is executed by the WSH.
Figure 4.3: A demonstration of variable scope within and outside of VBScript procedures
Browser Event Handling
Within the context of client-side Web page development, VBScript procedures have a special role in building event handlers that respond to browser events. This adds interactivity to Web pages and allows front-end processing to be performed on the client computer. An event is an occurrence of an action within a browser. For example, a mouse click on an image, button, or link represents a click event. Other examples of events include double-clicking on Web page objects, typing text into form elements, clicking on form buttons, and moving the pointer over and off of objects. Browser events also occur when Web pages load or unload.
To react to an event, you must add event handlers to your scripts. An event handler is a trap that recognizes when an event occurs and executes one or more VBScript statements. For example, if a visitor clicks on a form's submit button, the click event associated with that button can be used to trigger the execution of an event handler that performs form validation.
By defining functions and subroutines and storing them in the head section of an HTML page, you can create a library of event handlers that can be associated with any object on a Web page.
Examining Events and Event Handlers
Table 4.1 provides a list of browser events for which you can define event handlers. Table 4.1 also provides the name of the event handler associated with each event and a description of the event and event handler. As you can see, event handlers are named by adding on to the beginning of the event name with which it is associated.
Property |
Event Handler |
Description |
---|---|---|
Abort |
onAbort |
Executes when the visitor aborts an image while it is loading |
Blur |
onBlur |
Executes when the currently selected object loses focus |
Change |
onChange |
Executes when the visitor changes an object |
Click |
onClick |
Executes when the visitor clicks an object |
DblClick |
onDblClick |
Executes when the visitor double-clicks an object |
DragDrop |
onDragDrop |
Executes when the visitor drags and drops an object onto a frame or window |
Error |
onError |
Executes when an error occurs on the HTML page |
Focus |
onFocus |
Executes when a visitor selects an object |
KeyDown |
onKeyDown |
Executes when a visitor presses down on a key |
KeyPress |
onKeyPress |
Executes when a visitor presses and releases a key |
KeyUp |
onKeyUp |
Executes when a visitor releases a key |
Load |
onLoad |
Executes when an HTML page or image finishes loading |
MouseDown |
onMouseDown |
Executes when a visitor presses a mouse button |
MouseMove |
onMouseMove |
Executes when a visitor moves the pointer |
MouseOut |
onMouseOut |
Executes when a visitor moves the pointer off of an object |
MouseOver |
onMouseOver |
Executes when a visitor moves the pointer over an object |
MouseUp |
onMouseUp |
Executes when a visitor releases a mouse button |
MouseWheel |
onMouseWheel |
Executes when a mouse wheel is rotated |
Move |
onMove |
Executes when the visitor moves a frame or window |
Reset |
onReset |
Executes when a visitor clicks on a reset button |
Resize |
onResize |
Executes when the visitor resizes a frame or window |
Select |
onSelect |
Executes when a visitor selects the contents of a form select menu |
Submit |
onSubmit |
Executes when a visitor clicks on a submit button |
Unload |
onUnload |
Executes when a visitor closes the browser window or frame or loads a different URL |
Setting Up Event Handlers
Events are associated with specific objects. Likewise, event handlers are associated with specific events and objects. When an event occurs, its associated event handler, if one has been written, is automatically executed. There are three different ways in which to set up the execution of an event handler. The first option is to embed the event handler inside an HTML tag, as demonstrated below.
In the case of this example, the onLoad event is automatically triggered when the HTML page is loaded by the browser, displaying a pop-up message. While convenient for performing tasks that require minimal coding, this option is limited. Another option provided by VBScript is to set up event handlers, as demonstrated below.
The third and most commonly used option is to define event handlers that call procedures stored within VBScripts located within the HTML page's HEAD section, as demonstrated below.
Sub SubmitButton_onMouseOver window.status = "Click here to submit your request." End Sub
When used in conjunction with event handlers, procedure names are created by combining the name of an object button and the name of the appropriate event handler. For example, the previous subroutine is automatically triggered whenever the pointer is moved over a form button named SubmitButton on the HTML page. When executed, it displays a text message in the browser's status bar located at the bottom of the browser.
To further demonstrate the use of VBScript procedures as constructs for storing statements that are called by event handlers, look at two more examples. In the first example shown below, an HTML page has been set up that contains a VBScript in its HEAD section. This VBScript defines a single function called ShowGreetingMsg(). This function will execute when called by the onLoad event handler specified in the
tag example, as highlighted below.
Script 4.2 - onLoad event handler exampleonLoad=ShowGreetingMsg()> onLoad event handler example
Figure 4.4 shows the output produced when this HTML page is loaded by Internet Explorer.
Figure 4.4: A pop-up dialog box displayed by a function that has been called by a VBScript event handler
Another popular use of event handlers is in the creation of animated rollover effects, which change the appearance of a link, image, or object in some manner whenever the pointer is moved over or off of the object. Rollovers can be created using the onMouseOver and onMouseOut events, which are listed below.
- onMouseOver. Triggered whenever the pointer is moved over an object
- onMouseOut. Triggered whenever the pointer is moved off of an object
For example, the following script demonstrates how to set up an HTML page with two rollover links. One is for the Premier Press Web site and the other is for Microsoft's Web site.
Script 4.3 - A demo of how to creak a link rollover<a href="http://www.premierpressbooks.com" name="Premier">Premier</a>
<a href="http://www.microsoft.com" name="Microsoft">Microsoft</a>
In order to set up a rollover for each link, two functions must be set up as event handlers for each link. The first function defines the statements to be executed for the onMouseOut event handler and the second function defines the statements to be executed for the onMouseOver event handler. Notice that unlike the previous example in which the
tag explicitly called the function specified by the onLoad event handler, the functions in this example are automatically associated with links because of the manner in which their names were formulated.
When executed, these functions modify the color of the text used to display each link, depending on which event handler is being executed. Figure 4.5 shows the output produced when this HTML page is loaded by Internet Explorer. However, it is difficult to see how the rollover links work from an examination of Figure 4.5. To get a better understanding, create and run this script yourself.
Figure 4.5: Creating rollovers using event handlers
Built in Functions
In this chapter, you learned how to create your own custom functions. Using functions, you can create modular scripts and group related VBScript statements together in some logical manner. VBScript also provides a large collection of ready-to-use built-in functions that you can reference from your VBScripts. Using built-in VBScripts saves you the time and trouble required to reinvent a function to perform a task for which Microsoft has already provided a solution. This speeds up script development time while making for smaller scripts that are easier to manage. Table 4.2 provides a list of VBScript's built-in functions.
Function |
Description |
---|---|
Abs |
Returns a number's absolute value |
Array |
Returns an array based on the supplied argument list |
Asc |
Returns the ANSI code of the first letter in the supplied argument |
Atn |
Inverse trigonometric function that returns the arctangent of the argument |
CBool |
Converts an expression to a Boolean value and returns the result |
CByte |
Converts an expression to a variant subtype of Byte and returns the result |
CCur |
Converts an expression to a variant subtype of Currency and returns the result |
Cdate |
Converts an expression to a variant subtype of Date and returns the result |
CDbl |
Converts an expression to a variant subtype of Double and returns the result |
Chr |
Returns a character based on the supplied ANSI code |
Cint |
Converts an expression to a variant subtype of Integer and returns the result |
CLng |
Converts an expression to a variant subtype of Long and returns the result |
Cos |
Trigonometric function that returns the cosine of the argument |
CreateObject |
Creates an automation object and returns a reference to it |
CSng |
Converts an expression to a variant subtype of Single and returns the result |
Date |
Returns the current date |
DateAdd |
Adds an additional time interval to the current date and returns the result |
DateDiff |
Compares two dates and returns the number of intervals between them |
DatePart |
Returns a portion of the specified date |
DateSerial |
Returns a variant (subtype Date) based on the supplied year, month, and day |
DateValue |
Converts a string expression into a variant of type Date and returns the result |
Day |
Converts an expression representing a date into a number between 1 and 31 and returns the result |
Eval |
Returns the results of an evaluated expression |
Exp |
Returns the value of an argument raised to a power |
Filter |
Returns an array based on a filtered set of elements using supplied filter criteria |
FormatCurrency |
Returns an expression that has been formatted as a currency value |
FormatDateTime |
Returns an expression that has been formatted as a date or time value |
FormatNumber |
Returns an expression that has been formatted as a numeric value |
FormatPercent |
Returns an expression that has been formatted as a percentage (including the accompanying %) |
GetLocale |
Returns the locale ID |
GetObject |
Returns a reference for an automation object |
GetRef |
Returns a reference for a procedure |
Hex |
Returns a hexadecimal string that represents a number |
Hour |
Returns a whole number representing an hour in a day (0 to 23) |
InputBox |
Returns user input from a dialog box |
InStr |
Returns the starting location of the first occurrence of a substring within a string |
InStrRev |
Returns the ending location of the first occurrence of a substring within a string |
Int |
Returns the integer portion from the supplied number |
IsArray |
Returns a value of True or False depending on whether a variable is an array |
IsDate |
Returns a value of True or False depending on whether an expression is properly formatted for a data conversion |
IsEmpty |
Returns a value of True or False depending on whether a variable is initialized |
IsNull |
Returns a value of True or False depending on whether an expression is set to Null |
IsNumeric |
Returns a value of True or False depending on whether an expression evaluates to a number |
IsObject |
Returns a value of True or False depending on whether an expression has a valid reference for an automation object |
Join |
Returns a string that has been created by concatenating the contents of an array |
Lbound |
Returns the smallest possible subscript for the specified array dimension |
Lcase |
Returns a lowercase string |
Left |
Returns characters from the left side of a string |
Len |
Returns a number or string's character length |
LoadPicture |
Returns a picture object |
Log |
Returns the natural log of the specified argument |
LTrim |
Trims any leading blank spaces from a string and returns the result |
Mid |
Returns a number of characters from a string based on the supplied start and length arguments |
Minute |
Returns a number representing a minute within an hour in the range of 0 to 59 |
Month |
Returns a number representing a month within a year in the range of 1 to 12 |
MonthName |
Returns a string containing the name of the specified month |
MsgBox |
Returns a value specifying the button that users click on in a dialog box |
Now |
Returns the current date and time |
Oct |
Returns a string containing an octal number representation |
Replace |
Returns a string after replacing occurrences of one substring with another substring |
RGB |
Returns a number that represents an RGB color |
Right |
Returns characters from the right side of a string |
Rnd |
Returns a randomly generated number |
Round |
Returns a number after rounding it by a specified number of decimal positions |
RTrim |
Trims any trailing blank spaces from a string and returns the result |
ScriptEngine |
Returns a string identifying the current scripting language |
ScriptEngineBuildVersion |
Returns the scripting engine's build number |
ScriptEngineMajorVersion |
Returns the scripting engine's major version number |
ScriptEngineMinorVersion |
Returns the scripting engine's minor version number |
Second |
Returns a number representing a second within a minute in the range of 0 to 59 |
Sgn |
Returns the sign of the specified argument |
Sin |
Trigonometric function that returns the sine of the argument |
Space |
Returns a string consisting of a number of blank spaces |
Split |
Organizes a string into an array |
Sqr |
Returns a number's square root |
StrComp |
Returns a value that specifies the results of a string comparison |
String |
Returns a character string made up of a repeated sequence of characters |
Tan |
Trigonometric function that returns the tangent of the argument |
Time |
Returns a variant of subtype Date that has been set equal to the system's current time |
Timer |
Returns a value representing the number of seconds that have passed since midnight |
TimeSerial |
Returns a variant of subtype Date that has been set equal to containing the specified hour, minute, and second |
TimeValue |
Returns a variant of subtype Date that has been set using the specified time |
Trims |
Returns a string after removing any leading or trailing spaces |
TypeName |
Returns a string that specified the variant subtype information regarding the specified variable |
Ubound |
Returns the largest subscript for the specified array dimension |
Ucase |
Returns an uppercase string |
VarType |
Returns a string that specified the variant subtype information regarding the specified variable |
Weekday |
Returns a whole number in the form of 1 to 7, which represents a given day in a week |
WeekdayName |
Returns a string identifying a particular day in the week |
Year |
Returns a number specifying the year |
As a quick example of the benefit of using a built-in VBScript function to save time and simplify your VBScripts, look at the following custom function, which consists of five VBScript statements.
Function SqrRootSolver() intUserInput = InputBox ("Type a number", "Custom Square Root Function") X = 1 For Counter = 1 To 15 X = X - ((X^2 - intUserInput) / (2 * X)) Next MsgBox "The square root of " & intUserInput & " is " & X End Function
The five statements contained in the function ask the user to type a number and then use a For…Next loop to determine the square root of that number using some fairly sophisticated math. Figures 4.6 and 4.7 demonstrate the operation of this function.
Figure 4.6: Creating a custom function that determines the square root on an input number
Figure 4.7: Displaying the results of the square root calculation
Using VBScript's built-in Sqr() function, you can perform the same task with just two lines of code, as shown below.
UserInput = InputBox ("Type a number", "Square Root Calculator") MsgBox "The square root of " & UserInput & " is " & Sqr(UserInput)
Not only does using the built-in VBScript Sqr() function reduce the number of lines of code, but it also greatly reduces the complexity of the script, thus reducing the amount of time that it takes to develop it.
Summary
In this chapter, you learned how to enhance your VBScripts by organizing them into subroutines and functions. This included developing an understanding of the differences between these two types of procedures and how to leverage the power and convenience provided by VBScript's built-in collection of functions. In addition to making scripts easier to read and maintain, procedures provide a mechanism for limiting variable scope. You also learned how to call VBScript procedures using event handlers in order to develop VBScripts that can react dynamically to both user and browser activity.