Chapter 12. Built-in Functions and Statements

VBA has a large number of built-in functions and statements. For possible reference, Table 12-1 shows the VBA functions, and Table 12-2 shows the statements. We will take a look at a few of the more commonly used functions and statements in this chapter and the next.

Table 12-1. VBA functions

Abs

CreateObject

Error

InputB

Len

PPmt

StrComp

Array

CSng

Exp

InputBox

LenB

PV

StrConv

Asc

CStr

FileAttr

InStr

LoadPicture

QBColor

String

AscB

CurDir

FileDateTime

InStrB

Loc

Rate

Switch

AscW

Cvar

FileLen

Int

LOF

RGB

SYD

Atn

CVDate

Fix

Ipmt

Log

Right

Tab

CBool

CVErr

Format

IRR

Ltrim

RightB

Tan

CByte

Date

FreeFile

IsArray

Mid

Rnd

Time

CCur

DateAdd

FV

IsDate

MidB

RTrim

Timer

CDate

DateDiff

GetAllSettings

IsEmpty

Minute

Second

TimeSerial

CDbl

DatePart

GetAttr

IsError

MIRR

Seek

TimeValue

CDec

DateSerial

GetAutoServerSettings

IsMissing

Month

Sgn

Trim

Choose

DateValue

GetObject

IsNull

MsgBox

Shell

TypeName

Chr

Day

GetSetting

IsNumeric

Now

Sin

UBound

ChrB

DDB

Hex

IsObject

Nper

SLN

UCase

ChrW

Dir

Hour

Lbound

NPV

Space

Val

CInt

DoEvents

Iif

Lcase

Oct

Spc

VarType

CLng

Environ

IMEStatus

Left

Partition

Sqr

Weekday

Command

EOF

Input

LeftB

Pmt

Str

Year

Cos

      
Table 12-2. VBA statements

AppActivate

DefDec

Error

Kill

Open

Randomize

Set

Beep

DefInt

Event

Let

Option Base

ReDim

SetAttr

Call

DefLng

Exit

Line Input #

Option Compare

Rem

Static

ChDir

DefObj

FileCopy

Load

Option Explicit

Reset

Stop

ChDrive

DefSng

For Each...Next

Lock

Option Private

Resume

Sub

Close

DefStr

For...Next

LSet

Print #

Return

Time

Const

DefVar

Function

Mid

Private

RmDir

Type

Date

DeleteSetting

Get

MidB

Property Get

RSet

Unload

Declare

Dim

GoSub...Return

MkDir

Property Let

SavePicture

Unlock

DefBool

Do...Loop

GoTo

Name

Property Set

SaveSetting

While...Wend

DefByte

End

If...Then...Else

On Error

Public

Seek

Width #

DefCur

Enum

Implements

On...GoSub

Put

Select Case

With

DefDate

Erase

Input #

On...GoTo

RaiseEvent

SendKeys

Write #

DefDbl

      

To help simplify the exposition, we will follow Microsoft’s lead and use square brackets to indicate optional parameters. Thus, for instance, the second parameter in the following procedure is optional:

Sub ChangeFieldType(sFieldName, [NewSize])

Note that we have also omitted the data type declarations, which will be discussed separately.

The MsgBox Function

We have been using the MsgBox function unofficially for some time now. Let us introduce it officially. The MsgBox function is used to display a message and wait for the user to respond by pushing a button. The most commonly used syntax is:

MsgBox(prompt [, buttons] [, title])

(This is not the function’s complete syntax. There are some additional optional parameters related to help contexts that you can look up in the help documentation.)

prompt is a String parameter containing the message to be displayed in the dialog box. Note that a multiline message can be created by interspersing the vbCrLf constant within the message.

buttons is a Long parameter giving the sum of values that specify various properties of the message box. These properties are the number and type of buttons to display, the icon style to use, the identity of the default button, and the modality of the message box. (A system modal dialog box remains on top of all currently open windows and captures the input focus systemwide, whereas an application modal dialog box remains on top of the application’s windows only and captures the application’s focus.) The various values of buttons that we can sum are shown in Table 12-3. (They are officially defined in the VbMsgBoxStyle enum.)

