Conditionals and loops are key elements for building powerful and flexible macros. They are defined as follows:
Conditional and loop statements are often referred to as control structures because they control when and how other statements are run. Generally, a control structure is composed of a beginning instruction and an ending one, with the instructions being controlled in the middle.
WordBasic offers more than one conditional statement and more than one way to create a loop. This chapter covers the If conditional and the While¼Wend loop; the next chapter covers the Select Case conditional and the For¼Next loop.
A condition is an expression that is either true or false. WordBasic uses conditions to determine whether or not to run the statements in an If conditional or a While¼Wend loop.
Consider the statement "Today is Monday." This statement is either true or false: either today is Monday or it isn't. The statement becomes a condition when it is put into a conditional sentence: "If today is Monday, I'll go to work." This conditional says that if the condition ("today is Monday") is true, the second part of the sentence will occur ("I'll go to work").
In WordBasic and other programming languages, you express a condition by comparing values. For example, if you say "Today is Monday," you are comparing today to Monday and saying that Monday and today are the same. In WordBasic, you compare values by using relational operators — symbols that state how values stand in relation to each other (they're equal, one is greater than the other, and so on). The symbols in the following table are probably familiar to you from math, although some might look a little different (for example, > = rather than >).
Relational operator | Meaning | |
= | Equal to | |
<> | Not equal to | |
> | Greater than | |
< | Less than | |
>= | Greater than or equal to | |
<= | Less than or equal to |
Word evaluates conditions — expressions that use relational operators — as either true or false. Here are some examples.
Condition | Evaluation | |
7 = 35 | False | |
7 <> 6 | True | |
7 <= 7 | True |
You can also compare strings.
Condition | Evaluation | |
"Bob" = "Bob" | True | |
"Bob" = "bob" | False | |
"Bob" <> "Jerry" | True | |
"Blue" < "Green" | True | |
"love" > "life" | True |
Most often, string comparisons are used to determine whether two strings match. For example, a macro might contain a condition such as StyleName$() = "Heading 2" which tests whether the current style name is "Heading 2." As the condition "Bob" = "bob" (which evaluates as false) reveals, the case of letters is significant in string comparisons; an uppercase "B" does not match a lowercase "b." You can use the WordBasic functions LCase$() and UCase$(), which return strings in lowercase and uppercase characters, to equalize case when doing string comparisons where case should be ignored.
How Word Evaluates String Comparisons You can use the > or < operator to compare whether one string is "greater than" or "less than" another. This sort of comparison is rare, but if you do use it, you need to know a little more about how string comparisons are evaluated. Word evaluates string comparisons character by character until it finds characters that don't match; the alphabetic or character code values for each character are then compared. If the characters are letters in the alphabet, Word evaluates them according to which letter is first in the alphabet. For example, "B" follows "A" in the alphabet, so "B" is evaluated as greater than "A." Likewise, an uppercase "B" follows a lowercase "a" in alphabetic order, so "B" is evaluated as greater than "a," even though the character code for "B" (66) is less than the character code for "a" (97). (The character codes for all lowercase letters are higher than the character codes for all uppercase letters; for that reason "b" is evaluated as greater than "B.") If the characters are nonalphabetic, Word evaluates them according to their character code value. For example, a period (.) is greater than a comma (,) because 46, the code for a period, is greater than 44, the code for a comma. Thus, "Blue" < "Green" is true because "B" comes before "G" in the alphabet. In the condition "love" > "life", both strings begin with "l," so Word evaluates the second characters in the strings; "o" comes after "i" in the alphabet, so the first string is evaluated as greater than the second one. |
Note
You can use numbers to represent "true" and "false". In a conditional, false can be represented as 0 (zero), and true can be represented as –1. Therefore, if the result of a conditional expression is 0 (zero), it is evaluated as false. If the result is any nonzero number (not just –1), it is evaluated as true. See "The While¼Wend Loop" later in this chapter for an example of a macro that uses this capability.
You can create a macro that is the WordBasic equivalent of the sentence "If today is Monday, I'll go to work."
To start with, create a series of numeric variables corresponding to the days of the week:
Sunday = 1 Monday = 2 Tuesday = 3 Wednesday = 4 Thursday = 5 Friday = 6 Saturday = 7
Next, add this instruction:
ThisDay = WeekDay(Today())
The numeric variable ThisDay holds the value returned by the WordBasic functions Today() and WeekDay(). Today() returns a serial number that represents the current date; WeekDay() converts that serial number into a number from 1 to 7, where 2 represents Monday, just like the variables you've set up. Now the macro is ready for the following conditional statement:
If ThisDay = Monday Then MsgBox "Time to go to work!"
The MsgBox statement displays a message box, so if the day happens to be Monday and you run the macro, you'll get this message box on your screen.
You can write the If conditional in several different ways, depending on how complex your control structure needs to be. The previous example used the shortest form, or syntax, as shown here:
If condition Then instruction
This syntax says that if the condition is true, the instruction will run. Generally, this form is used just for a single instruction because every instruction that is part of this form of the If conditional must be on the same line. In the following example, if the text is bold, bold formatting is removed:
If Bold() = 1 Then Bold 0
You could add instructions on the same line, separating each one with a colon (:). In the following example, if the text is bold, bold formatting is removed and italic applied:
If Bold() = 1 Then Bold 0 : Italic 1
But if you want to include more than one instruction within the If control structure, you generally use the following syntax:
If condition Then
Series of instructions
End If
All the instructions between If and End If are dependent on the condition. In the following example, If evaluates, or "tests," the condition to determine whether selected text is formatted as bold. If it is, the instructions remove the bold formatting and apply italic and underline formatting:
If Bold() = 1 Then 'If the selected text is bold, then Bold 0 'remove bold formatting Italic 1 'apply italic formatting Underline 1 'apply underline formatting End If
If control structures can include an Else instruction. Instructions subject to Else run if the condition is not true:
If condition Then
Series of instructions to run if condition is true
Else
Series of instructions to run if condition is false
End If
The following example toggles bold formatting. That is, if the selected text is formatted as bold, the first Bold instruction removes bold formatting; if the text is not bold, the second Bold instruction applies bold formatting (this is how the Bold button on the Formatting toolbar works):
If Bold() = 1 Then 'If the selected text is bold, then Bold 0 'remove bold formatting Else 'otherwise Bold 1 'apply bold formatting End If
An abbreviated, one-line version of the If¼Then¼Else syntax is available without the ending End If:
If condition Then instruction Else instruction
Again, this one-line structure works well for conditionals where only one or two instructions are involved. For example:
If Bold() = 1 Then Bold 0 Else Bold 1
For cases where multiple instructions are involved, the full syntax with End If works better.
The most complex form of the If conditional includes the ElseIf instruction:
If condition1 Then
Series of instructions to run if condition1 is true
ElseIf condition2 Then
Series of instructions to run if condition2 is true
Else
Series of instructions to run if no condition is true
End If
ElseIf is a second If conditional contained within a single If control structure. You could add an ElseIf instruction to the "days of the week" example presented earlier. In English, the conditional could be expressed as "If today is Saturday or Sunday, I'll stay at home; otherwise, I'll go to work." In WordBasic, the conditional might look like the following:
If ThisDay = Saturday Then MsgBox "Stay at home!" ElseIf ThisDay = Sunday Then MsgBox "Stay at home!" Else MsgBox "Go to work!" End If
You can add as many ElseIf instructions to an If conditional as you need. For example, you could use ElseIf to test a condition for every day of the week (although this wouldn't be a very efficient technique).
You can think of a While¼Wend loop as a conditional that can run the statements it controls more than once. Here's the syntax for the While¼Wend loop:
While condition
Series of instructions to run if condition is true
Wend
As with the If conditional, the instructions within a While¼Wend loop will not run unless condition is true. If condition is true, the instructions repeat until the condition is no longer true. If the condition never changes, an "endless loop" occurs — the instructions within the loop repeat endlessly until someone interrupts the macro by pressing ESC or clicking the Stop button on the toolbar. This is not usually an effect you want to achieve, so when you create a While¼Wend loop, you must build into it a means of changing the condition that starts the loop from true to false. This may sound difficult, but in practice it usually isn't. Consider the following example:
Sub MAIN StartOfDocument TRUE = - 1 EditFind .Find = "cool", .Direction = 0, .MatchCase = 0, \ .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0, \ .FindAllWordForms = 0, .Format = 0, .Wrap = 0 count = 0 While EditFindFound() = TRUE count = count + 1 RepeatFind Wend MsgBox "Cool was found" + Str$(count) + " times." End Sub
This macro moves the insertion point to the start of the document and then searches for the word "cool." It uses a While¼Wend loop to continue searching for "cool" until every instance of the word has been found. The macro then reports how many times it found the word in the document.
The condition EditFindFound() = TRUE controls the While...Wend loop. The EditFindFound() function returns a value of –1 if the result of the most recent search using EditFind was successful. If the search wasn't successful, EditFindFound() returns 0 (zero). In a condition, a result of 0 (zero) corresponds to "false," and –1 corresponds to "true." So if the search is not successful, EditFindFound() returns 0 (zero) and the condition is no longer true. Note that the variable TRUE, defined earlier as –1, is used instead of –1 to make the condition easier to read.
You can link two or more conditions together into a compound expression that is evaluated as a single condition. To link conditions together, you use the logical operators AND and OR, described as follows:
The following table provides some examples of compound expressions.
Compound expression | Evaluation |
10 > 5 And 100 < 200 | True |
3 < 6 And 7 > 10 | False |
8 < 7 Or 90 > 80 | True |
2 < 1 Or 3 > 60 | False |
"Y" > "N" And "yes" <> "no" | True |
"Y" < "N" Or 4 <> 4 | False |
Earlier in this section, the ElseIf instruction was used in an If control structure to express the conditional "If today is Saturday or Sunday, I'll stay at home; otherwise, I'll go to work." The following example uses a compound expression instead:
If ThisDay = Saturday Or ThisDay = Sunday Then MsgBox "Stay home today!" Else MsgBox "Time to go to work!" End If
The compound expression is more efficient in this case than using ElseIf — fewer instructions are needed to accomplish the same task and the instructions are also easier to understand, since they're closer to the way you would express the condition in English.
Note that the following instruction would not work properly:
If ThisDay = Saturday OR Sunday 'Produces the wrong result
Although this instruction reads like English, and you might therefore expect it to work, it does not. The expression ThisDay = Saturday is one condition and, on the other side of OR, Sunday is the other condition. WordBasic reads the compound expression as something like "If today is Saturday or if Sunday is Sunday." Because Sunday is always Sunday, the compound expression is always evaluated as true, no matter what day it is.
When WordBasic evaluates compound expressions, it proceeds from left to right; all conditions are evaluated first, then all compound expressions with AND, then all compound expressions with OR. You can use parentheses to control the order of evaluation, as in mathematical expressions.
Note
The AND and OR operators can be tricky. It is easy in some cases to use an OR operator when you need to use an AND. If you have any uncertainty over which one to use, test your macro.
A third logical operator available in WordBasic is NOT. The NOT operator negates the expression that follows it. The following table shows some examples.
Expression | Evaluation | |
Not (5 > 10) | True | |
Not (8 < 7 Or 90 > 80) | False | |
Not (0) | True |
The logic of the last example may not be immediately obvious. Because 0 (zero) is evaluated as false, Not (0) means "not (false)," or true.
The NOT operator is useful as a way to make a condition easier to read. For example, compare the following two instructions:
If ViewOutline() = 0 Then ViewOutline If Not ViewOutline() Then ViewOutline
The instructions have the same effect, but the second one is closer to the way the conditional would be expressed in English: "If the document is not in outline view, then switch to outline view."
Note
The NOT operator works well with functions such as ViewOutline() that return –1 (true) or 0 (false); it can reverse either value the function returns. It is usually not appropriate to use NOT with functions that can return other values. For more detailed information on NOT, see "Operators and Predefined Bookmarks" in Part 2, "WordBasic Reference."