Excel 2019 Power Programming with VBA - Michael Alexander 21 стр.


The preceding section describes the For Each-Next construct, which is a type of loop. This section discusses the additional ways of controlling the execution of your VBA procedures.

 GoTo statements

 If-Then constructs

 Select Case constructs

 For-Next loops

 Do While loops

 Do Until loops

GoTo statements

The most straightforward way to change the flow of a program is to use a GoTo statement. This statement simply transfers program execution to a new instruction, which must be preceded by a label (a text string followed by a colon, or a number with no colon). VBA procedures can contain any number of labels, but a GoTo statement can't branch outside a procedure.

The following procedure uses the VBA InputBox function to get the user's name. If the name is not Howard, the procedure branches to the WrongName label and ends. Otherwise, the procedure executes some additional code. The Exit Sub statement causes the procedure to end.

Sub GoToDemo() UserName = InputBox("Enter Your Name:") If UserName <> "Howard" Then GoTo WrongName MsgBox ("Welcome Howard") ' -[More code here] - Exit Sub WrongName: MsgBox "Sorry. Only Howard can run this macro." End Sub

This simple procedure works, but it's not an example of good programming. In general, you should use the GoTo statement only when you have no other way to perform an action. In fact, the only time you really need to use a GoTo statement in VBA is for error handling (refer to Chapter 4, Working with VBA Sub Procedures).

If-Then constructs

Perhaps the most commonly used instruction grouping in VBA is the If-Then construct. This common instruction is one way to endow your applications with decision-making capability. Good decision-making is the key to writing successful programs.

The basic syntax of the If-Then construct is as follows:

If condition Then true_instructions [Else false_instructions]

The If-Then construct is used to execute one or more statements conditionally. The Else clause is optional. If included, the Else clause lets you execute one or more instructions when the condition that you're testing isn't True.

The following procedure demonstrates an If-Then structure without an Else clause. The example deals with time, and VBA uses a date-and-time serial number system similar to Excel's. The time of day is expressed as a fractional valuefor example, noon is represented as .5. The VBA Time function returns a value that represents the time of day, as reported by the system clock.

In the following example, a message is displayed if the time is before noon. If the current system time is greater than or equal to .5, the procedure ends, and nothing happens.

Sub GreetMe1() If Time < 0.5 Then MsgBox "Good Morning" End Sub

Another way to code this routine is to use multiple statements, as follows:

Sub GreetMe1a() If Time < 0.5 Then MsgBox "Good Morning" End If End Sub

Note that the If statement has a corresponding End If statement. In this example, only one statement is executed if the condition is True. You can, however, place any number of statements between the If and End If statements.

If you want to display a different greeting when the time of day is after noon, add another If-Then statement, as follows:

Sub GreetMe2() If Time < 0.5 Then MsgBox "Good Morning" If Time >= 0.5 Then MsgBox "Good Afternoon" End Sub

Notice that we used >= (greater than or equal to) for the second If-Then statement. This covers the remote chance that the time is precisely 12 p.m.

Sub GreetMe3() If Time < 0.5 Then MsgBox "Good Morning" Else _ MsgBox "Good Afternoon" End Sub

Notice that we used the line continuation sequence; If-Then-Else is actually a single statement.

If you need to execute multiple statements based on the condition, use this form:

Sub GreetMe3a() If Time < 0.5 Then MsgBox "Good Morning" ' Other statements go here Else MsgBox "Good Afternoon" ' Other statements go here End If End Sub

If you need to expand a routine to handle three conditions (for example, morning, afternoon, and evening), you can use either three If-Then statements or a form that uses ElseIf. The first approach is simpler.

Sub GreetMe4() If Time < 0.5 Then MsgBox "Good Morning" If Time >= 0.5 And Time < 0.75 Then MsgBox "Good Afternoon" If Time >= 0.75 Then MsgBox "Good Evening" End Sub

The value 0.75 represents 6 p.m.three-quarters of the way through the day and a good point at which to call it an evening.

