VBA-Fehlerbehandlung revolutioniert

Es kracht hin und wieder beim Ausführen Ihres VBA-Codes und Sie klicken auf die Debuggen-Schaltfläche der Fehlermeldung Macht nichts – das kommt vor. Sie verteilen Ihr Werk und der Benutzer berichtet von seltsamen Fenstern und sich öffnendem VBA-Editor Weniger schön. Sie liefern Ihre Datenbank mit der Access-Runtime aus und der Kunde meldet ungehalten, dass sich die Anwendung allenthalben einfach schließe Spätestens dann ist Schluss. Es geht aber auch anders …

Die Fehlerbehandlung ist fester Bestandteil jedes Programmcodes – oder sollte es zumindest sein. Es ist sicher legitim, während der Entwicklung einer Prozedur oder eines Moduls Fehlerbehandlungsmechanismen außen vor zu lassen. Das ist im Gegenteil sogar hilfreich, weil bei auftretenden Fehlern der VBA-Debugger an der richtigen Stelle anhält, diese markiert und Sie nun etwa Variablen auf falsche Werte inspizieren können. Sobald jedoch andere Benutzer oder sogar Kunden mit der Anwendung arbeiten, sollten Fehlerbehandlungen in allen Prozeduren eingebaut sein, damit die Benutzer nicht mit kryptischen Meldungen konfrontiert werden oder gar den VBA-Editor zu Gesicht bekommen.

Besonders wichtig ist das, wenn Ihre Datenbank mit der Runtime-Version von Access gestartet wird, denn diese verzeiht keine Nachlässigkeiten und beendet sich kurzerhand bei jedem unbehandelten Fehler selbst. Das kann auch Datenverlust nach sich ziehen.

Möglichkeiten zur Fehlerbehandlung von VBA-Routinen wurden in Access im Unternehmen bereits vielfach dargestellt. Ob Sie in den Zweig zur Fehlerauswertung einfach eine schnöde Messagebox setzen, die die Fehlerbeschreibung ausgibt, oder die Fehlerbearbeitung an eine separate Fehlerfunktion delegieren, die sich um Ausgabe, Loggen oder gar Versenden per E-Mail kümmert, von einer Arbeit kann Sie niemand befreien: In jede einzelne Prozedur Ihres Projekts müssen entsprechende Anweisungen geschrieben werden, die das Verhalten bei einem auftretenden Fehler regeln.

Zwar erleichtern Ihnen Hilfsmittel, wie die MZ-Tools, die Arbeit beim Anlegen eines Rahmens zur Fehlerbehandlung und optional beim Durchnummerieren der Code-Zeilen. Im Eifer des Gefechts wird es Ihnen versehentlich aber sicher immer wieder passieren, dass Sie mal schnell eine Funktion in ein Modul hineinschreiben, die ohne Fehlerbehandlung bleibt. Lehnen Sie sich zurück! Mit dem brandneuen SimplyVBA Global VBA Error Handler [1] hat Wayne Phillips von everythingaccess.com eine revolutionäre Schnittstelle geschaffen, die Fehlerbehandlung unter VBA auf ein neues Level hebt, ganz neue Konzepte erschließt und Sie in Zukunft ruhig schlafen lässt.

The SimplyVBA Global Error Handler – SVGEH

Der Name Wayne Phillips dürfte den meisten Access-Entwicklern kein Begriff sein. Er ist kaum in Foren präsent, kein MVP und doch möglicherweise der Entwickler mit den tiefsten Kenntnissen zu Interna von Access und VBA weltweit – außerhalb des Microsoft Entwickler-Teams selbstredend.

Seine englische Firma Everythingaccess.com aka iTechMasters dagegen könnte dem einen oder anderen bereits beim Surfen begegnet sein: Dort wird ein Service zum Dekompilieren von Access-MDE-Datenbanken angeboten. Niemand sonst kann seit zwei Jahren einen solchen Dienst anbieten. Karl Donaubauer berichtete in der Ausgabe 4/2006 von Access im Unternehmen darüber. Ich hatte die Ehre, zur Runde der Beta-Tester des Global Error Handlers zu gehören, mit einigen Vorschlägen an der Entwicklung teilhaben zu dürfen und dabei einige Hintergründe über die Wirkungsweise der Schnittstelle zu erfahren. Rein äußerlich handelt es sich um eine ActiveX-DLL, die, zumindest in der Freeware-Version, in die Verweise der eigenen Datenbank, also des VBA-Projekts, aufgenommen wird. Sie klinkt sich außerdem bei Registrierung, wahlweise über ein Setup oder über regsvr32, als COM-Addin in Access ein. Über den Aufruf einer einzigen Methode in der Schnittstellenbibliothek verändert sich der VBA-Debugger komplett und leitet alle Fehlerereignisse an eine wählbare eigene Prozedur weiter – ganz unabhängig davon, wo sich der Fehler ereignet und ob Sie Statements zur Fehlerbehandlung in den Prozeduren Ihres Projekts implementiert haben.

