All Categories :
ActiveX
Chapter 9
Making Your Program Flow
CONTENTS
To achieve more than the simplest "Hello World" task
in any programming language, you need to get into some real programming.
Just as trying to hold a conversation in French knowing only Bonjour
can be somewhat limiting, programming in VBScript can be difficult
knowing only Alert "Hello World".
To write scripts or programs that achieve a goal or provide a
solution, you first need to clearly define the task at hand. Because
VBScript is a logical and easy-to-use language, you will soon
see that the definition you have come up with for your problem
can be translated directly into a program.
But writing modern event-driven programs with VBScript is not
a straightforward, start-to-finish affair. Many times, you need
the program to make decisions and, based on that decision, maybe
jump to another part of the program. Or, perhaps, a calculation
is required to produce a value you use regularly in the program,
so your program jumps off in another direction to get that value
and then comes back to continue. This is where managing program
flow becomes vital.
In this chapter, you'll see the main constituents of program flow.
Program flow is dictated by calls to functions and procedures,
loops, and decisions-parts of the program that force execution
to be either diverted somewhere else in the program or held in
a certain part for a given period. Before this gets too cryptic,
let's move on and see this in action.
Subroutines are small, almost self-contained programs that are
called by another part of the program as they are required. The
term subroutine can be thought of as a general term for
the individually defined sections of the overall script.
Subroutines in VBScript include the following:
- Event handlers: The code within an event handler is executed
as the result of an action acting upon the object or control to
which the event is attached, as in the following example:
Sub myButton_OnClick
Alert "Hello World"
End Sub
- Functions: A function returns a value to the part of the script
that called it, as in the following example:
Function ConvertToInches(Feet)
ConvertToInches = Feet * 12
End Function
- Procedures: A procedure does not return a value. It is usually
a self-contained program that can be called from anywhere within
the overall script.
Sub myCustomSub()
Window.Status = "Hello World"
End Sub
Functions are separate subroutines that return a value-simple
as that. Declaring a function is very straightforward:
Function myFunctionName()
.....
End Function
You use the keyword Function, followed by the name you've
given to the function. The parentheses are used to hold the variable
names for any values being passed into the function from outside,
which is covered later in this section. To complete the function
definition, use the words End Function. The following
is a quick example, with the result shown in Figure 9.1.
Figure 9.1 : The custom function (myfunction.htm) in
the browser.
<HTML>
<HEAD>
<TITLE>My Function</TITLE>
<SCRIPT LANGUAGE="vbscript">
Sub myButton_OnClick
myVar = Document.Form1.Input.Value
Document.Form1.Output.Value = myFunction(myVar)
End Sub
Function myFunction(ByVal AnyValue)
myFunction = AnyValue & " added by my function"
End Function
</SCRIPT>
</HEAD>
<BODY BGCOLOR="white">
<CENTER>
<FORM NAME="Form1">
Input <INPUT TYPE="text" NAME="Input"><P>
<INPUT TYPE="button" NAME="myButton" VALUE="Click Me"><P>
Output <INPUT TYPE="text" NAME="Output" SIZE=40></FORM
</CENTER>
</BODY>
</HTML>
In this example, execution of the script commences when you click
the button. This fires an OnClick event, which is handled
by the myButton_OnClick event handler, shown here:
Sub myButton_OnClick
myVar = Document.Form1.Input.Value
Document.Form1.Output.Value = myFunction(myVar)
End Sub
The value in the Input text box is copied into the myVar
variable. The next line basically says to the program, "Go
and do myFunction, take myVar with you and bring
back the result; then show that result in the Output text box."
So, off it goes to myFunction, taking myVar
with it. Here's the myFunction function:
Function myFunction(ByVal AnyValue)
myFunction = AnyValue & " added by my function"
End Function
This function has been defined to receive one variable, which
can be any variable. The ByVal keyword tells the scripting
engine that it wants to receive just the value of the passed variable.
If you try to call this function without any variables (or arguments),
like
x = myFunction()
or if you call it with more than one argument, like
x = myFunction(y, a, I, strMyString)
you generate a runtime error. The number of arguments (or variables)
must be the same. The names you use for the argument are irrelevant,
but the order in which they appear is the same. Here is an example:
a = 10
b = 20
c = 30
d = 40
x = anyFunction(a,b,c,d)
Function anyFunction(e,f,g,h)
Within the anyFunction function, the values are e
= 10, f = 20, g = 30, and h = 40.
To return the result of the function to the code that called it,
you use the function name as the left side of an assignment, like
this:
myFunction = AnyValue & " added by my function"
When the execution reaches the End Function, the value
that has been assigned to the function is passed back to the calling
script as the result.
But why not just put the code in line with the rest of the program?
Well, it really depends on what you are trying to achieve. Let's
say you use a particular calculation in many different parts of
the program. Each time you use the calculation, you have to enter
the same lines of code. It would be much easier to enter the code
once in a function, and then call the function each time you need
to use the calculation. Another benefit of a function is that
it makes the code easier to read. Separating the code that performs
a calculation makes for a tidier, less cluttered appearance. Look
at the following "before and after" example:
<SCRIPT LANGUAGE="vbscript">
Sub cmdButton1_OnClick
x = CDbl(Document.Form1.Text1.Value)
y = CDbl(Document.Form1.Text2.Value)
z = x * 34 + y
b = z / (35 * 9) + 1
i = b ^ 789 - 93
Document.Form1.Text3.Value = CStr(i)
End Sub
Sub cmdButton2_OnClick
x = CDbl(Document.Form1.Text4.Value)
y = CDbl(Document.Form1.Text5.Value)
z = x * 80 + y
b = z / (35 * 9) + 1
i = b ^ 789 - 93
Document.Form1.Text6.Value = CStr(i)
End Sub
Sub cmdButton3_OnClick
x = CDbl(Document.Form1.Text7.Value)
y = 989
z = x * 20 + y
b = z / (35 * 9) + 1
i = b ^ 789 - 93
Document.Form1.Text9.Value = CStr(i)
End Sub
</SCRIPT>
In this totally imaginary script, each of three buttons has a
similar event handler. But notice the subtle differences in each
one. The following is how it could be rescripted using a single
function:
<SCRIPT LANGUAGE="vbscript">
Function myFunction(ByVal x, ByVal y, ByVal v)
x = CDbl(x)
y = CDbl(y)
z = x * v + y
b = z / (35 * 9) + 1
i = b ^ 789 - 93
myFunction = CStr(i)
End Function
Sub cmdButton1_OnClick
Document.Form1.Text3.Value = myFunction(Document.Form1.Text1.Value,
åDocument.Form1.Text2.Value, 34)
End Sub
Sub cmdButton2_OnClick
Document.Form1.Text6.Value = myFunction(Document.Form1.Text4.Value,
åDocument.Form1.Text5.Value, 80)
End Sub
Sub cmdButton3_OnClick
Document.Form1.Text9.Value = myFunction(Document.Form1.Text7.Value, 989, 20)
End Sub
</SCRIPT>
Not only does it look tidier, but it is also easier to maintain.
Any modification to the formula needs to be made in only one place
rather than three, which reduces the chance of error.
A custom procedure is a subroutine that doesn't return a value.
Like functions, procedures can accept variables from other parts
of the program. To declare a custom procedure, you use the Sub
keyword, followed by the name of the procedure.
Sub myProcedure()
....
End Sub
You can use two types of syntax to call a custom procedure. The
first method is to use the keyword Call, like this:
Call myProcedure()
If you use the keyword Call, you must use parentheses
around the argument list or use empty parentheses. The other method
is to simply use the procedure name without the word Call,
like this:
myProcedure
If you omit the keyword Call, you cannot use parentheses
around your argument list.
The following example uses both methods. The result is shown in
Figure 9.2.
Figure 9.2 : The custom procedure, proc.htm, in the browser.
<HTML>
<HEAD>
<TITLE>My Custom Procedure</TITLE>
<SCRIPT LANGUAGE="vbscript">
Sub Button1_OnClick
Call DoComplexMessage("First Message")
End Sub
Sub Button2_OnClick
DoComplexMessage "Second Message"
End Sub
Sub DoComplexMessage(ByVal Message)
Dim CRLF
Dim strTitle
Dim strMainMessage
CRLF = Chr(10) & Chr(13)
strTitle = "My Custom Procedure"
strMainMessage = "Hello this is the " & Message & CRLF
strMainMessage = strMainMessage & "This is my procedure to show " & CRLF
strMainMessage = strMainMessage & "a message box which is similar " & CRLF
strMainMessage = strMainMessage & "from both buttons"
x = MsgBox(strMainMessage,0,strTitle)
End Sub
</SCRIPT>
</HEAD>
<BODY BGCOLOR="white">
<CENTER>
<INPUT TYPE="button" NAME="Button1" VALUE="Button 1">
<INPUT TYPE="button" NAME="Button2" VALUE="Button 2">
</CENTER>
</BODY>
</HTML>
Both event handlers for the buttons call the DoComplexMessage
procedure. One uses Call and parentheses, and the other
simply uses the procedure name. As you can clearly see, the use
of a custom procedure in this example removes the need for you
to write the same code more than once.
The ActiveX Control Pad enables you to quickly create custom procedures
and functions, and it also makes it easy to add the calls to your
custom procedures and functions.
To see how this works, let's re-create the example used in the
last section using the ActiveX Control Pad.
- Open the ActiveX Control Pad and, using the HTML template
provided, create the HTML part of the page, which should now look
like what you see in Figure 9.3.
Figure 9.3 : The custom procedure example's HTML.
- Now open the Script Wizard by clicking the script button on
the toolbar or selecting Script Wizard from the Tools menu.
- To create a custom procedure, right-click anywhere in the
right actions pane, and select New Procedure from the pop-up menu.
The Script Wizard then opens a new custom procedure in the script
pane and gives it a default name of Procedure1(). (See
Figure 9.4.)
Figure9.4: The new custom procedure.
- Rename the procedure by changing Procedure1 to DoComplexMessage,
and add ByVal Message between the parentheses.
- Enter the following code into the script pane:Dim CRLF
Dim strTitle
Dim strMainMessage
CRLF = Chr(10) & Chr(13)
strTitle = "My Custom Procedure"
strMainMessage = "Hello this is the " & Message & CRLF
strMainMessage = strMainMessage & "This is my procedure to show " & CRLF
strMainMessage = strMainMessage & "a message box which is similar " & åCRLF
strMainMessage = strMainMessage & "from both buttons"
x = MsgBox(strMainMessage,0,strTitle)
- Click the plus sign that appears next to the word Procedures
in the right actions pane, and you can see that your new custom
procedure is available to be used by any of the events. Your Script
Wizard should now resemble the one in Figure 9.5.
Figure 9.5 : The completed custom procedure.
- To call the custom procedure from the buttons events, click
the plus sign to the left of Button1 in the left events
frame, and select the OnClick event.
- Double-click the DoComplexMessage procedure in the
right actions pane. Automatically, the Script Wizard adds the
words Call DoComplexMessage() to the script pane.
- Edit the statement by adding "First Message"
between the parentheses. Your Script Wizard now looks like the
one in Figure 9.6.
Figure 9.6 : Calling the procedure from the OnClick
event.
- Repeat this for Button2, using "Second Message"
between the parentheses.
- To finish, click OK and the Script Wizard automatically generates
the code, which looks like this:
<HTML>
<HEAD>
<SCRIPT LANGUAGE="VBScript">
<!--
Sub DoComplexMessage(ByVal Message)
Dim CRLF
Dim strTitle
Dim strMainMessage
CRLF = Chr(10) & Chr(13)
strTitle = "My Custom Procedure"
strMainMessage = "Hello this is the " & Message & CRLF
strMainMessage = strMainMessage & "This is my procedure to show "
å & CRLF
strMainMessage = strMainMessage & "a message box which is similar "
å & CRLF
strMainMessage = strMainMessage & "from both buttons"
x = MsgBox(strMainMessage,0,strTitle)
end sub
-->
</SCRIPT>
<TITLE>My Custom Procedure</TITLE>
</HEAD>
<BODY BGCOLOR="white">
<CENTER>
<INPUT LANGUAGE="VBScript" TYPE=button VALUE="Button 1"
åONCLICK="call DoComplexMessage("First Message")"
NAME="Button1">
<INPUT LANGUAGE="VBScript" TYPE=button VALUE="Button 2"
åONCLICK="call DoComplexMessage("Second Message")"
NAME="Button2">
</CENTER>
</BODY>
</HTML>
Note that the custom procedure code is identical to the one you
created manually earlier. However, the Script Wizard places event
handlers for HTML Intrinsic controls within the HTML definition
of the control. Save the file and test it in the browser.
NOTE |
You can also create custom functions using the ActiveX Script Wizard. Follow the previous instructions, and simply replace the word Sub with Function. When the Script Wizard generates the code, it will automatically place End Function rather than End Sub at the end of the script.
|
Adding some pseudo-intelligence to your script is possible only
if you can enable your script to make decisions. You can add decision-making
capabilities in two ways.
The If...Then conditional statement is the most widely
used construct in any programming language. It is easy and quick
to use and enables you to branch the program based on the result
of the condition, like this:
If myVariable = yourVariable Then
Alert "got a match"
End
If...Then statements can also be nested, which means
you can have a condition that is tested only if the condition
of the first statement is true. Here is an example:
If myVariable = yourVariable Then
If aVariable = bVariable Then
Alert "Both sets match"
End If
End If
For the code within the conditional statement to execute, the
condition must evaluate True.
if x = 10 then
Alert "yes, x does equal 10"
end if
But what happens if it evaluates to False? Well, normally
execution continues with the code directly after the End If
statement. However, you can add an Else statement within
the condition, which makes the code execute only if the condition
is False. Here is an example:
If x = 10 then
Alert "Yes, x does equal 10"
Else
Alert "No, x does not equal 10"
End If
You can even add a further condition within the Else
section. Just use the ElseIf keyword, like this:
If x = 10 then
Alert "Yes, x does equal 10"
ElseIf x = 20 Then
Alert "x does not equal 10 but it equals 20"
Else
Alert "x does not equal 10 or 20"
End If
You can turn the condition on its head and have the code execute
only if the condition evaluates to False. This is done
by including the negation operator Not.
If Not x = 10 Then
Alert "Sorry but x does not equal 10"
End If
Note that, in truth, the overall statement still evaluates to
True. Essentially, the statement says, "Does x not
equal 10? Yes, it doesn't."
The other type of conditional statement you have at your disposal
is the Select Case block. With Select Case,
you start with a known value and then use the Case statement
to compare whether the case variable matches the selection variable.
If the comparison evaluates to true, the line following Case
is executed. After execution, the program continues with the line
following End Select.
Select Case x
Case 5
Alert "x equals 5"
Case 10
Alert "x equals 10"
Case 15
Alert "x equals 15"
End Select
Again, let's look at how you can have at least one line of the
block execute no matter what the result. You use Case Else,
like this:
Select Case x
Case 5
Alert "x equals 5"
Case 10
Alert "x equals 10"
Case 15
Alert "x equals 15"
Case Else
Alert "I dont care what value x is but its not 5, 10 or 15"
End Select
NOTE |
Unlike Select Case in Visual Basic, the VBScript version does not allow statements like Case Is < 8 or Case Is 10 To 100. All values for the Case statements must be explicit, which restricts its usage drastically.
|
What do you do if you need to execute the same section of code
many times over, possibly with a slight change to the code? You
could write the code over and over again, like this:
x = 0
Document.Write x
Document.Write x + 1
Document.Write x + 2
Document.Write x + 3
Document.Write x + 4
Document.Write x + 5
This could continue on, and copying and pasting it wouldn't take
too long to reach 100! But there's a much easier method to achieve
the same result. It's known as a loop.
VBScript gives you two ways in which you can repeat the same code
as many times as you want:
A For...Next loop enables you to repeat execution of
the code held within the loop a given number of times. You specify
the upper and lower parameters of the loop counter, and the scripting
engine increments the loop counter automatically as the loop is
executed.
For x = 1 to 100
do some code 100 times
Next
NOTE |
VB programmers should keep in mind that in VBScript, you can use only Next. You do not have the option to use the old Next x as you do in VB4.
|
By default, the loop counter is incremented by one every time
the program reaches the Next statement, until the upper
limit is reached, at which point the program continues execution
with the line following Next.
Let's have a look at a few variations on the For...Next
theme. First, what if you want the counter to increment in reverse,
or maybe increment by more than one each time? There's a special
keyword called Step. Step is used to change
the behavior of the increment. If Step is negative, the
loop goes backward, like so:
For x = 100 to 0 Step -1
Do something 100 times
Next
In this example, x starts at 100 and is reduced
by 1 with every loop until it reaches 0, at
which point the loop is terminated. Step can be any number,
and that number then becomes the increment.
For x = 0 to 100 Step 2
Do something 50 times
Next
Second, what if you want to initially loop a certain number of
times, but jump out of the loop if a particular condition is met?
For this, you use Exit For. Exit For takes the
execution out of the loop and resumes the program at the line
immediately following the Next statement.
For x = 0 to 50
y = y + 1
If y = z then
Exit For
End If
Next
Another way you can repeat the same code over and over is to use
a Do...Loop statement, like this:
Do
code to execute for ever
Loop
But, actually, it's not like this at all. If you wrote that into
your script, your script would never finish. You need to give
the loop a condition so that it knows when to stop repeating.
The two conditions are While and Until.
A Do While loop repeats while a condition is True,
as in the following example:
x = 2
Do While x < 10
x = x + 1
Loop
A Do Until loop repeats until a condition is True,
as in the following example:
Do Until x = 10
x = x + 1
Loop
As with the For...Next loop, you have several options
that you can use with the Do...Loop statement. The first
is Exit Do. Again, this is to allow an exit route for
your program in case the need arises.
Do While x < 100
x = x + 1
z = z - 1
If z = 50
Exit Do
End if
Loop
The next option is to place the While or Until
on the same line as Loop, rather than on the same line
as Do, like this:
Do
x = x + 1
Loop Until x = 100
The difference is that placing While or Until
next to Loop forces the statement block to be executed
at least once. If the condition is placed next to Do,
and the condition is True as the program arrives at the
statement block, then the loop is not executed. Here is an example:
x = 200
Do While x < 100
This code never executes
Loop
However, if the code was rewritten like the following, the code
executes once:
x = 200
Do
This Code executes only once
Loop While x < 100
In this chapter, you've been through the main language components
that enable you to control the flow within your script. From defining
subroutines and functions, to decision-making statements, and
finally how to execute code over and over. Here's a brief summary:
- Functions are subroutines that return a value.
- Procedures are subroutines that do not return a value.
- Event handlers are subroutines that are called in response
to an action acting upon an object or control.
- Use If...Then or If...Else...Then to execute
code based on the result of a condition.
- Use Select Case to specify which code should execute.
- Loop a given number of times with For...Next. Use
Step to change the default increment.
- Do While Loop repeats while a condition is True.
- Do Until Loop repeats until a condition is True.
- Do Loop While and Do Loop Until repeat at
least once.
Now you know how to create scripts that can make decisions, branch
to other parts of the script, repeat sections of code, and generally
perform like they know what they're doing. You can add even more
functionality to your scripts by looking at the following chapters:
- To complete your knowledge of the VBScript language elements,
see Chapter 10, "Using the Power of Arrays."
- For a further example of using If...Then and loops,
see Chapter 5 "Interfacing VBScript with an HTML Form."
- For an example of using Select Case, see Chapter
8, "Adding Date and Time Functions."
Q:
|
How do you decide when to subdivide a program into smaller sections?
|
A:
|
Many of the reasons for creating separate subroutines and functions will give you an idea about when it is right to create a separate subroutine. Subroutines save coding. If you find yourself coding the same lines over and over, you probably need a subroutine. If you have a routine that returns a value, and that value might (now or in future) be needed by several parts of the program, or if the routine to produce the value is more than a few lines of code, I would suggest that it be placed in its own function.
|