Using Error Handling to Process Code (1 Viewer)

mresann

Registered User.
Local time
Today, 02:46
Joined
Jan 11, 2005
Messages
357
This is not a specific problem, but a question I have in general about VBA code. I have seen a lot of examples from beginners to experts that use error code numbers to process a procedure, not just to trap an error. In my opinion, I consider it a very poor approach to code design. I wanted to find out from people who have used Error handling to process their code, and why they did it, rather than find a way to handle the code that didn't involve invoking the Error protocols on Access VBA.

What type of examples do you have that justify Error handling over "proper" code design?
 

ghudson

Registered User.
Local time
Today, 05:46
Joined
Jun 8, 2002
Messages
6,195
In my opinion, I consider it a very poor approach to code design.
Lucky us we are each entitled to one. ;)

Using error handling is a must for any good programmer. A db opened in the runtime will just close if a runtime error is encountered and error handling was not used for the offending sub or function.

Trapping for a specific error is a must if you know the error could occur. That is why a good programmer will test and test and test their programs and trap for specific errors if they know that they could occur.

As an example, you have a VBA routine that prints a report and the user clicks the Cancel button while the report is spooling. If you do not trap for the runtime error # 2501 the user would get a runtime error message because of their action. If you were trapping for the runtime error # 2501 then you could provide a custom error message or just have the error handler exit that function for the runtime error # 2501.

But hey, that is just my opinion. Maybe your users are perfect and they will never do anything that could produce an unexpected or expected runtime error.

Code:
Private Sub bDeleteRecord_Click()
On Error GoTo bDeleteRecord_Click_Err
    
    If Me.Dirty Then
        Beep
        MsgBox "Please Save This Record!" & vbCrLf & vbLf & "You can not delete this record until you either 'Save' the changes made to this record or 'Undo' your changes.", vbExclamation, "Save Required"
    Else
        Beep
        If MsgBox("Delete record for vehicle " & LicenseNumber & "?", vbQuestion + vbYesNo, "Delete Current Record?") = vbYes Then
        DoCmd.RunCommand acCmdDeleteRecord
        End If
    End If
    
bDeleteRecord_Click_Exit:
    Exit Sub
    
bDeleteRecord_Click_Err:
    If Err = 2046 Then 'The command or action 'DeleteRecord' isn't available now
        Exit Sub
    ElseIf Err = 2501 Then 'The RunCommand action was canceled
        Exit Sub
    Else
        MsgBox Err.Number & " - " & Err.Description
        Resume bDeleteRecord_Click_Exit
    End If
    
End Sub
 

mresann

Registered User.
Local time
Today, 02:46
Joined
Jan 11, 2005
Messages
357
OK, maybe I didn't make myself clear enough.

Of course I am emphatic about error handling. But I'm not talking about the coding that is done to prevent runtime or procedural errors from unconventional operations, such as canceling, etc. Let me try to give an example.

Let's say you are trying to update an open recordset, and you try to update a record with a duplicate key. Sometimes coders don't bother preventing the duplicate entry, instead letting the On Error GoTo procedure to send the code to the Error handler, where the particular Error handler would identify the Error code for duplicate entry, and then process the duplicate record there. My contention is that there should be a more active method of identifying the duplicate record, either through a DLookup function or, preferably, through a query. Since it's a normal situation to prevent duplicate records from being entered into a table, I contend it should be done through robust coding than the "backdoor" error handling procedure.

Maybe I'm splitting hairs, but just need to hear other's thoughts on this.
 

pono1

Registered User.
Local time
Today, 02:46
Joined
Jun 23, 2002
Messages
1,186
I agree that some apps don't actively anticipate common errors and provide meaningful feedback to the user when the error hits.

But you can actively use the Err Object. And assuming the error is the exception rather than the norm, letting an Error handler catch a boo-boo is usually more efficient because you will save on the processing time you incur checking for an error before every "try" -- where try represents whatever you're attempting to do. Another perspective: writing error checking code is often redundant -- the Err object (like any object) is code already written and debugged by somebody else to do the work for you; tapping into it generally saves you time and standardizes your work, which will make it easier for you to understand your own code in the future when -- if you're like me -- you've forgotten most everything else about it...


Code:
Function AddRecord(NewRecID As Long, _
                  Optional sFirstName As String = "") _
As Boolean

On Error GoTo HandleError

Dim sSQL As String
sSQL = "INSERT INTO MyTable (RecID, FirstName) " & _
        "VALUES (" & NewRecID & "," & "'" & sFirstName & "'" & ")"

CurrentProject.Connection.Execute sSQL

AddRecord = True
Exit Function

HandleError:   
   Select Case Err.Number
      Case -2147467259  'Duplicate
         MsgBox "No Dups Please" & vbCrLf & vbCrLf & Err.Description, vbCritical, "Duplicate"
      Case -9999999999999999 'Something else
         MsgBox "Etc"	
      Case -5555555555555555  'Another Something else
         MsgBox "Etc2"
      Case Else
         MsgBox Err.Description, vbCritical, Err.Number
   End Select

End Function

Regards,
Tim
 

ChrisO

