Algmene beschouwingen over foutbehaandeling.
Na jaren lange ervaring met het schrijven van VBA code in Access ontwikkelt men zich een stijl die men consequent volgt. Ik denk aan het toepassen
van Benamingsconventies, het voldoende documenteren door commentaar in de code te voorzien, het intensief testen van de toepassing, en andere technieken, zie
ook Optimaliseren VBA-code en nuttige tips.
Met deze strategie vermijdt men ongewenste fouten. Maar ondanks alle inspanninge om foutvrije code te schrijven dient men er rekening mee te houden dat onverwacht
er zich een fout bij de gebruikers kan voordoen en deze met een onbegrijpelijke boodschap geconfronteerd worden. Met alle vervelende implicaties vandien.
Daarom is foutbehandeling in de code een absolute vereiste.
Men kan 3 types van mogelijke fouten onderscheiden:
Een belangrijk verklaring of statement bij fout behandeling is :
On Error GoTo, waarna men verwijst naar een label in de code, bijvoorbeeld FoutBehandeling :
On Error GoTo Foutbehandeling
In de code voorziet men na het Label Foutbehandeling hoe men met de fout zal omgaan, hier speelt het Err object een belangrijke rol:
FoutBehandeling :
MsgBox "Er heeft zich een fout voorgedaan" _
& vbCrLf & Err.Number & " " & Err.Description, _
vbCritical + vbOKOnly, "Fout in Toepassing"
Hier krijgt men een bericht met het nummer en de omschrijving van de fout.
Een eenvoudige procedure voor foutbehandeling :
Sub sTest
On Erro GoTo FoutBehandeling
Verlaten:
Exit Sub (of Function)
FoutBehandeling :
MsgBox "Er heeft zich een fout voorgedaan" _
& vbCrLf & Err.Number & " " & Err.Description, _
vbCritical + vbOKOnly, "Fout in Toepassing"
Resume Verlaten (waar Resume wil zeggen herneem..en verwijzing naar een label, hier Verlaten.)
End Sub
Voor gegevens over VBA fouten zie tabel.
Natuurlijk moet men er naar streven om zoveel als mogelijk fouten te voorkomen. Fouten opsporen 'Debugging' tijdens de ontwikkelings fase is van cruciaal belang. De VBA-editor, de zogenaamde IDE (integrated devlopment environment) voorziet de daartoe nodige instrumenten.
Bij gebrek aan foutbehandeling zal bij het uitvoeren van de code getoond worden waar de fout zich voordoet. Dit mag natuurlijk niet bij een applicatie die in productie is,
maar maar het is wel handing in de ontwikkelings fase. Daarom voorzie ik in mijn toepassingen een globale constante :
Public Const gInProducie As Boolean = False (in ontwikkelingsfase) True (in productie)
In de foutbehandeling dan:
If gInProducie Then On Error GoTo FoutBehandeling
Wat toelaat de foutbehandeling in de ontwikkelingsfase uit te schakelen en zo te ontdekken waar de fout zich voordoet en hoe ze te vermijden.
On Error Resume next, komt erop neer dat men de instructie geeft de fout te negeren en de code verder uit te voeren,
is ook soms handig maar moet toch met de nodige omzichtigheid gebruikt worden.
Bijvoorbeeld men wil
alvorens een tekstbestand te creëren en er naar te schrijven eerst het oude verwijderen, maar omwille van één of andere reden is het al verwijderd. Met On
Error Resume next zal de code dus verder lopen ondanks de fout op de lijn waarmee het tekstbestand wil verwijderen.
Om daarna de foutbehandeling weer in te schakelen met
Err.clear
On Error GoTo FoutBehandeling
Of ook met
On Error GoTo 0
Technieken te gebruiken tijdens de ontwikkelings fase.
Voorbeeld van foutbehandeling die ik toepas.
Doorheen de jaren heb ik een eigen foutbehandeling, geïnspireerd op verschillende bronnen, waarbij de fouten weggeschreven worden naar een tekstbestand.
Gebruikers kunnen mij dat doorsturen. Zodoende weet ik waar en wanneer de fout zich heeft voorgedaan en welke oplossing er moet aan gegeven worden.
In de toepassing voorzie ik een tabel tblFoutLog :
| Tijdstip | Date/Time |
| FoutNummer | Long |
| FoutOmschr | Tekst |
| ModuleNaam | Tekst |
| ProcedureNaam | Tekst |
| AlineaNummer | Integer |
| Gebruiker | Tekst |
| PCNaam | Tekst |
| VersieToepassing | Tekst |
| Notitie | Tekst |
Een module basGlobalErr met één constante :
Option Compare Database
Option Explicit
' wanneer de toepassing volledig afgewerkt en voor zover gekend fout vrij is
'Public Const gInProducie As Boolean = True
' Wanneer men de toepassing aan het bouwen is zodanig dat men in de IDE kan zien waar de fout zich voordoet
Public Const gInProducie As Boolean = False
Een module basFoutlog met daarin:
Hier de code van de module:
Option Compare Database
Option Explicit
Const gstrVersieToep As String = "Versie 13/01/2012"
---------------------------------------------------------------------------------------------------
Public Sub Log_Fout( _
Optional ByVal lngFoutNummer As Long = -1, _
Optional ByVal strOmschrijving As String = "Onbekend", _
Optional ByVal strModuleNaam As String = "Onbekend", _
Optional ByVal strProcedureNaam As String = "Onbekend", _
Optional ByVal lngAlineaNummer As Long = -1, _
Optional ByVal strNotitie As String = "Niet voorzien", _
Optional ByVal blnInfoGebruiker As Boolean = True)
Dim strSQL As String
Dim db As DAO.Database
On Error GoTo gFoutBehandeling
If blnInfoGebruiker = True Then
'Toon frm_av_fout om gebruiker te informeren
DoCmd.OpenForm FormName:="frm_av_Fout"
Call Forms("frm_av_Fout").FoutBericht( _
strLabelTekst:="Er heeft zich een fout voorgedaan!", _
strBoodschap:=strModuleNaam & " : " _
& strProcedureNaam & " : " & lngFoutNummer _
& vbCrLf & strOmschrijving)
End If 'If blnInfoGebruiker ...
strSQL = "INSERT INTO tblFoutLog " _
& "(" _
& "[Tijdstip], [FoutNummer], " _
& "[FoutOmschr], [ModuleNaam], " _
& "[ProcedureNaam], [AlineaNummer], " _
& "[Gebruiker], [PCNaam], " _
& "[VersieToepassing], [Notitie]" _
& ") VALUES (" _
& "'" & CStr(Now()) & "', " _
& "'" & lngFoutNummer & "', " _
& "'" & strOmschrijving & "', " _
& "'" & strModuleNaam & "', " _
& "'" & strProcedureNaam & "', " _
& "'" & lngAlineaNummer & "', " _
& "'" & Environ$("UserName") & "', " _
& "'" & Environ$("ComputerName") & "', " _
& "'" & gstrVersieToep & "', " _
& "'" & strNotitie & "')"
Set db = CurrentDb
Call db.Execute(strSQL, dbFailOnError)
Verlaten:
Exit Sub
gFoutBehandeling:
Call MsgBox(Err.Number & ":" & Err.Description, vbCritical, "Fout in log-toepassing!")
Resume Verlaten
End Sub
---------------------------------------------------------------------------------------------------
Public Function fFoutVerwerking(strProc As String, Optional varModuleNaam As Variant _
, Optional varNotitie As Variant) As Boolean
Dim strBoodschap As String
Dim strTitel As String
Dim intStijl As Integer
'Indien er geen fout optreedt verwerk ze, anders geef True terug
If Err.Number = 0 Then
fFoutVerwerking = True
Else
'Maak titel en boodschap
strTitel = "Fout " & Err.Number & " in " & Nz(strProc, "niet opgegeven routine")
strBoodschap = " Volgende fout gebeurde:" & vbCrLf & vbCrLf & Err.Description
fFoutVerwerking = (MsgBox(strBoodschap, vbExclamation, strTitel) = vbOK)
Call Log_Fout(Err.Number _
, Err.Description _
, strModuleNaam:=Nz(varModuleNaam, "module naam niet opgegeven") _
, strProcedureNaam:=strProc _
, lngAlineaNummer:=-1 _
, strNotitie:=Nz(varNotitie, "") _
, blnInfoGebruiker:=True)
End If
End Function
Tenslotte gebruik ik twee sjablonen één voor Sub en één voor Function om in iedere procedure te voorzien en die gebruikmaken van de functie fFoutVerwerking
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 'Project : 'Omschrijving: 'Auteur: 'Datum creatie: 'Datum Herzien: 'Kommentaar: ' 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX If gInProducie Then On Error GoTo FoutBehandeling Verlaten: On Error Resume Next Exit Sub FoutBehandeling: 'argumenten procedure, module, notitie If Not fFoutVerwerking("","","") Then Stop End If Resume Verlaten --------------------------------------------------------------------------------------------------- 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 'Project : 'Omschrijving: 'Auteur: 'Datum creatie: 'Datum Herzien: 'Kommentaar: ' 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX If gInProducie Then On Error GoTo FoutBehandeling Verlaten: On Error Resume Next Exit Function FoutBehandeling: 'argumenten procedure, module, notitie If Not fFoutVerwerking("","","") Then Stop End If