Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Error Handling 10

Status
Not open for further replies.

CasperTFG

Programmer
Nov 15, 2001
1,210
0
0
US
Through helping people out with their code I have noticed one thing which a lot of new programmers are missing. Error Handling is the most important part of your code beside the actual code that does the work. A good programmer knows that you should never have an un-handled error.

What is an un-handled error?
An unhandled error is any error that happens in your code that you allow windows to deal with. If you fail to include error handling in your code, then a simple error such as a file that you try to open went missing will cause your entire program to crash. If you handle the error in your code, then you can save it from crashing and possibly recover the error.

Helpful Error Handling Commands
On Error GoTo – This command will tell the program that If an error should occur you should go to this portion of code.
ErrorHandler: – This is a line label. It marks the start of a section of code. Anytime you place a : after a word this marks a line label.
On Error Resume Next – This code will tell your program to ignore any errors that may occur.
err – The err function has many values, it can pass you the desciption, the error number, and etc. There are also variations on this, such as ADOerr

How to Handle the Errors in your Code
Here is a sample of Error Handling in a Command button
[tt]
Private Sub Command1_Click()
On Error GoTo ErrorHandler

’Include Your Code Here

Exit Sub ’Include this line to unsure that if the code runs without problem it won’t hit the error handler
ErrorHandler:
’Include Your Error Handling Code Here
End Sub
[/tt]
You can See by the above code, the first line is On Error GoTo. This is done so that If an error should occur at any point throughout this entire function the error will be handled. However if there is a specific piece of code that you are worried may kick up an error (such as opening a file), this can be done with specific error handling. Like this:
[tt]
Private Sub Command1_Click()

’Include Your Code Here

On Error GoTo FileError ’Place this right before the line that may cause an error

’Include Your Code Here

Exit Sub ’Include this line to unsure that if the code runs without problem it won’t hit the error handler
FileError:
’Include Your Error Handling Code Here
End Sub
[/tt]

If the error that occurs is not a big error more of a small glitch, then you may want to continue on with your code. Such as If you are looking for a value from a file, but the file is gone, you don’t want to have your program stop and fail, instead you could continue on with a default value or the next line of code. The Resume Next function is ideal for this.
[tt]
Private Sub Command1_Click()
On Error Resume Next

’Include Your Code Here

End Sub
[/tt]

Bringing them all together
Now that we know several types of error Handling lets put them together into one.
[tt]
Private Sub Command1_Click()
On Error GoTo ErrorHandler

’Include Your Code Here

On Error GoTo FileError ’Place this right before the line that may cause a file error

’Include File opening code here

On Error GoTo ErrorHandler ’Place this right after the line that may cause a file error to resume regular error handling

’Put in the rest of your code here

Exit Sub ’Include this line to unsure that if the code runs without problem it won’t hit the error handler
FileError:
’Include Your Error Handling For not being able to open the file
Exit Sub ’Include this line to unsure that if the code runs without problem it won’t hit the error handler
ErrorHandler:
’Include Your Error Handling Code Here
Resume Next ’this will tell the Program to continue on with the rest of the code.
End Sub
[/tt]

Deciding how to Handle Errors
Depending on how you want your program to look to a user will help you decide on how to handle errors. A program to be used internally in a company might not have to be as clean looking, so you could simply use a message box to display the error. However if you want to sell this product, then the last thing your user should see is errors popping up. In fact they should never see an error pop-up, this will give the illusion that there are no problems with your code. These should be handled by logging the error to a file.

Visible Errors
This type of error Handling is good for debugging your own code, or for errors that would cause the program to stop anyway.
[tt]
ErrorHandler:
’Include Your Error Handling Code Here
MsgBox “An Error Occurred” & vbCrLf & _
“Error Number: “ & err.Number & vbCrLf & _
“Error Description: “ & err.Description, vbOkOnly, “Program Error”
End Sub
[/tt]

Handled Errors
This is the best way to handle errors. If you know how to fix the given error then fix it.
[tt]
ErrorHandler:
’Include Your Error Handling Code Here
Select Case err.Number
Case 90 ’This is a database Error
’Code to re-connect to database
Case Else
MsgBox “An Error Occurred” & vbCrLf & _
“Error Number: “ & err.Number & vbCrLf & _
“Error Description: “ & err.Description, vbOkOnly, “Program Error”
End Select
End Sub
[/tt]

