The one thing you should have learned about programming in Visual Basic so far that the application is made up of small, self-contained segments. Similarly, the code you write won’t be a monolithic listing. It will be made up of small segments called procedures and you will work on one procedure at a time.
For example, when you write code for a control’s Click event, you will concentrate on the event at hand, namely how the program should react to the Click event. What happens when the control is double-clicked is something you will worry about later, in the DoubleClick subroutine. This “divide and conquer” approach isn’t unique to programming events. It permeates the Visual Basic language and even the longest applications are written by breaking them into small, well-defined tasks. Each task is performed by a separate procedure that is written and tested separately from the others.
Procedures are useful for implementing repeated tasks, such as frequently used calculations. Suppose you’re writing an application that, at some point, must convert inches to centimeters or calculate the smaller of two numbers. You can always do the calculations inline and repeat them in your code wherever they are needed, or you can write a procedure that performs the calculations and call this procedure. The benefit of the second approach is that code is cleaner and easier to understand and maintain. If you discover a more efficient way to implement the task, you need change it in only one place. If the.same code is repeated in several places through out the application, you will have to change every instance.
The two types of procedures are subroutines and functions-the building blocks of your applications .
Subroutines
A subroutine is a block of statements that carries out a well-defined task. The block of statements is placed.with a pair of Sub/End Sub statements and can be invoked by name. The following subroutine displays the current date in a Message Box and can be called by its name, ShowDate:
Sub ShowDate()
MsgBox Date()
End.Sub
A subroutine normally performs a more complicated task than this one, nevertheless, it’s a block of code isolated from the rest of the application: All the event procedures in Visual Basic, for example, are coded as subroutines. The actions that must be performed each time a Command button is clicked are coded in the button’s Click procedure. This subroutine is called each time the button is clicked.
The statements in a subroutine are executed, and when the End Sub statement is reached, control returns to the calling program. It’s possible to exit a Subroutine prematurely with the Exit statement. For example, some condition may stop the subroutine from successfully completing its task’.
Subroutines and Event Handlers
In the first couple of chapters, you learned to develop applications by placing code in event handlers, An event handler is a short segment of code that is executed each time an external (or internal to your application) condition triggers the event. When the user clicks a control, the control’s Click event handler executes, This handler is nothing more than a subroutine, which performs all the actions you want to per- form when the control is clicked. It is separate from the rest of the code and doesn’t have to know what would happen if another control was clicked or if the same control was double-clicked. It’s a self contained piece of code that’s executed when needed.
Every application contains a number of event handlers, which contain code to react to user actions. Event handlers need not return any results and they’re implemented as subroutines. For example, to react to the click of the mouse on the Command!button, your application must provide the Command1_Click() subroutine. The code in’ this subroutine is executed independently of any other event handler and it doesn’t return a result because there is no main program to-accept it. The code of a Visual Basic application consists of event handlers, which may call other subroutines and functions, but they aren’t called by a main program. They are automatically activated by Visual Basic in response to external events.
If you need a procedure to perform certain actions, such as change the background color of a control or display the fields of a record on the Form, you can implement it either as a function or subroutine. The choice of the procedure type isn’t going to affect the code. The same statements can be used with either type of procedure. However, if your procedure doesn’t return a value, then it should be
implemented as a subroutine.
Functions
A function is similar to a subroutine, but a function returns a result. Subroutines perform a task and don’t report anything to the calling program; functions commonly carry out calculations and report the result. The statements that make up a function are placed in a pair of Function/End Function statements, Moreover, because a function reports a result, it must have a type, for example:
Function NextDay() As Date
NextDay – Date() + 1
End Function
The NextDay() function returns tomorrow’s date by adding one day to the current date. Because it must report the result to the calling program, the NextDay() function has a type, as do variables, and the result is assigned to its name (something You.can’t do with subroutines).
The Abs() Function
This function returns the absolute value of its argument. If the argument is positive, it returns it a,s is; if it’s negative, it inverts its sign. The Abs() function could be implemented as follows:
Function Abs(X As Double) As Double”
If X>=O Then
Abs = X
Else
Abs = -x End If
End Function
This is a trivial procedure, yet it’s built into Visual Basic because it’s used frequently in math and “science calculations. Developers can call a single function rather than supplying their own Abs() functions. Visual Basic and all other programming languages provide a number of built-in functions for those needed most frequently by developers. But each developer has special needs and you can’t expect to find all the procedures you may ever need in a programming language. Sooner or later, you will have to supply your own.
Calling Procedures
When you call a procedure, you must supply values for all the arguments specified in the procedure’s definition and in the same order. To call a procedure, you use the Call statement and supply its name and arguments in parentheses as follows:
Call PrintLotto(Numl, Num2, Num3, Num4, Num5, Num6)
The values of the arguments must match their declared type. If a procedure expects an Integer value, you shouldn’t supply a Double value.
Subroutines
You can omit the Call statement and call the subroutine by name. The arguments are supplied without the parentheses, as follows:
PrintLotto Numl, Num2, hum3, Num4, Num5, Num6
The number of arguments you supply to the subroutine and their types must match those in the procedure declaration. If the Subroutine expects six Integer values, but the variables you pass to it tare long or floating point numbers, a Type Mismatch” runtime error will be generated. You’a expect Visual Basic to figure out what you intend to do and adjust the arguments accordingly, but it won’t. Fortunately, you can instruct it to adjust the argument values so that they match with the arguments in the declaration of the subroutine, or function, by enclosing them In parentheses (see the sidebar “Automatic Argument Type Matching,” later in this chapter).
Functions
Functions are called by name and a list of arguments follows the name in parentheses as shown:
Degrees = Fahrenheit(Temperature)
In this example, the Fahrenheit() function converts the Temperature argument (which presumably is the temperature in degrees Celsius) to degrees Fahrenheit, and the result is assigned to the Degrees variable.
Functions can be called from within expressions as the following shows:
MsgBox ’40 degrees Celsius are ‘ & Fahrenheit(40) & _ • degrees Fehrenheit’
Suppose the function CountWords() counts the number of words and the function CountChars() counts the number of characters in a string. The average length of a word could be calculated as follows:
LongString a Text1.Text
AvgLen = (ountChars(LongString) / CountWords(LongString)
The first statement gets the text of a TextBox control and assigns it to a variable, which is then used as an argument to the two functions. When the second statement executes, Visual Basic first calls the functions CountChars() and Count- Words() with the specified arguments and the divides the results they return.
You can call functions in the same way that you call subroutines, with the Call statement, but the result won’t be stored anywhere. For example, the function Convert() may convert the text in a textbox to uppercase and return the number of characters it converts. Normally, you’d call this function as follows:
nChars = Convert()
If you don’t care about the return value, you would call the Convert() function with the Call statement: .
Call Convert()
Arguments
Subroutines and functions aren’t entirely isolated from the rest or the application. Most procedures accept arguments from the calling program. Recall that an argument is a value you pas~ to the procedure and on which the procedure usually acts. This .is how subroutines and functions communicate with the. rest of the application.
In the previous examples, the subroutines that handled the various events either didn’t provide arguments or had one or more. The Click subroutine, for instance, didn’t have arguments because all that was needed was the name of the subroutine. It needed code to handle the user clicking a control, but it didn’t need any additional information.
Unlike the argument-less Click event, the KeyPress subroutine provides an integer argument, which is the ASCII code of the character pressed. The definition’ of the KeyPress subroutine is as follows:
Private Sub Command1_KeyPress(KeyAscii As Integer)
End Sub
You specify arguments in the procedure declaration, but without the Dim statement. KeyAscii is an argument that conveys information about the key pressed. The code in the Keypress subroutine will most likely process the keystroke, and it needs this information.
Functions also accept arguments, and in many cases, more than one. The function Mint), for instance, accepts two numbers and returns the smaller one:
Function Min(a As Variant, b As Variant) As Variant
Min = Iff(a < b, a, b)
End Function
Iff() is a built-in function that evaluates the first argument, which is a logical expression. If the expression is True, the Iff() function returns the second argument. If the expression is False, the function returns the third argument. Because the arguments of the Mint) function were declared As Variants, the function works with all types of data, not just Numeric data types. Test the Min() function with strings or date and time values to see how it behaves.