Home > Artikel > Ausgabe 2/2013 > Debugging im VBA-Editor, Teil 1

Debugging im VBA-Editor, Teil 1

  PDF ansehen

  Download PDF

Wer mit VBA arbeitet, hat im Gegensatz zu Makros einige Möglichkeiten, den Programmablauf zu beobachten und auf diese Weise Fehler aufzudecken. Auch wenn der VBA-Editor bereits einige Jährchen auf dem Buckel hat und seit Jahren weder VBA noch der VBA-Editor erweitert wurde, bietet er doch einige Möglichkeiten zum Debugging. Dieser Artikel zeigt, wie Debugging funktioniert und welche Werkzeuge der VBA-Editor dazu anbietet.

Was ist Debugging?

Unter Debugging versteht man das Entfernen von Bugs. Bugs? Damit sind Programmfehler gemeint. Während diese Bezeichnung für Fehler wohl unter Ingenieuren schon länger gängig war, wurde er von Grace Hopper salonfähig gemacht: Dieser fand nämlich 1947 bei den Arbeiten am Mark II tatsächlich eine Motte als Auslöser eines Fehlers vor (siehe Wikipedia).

Unter VBA versteht man unter Debugging vor allem die Untersuchung des Pro­gramm­ablaufs, wobei Prozeduren mit geeigneten Menübefehlen oder Tasten­kom­bi­nationen in mehr oder weniger großen Schritten durchlaufen werden. Bei jedem Schritt lassen sich die aktuellen Werte von Variablen ermitteln. Falsch oder nicht gefüllte beziehungsweise gesetzte Variablen sind der Hauptgrund für logische Fehler im Programmablauf.

Statt die Prozeduren schrittweise zu durchlaufen, können Sie auch gleich festlegen, an welcher Stelle diese angehalten werden soll. Tritt hingegen ein Laufzeitfehler auf, bietet der VBA-Editor automatisch die Möglichkeit, die fehlerhafte Stelle zu untersuchen. Doch genug der warmen Worte – schauen wir uns doch gleich die passenden Werkzeuge an.

Debugging im Fehlerfall

Wer sich noch nicht aktiv um das Thema Debugging gekümmert hat, wird wohl am ehesten durch einen Fehler damit in Verbindung gekommen sein. Nehmen wir folgende Funktion zum Dividieren als Beispiel:

Public Function Dividieren(intDividend As Integer, _

         intDivisor As Integer) As Single

     Dim sngErgebnis As Single

     sngErgebnis = intDividend / intDivisor

     Dividieren = sngErgebnis

End Function

Wenn Sie diese Funktion mit den Werten 3 und 0 über das Direktfenster aufrufen, erscheint die Fehlermeldung aus Bild 1. Dort finden Sie unter anderem eine Schaltfläche mit der Beschriftung Debuggen, mit der Sie in den Debugging-Modus einsteigen können.

Laufzeitfehler mit der Möglichkeit, zu debuggen

Bild 1: Laufzeitfehler mit der Möglichkeit, zu debuggen

Ein Klick auf diese Schaltfläche schließt die Fehlermeldung und hebt die den Fehler auslösende Zeile im VBA-Editor farblich hervor (siehe Bild 2). Sie können nun beispielsweise mit der Maus über die in der Zeile enthaltenen Variablen fahren, um ihre Werte anzuzeigen.

Debugging eines Laufzeitfehlers

Bild 2: Debugging eines Laufzeitfehlers

Dies gelingt übrigens auch auf andere Weise (manchmal – vor allem bei komplizierteren Ausdrücken – zeigt sich die direkte Anzeige im Codefenster etwas störrisch): Dabei nehmen Sie das Direktfenster zuhilfe und lassen sich dort mit der Debug.Print-Anweisung den Inhalt der zu untersuchenden Variablen ausgeben. Dabei geben Sie den Namen der Variablen als Parameter an (siehe Bild 3). Hier erkennen Sie direkt, dass der Divisor einen unzulässigen Werte angenommen hat (vermutlich unerwarteterweise) und können eine entsprechende Prüfung einbauen.

