|
This Microsoft Word Help & Tips page provides
a basic introduction to error handling and gives you some examples of
error handling methods. A more detailed discussion of the material can be
found in the VBA Help file under the topics "On Error Statement" and "Resume
Statement."
Why use error
handling? VBA help puts it like this: |
|

|
|
What is a run-time error? A run-time
error is an error that occurs when code is running. A run-time error results
when a code statement attempts an invalid operation. For a lengthy list of
things that can cause a run-time error see: "Trappable Errors" in the VBA
Help file.
With the following example macros you can produce
some rather obvious run-time errors and then use On Error and Resume
statements to illustrate some of the error
handling methods. To use these examples, start with a new blank
document and copy the example macros to the document VBA project. If
you need help copying or applying a macro see
fellow MVP Graham Mayor's tips here:
Installing Macros From
Listings
Once you have the macros copied to the
document VBA project, step through the lines of code using the F8 key or
the Debug toolbar Step Into command and
observe the results. |
|
Sub BacicA()
Dim i As Integer
ActiveDocument.Variables("Test2").Value = "Testing"
For i = 1 To 3
ActiveDocument.Variables("Test" & i).Delete
Next
End Sub |
|
In this first example there is no error handler
statement. The procedure creates a variable named "Test2" then
starts a For ... Next loop to delete variables named "Test1, Test2 and Test3."
Go ahead and step through the procedure. You will
see that when the
procedure attempts to delete the Variable "Test1" (an object that does not
exist) the attempt is an "invalid operation" and a run-time error is generated. |
|