Selbst Fehler, die im VBA-Direktfenster ausgelöst werden, landen dann bei dieser Prozedur, in deren Ablauf beliebige Fehlerauswertungen vorgenommen werden können.

Wie hat er das gemacht

Bevor ich Ihnen die Verfahrensweisen im Umgang mit dem Global Error Handler beschreibe, soll erwähnt werden, was da intern vor sich geht. Wayne Phillips hat die DLL mit Borland C++ entwickelt und auch vor Assembler-Einsatz nicht Halt gemacht. Der Grund dafür ist, dass das Ausschalten des VBA-internen Debuggers und das Weiterleiten von Fehlerereignissen an eine benutzerdefinierte Funktion sich nur mit einem Patchen der geladenen VBA-System-DLLs erreichen lässt. Das passiert, wohlgemerkt, nur im Access zugewiesenen Arbeitsspeicher und verändert nicht etwa Dateien von Access oder VBA. Um dies zu erreichen, also geschützte Speicherbereiche zu manipulieren, müssen scharfe API-Geschütze aufgefahren werden. Man könnte nun misstrauisch werden, ob solche tief greifenden Manipulationen nicht die Stabilität von VBA gefährden. Tatsächlich kann ich aber seit einigen Versionen der DLL von keinem einzigen Absturz oder irgendwelchen Unzulänglichkeiten oder Fehlfunktionen in allen Testprojekten berichten. Wayne Phillips ist, davon abgesehen, ein zugänglicher Entwickler, der Bugs außerordentlich schnell behebt. Sollten Sie problematisches Verhalten des Error Handlers feststellen, dann zögern Sie nicht, ihm dies in einer kurzen E-Mail mitzuteilen – dann allerdings in Englisch.

Der VBA-Debugger

Ein Ausflug in die Funktionsweise des VBA-Debuggers soll zunächst klären, wie VBA mit Fehlern umgeht.

Dazu legen wir eine einfache Prozedur an, die absichtlich einen Fehler hervorruft:

Sub LetItCrash
    Dim obj As Object
    Set obj = CreateObject("Sascha.Trowitzsch")
End Sub

Hier wird versucht, ein COM-Objekt zu erzeugen, das es (nach meiner Kenntnis) gar nicht gibt. Beim Ausführen der Prozedur werden wir folglich mit dem Fehlerdialog des VBA-Debuggers konfrontiert (siehe Bild 1). Der Benutzer Ihrer Anwendung wird erst mal ratlos sein, was das zu bedeuten hat, und anschließend möglicherweise die Eingabetaste drücken, weil der Begriff Debuggen so chic aussieht und ohnehin den Fokus hat.

debugmsg.png

Bild 1: Eine konventionelle VBA-Fehlermeldung

Das jedoch ist der denkbar ungünstigste Fall, weil sich nun ein Fenster öffnet, von dem er noch nicht mal weiß, ob es zu Ihrer Anwendung gehört und ob er hier Daten eingeben soll, weil er bei der Schulung geschlafen hat (siehe Bild 2). Aber verfolgen wir lieber nicht, wie der Benutzer in seiner Verwirrung weiter verfährt… …

debugline.png

Bild 2: Eine Fehlermeldung im VBA-Editor

Was hat VBA gemacht