Variablenwerte über das Direktfenster ermitteln

Bild 3: Variablenwerte über das Direktfenster ermitteln

Variableninhalt ändern

Wenn Sie eine umfangreichere Abfolge von Routinen testen, möchten Sie an dieser Stelle möglicherweise nicht von vorn beginnen.

Dann gibt es mehrere Möglichkeiten (die alle natürlich nicht mit einem Neustart mit korrigiertem Code gleichzusetzen sind) – zum Beispiel diese:

  • Sie ändern den unerwünschten Variablenwert und fahren mit der Prozedur fort.
  • Sie ändern das Ergebnis und fahren dann mit der Prozedur fort.

Im ersten Fall weisen Sie der Variablen intDivisor über den Direktbereich einen neuen Wert zu:

intDivisor = 1

Danach führen Sie die Prozedur mit einem Klick auf die Taste F5 oder durch das Aufrufen des Menü­befehls Ausführen|Fortsetzen fort. Die Zeile löst keinen Fehler mehr aus und die Funktion liefert das entsprechende Ergebnis. Wenn Sie lieber gleich den vollständigen Rückgabewert der Funktion ändern möchten, verschieben Sie den gelben Pfeil, der die aktuell auszuführende Zeile markiert, einfach auf die Zeile End Function und weisen Sie dem Rückgabewert Dividieren der Funktion den gewünschten Wert zu – beispielsweise so (siehe Bild 4):

Aktuelle Zeile ändern

Bild 4: Aktuelle Zeile ändern

Dividieren = 3

Auf diese Weise können Sie auch alle anderen Zeilen anspringen oder Variablenwerte ändern.

Starten, unterbrechen und beenden

Weiter oben haben Sie nun bereits die Taste F5 beziehungsweise den Menübefehl Ausführen|Fortsetzen kennengelernt, um eine angehaltene Prozedur fortzuführen. Im Menü Ausführen und auch unter Debuggen gibt es noch weitere Befehle, die wir uns bei dieser Gelegenheit ansehen.

Beginnen wir mit dem Menü Ausführen. Dort finden Sie die folgenden Befehle (siehe Bild 5):

Starten, unterbrechen und zurücksetzen einer Prozedur

Bild 5: Starten, unterbrechen und zurücksetzen einer Prozedur

  • Sub/Userform ausführen: Mit diesem Befehl oder mit der Taste F5 starten Sie die Prozedur, in der sich aktuell die Einfügemarke befindet.
  • Unterbrechen: Hält eine laufende Prozedur an und zeigt die als nächste auszuführende Zeile gelb markiert an (auch mit Strg + Unterbrechen aufrufbar).
  • Zurücksetzen: Beendet eine laufende Prozedur.

Nun gibt es hier die eine oder andere Besonderheit. Wenn Sie eine Prozedur mit F5 starten möchten und gerade nicht sicher sind, wo sich die Einfügemarke befindet (weil sich diese etwa in einer aus dem Bild gescrollten Zeile befindet), können Sie im rechten Kombinationsfeld des Codefensters nachlesen, welche Routine bei Betätigung von F5 ausgeführt wird (siehe Bild 6). Es gibt jedoch auf Routinen, die sich nicht ausführen lassen. Dabei handelt es sich um solche, die Parameter verwenden und um Routinen innerhalb von Klassenmodulen. Wenn Sie eine solche Routine markieren und F5 betätigen, um diese auszuführen, erscheint der Dialog aus Bild 7 und zeigt alle aktuell ausführbaren Routinen an. Diese können Sie dann markieren und auf verschiedene Arten ausführen.

Anzeige der aktuellen Prozedur in den Kombinationsfeldern im Kopf des Codefensters

Bild 6: Anzeige der aktuellen Prozedur in den Kombinationsfeldern im Kopf des Codefensters

Alle ausführbaren Prozeduren

Bild 7: Alle ausführbaren Prozeduren

Zwischenstopp