In the preceding examples, every instruction in the procedure gets executed, even if the first condition is satisfied (that is, it's morning). A more efficient procedure would include a structure that ends the routine when a condition is found to be True. For example, it might display the Good Morning message in the morning and then exit without evaluating the other, superfluous conditions. True, the difference in speed is inconsequential when you design a procedure as small as this routine. For more complex applications, however, you need another syntax.

If condition Then [true_instructions] [ElseIf condition-n Then [alternate_instructions]] [Else [default_instructions]] End If

Sub GreetMe5() If Time < 0.5 Then MsgBox "Good Morning" ElseIf Time >= 0.5 And Time < 0.75 Then MsgBox "Good Afternoon" Else MsgBox "Good Evening" End If End Sub

With this syntax, when a condition is True, the conditional statements are executed, and the If-Then construct ends. In other words, the extraneous conditions aren't evaluated. Although this syntax makes for greater efficiency, some find the code to be more difficult to understand.

The following procedure demonstrates yet another way to code this example. It uses nested If-Then-Else constructs (without using ElseIf). This procedure is efficient and also easy to understand. Note that each If statement has a corresponding End If statement.

Sub GreetMe6() If Time < 0.5 Then MsgBox "Good Morning" Else If Time >= 0.5 And Time < 0.75 Then MsgBox "Good Afternoon" Else If Time >= 0.75 Then MsgBox "Good Evening" End If End If End If End Sub

The following is another example that uses the simple form of the If-Then construct. This procedure prompts the user for a value for Quantity and then displays the appropriate discount based on that value. Note that Quantity is declared as a Variant data type. This is because Quantity contains an empty string (not a numeric value) if InputBox is cancelled. To keep the procedure simple, it doesn't perform any other error checking. For example, it doesn't ensure that the quantity entered is a non-negative numeric value.

Notice that every If-Then statement in this procedure is always executed, and the value for Discount can change. The final value, however, is the desired value.

The following procedure is the previous one rewritten to use the alternate syntax. In this alternate version, only the If-Then statement that evaluates to True is actually executed.

VBA's IIf function

VBA offers an alternative to the If-Then construct: the IIf function. This function takes three arguments and works much like Excel's IF worksheet function. The syntax is as follows:

IIf(expr, truepart, falsepart)

 expr: (Required) Expression you want to evaluate

 truepart: (Required) Value or expression returned if expr is True

 falsepart: (Required) Value or expression returned if expr is False

The following instruction demonstrates the use of the IIf function. The message box displays Zero if cell A1 contains a 0 or is empty and displays Nonzero if cell A1 contains anything else.

MsgBox IIf(Range("A1") = 0, "Zero", "Nonzero")

It's important to understand that the third argument (falsepart) is always evaluated, even if the first argument (expr) is True. Therefore, the following statement generates a division-by-zero error if the value of n is 0 (zero):

MsgBox IIf(n = 0, 0, 1 / n)

Select Case constructs

The Select Case construct is useful for choosing among three or more options. This construct also works with two options, and it is a good alternative to If-Then-Else. The syntax for Select Case is as follows:

Select Case testexpression [Case expressionlist-n [instructions-n]] [Case Else [default_instructions]] End Select

The following example of a Select Case construct shows another way to code the GreetMe examples presented in the preceding section:

Sub GreetMe() Dim Msg As String Select Case Time Case Is < 0.5 Msg = "Good Morning" Case 0.5 To 0.75 Msg = "Good Afternoon" Case Else Msg = "Good Evening" End Select MsgBox Msg End Sub

And here's a rewritten version of the Discount example using a Select Case construct. This procedure assumes that Quantity is always an integer value. For simplicity, the procedure performs no error checking.

Sub Discount3() Dim Quantity As Variant Dim Discount As Double Quantity = InputBox("Enter Quantity: ") Select Case Quantity Case "" Exit Sub Case 0 To 24 Discount = 0.1 Case 25 To 49 Discount = 0.15 Case 50 To 74 Discount = 0.2 Case Is >= 75 Discount = 0.25 End Select MsgBox "Discount: " & Discount End Sub

Sub GreetUser1() Select Case Weekday(Now) Case 1, 7 MsgBox "This is the weekend" Case Else MsgBox "This is not the weekend" End Select End Sub

The following example shows another way to code the previous procedure:

Sub GreetUser2() Select Case Weekday(Now) Case 2, 3, 4, 5, 6 MsgBox "This is not the weekend" Case Else MsgBox "This is the weekend" End Select End Sub

Here's another way to code the procedure, using the To keyword to specify a range of values:

Sub GreetUser3() Select Case Weekday(Now) Case 2 To 6 MsgBox "This is not the weekend" Case Else MsgBox "This is the weekend" End Select End Sub

To demonstrate the flexibility of VBA, here is a final example in which each case is evaluated until one of the expressions evaluates to True:

Sub GreetUser4() Select Case True Case Weekday(Now) = 1 MsgBox "This is the weekend" Case Weekday(Now) = 7 MsgBox "This is the weekend" Case Else MsgBox "This is not the weekend" End Select End Sub

Sub Discount3() Dim Quantity As Variant Dim Discount As Double Quantity = InputBox("Enter Quantity: ") Select Case Quantity Case "": Exit Sub Case 0 To 24: Discount = 0.1 Case 25 To 49: Discount = 0.15 Case 50 To 74: Discount = 0.2 Case Is >= 75: Discount = 0.25 End Select MsgBox "Discount: " & Discount End Sub

TIP

VBA exits a Select Case construct as soon as a True case is found. Therefore, for maximum efficiency, you should check the most likely case first.

Select Case structures can also be nested. The following procedure, for example, uses the VBA TypeName function to determine what is selected (a range, nothing, or anything else). If a range is selected, the procedure executes a nested Select Case and tests for the number of cells in the range. If one cell is selected, it displays One cell is selected. Otherwise, it displays a message with the number of selected rows.

Sub SelectionType() Select Case TypeName(Selection) Case "Range" Select Case Selection.Count Case 1 MsgBox "One cell is selected" Case Else MsgBox Selection.Rows.Count & " rows" End Select Case "Nothing" MsgBox "Nothing is selected" Case Else MsgBox "Something other than a range" End Select End Sub

Назад Дальше