Registered User.
Local time
Today, 19:46
Joined
Apr 30, 2003
Messages
3,202
G’day mresann and please ‘split hairs’ all you like, it’s an excellent thread and thanks for starting it.

Let’s just hope that many others share their experiences and preferences.

If I may, a little bit of deliberate error generating with which to start: -

Code:
Option Explicit
Option Compare Text


Public Sub ParkCursorInMeAndHitF5_WhatDoWeGet()

    On Error GoTo ErrorHandler

    TestIt

    MsgBox "Error " & Err.Number & ":   " & Err.Description

ExitProcedure:
    Exit Sub
    
ErrorHandler:
    MsgBox "Error " & Err.Number & ":   " & Err.Description
    Resume ExitProcedure

End Sub


Public Sub TestIt()
    Dim lngX As Long
    
    On Error GoTo ErrorHandler
    
    lngX = 1 / 0
    
ExitProcedure:
    Exit Sub
    
ErrorHandler:
    lngX = 1 / 0
    Resume ExitProcedure
   
End Sub
Well what we get is a subtle transfer of an error back to the caller that would possibly not expect it.

And all it took was a very simple one-liner: - lngX = 1 / 0
(One simple error for man…one giant error for mankind.)
(I got that from somewhere but don’t think it was on this planet. :rolleyes: )

So if we take the point of view that “the more code we write…the more errors may occur” then I think we come to a ‘partial conclusion’ that code written within an error handler either needs to be bullet proof (which is almost impossible) or kept to a minimum.

However, and there is almost always a however, simple error handling code is usually restricted to reporting the error but not fixing the problem.

There are other considerations to be made as well, not the least of which is to protect data in the instance of an error, and hardware solutions that are not generally available to PC users. (Old hat in minicomputers but fencing registers, error detection and correction of RAM, and watchdog timers (the ultimate shutdown) spring to mind.)

Now it might seem somewhat esoteric to mention these things but they had something in common.
Their aim was to protect the data, or process, and not to allow a wayward computer corrupting the very thing it was built to ‘order’.

Strangely, the example you gave has another and opposite approach which involves deliberately raising an error to overcome that particular problem in a multi-user environment.

As you might detect, this one of my pet subjects but I won’t bore you anymore... at the moment. ;)

Again, nice thread.

Regards,
Chris.
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Today, 05:46
Joined
Feb 19, 2002
Messages
43,263
My contention is that there should be a more active method of identifying the duplicate record, either through a DLookup function or, preferably, through a query. Since it's a normal situation to prevent duplicate records from being entered into a table, I contend it should be done through robust coding than the "backdoor" error handling procedure.
- There is a more active method! It is called Declarative Referential Integrity and it is enforced by your database engine. Add my name to the list on the side of "let the db engine do it". I never write code to duplicate an existing function provided by my RDBMS. It is wasteful of resources and increases the risk of programming errors since the more code you write, the more code you have that could contain errors. I do frequently add my own messages in place of those generated by Access to give my users a friendlier alternative.

The example you posted is actually a prime example of why it is correct to let the db engine do it rather than doing it yourself. In a busy multi-user environment it is quite possible for someone to add a "duplicate" record between the time you check for an existing record and the time you add a new record. Now, I admit, this is not a frequent scenario but why take the chance?
 

mresann

Registered User.
Local time
Today, 02:46
Joined
Jan 11, 2005
Messages
357
OK, thanks for the insights. I actually used the duplicate record example as probably the most common use of the Error Handling function to process code which, on the surface, I find "lazy". Indeed, if you've seen my code in some of my examples, I use a standard msgbox notification system, but I also have another function error handler template which allows errors to be recorded to a log or db in a class or global module. Although I would use the class module in a solution release, I use the global module for most development and testing purposes.

However, when I code for trapping errors, they are for handling exceptions, rather than for a 'normal' processing decision, such as trying to pass a duplicate record into a primary key. In addition, sometimes I pass errors back in the calling queue if it makes more sense to process the code in that fashion. In any case, I record every error through a text file or, if the customer requests it, in a database entity, even if the error is processed behind the scenes from the user.

In retrospect, I think I am splitting a few more hairs than I should have in this case. I think it's more of a complaint of bad coding practices than error handling, but then again it's a personal preference.
 

ChrisO

Registered User.
Local time
Today, 19:46
Joined
Apr 30, 2003
Messages
3,202
G’day mresann

“In retrospect, I think I am splitting a few more hairs than I should have in this case.”

Like hell you are…I can split hairs as well and this is the exact topic in which to do it.

The problem is that, as I see it, we are talking about errors; but in this thread the concept of an error has not yet been defined.

So I will ask a question or three…
1. If we write code that is designed to deliberately cause an error (exception), is it an error if the error (exception) is raised or is it an error if the error (exception) is not raised?
2. Do we attempt to handle the error (exception) or the failure to raise it?
3. What, therefore, is the difference between an error and an exception?

I thought this was a good thread from the outset, but if we don’t at least try to define that of which we speak then where will we go…down that dark cul-de-sac from which there is no return?

We need a limit of competency placed on the software, and/or computer, beyond which the software, and/or computer, is deemed incompetent.

An error handler may very well be deemed incompetent.

Regards,
Chris.
 

Users who are viewing this thread

Top Bottom