Microsoft Certified Professional

 

View Andrew Comeau's profile on LinkedIn

 

On Facebook ...

 

 

Andrew Comeau

 

Available on Amazon.com!

Programming Microsoft Access

VIII - Decision Structures

One of the advantages of using Visual Basic for Applications (VBA) rather than macros is the ability to control the order in which actions are performed and allow the code to make decisions based on the conditions it finds as it runs.  This is partially done through the event-driven programming structure of VBA.  Within procedures, it's done through the use of decision structures. 

IF ... THEN ... ELSE

The most basic structure is the IF ... THEN ... ELSE statement.  This statement controls the actions of the code depending on one or more conditions.  It's basic syntax is:

If <boolean condition> Then
  <action>
ElseIf
  <action>
Else
  <action>
End If

The Else and ElseIf statements are optional but the IF ... THEN and END IF statements are required.   Here's an example of IF ... THEN in action:

Public Function StrongPassword (Password as String) as Boolean

If Len(Password) > 7 Then
    StrongPassword = True
Else
    StrongPassword = False
End If

End Sub

The example above tests the length of the password entered, returns True if it's more than seven characters and False otherwise, thus making it an example of a boolean condition. Obviously, more than size matters when it comes to password strength but this is a start.

The IF .. THEN statement can also support multiple conditions:

If Len(Password) > 7 AND IsNumeric(Left(Password, 1)) Then
  StrongPassword = True
Else
  StrongPassword = False
End If

This is a variation on the password example where the length must be greater than 7 characters and the first character must be a number.  In this case, if both conditions are true, the function will return True.  Otherwise it will return false.  Aside from the logical AND operator used above, you could also use one of the other logical operators such as OR or XOR to govern the decision made by an IF ... THEN statement.

If I wanted to add a third test for the password, I could write this:

If Len(Password) > 7 AND IsNumeric(Left(Password, 1)) AND NOT IsNumeric(Password) Then ...

Writing it this way is considered bad practice, though, because it's unwieldy (a.k.a. ugly) code and causes VBA to do unnecessary calculations. If the first condition fails, the other two still have to be tested.  A better way to write this is to nest the IF ... THEN statements like so:

If Len(Password) > 7 Then
  If IsNumeric(Left(Password, 1)) Then
    If Not IsNumeric(Password) Then
      StrongPassword = True
    End If
  End If
End If

The three  conditions are now split into three decision statements and nested within each other.  If the password fails the first test, the others don't even execute and StrongPassword is not set to True unless all three pass.

With nesting, it's still best not to get carried away with too many levels because it can be hard to read and support later but this does allow for more operations.  It's also important not to get the levels of nesting tangled by accident. Close the most recently opened decision statement first.

As a final example, IF ... THEN can also test for multiple results from the same condition.

Public Function DayMessage(TestDate As Date) As String

If Weekday(TestDate) = vbSunday Then
  DayMessage = "It's a brand new week!"
ElseIf Weekday(TestDate) = vbMonday Then
  DayMessage = "Back to work ..."
ElseIf Weekday(TestDate) = vbFriday Then
  DayMessage = "T.G.I.F!!!"
Else
  DayMessage = "Have a great day!"
End If

End Function

In this example, the function accepts a date value that's passed in and uses the VBA Weekday function to determine the day of the week that it represents and provides the appropriate message.  The ElseIf statements test the date against the VBA weekday constants one at a time until a match is found.  If no match is found, the final Else statement acts as a catchall.

You can find more information on VBA functions like Weekday, Len and others used in these examples online in the Access help system.

Optimizing Code

When you're writing code, you can often find ways to make the code more efficient, just as you might find better ways of saying something as you're writing a letter or e-mail.  In programming, this is referred to as "optimizing" the code.  After writing this example, I remembered there was a better way to write it:

Public Function DayMessage(TestDate As Date) As String

Dim DayValue As Integer

DayValue = Weekday(TestDate)

If DayValue = vbSunday Then
  DayMessage = "It's a brand new week!"
ElseIf DayValue = vbMonday Then
  DayMessage = "Back to work ..."
ElseIf DayValue = vbFriday Then
  DayMessage = "T.G.I.F!!!"
Else
  DayMessage = "Have a great day!"
End If

End Function

In this variation, notice that the WeekDay function is only called once and the result is assigned to the Integer variable DayValue.  Instead of running the Weekday function over and over again, the DayValue variable is tested against the weekday constants which, although they are named, correspond to the numbers 1 through 7. In this case, the change won't make any noticeable difference but if the Weekday function was a large function that took even a couple seconds to run or accessed data tables, the time difference could be very noticeable, especially if the function or method calling it ran repeatedly. 

Another advantage would be if the result of the function being called could change from one moment to the next.  In this case, you might want to capture the result at a given moment in time and then refer to that result instead of calling the function again.  This is where programming goes beyond knowing the commands and syntax and involves design decisions and an understanding of how the system works.  I'll talk about this more in the chapter on algorithms.

SELECT CASE

While the above example for the IF ... THEN statement is acceptable and works perfectly well, the ElseIf statement isn't always appropriate for testing all the possible values of a given condition.  If there are more than three possible values to test against or you need to carry out the same action or a range of values, a SELECT CASE statement might be the better choice.  Here's the basic syntax:

Select Case <statement>
  Case <value>
    <action>
  Case <value>
    <action>
      ..
  Case Else
    <action>
End Select

Here's the IF ... THEN example rewritten in Case statements and expanded with more options.

Public Function DayMessage(TestDate As Date) As String

Select Case Weekday(TestDate)
  Case vbSunday
    DayMessage = "It's a brand new week!"
  Case vbMonday
    DayMessage = "Wake me when Monday's over."
  Case vbWednesday
    DayMessage = "Halfway there!"
  Case vbFriday
    DayMessage = "T.G.I.F.!!!!"
  Case vbSaturday
    DayMessage = "Sleep in today. It's Saturday!!"
  Case Else
    DayMessage = "Have a great day!"
End Select

End Function

Notice how much cleaner the code looks.  It's easier to read and understand.  Another advantage is that it evaluates the expression once at the top of the SELECT CASE statement rather than multiple times.  This eliminates extra processing and the need for the proxy variable that I declared in the IF...THEN statement.  There is still a catchall statement at the end where Case Else handles any result that doesn't match any of the other statements.  It's best to get in the habit of using an Else statement since it's possible to leave conditions unhandled without one and this can lead to errors, the cause of which isn't immediately obvious.

As with the IF...THEN statement, only the first matching Case statement is used and the code then continues after the End Select statement.  You can put any number of lines for execution after each Case statement.  You could even have Case statements with no code to execute if you wanted to take no action for a particular result.

The Case statements also have flexibility in specifying groups or ranges of values.  The following statements are all valid assuming that any variables used have been declared.

Case 100 to 199

Case 5, 10, 15, 20, 25 To 30

Case Is < 21, Is > 45

Case "Red", "Yellow", "Blue"

Case #1/1/2010# To #1/31/2010#

Note the use of the Is keyword with the greater/less than operators and the # around the date values.  The # is a type declaration character which signals to the code that the value should be treated as a date rather than a division formula.  It's used just as the quotation mark is used for strings.

Next:  Loops - Part 1

Back to Series Index

© 2011, Andrew Comeau, except where otherwise noted. Drewslair.com content should not be republished without written permission from the author.  Read our privacy policy.  More questions? Contact us at this address.

Microsoft is a registered trademark of Microsoft Corporation in the United States and other countries.