Gelegentlich wird es passieren, dass eine Prozedur in eine Endlosschleife läuft oder dass ein Vorgang solange dauert, dass Sie bei laufender Prozedur eingreifen müssen.

Ein gutes Beispiel ist eine Endlosschleife wie die folgende:

Public Sub Test()

     Dim l As Long

     Do While Not 1 = 2

         l = l + 1

         DoEvents

     Loop

End Sub

Die Bedingung in der Do While-Zeile wird niemals wahr, dementsprechend verlässt die Prozedur auch nicht die Schleife. Wie kommen Sie da wieder heraus? Access über den Task-Manager abschießen? Nein: Dazu gibt es die Tastenkombination Strg + Unterbrechen. Dies hält die aktuelle Prozedur an und markiert wiederum die anstehende Programmzeile mit einem gelben Pfeil und entsprechendem Texthintergrund (siehe Bild 8).

Eine unterbrochene Prozedur

Bild 8: Eine unterbrochene Prozedur

Auch zu diesem Zeitpunkt können Sie die Inhalte von Variablen abfragen oder ändern. Außerdem können Sie die Funktion fortsetzen (am einfachsten mit F5) oder diese abbrechen (mit dem Menübefehl Ausführen|Zurücksetzen). Oder Sie verschieben den gelben Pfeil nach unten auf die Zeile End Sub, um die Prozedur regulär zu beenden.

Schritt für Schritt

Wenn Sie gleich von Beginn an wissen, das in einer Prozedur etwas nicht richtig läuft, finden Sie im Menü Debuggen die richtigen Befehle. Der erste Befehl Kompilieren von kompiliert die Datenbank und meldet sich, wenn der VBA-Code Syntaxfehler enthält – dies nur der Vollständigkeit halber.

Der Befehl Einzelschritt ist auch mit der Schaltfläche F8 erreichbar (siehe Bild 9). Sollte sich die Einfügemarke in einer direkt ausführbaren Prozedur befinden, markiert der VBA-Editor zu Beginn die erste Zeile der Prozedur und fährt dann mit jeder Betätigung von F8 zeilenweise mit dem Code fort.

Verschiedene Arten, eine Prozedur auszuführen

Bild 9: Verschiedene Arten, eine Prozedur auszuführen

Dabei werden Schleifen wie gewohnt ein- oder mehrmals durchlaufen und auch das Aufrufen weiterer Routinen von einer Prozedur aus gelingt problemlos.

Prozedurschritt

Was aber ist der mit Umschalt + F8 erreichbare Prozedurschritt? Wird hier direkt die komplette Prozedur ausgeführt? Nicht direkt. Am besten lässt sich dies an folgendem Beispiel erläutern. Dort ruft die erste Funktion zwischen zwei Debug.Print-Anweisungen eine zweite Funktion auf, die eine weitere Debug.Print-Anweisung ausführt:

01 Public Sub ErsteProzedur()

02 Debug.Print "1"

03 ZweiteProzedur

04 Debug.Print "3"

05 End Sub

06 Public Sub ZweiteProzedur()

07 Debug.Print "2"

08 End Sub

Als Ergebnis sollten immer die drei Zahlen 1, 2 und 3 im Direktbereich des VBA-Editors landen. Wenn Sie die Prozedur mit F8 durchlaufen, geschieht das in dieser Reihenfolge: 01, 02, 03, 06, 07, 08, 04, 05. Sie machen also einen netten kleinen Ausflug durch alle aufgerufenen Routinen. Wenn Sie die Prozedur ZweiteProzedur und ihre Funktion ausreichend kennen und Sie diese nicht mehr beobachten möchten, halten Sie beim Ausführen von Zeile 03 mit der Taste F8 einfach die Umschalttaste gedrückt! Der VBA-Editor springt dann von Zeile 03 direkt zu Zeile 04. Die Anweisungen der Prozedur ZweiteProzedur werden allerdings dennoch ausgeführt – dies zeigt ein Blick in den Direktbereich und die Ausgabe der Zahlen 1, 2 und 3.