Wenn VBA auf eine Zeile stößt, die es nicht ausführen kann, weil Syntax oder Werte nicht seinen Regeln entsprechen, dann schaut es zunächst nach, in welchem Modus sich sein Debugger befindet. Dieser Modus kann durch On Error-Direktiven im Code gesteuert werden. In unserem Prozedurbeispiel gibt es keine solche Direktive und der Modus des Debuggers ist damit quasi auf “Interaktiv” geschaltet, was bedeutet, dass VBA nun Entscheidungshilfe benötigt, wie es mit dem Fehler weiter umgehen soll. Da es darüber keine Informationen aus dem VBA-Projekt selbst bekommt, fragt es eben beim Benutzer nach und präsentiert den Fehlerdialog, nachdem es vorsorglich den Code in gelb markierter Zeile angehalten hat (siehe Bild 2).

Wenn Sie die Debuggen-Schaltfläche betätigen, dann gelangen Sie genau zu dieser Zeile und haben nun noch die Möglichkeit, die Zeile syntaktisch oder durch andere Variablenwerte zu korrigieren – etwa die ProgID des zu erzeugenden COM-Objekts auf Forms.Form.1 zu ändern. VBA versucht dann, die korrigierte Zeile nochmals auszuführen. Klicken Sie hingegen die Beenden-Schaltfläche, dann bricht VBA die Ausführung des Codes ab und zerstört nebenbei noch sämtliche lokalen und globalen Variablen, die Sie möglicherweise in Ihrem Projekt untergebracht haben. Der Gedanke dahinter ist der, dass VBA wegen des nicht weiter ausgeführten Codes vorlaut davon ausgeht, dass die Werte der Variablen nun wahrscheinlich eh nicht mehr passen.

Nicht unerwähnt sollte bleiben, dass dies nur das Verhalten unter der Vollversion von Access ist. Die Runtime-Version erlaubt ja keinen Einblick in die VBA-Entwicklungsumgebung und ein Debuggen-Knopf im Fehlerdialog ergibt somit keinen Sinn. Die Runtime stuft jeden VBA-Fehler als kritisch ein und beendet die Datenbank kurzerhand, nachdem sie den Benutzer recht wortkarg über die Ursache informiert (siehe Bild 3). All diese unschönen Auswirkungen unterlassener Anweisungen zur Fehlerbehandlung lassen sich vermeiden, wenn dem VBA-Debugger gesagt wird, was er im Fehlerfall tun soll. Im Prinzip gibt es nur zwei Modi, die Sie einstellen können. Über On Error Resume Next sagen Sie ihm schlicht, dass er nicht ausführbare Zeilen überspringen soll (s. Listing 1).

Listing 1: Fehler übergehen mit On Error Resume Next

Sub LetItCrash2()
    Dim obj As Object
    On Error Resume Next
    Set obj = CreateObject("Sascha.Trowitzsch")
End Sub

missing image file

Bild 3: Unbehandelter Fehler unter der Access-Runtime – peng!

Mit On Error Goto Label teilen Sie dem Debugger mit, dass er bei nicht ausführbarer Zeile an eine andere Stelle im Code springen soll, die mit einer Zeichenkette, dem Label, gekennzeichnet ist. In diesem Codeabschnitt lassen sich dann weitere Entscheidungen treffen, wie die Ausführung des Codes abschließend aussehen soll (s. Listing 2). Immerhin wird dem Anwender mit dieser Routine eine Meldung angezeigt, die keinen Debuggen-Knopf mehr aufweist, und gesetzte Variablen verlieren auch nicht mehr ihre Werte (siehe Bild 4).

Listing 2: Fehlerbehandlung mit Sprungmarke

Sub LetItCrash3()
    Dim obj As Object
    On Error GoTo Fehler
    Set obj = CreateObject("Sascha.Trowitzsch")
Ende:
    Set obj = Nothing
    Exit Sub
 
Fehler:
    MsgBox Err.Description, vbCritical
    Resume Ende
End Sub

Listing 3: Fehlerbehandlung mit Nummerierung und Sprungmarke

Sub LetItCrash4()
    Dim obj As Object
 
    20 On Error GoTo Fehler
    40 Set obj = CreateObject("Sascha.Trowitzsch")
 
Ende:
    60 Set obj = Nothing
    80 Exit Sub
 
Fehler:
    100 MsgBox "Fehler in Zeile " & Erl & _
    " von mdlDemos.LetItCrash4:" & vbCrLf & _
    Err.Description, vbCritical, "Anwendungsfehler"
    120 Resume Ende
End Sub

errormsgbox.png

Bild 4: Fehlermeldung ohne Debugging-Schaltfläche