Table 12-3. The MsgBox buttons argument values

Purpose

Constant

Value

Description

Button types

vbOKOnly

0

Display OK button only

 

vbOKCancel

1

Display OK and Cancel buttons

 

vbAbortRetryIgnore

2

Display Abort, Retry, and Ignore buttons

 

vbYesNoCancel

3

Display Yes, No, and Cancel buttons

 

vbYesNo

4

Display Yes and No buttons

 

vbRetryCancel

5

Display Retry and Cancel buttons

Icon types

vbCritical

16

Display Critical Message icon

 

vbQuestion

32

Display Warning Query icon

 

vbExclamation

48

Display Warning Message icon

 

vbInformation

64

Display Information Message icon

Default button

vbDefaultButton1

0

First button is default

 

vbDefaultButton2

256

Second button is default

 

vbDefaultButton3

512

Third button is default

 

vbDefaultButton4

768

Fourth button is default

Modality

vbApplicationModal

0

Application modal message box

 

vbSystemModal

4096

System modal message box

For instance, the code:

MsgBox "Proceed?", vbQuestion + vbYesNo

displays the message box shown in Figure 12-1, which includes a question-mark icon and two command buttons, labeled Yes and No.

A MsgBox dialog box
Figure 12-1. A MsgBox dialog box

The title parameter is a string expression that is displayed in the title bar of the dialog box. If we omit this argument, then Microsoft Access will be displayed, as in Figure 12-1.

The MsgBox function returns a number indicating which button was selected. These return values are given in Table 12-4. (They are officially defined in the VbMsgBoxResult enum.)

Table 12-4. MsgBox return values

Constant

Value

Description

vbOK

1

OK button pressed

vbCancel

2

Cancel button pressed

vbAbort

3

Abort button pressed

vbRetry

4

Retry button pressed

vbIgnore

5

Ignore button pressed

vbYes

6

Yes button pressed

vbNo

7

No button pressed

The InputBox Function

The InputBox function is designed to get input from the user. The most commonly used (but not complete) syntax is:

InputBox(prompt [, title] [, default])

where prompt is the message in the input box, title is the title for the input box, and default is the default value that is displayed in the text box. For instance, the code:

sName = InputBox("Enter your name.", "Name", "Albert")

produces the dialog box in Figure 12-2.

An InputBox dialog box
Figure 12-2. An InputBox dialog box

The InputBox function returns the string that the user enters into the text box. Thus, in our example, the string variable sName will contain this string.

Note that if we want a number from the user, we can still use the InputBox function and simply convert the returned string (such as "12.55") to a number (12.55) using the Val function, discussed later in the chapter.

VBA String Functions

Here are a handful of useful functions that apply to strings (both constants and variables):

The Len function

The Len function returns the length of a string, that is, the number of characters in the string. Thus, the code:

Len("January Invoice")

returns the number 15.

The UCase and LCase functions

These functions return an all-uppercase or all-lowercase version of the string argument. The syntax is:

UCase(string)
LCase(string)

For instance:

MsgBox UCase("Donna")

will display the string DONNA.

The Left, Right, and Mid functions

These functions return a portion of a string. In particular:

Left(string, number)

returns the leftmost number characters in string, and:

Right(string, number)

returns the rightmost number characters in string. For instance:

MsgBox Right("Donna Smith", 5)

displays the string Smith.

The syntax for Mid is:

Mid(string, start, length)

This function returns the first length number of characters of string, starting at character number start. For instance:

Mid("Library.xls",9,3)

returns the string xls. If the length parameter is missing, as in:

Mid("Library.xls",9)

the function will return the rest of the string, starting at start.

The InStr function

The syntax for this very useful function is:

InStr(Start, StringToSearch, StringToFind)

The return value is the position, starting at Start, of the first occurrence of StringToFind within StringToSearch. If Start is missing, then the function starts searching at the beginning of StringToSearch. For instance:

MsgBox InStr(1, "Donna Smith", "Smith")

displays the number 7, because "Smith" begins at the seventh position in the string "Donna Smith".

The Str and Val functions