|
|
Whenever you know, expect, or even suspect that a procedure
will produce a run-time error, and in this case it is obvious, then one
or more error handling statements can be used to complete execution and achieve the
desired result.
In the next example an "On Error Resume Next"
statement enables the error handler in the procedure and allows execution to
continue with the "next" statement immediately following the statement that
caused the error. Run-time error messaging and subsequent fatal stops are
suspended while the error handler is enabled. Step through this procedure to
observe that the expected errors (attempts to delete Varialbles1 and
Variables3) are handled by simply continuing through
the procedure until completion. |
|
Sub BacicB()
Dim i As Integer
ActiveDocument.Variables("Test2").Value = "Testing"
For i = 1 To 3
On Error Resume Next 'Enable
error handler
ActiveDocument.Variables("Test" & i).Delete
MsgBox "If present, variable Test" & i & " was deleted."
Next
End Sub |
|
In the
example above the On Error Resume Next statement works as intended without
complications. However, as you have seen the On Error Resume Next enables
an error handler and suspends the run-time error messaging and subsequent
fatal stops. Therefore it is not a good practice to use On Error Resume
Next by itself if additional errors could occur in the procedure. Consider
this example: |
|
Sub BacicC()
Dim i As Integer
ActiveDocument.Variables("Test2").Value = "Testing"
For i = 1 To 3
On Error Resume Next 'Enable
error handler
ActiveDocument.Variables("Test" & i).Delete
If i = 2 Then
MsgBox "You have won a million
dollars>." _
&
ActiveDocument.Variables("Test2").Value 'No
longer exists.
End If
Next
End Sub |
|
Here the On Error
Resume Next statement enables the procedures error handler when the
procedure tries to delete the non-existent Test1 variable. Run-time
messaging and fatal stop is suspended. Next the variable Test2 is
deleted. You would certainly be interested in getting that fanciful
message about the million dollars. However, the attempt to display
that message will fail because the message requires a result from variable
Test2 which has been deleted. Unfortunately since the procedures
error handler was previously enabled the
run-time messaging and fatal stops are suspended. The failed attempt
to
deliver the message passes without a whisper!
By adding another
simple statement to your procedure, you can clear the err object and thereby reset the error handler that had been so recklessly
left to go on unabated: |
|
Sub HandlingErrorsBacicD()
Dim i As Integer
ActiveDocument.Variables("Test2").Value = "Testing"
For i = 1 To 3
On Error Resume Next 'Enable
error handler
ActiveDocument.Variables("Test" & i).Delete
On Error GoTo 0 'Clear the err
object
If i = 2 Then
MsgBox "You have one a million
dollars>." _
&
ActiveDocument.Variables("Test2").Value
MsgBox "Aren't you glad you handled
that error!"
End If
Next
End Sub |
|
When you step through this time you will experience a
run-time error and fatal stop when the procedure tries to display the
message about your windfall! The added On Error GoTo 0 statement
cleared the err object and reset the error handler so the default run-time error messaging and
fatal stop was restored. You should make it a practice to use an On Error GoTo
0 in your procedures as soon as the expected error
stage following the On Error Resume Next statement is completed to ensure other unrelated
errors are not missed or improperly handled.
Of course you don't want to
really see that jarring new error message. You just want it properly
handled behind the scene and you want to get your important message.
This next
example uses the GoTo (line) method to achieve both of your goals: |
|
Sub BacicE()
Dim i As Integer
ActiveDocument.Variables("Test2").Value = "Testing"
For i = 1 To 3
On Error Resume Next 'Enable
error handler
ActiveDocument.Variables("Test" & i).Delete
On Error GoTo BasicE_Error 'Clears
the previous err object and enables
error handler
If i = 2 Then
MsgBox "You have one a million
dollars>." _
&
ActiveDocument.Variables("Test2").Value
MsgBox "Aren't you glad you handled
that error!"
End If
Next
Exit Sub
BasicE_Error:
If Err.Number = 5825 Then
MsgBox "You have won a million
dollars."
Resume Next
Else
MsgBox "Unexpected error. Type: " &
Err.Description
End If
End Sub |
|
Here the GoTo
ErrHandler statement enables the error handler and directs execution to the
line labeled ErrHandler: The error is evaluated and if the error is 5825 or
"Object has been deleted" as expected, then the important message is
delivered and execution is returned to next line following the line that
caused the error to occur.
Note: The
line label "ErrHandler:" is arbitary. If can be called anything you
like to make reading your code convienient. The important thing
is that the lable must be unique to the project and end with a colon(:). You should place a Exit
Sub line above the line lable so that the error
handling procedure
is bypassed when an error does not occur. |
|
In each of the preceding
examples you established conditions that would repeatedly fail. You
can never delete a variable or display the value of a varialbe that does not
exist. You have seen how On
Error and Resume statements can be used to complete the execution of your
prodecures seamlessly
despite known errros.
The next
example demonstates using error handling to identify and help "resolve" the
problem that caused the run-time error in the first place. Once
resolved, execution is returned to
the line that caused the failure and run again. |
|
Sub BacicF()
Dim i As Double
Dim j As Double
i = 6
j = 0 'Setting it up for initial failure
On Error GoTo BasicF_Error
MsgBox i / j 'Error occurs if j = 0
Exit Sub
BasicF_Error:
If Err.Number = 11 Then
j = InputBox(Err.Description & " is
not allowed." _
& " Enter a
non-zero denominator.")
Resume
Else
MsgBox "Unexpected error. Type: " &
Err.Description
End If
End Sub |
|
Here an error is
generated by establishing the denominator in a simple
calculation as zero. Division by zero is illogical. When the
error occurs, the
error handler is enabled and the error evaluated. The error handler
routine
provides an input box for the user to provide a non-zero denominator. With
the new denominator defined, the
"Resume" statement directes execution back to the step in the procedure that
caused the error. If the user entered a non-zero value in the input
box then the procedure executes to completion. |
For humans, the word 'error' has
connotations of 'bad' and 'mistake'; the computer has no such
preconceptions: an error is an just a condition, same as 'no error'.
--Regular Word newsgroup contributor Jezebel
|
| Err is an object, with properties and methods.
Using the err object is often useful to simplify or speed up
your code. Consider the task of determining if a particular style
exists in a document. An error free example would look something like
this: |
Sub ErrorFree()
Dim oStyle As Style
Dim styleName As String
styleName = "Goobledygook"
For Each oStyle In ActiveDocument.Styles
If oStyle.NameLocal = styleName Then
MsgBox styleName & " style exists in this
document."
Exit Sub
End If
Next oStyle
MsgBox styleName & " style is not found in this document."
End Sub |
| The code above is looking at every style in the document to
determine if that style is the style sought. The time taken to do this for a
few dozen sytels is
inconsequential, but consider iterating a few thousand items and an approach using error handling: |
Sub UsingErrorHandling()
Dim oStyle As Style
Dim styleName As String
styleName = "Goobledygook"
Set oStyle = Nothing
On Error Resume Next
Set oStyle = ActiveDocument.Styles(styleName)
On Error GoTo 0
If Not oStyle Is Nothing Then
MsgBox StyleName & " style exists in this docuement"
Else
MsgBox StyleName & " style is not found in this docuement"
End If
End Sub |
| The code above attempts to set the object variable oStyle to the style
Goobledygook. If the sytle does not exist an error occurs. The
Resume Next statement
suspends run-time
messaging. The On Error GoTo 0 resets error handling and restores run time messaging. An
error occurred but you the user were unaware of it. oStyle is "still"
Nothing and the Else statement is executed. If "Goobledygook" style
where present and regardless if it was the first or last style is a
collection of a billion, we would know it immediately and end the process. |
|
| Remember: |
| "Err" is an object with methods
and properties. |
| All "On Error" and "Resume"
statements clear the Err object. |
|
Sub BasicG()
On Error Resume Next
Err.Raise 6 'Create an overload error
MsgBox Err.Number 'Display the error number
using the err.numbernumber property
On Error GoTo 0 'Clear the err oject and resets
run time messaging/fatal stop
If Err.Number <> 0 Then
MsgBox Err.Number 'If it is
still 6 you would see this message
Else
MsgBox "You see the err object has been cleared. All " _
& "On Error and Resume statements
clear the " _
& "err object."
End If
On Error GoTo BasicG_Error:
Err.Raise 6
BasicG_Exit:
If Err.Number <> 0 Then
MsgBox Err.Number
Else
MsgBox "You see the err object has been cleared. All " _
& "On Error and Resume statements
clear the " _
& "err object."
End If
Exit Sub
BasicG_Error:
MsgBox Err.Number
Resume BasicG_Exit
End Sub |
| The error handler doesn't have to be in
the procedure that throws the error: |
| |
Sub A()
On Error GoTo A_Error:
Call B
A_Exit:
Exit Sub
A_Error:
MsgBox "Error number: " & Err.Number & " , Description: " & Err.Description
Resume A_Exit
End Sub
Sub B()
Call C
End Sub
Sub C()
Err.Raise 6 'Throw error here
End Sub |
| You can use the err object to raise your own
errors with all the object properties. The following main procedure
asks the user to open a Word file. Notice how the error handler raises
custom errors to deal with uncooperative user actions ;-) |
| |
Sub Main()
Dim oFile As String
On Error GoTo Main_Error
oFile = PickFile 'Pick a Word file to open
Documents.Open (oFile)
Main_Exit:
Exit Sub
Main_Error:
Select Case Err.Number
Case Is = vbObjectError + 1
'Do nothing. User canceled
Case Is = vbObjectError + 2
'User is having problems picking a
Word file. Create a new file.
Documents.Add
MsgBox "A new document was created
for you."
End Select
Resume Main_Exit
End Sub
Function PickFile() As String
Dim pFileName As String
Dim i As Long
For i = 1 To 3
With Dialogs(wdDialogFileOpen)
.Display
pFileName = .Name
End With
If Len(pFileName) = 0 Then
Err.Raise Number:=vbObjectError + 1,
Description:="User cancelled file selection"
ElseIf Not Right(pFileName, 5) = ".doc""" And i < 3 Then
MsgBox "That is not a Word file. Try
again.", vbOKOnly, "Wrong file type"
ElseIf Not Right(pFileName, 5) = ".doc""" And i = 3 Then
Err.Raise Number:=vbObjectError + 2,
Description:="Slow user."
ElseIf Right(pFileName, 5) = ".doc""" Then
Exit For
End If
Next i
PickFile = pFileName
End Function |
| I hope that you have found these examples informative and
useful. There is plenty of additional information available in the VBA
Help menu that you can review to expand on the basics presented here.
You can download a document with all the above macros here:
Download |
|
|
Looking for something else?
|
|
|
|
|