Hidden or logged Errors
This way of handling errors is the preferred. It hides the error from the user, but logs it to a file instead. This is useful so that the user never sees the error, but if they report a problem to you, then you can ask for the error log to see what happened. I Usually pass this to a separate function to keep it clean in the code.
[tt]
ErrorHandler:
’Include Your Error Handling Code Here
Call GlogalErr(err.Number, err.Description, ’Any additional Parameters.)
End Sub

’My Global Error handler for all error Handling
Public Function GlobalErr(ByRef ErrNo As Integer, ByRef ErrDesc As String, ByRef Message As String)
Dim FileNum As Integer
Dim strDate As String
NL = Chr(10)
FileNum = FreeFile
strDate = Format(Date + Time, "YYYY/MM/DD hh:mm:ss ")

Open App.Path & "\ErrorLog.txt" For Append Shared As #FileNum
Print #FileNum, strDate & ErrNo & ErrDesc & Message
Close #FileNum
End Function
[/tt]

Additional Error Handling
There are many other types of error handling you can look at. I would suggest going to and checking it out. There are neat things such as ADO errors if you’re using ADO, and ReRaise Error.

Useful Stuff
Now that I’ve badgered you with all this neat stuff, I’ll give you something Useful. You’ll notice that I’m using a variable called myName. This is very useful in debugging your code, you change the value of myName for each Sub or Function, this way, not only do you get the error reported but you also get to see which function the error was triggered in.
[tt]
’Place this code in each and every one of your code modules
Private Sub SampleCodeSub(ByVal PassedValue as String)
On Error GoTo ErrorHandler
Dim myName as String
’Set MyName equal to the name of the function or sub, and include any passed values
MyName = “Command1_Click( PassedValue=” & PassedValue & “)”

’Include the body of your program here

Exit Sub ‘/or Function
ErrorHandler:
’Include Your Error Handling Code Here
Call GlogalErr(err.Number, err.Description, ’Any additional Parameters.)
Resume Next
End Sub ‘/or Function

’Place this code once in your main code module
Public Function GlobalErr(ByRef ErrNo As Integer, ByRef ErrDesc As String, ByRef Message As String)
Dim FileNum As Integer
Dim strDate As String
NL = Chr(10)
FileNum = FreeFile
strDate = Format(Date + Time, "YYYY/MM/DD hh:mm:ss ")

Open App.Path & "\ErrorLog.txt" For Append Shared As #FileNum
Print #FileNum, strDate & ErrNo & ErrDesc & Message
Close #FileNum
End Function
[/tt]

And that my friends is error handling in a nutshell...
Craig, mailto:sander@cogeco.ca
"Procrastination is the art of keeping up with yesterday."
I hope my post was helpful!!!
 
You should probably post this as a FAQ.
 
How do you do that. I couldn't find it. Craig, mailto:sander@cogeco.ca
"Procrastination is the art of keeping up with yesterday."
I hope my post was helpful!!!
 
OK I jsut submitted it. Craig, mailto:sander@cogeco.ca
"Procrastination is the art of keeping up with yesterday."
I hope my post was helpful!!!
 
Excellent job. Well done.

Thanks
 
Currently I have been sending the error messages to the screen and to an error log. I can't tell you how much walking time I've saved myself. By being able to access the error log remotely, I can trouble shoot the problem at my desk without walking through our plant to the pc. I'm glad you included that in your FAQ. Scott
Programmer Analyst
 
Further to this.

I have a form which has several controls and each control has several event procedures etc...

can I hadle errors for EVERY Sub () without putting:

On Error GoTo ErrorHandler:

ErrorHandler:
' do whatever I want

in ALL of my Subs?

Does this make sense?

Can I set a global On Error GoTo?

thanks
Jo
 
Wonderful post, the file based error logging is a must for any type of program.
 
Also look at the project options:

Break on all errors
Means that an error will stop executing the code, even if you have error handling. Useful for debugging (you know in what line thing go wrong), but not for production code.