The Str function converts a number to a string. For instance:

Str(123)

returns the string 123. Conversely, the Val function converts a string that represents a number into a number (so that we can do arithmetic with it, for instance). For example:

Val("4.5")

returns the number 4.5 and:

Val("1234 Main Street")

returns the number 1234. Note, however, that Val does not recognize dollar signs or commas. Thus:

Val($12.00)

returns 0, not 12.00.

The type-conversion functions

The Str and Val functions have been replaced by the more modern type-conversion functions: CBool, CByte, CCur, CDate, CDbl, CDec, CInt, CLng, CSng, CVar, and CStr. For instance, the function CStr converts its argument to a string, as in:

CStr(123)

One advantage of the newer type-conversion functions over the older Str and Val functions is that the new functions are international-aware. For instance, the CCur function converts an expression to currency format, taking into account the particular decimal separators, thousands separators, and other currency options that are determined by the locale setting of the computer upon which the function is being used.

The Trim , LTrim, and RTrim functions

The LTrim function removes leading spaces from a string. Similarly, RTrim removes trailing spaces, and Trim removes both leading and trailing spaces. Thus:

Trim("  extra   ")

returns the string extra.

The String and Space functions

The String function provides a way to create a string quickly that consists of a single character repeated a number of times. For instance:

sText = String(25, "B")

sets sText to a string consisting of 25 Bs. Also, the Space function returns a string consisting of a given number of spaces. For instance:

sText = Space(25)

sets sText to a string consisting of 25 spaces.

The Like operator and StrCmp function

The Like operator is very useful for comparing two strings. Of course, we can use the equal sign:

string1 = string2

which is true when the two strings are identical. However, Like will also make a case-insensitive comparison or allow the use of pattern matching.

The expression:

string Like pattern

returns True if string fits pattern and returns False otherwise. (Actually, the expression can also return Null.) We will describe pattern in a moment.

The type of string comparison that the Like operator uses depends upon the setting of the Option Compare statement. There are two possibilities:

Option Compare Binary
Option Compare Text

one of which should be placed in the Declarations section of a module (in the same place as Option Explicit). Note that the default is Option Compare Binary.

Under Option Compare Binary, string comparison is in the order given by the ANSI character code, as shown here:

A < B < . . . < Z < a < b < . . . < z < À < . . . < Ø < à < . . . <

Under Option Compare Text, string comparison is based on a case-insensitive sort order (determined by your PC’s locale setting). This gives a sort order as shown here:

A = a < À = à < B = b < . . . < Z = z < Ø =

By the way, the last item in the Text sort order is the left bracket ( [ ) character, with ANSI value 91. This is useful to know if you want to place an item last in alphabetical order—just surround it by square brackets.

The pattern-matching features of the Like operator allow the use of wildcard characters, character lists, or character ranges. For example:

?

Matches any single character

*

Matches zero or more characters

#

Matches any single digit (0-9)

[charlist]

Matches any single character in charlist

[!charlist]

Matches any single character not in charlist

For more details, check the VBA help file.

The StrComp function also compares two strings. Its syntax is:

StrComp(string1, string2 [, compare])

and it returns a value indicating whether string1 is equal to, greater than, or less than string2. For more details, check the VBA help file.

Miscellaneous Functions and Statements

We’ll conclude our discussion of Access VBA functions and statements by examining a hodgepodge of language constructs that perform such tasks as evaluating objects or variables, evaluating an expression, and altering program flow based on an expression’s values.

The Is Functions

VBA has several Is functions that return Boolean values indicating whether a certain condition holds. We have already discussed the IsMissing function in connection with optional arguments. Here are some additional Is functions.

The IsDate function

This function indicates whether an expression can be converted to a date. For instance, the code:

Dim x As String
x = "1/1/45"
Debug.Print IsDate(x)

will print True to the Immediate window.

The IsEmpty function

This function indicates whether a variable has been initialized. For example, the code:

Dim x As Variant
If IsEmpty(x) Then . . .

tests whether the variable x is empty.

The IsNull function

This function is used to test whether a variable or field is Null (that is, contains no data). Note that code such as:

If var = Null Then

will always return False because most expressions that involve Null automatically return Null. The proper way to determine if the variable var is Null is to write:

If IsNull(var) Then

Here is a typical scenario:

Dim rs As Recordset
Dim s As String
Set rs = CurrentDb.OpenRecordset("Names")
rs.MoveFirst
If Not IsNull(rs!LastName) Then
	s = rs!LastName
	. . .
End If

The IsNumeric function

This function indicates whether an expression can be evaluated as a number. For instance, consider the code:

Dim s As String
s = "123"
If IsNumeric(s) Then Debug.Print "Number"

This will print the word “Number.” However, if we change the second line to:

s = "123 Main St"

then the Debug.Print statement will not execute.

The Immediate If Function

The Immediate If function has the syntax:

IIf(Expression, TruePart, FalsePart)

If Expression is True, then the function returns TruePart. If Expression is False, the function returns FalsePart. For instance, consider the following code:

Dim rs As Recordset
Dim s As String

Set rs = CurrentDb.OpenRecordset("Names")
rs.MoveFirst

If Not IsNull(rs!LastName) Then
	s = rs!LastName)