Davon abgesehen bringt diese Meldung weder den Benutzer, noch den Entwickler wirklich weiter. Was fangen Sie damit an, wenn der User Ihnen am Telefon die Meldung vorliest Sie enthält vor allem keine Informationen darüber, wo der Fehler auftrat. Eine aussagekräftigere Meldung enthielte daher zusätzliche Angaben zu Modulnamen, Prozedurnamen und möglichst auch Zeilennummer der nicht ausführbaren Codezeile (siehe Bild 5). Das lässt sich durch eine Erweiterung der Prozedur wie in Listing 3 erreichen. Die Tatsache, dass der Debugger für die Direktive On Error Goto Label immer die Angabe einer Sprungstelle innerhalb (!) der gleichen Prozedur erwartet, führt zu viel Arbeit: In Hunderten von Prozeduren Ihres Projekts müssen Sie die immer gleichen Anweisungen und Fehlerbehandlungsabschnitte einfügen. Und wenn Sie nicht übermäßig pingelig sind, werden Sie dabei immer noch eine Reihe Prozeduren übersehen …

Listing 4: Die Hauptroutine ruft eine Unterfunktion auf.

Private strTest As String
Public globRet As Boolean
 
Sub LetItCrash5()
    Dim a As Long
    a = 99
    strTest = "Sascha"
    globRet = SubLetItCrash(strTest)
End Sub
 
Function SubLetItCrash(strObj As String) As Boolean
    Dim obj As Object
    Set obj = CurrentDb
    Set obj = CreateObject(strObj & ".Trowitzsch")
    SubLetItCrash = obj.Name
    Set obj = Nothing
    SubLetItCrash = True
End Function

Listing 5: Variablenliste

*****************************************************
*** demo_globalerrorhandler.mdlDemos.SubLetItCrash *****************************************************
(PARAM) strObj As String = "Sascha"
(LOCAL) obj As Object = {Object}
(LOCAL) SubLetItCrash As Boolean = False
(MODULE) strTest As String = "Sascha"
(MODULE) globRet As Boolean = False
*****************************************************
*** demo_globalerrorhandler.mdlDemos.LetItCrash5 *****************************************************
(LOCAL) a As Long = 99
(MODULE) strTest As String = "Sascha"
(MODULE) globRet As Boolean = False
*****************************************************

errormsgbox2.png

Bild 5: Fehlermeldung mit Angabe der VBA-Quellzeile

Und hier setzt der Simply VBA Global Error Handler an. Er ermöglicht, dass bei Fehlern nicht das prozedureigene Label angesprungen wird, sondern eine beliebige öffentliche Fehlerbehandlungsprozedur, die Sie dafür umso reichhaltiger ausstatten und mit allen Schikanen zur Fehlerbeschreibung versehen können. Dabei lässt sich der SimplyVBA Global Error Handler, den ich ab hier abgekürzt nur noch SVGEH nennen werde, durchaus jederzeit über seine Schnittstelle so steuern, dass auch zu einer prozedureigenen Fehlerroutine zurückgesprungen werden kann.

SVGEH einsetzen

Wenn Sie den SVGEH verwenden möchten, dann laden Sie ihn zunächst unter [1] herunter. Es stehen drei Versionen zur Verfügung. Die Freeware-Version kommt erfreulicherweise ohne nervende Popups oder andere Werbemaßnahmen aus und enthält alle wesentlichen Features. Erst, wenn Sie Ihre Anwendung vertreiben wollen, fallen Kosten an, die jedoch relativ bescheiden ausfallen und mit der voraussichtlichen Zeitersparnis schnell wieder hereingeholt sind. Eine Übersicht über Versionsunterschiede finden Sie im Anhang. Die Freeware-Version erfordert die Installation über ein Setup, welches die VBAGlobalErrorHandler.dll als ActiveX-Komponente registriert. Die Installation enthält zusätzlich eine umfangreiche Demo-Datenbank, die alle Features gut demonstriert – allerdings in Englisch. Das gilt auch für die Hilfe, die bislang nur online unter [3] verfügbar ist. In der Freeware-Version benötigen Sie in Ihrem VBA-Projekt einen Verweis auf die SimplyVBA Global Error Handler Library.