Break in class modules
I never understood why MS would make a distinction between normal and class modules here. And if it was useful, I would probably want it the other way around... Needless to say I never use this option.

Break on unhandled errors
That's the one you should use for production code. Nice detail: not ALL your procedures need error code, only the top ones (usually a 'main' function and/or event procedures)
 
jojones,

The best you can do is place error handlers in the calling sub. By this I mean that if you have a group of calling subs like this

Private Sub cmdCallSub1_Click()
On Error GoTo errHnd 'error handled here
Sub1
Exit Sub
errHnd:
Print Err.Description
End Sub

Private Sub Sub1()
Sub2
End Sub

Private Sub Sub2()
Sub3
End Sub

Private Sub Sub3()
Sub4
End Sub

Private Sub Sub4()
Dim i As Long
i = 1 / 0 'error is here
End Sub

You can handle the error on the highest calling sub.

If you are looking to use a global type error handler you could also do something like this

Private Sub Command1_Click()
Dim i As Long
On Error GoTo errHnd

i = 1 / 0
Exit Sub
errHnd:
myErrorHandler "Command1"
Resume Next
End Sub

Private Sub Command2_Click()
Dim i As Long
On Error GoTo errHnd

i = 1 / 0
Exit Sub
errHnd:
myErrorHandler "Command2"
Resume Next
End Sub

Private Sub Command3_Click()
Dim i As Long
On Error GoTo errHnd

i = 1 / 0
Exit Sub
errHnd:
myErrorHandler "Command3"
Resume Next
End Sub

Private Sub myErrorHandler(ByVal sName As String)
Print sName
End Sub

I hope this helps some. If you choose to battle wits with the witless be prepared to lose.
[machinegun][hammer]
 
Would this be the proper way to handle errors in the following code:

Private Sub Form_BeforeUpdate(CANCEL As Integer)
On Error GoTo ErrorHandler
CANCEL = True
If Me.AcctNum_Combo & "" = "" Then
MsgBox "You must enter an Account number of the client ordering this request, this field cannot be left blank", vbCritical
Me.AcctNum_Combo.SetFocus
Exit Sub
End If

If Me.DateReceived & "" = "" Then
MsgBox "You must enter a date in the 'Date Received' field, this field cannot be left blank", vbCritical
Me.DateReceived.SetFocus
Exit Sub
End If

If Me.Attention & "" = "" Then
MsgBox "You must enter the name of the person who made this request, the field 'Attention' cannot be left blank", vbCritical
Me.Attention.SetFocus
Exit Sub
End If
Exit Sub
ErrorHandler:
MsgBox Err.Description
Resume Next
CANCEL = False
End Sub
 
Well, take a look on CraigSander's discussion uder the topic Deciding how to Handle Errors.

Looking on your code, it is likely you'll have error only on certain Setfocus calls if the object it applies is disabled or not visible. Still, this is trappable...
Code:
If Me.AcctNum_Combo.Enabled And Me.AcctNum_Combo.Visible Then Me.AcctNum_Combo.Setfocus

Or, you can restructure your code into...
Code:
If Me.AcctNum_Combo & "" = "" Then
    MsgBox "You must enter an Account number of the client ordering this request, this field cannot be left blank", vbCritical
    If Me.AcctNum_Combo.Enabled And _
        Me.AcctNum_Combo.Visible Then
          Me.AcctNum_Combo.Setfocus
          Cancel = True
    End If
    Exit Sub
End If
And looking at the bottom part of your code...
Code:
ErrorHandler:
    MsgBox Err.Description
    Resume Next
    CANCEL = False     'This has no effect
End Sub
Codes after Resume and Resume Next will be ignored. Check out CraigSander's discussion on this.

And, in addition to this post, there are errors that need to be persistent to force user feed the right data, or allow the user to make a few tries before exiting the errorhandler. And Resume, not Resume Next, will do the job. This is very useful for DBMS apps, like when a supposedly shared DB is locked due to some network timeouts (or something like it), rather than immediately exiting the error handler, a programmer can allow a loop of retries to reconnect until the user decides otherwise.

I know, this is already available on MS support site, just giving a snapshot. :)

To CraigSander, great post!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top