End If

This code fills a string variable with a field value. We must make a distinction between a Null and non-Null field value because the code:

s = rs!Lastname

will produce the error “Invalid use of Null” if we try to assign a Null value to a string variable.

It is very important to note that the Immediate If function always evaluates both TruePart and FalsePart, even though it returns only one of them. Hence, we must be careful about undesirable side effects. For example, the following code will produce a “Division by Zero” error because even though the IIf function returns 1/x only when x is not equal to 0, the expression 1/x is evaluated in all cases, including when x = 0:

x = 0
y = IIf(x = 0, x ^ 2, 1 / x)

The Switch Function

The syntax of the Switch function is:

Switch(expr1, value1, expr2, value2, ... , exprn, valuen)

where exprn and valuen are expressions. Note that there need only be one expression-value pair, but the function is more meaningful if there are at least two such pairs.

The Switch function evaluates each expression exprn. When it encounters the first True expression, it returns the corresponding value. As with the IIf function, Switch always evaluates all of the expressions. If none of the expressions is True, the function returns Null. This can be tested with the IsNull function.

The procedure in Example 12-1 displays the type of file based on its extension: Access database, text, or dbase database.

Example 12-1. The Switch function
Sub ShowFileType(FileExt As String)

Dim FileType As Variant

FileType = Switch(FileExt = "mdb", "Database", _
                  FileExt = "txt", "Text", _
                  FileExt = "dbf", "dBase")

' Display result
If Not IsNull(FileType) Then
   MsgBox FileType
Else
   MsgBox "Unrecognized type"
End If

End Sub

There is one subtlety in this code. Since the Switch function can return a Null value, we cannot assign the return value to a String variable, as we might first try to do:

Dim FileType As String

FileType = Switch(FileExt = "mdb", "Database", _
                  FileExt = "txt", "Text", _
                  FileExt = "dbf", "dBase")

This will produce an error if FileExt is not "mdb", "txt", or "dbf“, in which case we will get the very annoying error message, “Invalid use of Null.” The solution is to declare FileType as a Variant, which can hold any data type, including no data type, which is indicated by the Null keyword. (This issue can be avoided by using a Select Case statement, discussed in Chapter 13.)

The Beep Statement

This simple statement, whose syntax is:

Beep

sounds a single tone through the computer’s speakers. It can be useful (when used with restraint) if we want to get the user’s attention. However, there is a caveat: the results are dependent upon the computer’s hardware, and so the statement may not produce a sound at all! Thus, if you use this statement in your code, be sure to warn the user.

Handling Errors in Code

I discussed the various types of errors in Chapter 9 , but I have scrupulously avoided the question of how to handle runtime errors in code. Indeed, VBA provides several tools for handling errors (On Error, Resume, the Err object, and so on), and we could include an entire chapter on the subject in this book.

Proper error handling is extremely important. Indeed, if you are, or intend to become, a professional application developer, then you should familiarize yourself with error-handling procedures.

