Foutafhandeling in VBA

Inleiding

Niveau

  • Je hebt de eerste les VBA gevolgd.

Ondanks foutafhandeling een erg belangrijk aspect is, wordt het vaak niet of niet goed toegepast. Er is echter een heel eenvoudige manier om het goed, makkelijk en consistent toe te passen. We doen dat niet met een of andere wizard, want dan kunnen we niet consistent werken. Bovendien willen we goed begrijpen hoe het werkt. Daarom bewandelen we hier een andere weg: de handmatige.

Moet je in alle gevallen foutafhandeling toepassen? Nee. Alleen in gevallen waarin het absoluut zeker is dat het gewoonweg niet fout kan gaan, is foutafhandeling niet nodig. Wanneer je een procedure Function schrijft die de titel van een berichtvenster moet weergeven bijvoorbeeld, is het onzinnig daarvoor een foutafhandelingsroutine te plaatsen. In alle andere gevallen is het standaard toepassen van foutafhandeling een goede gewoonte.

Het afhandelen van fouten is een algemeen iets. Toch is het goed om een paar verschillende voorbeelden te bekijken.

Tip Voor de foutafhandeling is standaardcode beschikbaar die je vindt op de pagina Gemengd (menu).

Algemene werkwijze

In het volgende voorbeeld (de procedure Sub) wordt eenvoudig weergegeven hoe een foutafhandelingsroutine moet worden geschreven. Dit is dus je basis.

Coderegels (statements) worden per regel uitgevoerd, d.w.z. elke regel in het voorbeeld hieronder, behalve natuurlijk het comentaar. De procedure zelf is ook een statement. Wanneer deze wordt aangeroepen vanuit een andere procedure, is deze procedure even zo goed een regel. Bij de foutafhandeling zal je zien dat de code steeds van regel naar regel gaat.

De regels Bye_End: en Bye_Err: zijn slechts namen die we zelf bewust hebben gekozen. Deze namen gebruiken we altijd. Reden: louter omdat we dan makkelijk en consistent kunnen werken. De dubbele punt is verplicht. Bye_End: en Bye_Err: zijn labels (een soort van bladwijzers). Onder diverse omstandigheden en middels verschillende manieren kunnen we VBA instructies geven naar zo'n label te gaan zodat de uitvoering van het programma daar wordt voortgezet. Binnen een procedure kunnen we zowel vooruit als achteruit bewegen.

Komt programmacode de instructie Exit Sub tegen, dan wordt de procedure onmiddellijk verlaten.

Mocht er tijdens de uitvoering van de instructies een fout voordoen, dan moet VBA weten wat er moet gebeuren. Dit geven we vooraan in de procedure aan met de regel On Error GoTo Bye_Err. Hier geven we in dat geval dus de opdracht dat de uitvoering naar het label Bye_Err moet gaan.

Daar aangekomen leest VBA de regel die begint met de VBA functie MsgBox en wordt een bericht weergegeven. Dankzij onze procedures MsgErr en MT die in deze regel zijn opgenomen, hoeven we niets meer te doen. De gebruiker krijgt een correct bericht te zien met het nummer van de fout met de daaraan gekoppelde omschrijving.

Vervolgens wordt de regel Resume Bye_End uitgevoerd waarmee we VBA de instructie geven om naar Bye_End te gaan waarna de procedure wordt verlaten bij Exit Sub. We hebben nu de fout netjes afgehandeld zonder dat de applicatie plotseling wordt afgesloten of blijft hangen.

Opmerking Het nummer dat het object Err als resultaat heeft gegeven wordt op 0 ingesteld zodra een procedure is verlaten. Een fout in de huidige procedure kan ook door een aanroepende procedure worden getriggerd.

Voor een procedure Function geldt hetzelfde als voor een procedure Sub. Het enige verschil v.w.b. de foutafhandeling is dat Exit Sub dan Exit Function is.

