Hour 7

Making Decisions

You learned VB's mathematical operators in Hour 5, "Putting Code into Visual Basic"; but Visual Basic supports several more operators, as you'll learn in this lesson. The operators described here are called the comparison operators because they compare data and determine the results of the comparison. By using comparison operators, you can write your programs so that they make certain runtime decisions based on the comparison results.

The highlights of this hour include

Comparison Operators

All the comparison operators produce true or false results. In other words, the comparison is either true or the comparison is false. The mathematical operators produce numeric values, whereas the comparison operators produce true or false values. A comparison operator can produce nothing more than a true or false result. The rest of the program can use the true or false comparison operator result to make decisions. For example, if a comparison operator returns False when comparing whether an employee worked the last pay period, the rest of the program knows not to print a paycheck for that employee.

New Term: Comparison operators are operators that compare data values against each other and produce true or false results.


NOTE: This section describes just the operators; subsequent sections in this hour's lesson describe new programming statements that can make use of the comparison operators.

Table 7.1 describes VB's six comparison operators. The comparison operators always compare data, and that comparison is either true or false because data either compares as expected or does not.


TIP: Two values can be equal to one another or one can be greater than the other. Keep these possibilities in mind as you read through Table 7.1.

Table 7.1. The comparison operators determine how data compares.
Operator Usage Description
> lblSales.Caption > Goal The greater than operator returns True if the value on the left side of > is numerically or alphabetically greater than the value on the right.
< Pay < 2000.00 The less than operator returns True if the value on the left side of < is numerically or alphabetically less than the value on the right.
= Age = Limit The equal to operator (sometimes called the equal operator) returns True if the values on both sides of = are equal to each other.
>= FirstName >= "Mike" The greater than or equal to operator returns True if the value on the left side of >= is numerically or alphabetically greater than or equal to the value on the right.
<= Num <= lblAmt.Caption The less than or equal to operator returns True if the value on the left side of <= is numerically or alphabetically less than or equal to the value on the right.
<> txtAns.Text <> "Yes" The not equal to operator returns True if the value on the left side of <> is numerically or alphabetically unequal to the value on the right.


NOTE: Remember that if a comparison operator does not produce a true result, the result must be false.

As you can see from Table 7.1, the comparison operators compare either variables, literals, control values, or combinations of all those data sources. The comparison operators work on both numeric and alphabetic values. You can compare any kind of number against another number, or any kind of string against another string.

The Comparisons Nature

When you compare strings, Visual Basic uses the ASCII table, included in Appendix B, "ASCII Table," to determine how to compare the characters. For example, the ASCII table says that the uppercase letter A--whose ASCII numeric value is 65--is less than the uppercase letter B--whose ASCII numeric value is 66. Notice that all uppercase letters are less than lowercase letters. Therefore, the abbreviation ST is less than St.

New Term: An ASCII table contains a list of characters with corresponding unique numeric representations.

To understand how comparison operators work, you must understand how to use their true or false results. The If statement, introduced in the next section, explains how you can use true and false results to make decisions in your program. Before you read the next section, make sure that you understand how these operators compare values. Make sure that you understand the Result column of Table 7.2 before you go any further.

Table 7.2. Relationship results.
Relation Result
4 > 2 True
4 < 1 False
4 < 8 True
"Apple" <= "Orange" True
"Macmillan" < "Mc millan" True
0 >= 0 True
0 <= 0 True
1 <> 2 True
2 >= 3 False

Keep Each Sides Data Type Consistent

Take extra care that the expressions on both sides of a comparison operator conform to the same data type or at least compatible data types. In other words, you cannot compare a string to a numeric data type. If you try, you will get a type mismatch error because the data types don't match. You can compare any numeric data type against any other numeric data type most of the time. In other words, you can test whether a single-precision value is less than or greater than an integer value.