On the other hand, if your intention is to produce Access VBA code for your own personal use, then the reasons for adding error-handling routines are somewhat mitigated. When an error occurs within one of your own programs, VBA will stop execution, display an error message, and highlight the offending code. This should enable you to debug the application and fix the problem. (It would be unreasonable to expect another user of your program to debug your code, however.)

Let us undertake a brief discussion of the highlights of error handling. (For more details, may I suggest my book Concepts of Object-Oriented Programming in Visual Basic, published by Springer-Verlag. It has a detailed chapter on error handling.)

The On Error Goto Label Statement

The On Error statement tells VBA what to do when a runtime error occurs. The most common form of the statement is:

On Error GoTolabel

where label is a label. For instance, consider the following code:

Sub RecordCt(  )

On Error GoTo ERR_EXAMPLE

Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset("Name")

MsgBox rs.RecordCount

Exit Sub

ERR_EXAMPLE:
  MsgBox "Error " & Err.Number & " - " & Err.Description, vbCritical
  Exit Sub
    
End Sub

The purpose of this procedure is simply to display the number of rows in a table. However, the database does not happen to have a table called Name. Hence, when VBA encounters the line:

Set rs = CurrentDb.OpenRecordset("Name")

a runtime error will occur.

To deal with this possibility in a friendly manner, we add some error checking. The line:

On Error GoTo ERR_EXAMPLE

tells VBA to move execution to the label ERR_EXAMPLE if an error does occur. The code following this label is called the error-handling code. If an error should occur, the next line executed is the MsgBox line, in which case the dialog box in Figure 12-3 will be displayed. This message gives a description of the error, obtained from the error object, which we discuss in the next section.

An error dialog box
Figure 12-3. An error dialog box

It is important to note the:

Exit Sub

line just before the ERR_EXAMPLE label. Without this statement, the error-handling code will always be executed, even when there is no error! Omitting this line is a common mistake. Note also that labels always end with a colon.

The process of adding error-handling code to a procedure is sometimes referred to as error-trapping .

Handling Errors in the Calling Procedure

Consider the following version of the RecordCt function:

Function RecordCt(TableName As String) As Integer

On Error GoTo ERR_EXAMPLE

Dim rs As Recordset

Set rs = CurrentDb.OpenRecordset(TableName)
RecordCt = rs.RecordCount
rs.Close

Exit Function

ERR_EXAMPLE:
  RecordCt = -1  ' Indicates error
  rs.Close
  
Exit Function
    
End Function

In this case, if there is an error, the function will simply return the value -1, rather than displaying a message box. This behavior is better than that of the previous version, because in this case the calling procedure can decide what to do.

Here is a procedure that calls RecordCt:

Sub Main(  )

On Error GoTo Err_Main

Dim rc As Long
rc = RecordCt("Object")

If rc = -1 Then
   ' code here to handle error
Else
   ' code here for no error
End If
Exit Sub

Err_Main:
  MsgBox "Error " & Err.Number & " - " & Err.Description, vbCritical
  Exit Sub

End Sub

Note that a return value of -1 is not perceived by VBA as an error at all, so we need to handle the error using code such as:

If rc = -1 Then

The Calls Stack

What happens if we do not trap errors in a procedure?

If the procedure was not called by another procedure, but rather was called directly by the user, or if the procedure is an event procedure—that is, code that executes in response to a user manipulating a control on a form (for instance, clicking on a command button)—then VBA just displays an error message and halts the program.

However, if the procedure in which the error occurred was called by another procedure, then VBA passes the error to the calling procedure, just as though the calling procedure had caused the error.

To illustrate this, consider the following procedures:

Function RecordCt2(TableName As String) As Integer
Dim rs As Recordset
Set rs = CurrentDb.OpenRecordset(TableName)
RecordCt2 = rs.RecordCount
rs.Close
End Function

' -----

Sub Main2(  )

On Error GoTo Err_Main

Dim rc As Long
rc = RecordCt2("Objects")

' More code here

Exit Sub

Err_Main:
  MsgBox "Error " & Err.Number & " - " & Err.Description, vbCritical
  Exit Sub

End Sub

The RecordCt2 function has no error-trapping code. If Main2 calls RecordCt2 with a bad table name, the error in RecordCt2 will be passed to Main2, whose error-trapping code will execute. Thus, we will get an error message from Main2. (This may be just fine.)

More generally, if ProcedureA calls ProcedureB, which calls ProcedureC, and so on, then an error in any one procedure will be passed up the call stack (list of procedures in reverse order of execution) until a procedure with error-handling code is encountered. If none is encountered, then VBA will issue its own error message and terminate the program.

Incidentally, you can view the call stack while in break mode by choosing Call Stack from the View menu.

The Error Object

The error object, denoted by Err, belongs to the VBA object model. The most important properties of this object are:

Number

The VBA error number

Source

The name of the current VBA project

Description

A description of the error

Thus, for instance, the line:

MsgBox "Error " & Err.Number & " - " & Err.Description, vbCritical

displays the error number and its description.

The Err object has a Clear method:

Err.Clear

that will clear all of the properties of the Err object, setting its Number property to 0 (which indicates the absence of an error).

The On Error GoTo 0 Statement

The statement:

On Error GoTo 0

turns off any previous On Error GoTo label statements. Any error occurring subsequently will be handled by VBA in its own inimitable way.

The On Error Resume Next Statement

The syntax:

On Error Resume Next

tells VBA to continue executing the code immediately following the line that caused the error. There are two important uses for this form of On Error. The first is to cause VBA to ignore an error. For instance, the code:

Sub example(  )

On Error Resume Next
MsgBox rs.RecordCount

End Sub

will report the record count when rs is a valid recordset and do nothing otherwise.

Another important use for the On Error Resume Next syntax is for in-line error checking , where we check for errors immediately following the line that may have caused an error. For instance, another way to handle errors in the RecordCount property is as follows:

Sub example(  )

On Error Resume Next

MsgBox rs.RecordCount

If Err.Number <> 0 Then
  ' code to handle error here
End If
End Sub

The Resume Statement

It is also possible to include the Resume statement in the error-handling portion of the code. This will cause VBA to resume execution at the line that follows the one that caused the error. Thus, the previous code is equivalent to the following:

Sub example(  )

On Error GoTo ERR_EXAMPLE
MsgBox rs.RecordCount

' An error will cause execution to resume here after 
' displaying an error message

Exit Sub
ERR_EXAMPLE:
  MsgBox Err.Description, vbCritical
  Resume Next
    
End Sub

There are three variations on the Resume statement:

  • Resume

  • Resume Next

  • Resume ALabel

The first version will cause VBA to resume with the line that caused the error. This is useful if your error-handling code actually repairs the error condition and you want the line that caused the original error to be executed again.

To illustrate, if the procedure in Example 12-2 encounters an error, it branches to an error handler. This handler checks for error number 3078, which is the “Can’t find table” error. If this is the error, then the procedure displays a dialog box asking for a new table name. If the user enters a new name, the Resume statement is executed, and so the line:

Set rs = CurrentDb.OpenRecordset(TableName)

is repeated. Note that it is vital to give the user a way out, however. This is done by letting the user leave the dialog box blank. (Incidentally, I got the correct error number 3078 by simulating the error and reading the resulting error-message dialog box.)

Example 12-2. Error handling with the Resume statement
Function RecordCt3(TableName As String) As Integer

On Error GoTo ERR_EXAMPLE

Dim rs As Recordset

Set rs = CurrentDb.OpenRecordset(TableName)

RecordCt = rs.RecordCount

rs.Close
Exit Function

ERR_EXAMPLE:
   If Err.Number = 3078 Then
      ' Can't find table
      sTable = InputBox("Can't find table " & sTable & _
               ". Please enter table name again or leave blank to end.")
      If sTable = "" Then
         rs.Close
         TableName = sTable
         Exit Function
      Else
         Resume
      End If
   Else
      ' Unknown error
      MsgBox "Error " & Err.Number & " - " & Err.Description, vbCritical
      rs.Close
      Exit Function
   End If
    
End Function

The third variation:

Resume ALabel

causes VBA to resume execution at the line labeled ALabel .

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.161.153