Sub ProcName()

    

    On Error GoTo Bye_Err

    ' Instructies hier

    

Bye_End:

    Exit Sub

Bye_Err:

    MsgBox MsgErr, vbCritical, MT

    Resume Bye_End

End Sub

Function ProcName() As Boolean

    

    On Error GoTo Bye_Err

    ' Instructies hier

    

Bye_End:

    Exit Function

Bye_Err:

    MsgBox MsgErr, vbCritical, MT

    Resume Bye_End

End Function

Object variabelen correct afhandelen

Een belangrijk aspect waar aandacht naar uit dient te gaan is, waar we object variabelen op Nothing instellen. Ook dit laten we regelen door onze foutafhandelingsroutine.

Tip Lees meer over Variabelen.

Voor nu is het belangrijk te weten dat het goed is om object variabelen altijd op Nothing in te stellen. In het volgende voorbeeld zijn de object variabelen db en rst ingesteld door Set. Na Bye_End worden ze weer op Nothing ingesteld. Waarom juist daar?

Bij een fout wordt de uitvoering naar Bye_Err gestuurd. Resume Bye_End stuurt de uitvoering naar Bye_End en vervolgens worden de object variabelen op Nothing ingesteld. Nu is het zo dat object variabelen op Nothing worden ingesteld bij het verlaten van de procedure, maar er zijn ook situaties waarbij je dit toch moet doen. Daarbij is het een goede gewoonte. Volg de opmerking hierboven voor meer hierover.

TipObjecten zoals een Database en Recordset object in dit voorbeeld, kunnen worden gesloten met de methode Close. Dat kan soms nodig zijn als de object variabele wel in tact moet blijven. Is dat niet het geval, dan is het niet nodig het object te sluiten. Door een object variabele op Nothing in te stellen wordt namelijk elke verbinding met het object verbroken.

Sub ProcName()

    Dim db     As DAO.Database

    Dim rst     As DAO.Recordset

    

    On Error GoTo Bye_Err

    

    Set db = CurrentDb

    Set rst = rst.OpenRecordset("Orders", dbOpenSnapshot)

    

    ' Instructies hier

    

Bye_End:

    Set db = Nothing

    Set rst = Nothing

    Exit Sub

Bye_Err:

    MsgBox MsgErr, vbCritical, MT

    Resume Bye_End

End Sub

Select Case gebruiken

Het volgende voorbeeld toont hoe je kan antisiperen op fouten waarvan je weet dat ze zich kunnen voordoen. Op die manier kan je het programma zo goed als mogelijk is aansturen. Met het Select Case statement wordt het nummer van de fout geanalyseerd. In dit geval kan het zijn dat er geen data beschikbaar is of dat gebruiker zelf heeft geannuleerd. In dat geval wordt een voorgedefinieerd bericht weergegeven. In alle andere gevallen wordt de fout afgevangen zoals gebruikelijk.

In dit geval is er ook nog een Public variabele (ByPDF) die op False moet worden ingesteld als de procedure is uitgevoerd. Dat gebeurt ook netjes voordat de procedure wordt verlaten. Echter, als er zich een fout voordoet en we zouden geen correcte foutafhandelingsroutine hebben, dan blijft ByPDF de huidige waarde houden. Want in de regel waar de fout zich voordoet, daar wordt alles onmiddellijk onderbroken en wordt de procedure dus niet volledig uitgevoerd.

Let op de statements Resume Bye_End die in elke Case worden uitgevoerd. (In werkelijkheid is dit code van een procedure Function, maar het gaat om het voorbeeld.)

Sub ProcName

    On Error GoTo Bye_Err

    

    ' Instructies hier

    

Bye_End:

    ByPDF = False

    Exit Sub

Bye_Err:

    Select Case Err.Number

        Case 2501

            MsgGeenDataOfGeannuleerd

            Resume Bye_End

        Case Else

            MsgBox MsgErr, vbCritical, MT

            Resume Bye_End

    End Select

End Function

Cursussen