WARNING: Be careful when you compare non-integers for equality. Precision numbers are difficult to represent internally. For example, if you assigned 8.3221 to a single-precision variable and assigned 8.3221 to another single-precision variable, Visual Basic might return a false result if you compare the values for equality. Internally, one of the variables might actually hold 8.322100001 because of rounding errors that occur in insignificant decimal places. You can safely compare two currency values for equality, however, because Visual Basic maintains and compares their accuracy to two decimal places.


NOTE: The comparison operators are sometimes called the conditional operators because they test conditions that are either true or false.

The comparison operators compare values against one another. You can compare for equality, inequality, and size differences. The comparison operators work for both string data and numeric data. By themselves, the comparison operators would not be worth much. However, you can use them to compare data by using the If statement, which you'll learn about in the next section.

The If Statement

Perhaps the most important statement in a program is the If statement and its cousin statements. With logic that If provides, your application can begin to analyze data and make decisions based on that analysis. For example, your program can display a three-button message box and determine, with the If statement, which command button the user clicked to close the message box.

If uses the comparison operators you learned earlier in this lesson to test data values. If performs one of two possible code actions, depending on the result of the comparison. Visual Basic can test whether to execute complete blocks of code. In other words, If uses comparison operator results to test data. If might execute one or more lines of subsequent code, depending on the results of the comparison's test.

Before If, the code you wrote executed sequentially, one statement after another. If lets your program be more decisive and execute only parts of the program if the data warrants partial execution. For example, suppose you were writing an invoicing system. In such a system, no sales tax should be computed for tax-exempt organizations, so your program would skip over the tax computation code when processing such organizations.