Sollten Sie während der Ausführung einer weiteren Prozedur wie etwa ZweiteProzedur feststellen, dass hier nichts Interessantes geschieht, können Sie dort Strg + Umschalt + F8 drücken. Auf diese Weise verlassen Sie diese Prozedur und gelangen direkt zur folgenden Zeile der aufrufenden Prozedur.

Möchten Sie alle noch anstehenden Anweisungen ausführen und die Prozedur beenden, betätigen Sie die bereits bekannte Taste F5.

Ausführen bis zum Cursor

Vielleicht starten Sie mit der Taste F8 die Ausführung einer Prozedur und sehen dann im Codefenster, dass die zu untersuchende Codezeile ein ganzes Stück weiter unten oder innerhalb einer Bedingung liegt.

Wenn Sie nicht alle dazwischen liegenden Zeilen manuell durchlaufen möchten, können Sie das in einem Schritt erledigen. Dazu gibt es mehrere Möglichkeiten. Die erste ist diese: Sie platzieren die Einfügemarke in der Zeile, in welcher die Prozedur stoppen soll. Dann betätigen Sie die Tastenkombination Strg + F8. Die Prozedur wird nun genau in der angegebenen Zeile angehalten.

Diese Technik können Sie auch einsetzen, wenn die Prozedur noch gar nicht läuft – Sie markieren also einfach die zu untersuchende Zeile und springen mit Strg + F8 dorthin.

Ausführen bis zum Haltepunkt

Alternativ zur Markierung der Zeile, in der Sie den Code anhalten möchten, durch die Einfügemarke können Sie auch einen Haltepunkt setzen. Dies erledigen Sie auf eine der folgenden Arten:

  • Sie klicken mit der Maus auf Höhe der betroffenen Codezeile links auf den grauen Rand im Codefenster (siehe Bild 10).
  • Platzieren eines Haltepunktes

    Bild 10: Platzieren eines Haltepunktes

  • Sie platzieren die Einfügemarke in der betroffenen Zeile und betätigen die Taste F9.
  • Sie platzieren die Einfügemarke in der Zeile und wählen den Menüeintrag Debuggen|Haltepunkt ein/aus aus.

Ein solcher Haltepunkt hat erstens den Vorteil, dass er im weiteren Verlauf nicht verloren geht, weil Sie etwa die Einfügemarke woanders platzieren. Haltepunkt verschwinden erst, wenn Sie die Anwendung schließen und erneut öffnen.

Der zweite Vorteil ist, dass Sie mehr als einen Haltepunkt setzen können. Gibt es mehrere interessante Stellen innerhalb einer Prozedur, markieren Sie einfach alle.

Sie können dann mit der Taste F5 von Haltepunkt zu Haltepunkt springen.

Ändern und wiederholen

Fehler lassen sich teilweise bei Debuggen beheben. Wenn Sie also etwa eine fehlerhafte Zeile mit F8 ausführen und feststellen, dass Sie einen Fehler eingebaut haben, können Sie diesen in den meisten Fällen noch während des Debuggens korrigieren (manchmal gelingt dies nicht – etwa, wenn Sie einer Select Case-Anweisung einen neuen Zweig hinzufügen möchten).

Um gleich im aktuellen Durchlauf noch von der Korrektur des Fehlers profitieren zu können, verschieben Sie den gelben Pfeil, der die aktuelle Zeile markiert, einfach dorthin zurück, wo Sie fortfahren möchten. Prüfen Sie dann mit F8, ob die Zeile das gewünschte Ergebnis liefert.

Wenn Sie einmal mehrere Haltepunkte eingebaut haben und diese auf einen Schlag entfernen möchten, erledigen Sie dies übrigens mit der Tastenkombination Strg + Umschalt + F9.

Zusammenfassung und Ausblick

Neben dem Direktbereich und den Möglichkeiten zum Durchlaufen des Codes liefert der VBA-Editor noch weitere Werkzeuge, die beim Debuggen des Codes helfen. Diese schauen wir uns im zweiten Teil dieser Artikelreihe an.