Für die kommerziellen Versionen ist das nicht zwingend notwendig, weil diese zusätzlich einen Mechanismus anbieten, der das Laden der DLL über VBA-Anweisungen erlaubt. Die DLL muss dann lediglich etwa im Anwendungsordner liegen. Sollte diese auf einem Zielrechner nicht vorhanden sein, dann kann dies ebenfalls über VBA-Code ermittelt und dem Benutzer eine entsprechende Mitteilung für den Support präsentiert werden.

Für den Anfang sollten Sie aber mit Verweis arbeiten, weil Sie so durch IntelliSense unterstützt werden, und können nach Abschluss des Projekts auf die verweislose Variante umsteigen.

Übrigens: Der SVGEH lässt sich nicht nur unter Access einsetzen, sondern in allen durch VBA unterstützten Anwendungen wie Excel, Word et cetera. Nebenbei werden Sie nach Installation in der Liste der COM-Add-Ins von Access noch den Eintrag SimplyVBA Compiler Fix for MDEs finden, um den Sie sich nicht weiter zu kümmern brauchen. Dieses Add-In benötigt der SVGEH immer dann, wenn MDEs erstellt werden. Und schließlich zeigt der Add-In-Manager von VBA zusätzlich ein weiteres COM-Add-In an, den Simply VBA SourceCode Line Numberer, von dem später noch die Rede sein wird. Alle diese Komponenten befinden sich, wohlgemerkt, in der einen installierten DLL.

SVGEH aktivieren

Das zentrale Objekt, das der SVGEH zur Verfügung stellt, ist das ErrEx-Objekt. ähnlich, wie das immer aktive Err-Objekt von VBA, muss dieses Objekt nicht extra instanziert werden, sondern steht mit dem Laden des Verweises global bereit. Nur wenige Zeilen müssen geschrieben werden, damit Sie Ihre Fehlerbehandlung komplett umstellen:

ErrEx.EnableGlobalErrorHandler Application, "Fehlerbehandlung"
 
Function Fehlerbehandlung() As Boolean
 
End Function

Die erste Zeile zur Aktivierung des SVGEH können Sie testweise auch im VBA-Direktfenster absetzen. Sinnvoll ist natürlich, dass Sie diese letztlich in einer öffentlichen Funktion unterbringen, die später vom AutoExec-Makro beim Start der Anwendung aufgerufen wird. Die Methode EnableGlobalErrorHandler deaktiviert das eingebaute Verhalten des VBA-Debuggers. Sie übergeben der Methode einen Verweis auf das Application-Objekt sowie den Namen einer öffentlichen Prozedur, die bei Fehlern ausgeführt werden soll. Statt einer Function können Sie ebenso eine Sub-Prozedur einsetzen. Fehlt diese Routine im Quellcode, dann meldet sich der SVGEH mit der Info in Bild 6.

noerrfunction.png

Bild 6: Der SVGEH meldet, wenn eine Fehlerbehandlungsroutine fehlt

Obwohl die Angabe der Fehlerbehandlungsprozedur obligatorisch ist, braucht sie keinen Inhalt zu haben. Das Standardverhalten des SVGEH in diesem Fall ist, dass ein Dialog mit umfangreichen Angaben zum auslösenden Fehler erscheint. Führen Sie die Prozedur LetItCrash der Beispieldatenbank (demo_globalerrorhandler.mdb) wie oben aus, dann präsentiert sich ohne weiteres Zutun etwa ein Dialog wie in Bild 7.

globerrmsg1.png

Bild 7: Der Error Report des einbauten SVGEH-Fehlerdialogs

Sie sehen: Neben Fehlernummer und -beschreibung, also Angaben, die auch der übliche Fehlerdialog von VBA bereithält, finden sich noch mehr Informationen, wie Datum und Uhrzeit des Fehlerereignisses, die Prozedur und sogar die Quellcodezeile im Volltext.

Mega-Features

Ein Klick auf den Button Show call stack enthüllt schließlich noch die Aufrufreihenfolge der Prozeduren, die dem Fehler vorausgegangen war, wie in Bild 8. Es ist dort etwa zu erkennen, dass die Funktion LetItCrash vom VBA-Direktfenster aus aufgerufen wurde (VBE.Immediate.Window). Ein weiteres Feature ist allerdings den kommerziellen Versionen des SVGEH vorbehalten und zeigt sich durch Vorhandensein der Schaltfläche Show Variables. Wird diese angeklickt, so öffnet sich eine Übersicht mit den Inhalten aller (!) Variableninhalte, die zum Zeitpunkt des Fehlers gesetzt waren. Für Analysezwecke ist dies eine unschätzbare Unterstützung.