If makes decisions. If a comparison test is true, the body of the If statement executes. (In fact, the previous sentence is almost identical to Visual Basic's If statement!) Here is one format of If:

If comparisonTest Then
  One or more Visual Basic statements
End If

End If lets Visual Basic know where the body of the If statement ends. Suppose that the user enters a sales figure into a Text Box control named txtSales. The following If computes a bonus amount based on the sales:

If (txtSales.Text > 5000.00) Then
  sngBonus = txtSales.Text * .12
End If


NOTE: Data enters a control such as a text box as a Variant data type. When you perform arithmetic with a Variant and the Variant data type holds a numeric value, Visual Basic converts the Variant to a number for the calculation.

Remember that Visual Basic stores 0 in all numeric variables that you don't first initialize. Therefore, sngBonus has a 0 before the If executes. Once the If executes, the code changes the sngBonus variable only if the value of the txtSales.Text property is more than 5000.00. In a way, the If reads like this:

If the sales are more than $5,000.00, then compute a bonus based on that sales value.

Visual Basic stores a null zero in string variables that you have not yet initialized. If you use an uninitialized Variant data type variable, the variable holds a null value that becomes zero if you assign the variable to a numeric variable.

The body of an If can have more than one statement. The body is often called a block. The following If calculates a bonus, the cost of sales, and a reorder amount based on the value of the txtSales text box entry:

If (txtSales.Text > 5000.00) Then
   sngBonus = txtSales.Text * .12
   curCostOfSales = txtSales.Text * .41
   curReorderCost = txtSales.Text * .24
End If

The three statements that make up the body of the If execute only if the condition txtSales.Text > 5000.00 is true. Suppose that this code contains another assignment statement immediately after End If. That assignment statement is outside the body of the If, so the true or false result of the condition affects only the body of the If. Therefore, the tax computation in the following routine executes regardless of whether the sales are more than or less than $5,000.00:

If (txtSales.Text > 5000.00) Then
   sngBonus = txtSales.Text * .12
   curCostOfSales = txtSales.Text * .41
   curReorderCost = txtSales.Text * .24
End If
sngTax = .12 * txtSales.Text


TIP: The parentheses are not required around the comparison test in an If, but they help separate the test from the rest of the code. In addition, the indentation helps illustrate the code that appears inside the If statement's body.

Can you see how the program makes decisions using If? The body of the If executes only if the comparison test is true. Otherwise, the rest of the program continues as usual.

There is a shortcut form of If that you might run across. The single-line If statement has a format that looks like this:

If comparisonTest Then VBStatement

The single-line If does not require an End If statement because the comparison test and the body of the If reside on the same line. Single-line If statements do not provide for easy program maintenance. If you decide that you want to add to the body of the If, you must convert the single-line If to a multiple-line If, and you might forget to then add End If. Therefore, even if the body of an If statement takes only one line, code the If as a multiple-line If-End If statement to make the program more maintainable.

The If Statements Else Branch

Whereas If executes code based on the comparison test's true condition, the Else statement executes code based on the comparison test's false condition. Else is an optional part of the If statement. Else specifies the code that executes if the comparison test is false. Here is the complete format of the If statement with Else:

If comparisonTest Then
   One or more Visual Basic statements
Else
   One or more Visual Basic statements
End If

Typically, programmers call this full-blown If statement the If-Else statement. The If-Else statement is sometimes called a mutually exclusive statement. The term mutually exclusive simply means that one set of code or the other executes, but not both. The If-Else statement contains two sets of code--that is, two bodies of one or more Visual Basic statements--and only one set executes, depending on the result of the If. An If statement is either true or false because the If's comparison produces either a true or false result. Therefore, either the first or the second body of code in an If-Else executes.

Suppose that a salesperson receives a bonus if sales are high (over $5,000.00) or suffers a pay cut if sales are low (below $5,000.00). The If-Else shown next contains the code necessary to reward or punish the salesperson. The code body of the If computes the bonus as done in the previous section. The code body of the Else subtracts $25 from the salesperson's pay, which is stored in the variable named curPayAmt, if the sales quota is not met. The following code computes such a payment amount based on the quota:

If (txtSales.Text > 5000.00) Then
   sngBonus = .05 * txtSales.Text
Else
   curPayAmt = curPayAmt - 25.00
End If
curTaxes = curPayAmt * .42

The fourth line in these code lines may surprise you at first. The assignment appears to make the statement that the pay is equal to the pay minus 25. You know that nothing can be equal to itself minus 25. In math, the equal sign acts as a balance for the two sides of the equation. In Visual Basic, however, when the equal sign is not used inside an If's comparison test, it is an assignment that takes everything to the right of the equal sign and stores that value in the variable to the left of the equal sign. Therefore, the fourth line subtracts the 25 from the value stored in curPayAmt and then assigns that result back to curPayAmt. In effect, it lowers the value of curPayAmt by 25.


NOTE: When a variable appears on both sides of an assignment's equal sign, the variable is being updated in some way.

To further your understanding of the If-Else statement and to demonstrate testing for an input box's return value, study how Listing 7.1 uses If-Else to respond to an input box. The code asks the user for a company name and then accepts the name or recognizes that the user clicked Cancel to get rid of the input box without answering it. (When a user clicks Cancel in response to an input box, the input box returns a null string, "".)

Listing 7.1. Checking an input boxs return value.


Dim strCompName As String
Dim intPress As Integer   ` MsgBox return value
` Ask the user for a name
` Use XYZ, Inc. for the default name
strCompName = InputBox("What is the company name?", _
   "Company Request", "XYZ, Inc.")
` Check the return value
If (strCompName = "") Then
   ` The user pressed Cancel
   intPress = MsgBox("Thanks anyway")
Else
   ` The user entered a company name
   intPress = MsgBox("You entered " & strCompName)
End If

Compound Comparisons with the Logical Operators

Visual Basic supports three additional operators--And, Or, and Not--that look more like commands than operators. And, Or, and Not are called logical operators. Logical operators let you combine two or more comparison tests into a single compound comparison.

Table 7.3 describes the logical operators, which work just like their spoken counterparts.

Table 7.3. The logical operators.
Operator Usage Description
And If (A > B) And (C < D) Produces True if both sides of the And are true. Therefore, A must be greater than B and C must be less than D. Otherwise, the expression produces a false result.
Or If (A > B) Or (C < D) Produces True if either side of the Or is true. Therefore, A must be greater than B or C must be less than D. If both sides of the Or are false, the entire expression produces a false result.
Not If Not(strAns = "Yes") Produces the opposite true or false result. Therefore, if strAns holds "Yes", the Not turns the true result to false.

As you can see from Table 7.3, the And and Or logical operators let you combine more than one comparison test in a single If statement. The Not negates a comparison test. You can often turn a Not condition around. Not can produce difficult comparison tests, and you should use it cautiously. The last If in Table 7.3, for instance, could easily be changed to If (strAns <> "Yes") to eliminate the Not.

Your code often must perform an assignment, print a message, or display a label if two or more conditions are true. The logical operators make the combined condition easy to code. Suppose that you want to reward the salesperson if sales total more than $5,000 and if the salesperson sells more than 10,000 units of a particular product. Without And, you have to embed an If statement in the body of another If statement like this:

If (sngSales > 5000.00) Then
   If (intUnitsSold > 10000) Then
      sngBonus = 50.00
   End I
End If

Here is the same code rewritten as a single If. It is easier to read and to change later if you need to update the program:

If (sngSales > 5000.00) And (intUnitsSold > 10000) Then
   sngBonus = 50.00
End If

How can you rewrite this If to pay the bonus if the salesperson sells either more than $5,000 in sales or if the salesperson sells more than 10,000 units? Here is the code:

If (sngSales > 5000.00) Or (intUnitsSold > 10000) Then
   sngBonus = 50.00
End If

Listing 7.2 contains an If-Else that tests data from two divisions of a company and calculates values from the data.

Listing 7.2. Calculating sales figures for a companys divisions.


If (intDivNum = 3) Or (intDivNum = 4) Then
   curDivTotal = curDivSales3 + curDivSales4
   curGrandDivCosts = (curDivCost3 * 1.2) + (curDivCost4 * 1.4)
Else
   curDivTotal = curDivSales1 + curDivSales2
   curGrandDivCosts = (curDivCost1 * 1.1) + (curDivCost5 * 1.9)
End If 


If intDivNum contains either a 3 or a 4, the user is requesting figures for the East Coast, and the code in the first If branch executes to produce an East Coast pair of values. If intDivNum does not contain a 3 or a 4, the program assumes that intDivNum contains a 1 or a 2, and the West Coast pair of values is calculated in the Else portion.


TIP: Notice how easy it is to spot the variable's data type in code that names variables with a data type prefix such as cur (for currency) and sng (for single-precision). Use data type prefixes in all your variable names. Although you must type a little extra, your program code will be much clearer.

Multiple Choice with Select Case

If is great for data comparisons in cases where one or two comparison tests must be made. When you must test against more than two conditions, however, If becomes difficult to maintain. The logical operators help in only certain kinds of conditions. At other times, you must nest several If-Else statements inside one other.

Consider the If statement shown in Listing 7.3. Although the logic of the If statement is simple, the coding is extremely difficult to follow.

Listing 7.3. Nested If-Else statements get complex quickly.


If (intAge = 5) Then
   lblTitle.Caption = "Kindergarten"
Else
   If (intAge = 6) Then
      lblTitle.Caption = "1st Grade"
   Else
      If (intAge = 7) Then
         lblTitle.Caption = "2nd Grade"
      Else
         If (intAge = 8) Then
            lblTitle.Caption = "3rd Grade"
         Else
            If (intAge = 9) Then
               lblTitle.Caption = "4th Grade"
            Else
               If (intAge = 10) Then
                  lblTitle.Caption = "5th Grade"
               Else
                  If (intAge = 11) Then
                     lblTitle.Caption = "6th Grade"
                  Else
                     lblTitle.Caption = "Advanced"
                  End If
               End If
            End If
         End If
      End If
   End If
End If 


Visual Basic supports a statement, called Select Case, that handles such multiple-choice conditions better than If-Else. Here is the format of the Select Case statement:

Select Case Expression
   Case value
      One or more Visual Basic statements
   Case value
      One or more Visual Basic statements
   [Case value
      One or more Visual Basic statements]
   [Case Else
      One or more Visual Basic statements]
End Select

Select Case is a good substitute for long, nested If-Else conditions when several choices are possible. You set up your Visual Basic program to execute one set of Visual Basic statements from a list of statements inside Select Case.

The format of Select Case makes the statement look as difficult as a complex nested If-Else, but you will soon see that Select Case statements are actually easier to code and to maintain than their If-Else counterparts.

Expression can be any Visual Basic expression--such as a calculation, a string value, or a numeric value--provided that it results in an integer or a string value. Each value must be an integer or a string value that matches Expression's data type.

The Select Case statement is useful when you must make several choices based on data values. Select Case can have two or more Case value sections. The code that executes depends on which value matches Expression. If none of the values matches Expression, the Case Else body of code executes if you code the Case Else. Otherwise, nothing happens and control continues with the statement that follows End Select.


WARNING: Don't use Select Case when a simple If or If-Else will suffice. Test logic is often so straightforward that a Select Case would be overkill and even less clear than an If. Unless you need to compare against more than a couple values, stick with the If and If-Else statements because of their simplicity.

The fastest way to learn Select Case is to see an example of it. Listing 7.4 contains a Select Case version of the child grade assignments shown in Listing 7.3. Select Case organizes the multiple-choice selections into a more manageable format.

Listing 7.4. Using Select Case to simplify complex nested If-Else statements.


Select Case intAge
   Case 5:  lblTitle.Caption = "Kindergarten"
   Case 6:  lblTitle.Caption = "1st Grade"
   Case 7:  lblTitle.Caption = "2nd Grade"
   Case 8:  lblTitle.Caption = "3rd Grade"
   Case 9:  lblTitle.Caption = "4th Grade"
   Case 10: lblTitle.Caption = "5th Grade"
   Case 11: lblTitle.Caption = "6th Grade"
   Case Else:  lblTitle.Caption = "Advanced"
End Select


TIP: Use Select Case instead of embedded If-Else because, as you can see, Select Case keeps the code much simpler and easier to maintain.

Here's how the Select Case works: If the intAge variable holds the value 5, the label is assigned "Kindergarten" in the second line. If the intAge variable holds the value 6, the label is assigned "1st Grade" in the third line. The logic continues through the Case 11: statement. If intAge holds a value that does not fall within the range of 5 through 11, the final Case Else assigns "Advanced" to the label.

The body of each Case can consist of more than one statement, just as the body of an If or If-Else can consist of more than one statement. Visual Basic executes all the statements for any given Case match until the next Case is reached. Once Visual Basic executes a matching Case value, it skips the remaining Case statements and continues with the code that follows the End Select statement.

Notice the colons after each Case value statement in Listing 7.4. The colons are optional, but they do help separate the case being tested from its code that executes.


NOTE: Programmers often trigger the execution of complete procedures, such as event procedures, from within a Case statement. As you will learn in Hour 13, "Modular Programming," instead of putting several statements in the body of an If-Else or a Case, you can execute a procedure that contains all the statements that execute when a given condition is true.

Two Additional Select Case Formats

The two additional formats differ only slightly from the standard Select Case that you learned about in the previous section. They enable you to extend the power of Select Case so that Visual Basic can make Case matches on both comparison tests and on ranges of values. Here is the first additional format:

Select Case Expression
   Case Is Relation:
     One or more Visual Basic statements
   Case Is Relation:
     One or more Visual Basic statements
   [Case Is Relation:
     One or more Visual Basic statements]
   [Case Else:
     One or more Visual Basic statements]
End Select

Relation can be whatever comparison test you want to perform against Expression at the top of the Select Case. The standard Select Case statement, discussed in the previous section, compared the Expression value against an exact Case match. When you use the comparison Is Select Case option, each Case can be matched on a comparison test.

Here is the format of the second extra Select Case format:

Select Case Expression
   Case expr1 To expr2:
      One or more Visual Basic statements
   Case expr1 To expr2:
      One or more Visual Basic statements
   [Case expr1 To expr2:
      One or more Visual Basic statements]
   [Case Else:
      One or more Visual Basic statements]
End Select

The Case lines require a range, such as 4 To 6. The To Select Case option enables you to match against a range instead of a relation or an exact match.


TIP: You can combine the extended formats of Select Case with the standard Select Case so that two or more kinds of Case formats appear within the same Select Case statement.

Study Listing 7.5 to learn how to combine different Select Case statements to test for various values.

Listing 7.5. Using Select Case to simplify complex nested If-Else statements.


Rem The following Select Case to End Select code
Rem   assigns a student's grade and school name
Rem   to the label on the form. The code checks
Rem   to make sure that the student is not too
Rem   young to be going to school.
Select Case intAge
   ` Check for too young...
   Case Is <5:  lblTitle.Text = "Too young"

   ` Five-year olds are next assigned
   Case 5: lblTitle.Text = "Kindergarten"

   ` Six to eleven...
   Case 6 To 11:  lblTitle.Text = "Elementary"
                  lblSchool.Text = "Lincoln"

   ` Twelve to fifteen...
   Case 12 To 15: lblTitle.Text = "Intermediate"
                  lblSchool.Text = "Washington"

   ` Sixteen to eighteen
   Case 16 To 18: lblTitle.Text = "High School"
                  lblSchool.Text = "Betsy Ross"

   ` Everyone else must go to college
   Case Else: lblTitle.Text = "College"
              lblSchool.Text = "University"
End Select 


If the age is less than 5, the title label becomes Too young, and the school name remains blank. If the age is exactly 5 (intAge is obviously an integer value), the title gets Kindergarten, and the school name still remains blank. Only if the child is 5 or older do both the title and school name get initialized.

If you were to rewrite this code using embedded If-Else logic, the code would become a nightmare. The Select Case's range testing, such as Case 16 to 18, saves a tremendous amount of If-Else logic.

Summary

In this hour you have learned how to write Visual Basic programs that make decisions. Once your programs are able to test data values against certain conditions, your programs can begin to make execution decisions and perform smarter calculations. Visual Basic offers several forms of the If and the Select Case statements to make comparisons. The comparison operators, especially when combined with the logical operators, produce advanced compound conditions.

The next hour explains how to write looping statements so that your programs can repeat logic as often as needed.

Q&A

Q Which testing statement is better: If, If-Else, or Select Case?

A
No testing statement is better than another in all situations. The If statement is the fundamental building block for testing data, and If is extremely common in most applications. When you need the application to execute one block of code or another, depending on the result of an If test, use If-Else. If you need to embed several If-Else statements together because you've got to test for multiple comparisons, the Select Case almost always makes a better comparison statement than If-Else. You would not, however, save effort or program clarity if you used Select Case when a simple If-Else would do. The bottom line is that your application determines the best statement to use at any one time.

Q Why is the Not operator considered so bad?

A
Not is not considered bad, really, but the negative logic that Not produces often makes for confusing logic. Some logic is best performed with Not, but you can almost always turn the Not logic into positive and simpler logic by reversing the comparison being done.

Workshop

The quiz questions and exercises are provided for your further understanding. See Appendix C, "Answers," for answers.

Quiz

1. How do comparison operators differ from mathematical operators?

2. What role does the ASCII table play in comparison logic?

3. Which of the following produce true and which produce false results?

a.
25 <= 25

b. "a" >= "B"

c. 0 < -1

d. 234.32 > 234.321

4. When do you code the Else portion of an If statement?

5. True or false: The End If statement is not needed for one-line If statements.

6. Which statement replaces nested If-Else logic?

7. Which Case option checks for a range of values?

8. What happens if every Case fails and there is no Case Else option?

9. What role do code blocks play in Select Case statements?

10. What is wrong with this If statement?
If (intA < 1) And (intC >= 8) Then
   lblDraft.Caption = "Overdrawn"
Else
   lblDraft.Caption = "Underdrawn"
End Else

Exercises

1. Rewrite the following nested If statement using a single If with a logical operator:
If (A > 3) Then
   If (B > 10) Then
      lblAns.Caption = "Yes"
   End If
End If
2. Rewrite the following If to eliminate the Not and to clarify the code:
If Not(X < 10) Or Not(Y >= 20) Then