globerrmsgcallstack.png

Bild 8: Der SVGEH kann auch die Reihenfolge der Prozeduraufrufe ermitteln.

Um die Funktion der beiden letztgenannten Features etwas besser zu verdeutlichen, ist in Listing 4 eine etwas vertracktere Version unseres LetItCrash-Moduls angegeben.

Listing 6: Variablenliste

Function Fehlerbehandlung() As Boolean
    With ErrEx
    Select Case .Number
    Case 429
    .Description = "COM-Objekt konnte nicht erstellt werden"
    End Select
 
    .Description = .Description & vbCrLf & "(" & .SourceModule & "." & .SourceProcedure & _
    " Z." & .SourceLineNumber & ")"
    End With
End Function

Der Aufruf von LetItCrash5 aus einem Makro heraus führt dann zum Call Stack (Prozeduraufrufliste) in Bild 9.

callstack.png

Bild 9: Informationen zum Call Stack im Fehlerdialog des SVGEH

Zu lesen ist diese Liste von unten nach oben. Zuerst wurde die Funktion LetItCrash5 im VBA-Direktfenster aufgerufen, danach rief diese ihrerseits die Function SubLetItCrash auf, in der sich der eigentliche Fehler ereignete. Beteiligt waren die Zeilen #3 und #2 – davon wird gleich noch die Rede sein.

Der Klick auf den Button Show Variables öffnet die Variablenliste aus Listing 5.

Hier sind nicht nur die Variablennamen, -typen und -werte verzeichnet, sondern auch ihre Gültigkeitsbereiche, fein säuberlich sortiert nach den beteiligten Prozeduren.

Als wäre das nicht ohnehin schon obercool, der Hammer kommt erst noch: Das alles funktioniert auch in einer MDE und/oder Runtime!

Sollten Sie also bisher der beruhigenden Annahme erlegen sein, dass in einer MDE kein Quelltext mehr vorhanden sei – ist er eigentlich auch nicht! -, dann bekommen Sie hiermit eine Kostprobe von Wayne Phillips Fähigkeiten zum Reverse Engineering von P-Code geboten. Lediglich der Text der beteiligten Quellcodezeilen wird bei MDEs nicht wiedergegeben.

Die Schaltflächen Debug Source Code (Debuggen), End (Beenden) und Help (Hilfe) kennen sie schon aus den herkömmlichen VBA-Fehlermeldungen, und sie verhalten sich auch beim SVGEH analog.

Neu hingegen ist der Button Ignore and continue. Ein Klick darauf kommt einem momentanen On Error Resume gleich – die fehlerhafte Zeile wird also übersprungen.

Unmittelbar danach ist allerdings der gesetzte Fehlerbehandlungsstatus wieder aktiv. Um kurz zusammenzufassen, was das bisher Ausgeführte bedeuten kann:

  • Sie brauchen im Prinzip in keine Prozedur mehr eine Fehlerbehandlung einzubauen.
  • Sie bekommen bei Einsatz des SVGEH dennoch ausführlichste Informationen über jeden ausgelösten Fehler.
  • Unbehandelte Fehler können mit Ignore and continue übergangen werden, ohne dass VBA alle Variablenwerte zerstört. Mit dem Ablauf des Codes kann einfach fortgefahren werden – allerdings mit ungewissem Ausgang …
  • Das alles funktioniert in MDBs, ACCDBs, wie in MDEs und ACCDEs und außerdem auch unter Access Runtime-Umgebung (Tests fanden unter allen erdenklichen Konfigurationen von Office 2000 bis 2007 und Windows XP sowie Vista statt).

Zeilennummern

Über das neue COM-Addin SimplyVBA SourceCode Line Numberer kommt eine neue Toolbar mit einer einzigen Schaltfläche in die Entwicklungsumgebung (siehe Bild 10).

linenumberbutton.png

Bild 10: Der SVGEH liefert ein neues Toolbar für den VBA-Editor.

Ein Klick darauf lässt, wie in Bild 11, im gerade aktiven Codefenster eine vertikale Leiste erscheinen, die Codezeilen prozedurweise durchnummeriert. Sie brauchen dieses Feature nicht unbedingt.

linenumbering.png

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar