Access-Grundlagen #6 - VBA
6.1 Anlegen von Ereignisprozeduren | 6.2 Ermittlung von Konstantenwerten |
6.3 Ermittlung von Eigenschaftsnamen | 6.4 Verweisprobleme |
6.5 Fehler beheben | 6.6 Ersatz für Domänenaggregat-Funktionen |
6.1 Anlegen von Ereignisprozeduren
Um einem Formular,Textfeld, Bereich (Seitenkopf etc.) o.ä eine Ereignisprozedur zuzuweisen, muss man folgendermassen vorgehen (Beispiel anhand eines Textfeldes in einem Formular).
1. Im Formularentwurf wählt man das Textfeld aus und geht auf Ansicht/Eigenschaften ( ALT + ENTER ). Anschliessend öffnet sich ein Dialog, in dem man dann das Register "Ereignis" (s. oberste Markierung) auswählt. Jetzt bewegt man sich zu dem gewünschten Ereignis und klickt auf die rechts erscheinenden 3 Punkte (s. rote Markierung). In dem Beispiel wird dem Textfeld "KundenVorname" eine Prozedur bei dem Ereignis "Nach Aktualisierung" zugeordnet.
2. Nach Anklicken der 3 Punkte wählt man "Code-Generator" aus und bestätigt mit "OK".
3. Danach sollte sich der VBA-Editor öffnen, wo man dann endlich den vorgeschlagenen Code eintragen
kann. Dabei müssten die Zeilen
Private Sub TextFeldName_Ereignis()
und
End Sub
automatisch angelegt worden sein.
Einzelansicht
6.2 Ermittlung von Konstantenwerten
Wie bereits unter 2.3 erwähnt, gibt es eine schnelle Möglichkeit, den Wert einer VBA-Konstanten o.ä. ohne Nachschlagen in der Online-Hilfe zu ermitteln.
Den VBA-Editor öffnen (z.B. durch Entwurfsansicht eines Standardmoduls). Dort auf Ansicht/Direktfenster
(
STRG
+
G
) gehen und danach in dem Direktfenster
?NameDerKonstanten
eingeben. Die
Zeile mit
ENTER
bestätigen. Anschliessend erhält man den Wert. In dem Beispiel wurde der Wert der
Konstanten "vbProperCase" abgefragt.
Einzelansicht
6.3 Ermittlung von Eigenschaftsnamen
Entgegen der landläufigen Meinung besitzt Access eine gute und bisweilen tatsächlich kontextsensitive Online-Hilfe. Wenn man per VBA eine Objekteigenschaft ändern möchte und den Eigenschaftsnamen, den man unter VBA verwenden müsste, nicht kennt, dann hilft es meistens, im (Formular- bzw. Berichts-) Entwurf diese Eigenschaft erst einmal anzuwählen. Anschliessend drückt man F1 und erhält Hilfe zu der Eigenschaft. Ganz oben sollte auch der (englische) Name dieser Eigenschaft angezeigt werden. Meistens gelangt man aber so nur in die Access-Hilfe, in der nichts näheres zur VBA-Syntax steht.
Wenn man anschliessend im VBA-Editor (z.B. aus dem Entwurf eines Moduls heraus) die VBA-Hilfe aufruft und dort nach der vorher gefundenen Bezeichnung sucht, sollte man die möglichen Einstellungen etc. finden.
Einzelansicht6.4 Verweisprobleme
Nun steht die Lösung dieser Probleme eigentlich schon unter FAQ 7.1 (s. dort auch für weitere Hinweise):
ZitatIrgendein Modul öffnen, Menü: Extras/Verweise wählen.
aber es wird immer noch übersehen, dass man nur im VBA-Editor über den Menüpunkt Extras die Verweise setzen kann ( ALT + X , danach V ). Das folgende Bild sollte endlich Abhilfe schaffen:
Wenn das Setzen der Verweise nicht möglich ist, dann befindet man sich höchstwahrscheinlich im Debug-Modus, der zunächst beendet werden muss (d.h. einfach das Fenster mit der Code-Ansicht wieder schliessen). Der Debug-Modus wird gestartet, wenn die Prozedur auf einen unbehandelten Laufzeitfehler trifft und man beim daraufhin erscheinenden Meldefenster auf "Debuggen" klickt.
Einzelansicht6.5 Fehler beheben
Sehr viele Fehler können durch Beachtung der folgenden Punkte vermieden bzw. behoben werden.
6.5.1 Code kompilieren
Nach jeder Code-Änderung sollte vor der nächsten Ausführung der Code kompiliert werden, um evtl. versteckte Fehler ausfindig zu machen. Dazu muss man im VBA-Editor Debuggen/Kompilieren von Datenbankname ( ALT + G , anschliessend K ) aufrufen.
6.5.2 Explizites Deklarieren von Variablen durch Option Explicit
In jedem Deklarationsteil eines Moduls sollte als 2. Zeile die Anweisung
Option
Explicit
zu finden sein (s. auch Screenshot unter
6.4
). Dadurch wird man
gezwungen, die verwendeten Variablen vorher zu deklarieren und erspart sich so manche Fehlersuche wg.
Buchstabendrehern in Variablennamen. Man kann diese Zeile in jedem
neuen
Modul
erzwingen, indem man im VBA-Editor
Extras/Optionen
(
ALT
+
X
, dann
O
) aufruft und dort im Register
Editor
einen Haken bei
Variablendeklaration
erforderlich
setzt. Bereits bestehende Module müssen manuell ergänzt werden.
6.5.3 Richtiges Deklarieren der Variablen
Werden Variablen innerhalb einer Zeile deklariert, so muss der Typ hinter jede Variable gesetzt werden. Das folgende Beispiel ist falsch , da so nur die letzte Variable als String und die ersten zwei Variablen als Variant deklariert werden:
Dim strVariable1, strVariable2, strVariable3 As String
So ist es richtig :
Dim strVariable1 As String, strVariable2 As String, strVariable3 As String
Zudem sollte bei möglichen Überschneidungen von Variablentypen zwischen unterschiedlichen Verweisen
explizit die betreffende Bibliothek davor gesetzt werden. Der letztgenannte Punkt trifft vor allem ab Access
2000 und dort speziell bei der Deklaration von Recordsets zu, da der Typ
Recordset
in ADO und DAO vorhanden ist (s. auch
FAQ 7.11
):
Dim rs As DAO.Recordset 'ist besser als nur: 'Dim rs As Recordset
6.5.4 Verwenden von Debug.Print
Immer wieder kommt man in die Verlegenheit, Datenherkünfte oder dgl. dynamisch zu erstellen. Wenn es
nicht wie erwartet funktioniert, ist es ratsam, den SQL-String oder andere Werte zur Kontrolle mit
Debug.Print
auszugeben. Danach taucht der zugewiesene Wert im Direktfenster auf und
lässt sich somit besser als mit einer Msgbox oder mittels Haltepunkt kontrollieren. Man muss also
folgendermassen vorgehen: Bei der Code-Erstellung lässt man sich im VBA-Editor das Direktfenster
über
Ansicht/Direktfenster
anzeigen (oder durch den Tastenschlüssel
STRG
+
G
). Der zuzuweisende String (oder was auch immer) wird in einer Variablen gespeichert und vor der
Zuweisung zur Eigenschaft mittels
Debug.Print
ausgegeben. Startet man nun die
Prozedur und es treten Fehler auf, wechselt man in den VBA-Editor und schaut sich das Ergebnis im
Direktfenster an. Speziell SQL-Anweisungen lassen sich durch Kopieren
des im Direktfenster erhaltenen Strings
und Einfügen in die
SQL-Ansicht
einer neuen Abfrage sehr gut kontrollieren.
Weiteres zum Direktfenster findet man auch auf
DBWiki
.
Hier nun endlich ein Beispiel:
Private Sub lstZeitraeume_AfterUpdate() 'Dieser Beispiel-Code wertet den Wert eines 'Listenfeldes aus und ändert die Datenherkunft 'eines Formulares zur Laufzeit. Dim strSQL As String 'nimmt den SQL-String der neuen Datenherkunft auf strSQL = "SELECT TagDerVerbindung, PrK_IDdesTages, FrK_AbrechnungsID" _ & " FROM tblTage WHERE FrK_Abrechnungsid=" & Me!lstZeitraeume _ & " ORDER BY TagDerVerbindung;" 'Ausgabe der zuzuweisenden Datenherkunft im Direktfenster. 'Wenn alles funktioniert, sollte die Zeile wieder entfernt 'werden: Debug.Print strSQL 'Zuweisen der neuen Datenherkunft: Me.Recordsource = strSQL End Sub
6.5.5 Einzelschrittmodus und Haltepunkte
Um den Ablauf in einer Prozedur zu verfolgen, kann man Haltepunkte festlegen. Dazu geht man im VBA-Editor in die gewünschte Zeile, in der das möglich ist (im Deklarationsteil z.B. ist diese Option nicht gegeben) und legt über Debuggen/Haltepunkt ein/aus den Überwachungspunkt an. Schneller geht es sicherlich mit dem Hotkey F9 oder mit einem Klick auf den grauen Bereich neben dem VBA-Code. Wenn die Routine nun gestartet wird, wartet sie dort so lange, bis sie mittels F8 (oder Debuggen/Einzelschritt ) fortgesetzt wird.
6.5.6 Abfangen von Fehlern
Speziell bei Anwendungen, die in einer Runtime-Umgebung laufen sollen, müssen z.T. unvermeidliche Laufzeitfehler abgefangen werden. Dazu kann man sich einfach mal einen durch den Schaltflächen-Assistenten generierten Code anschauen und diesen ggf. anpassen. Wenn beispielsweise ein leerer Bericht nach der Variante #2 unter FAQ 5.8 nicht gedruckt werden soll, müsste der Code ungefähr so ausschauen (bei anderen Anweisungen muss die Fehlernummer sicherlich angepasst werden - 2501 gilt nur für diesen speziellen Fall):
Private Sub repBerichtsNameDrucken_Click() On Error GoTo Err_repBerichtsNameDrucken_Click DoCmd.OpenReport "Berichtsname" Exit_repBerichtsNameDrucken_Click: Exit Sub Err_repBerichtsNameDrucken_Click: If Err.Number <> 2501 Then MsgBox Err.Description, vbCritical, "Fehler# " & Err.Number End If Resume Exit_repBerichtsNameDrucken_Click End Sub
6.5.7 Code-Gestaltung und -Tools
Der Code sollte so gestaltet oder eingerückt werden, dass daraus schon der Ablauf einigermassen
ersichtlich wird. Dies erleichtert das Auffinden von fehlenden abschliessenden Zeilen wie beispielsweise
End If
bei einer IF-Klausel oder
Next
bei einer
For-Next-Schleife. Erweiterungen des Codes sind dann auch nicht mehr so schwierig. Für das
Einrücken bietet sich der
Smart Indenter
an. Ein weiteres praktisches Add-In sind die
MZ-Tools
, die eine Bibliothek für immer
wiederkehrende Code-Fragmente enthalten. Zeilen können nummeriert, Prozedurköpfe in Kommentarform
angelegt werden usw. Unbedingt anschauen!
6.6 Ersatz für Domänenaggregat-Funktionen
Die sehr einfach einzusetzenden Domänenaggregat-Funktionen wie z.B.
DLookup()
,
DCount()
,
DSum()
o.ä. haben den entscheidenden Nachteil, dass Indizes eher ungünstig eingesetzt werden. D.h., dass die Wertermittlung bei umfangreichen Tabellen länger als nötig dauern kann. Die 3 folgenden beispielhaften Ersatzfunktionen (
DAvg()
usw. könnten ähnlich umgesetzt werden) werden in derselben Art eingesetzt und nutzen Indizes, sofern diese in der Tabelle vorhanden sind und Kriterien benötigt werden. Außerdem werden im Fehlerfall etwas genauere Ausgaben generiert (statt z.B. nur
#Fehler
im Steuerelementinhalt):
Public Function TLookup(Expression As String, Domain As String, _ Optional Criteria) As Variant 'Ersatz für DLookup() On Error GoTo TLookup_Err Dim strSQL As String strSQL = "SELECT " & Expression & " FROM " & Domain If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria TLookup = DBEngine(0)(0).OpenRecordset(strSQL, 8)(0) Exit Function TLookup_Err: Select Case Err.Number Case 3021 'kein Datensatz gefunden TLookup = Null Case 3061 'einer der Feldnamen (Ausdruck oder Kriterium) stimmt nicht TLookup = "#Ausdruck/Kriterium" Case 3078 'Name der Tabelle oder Abfrage stimmt nicht TLookup = "#Domäne" Case 3464 'Datentyp im Kriterium ist falsch TLookup = "#Kriterium" Case Else 'Sonstige Fehler TLookup = "#Fehler" End Select End Function
Public Function TCount(Expression As String, Domain As String, _ Optional Criteria) As Variant 'Ersatz für DCount() On Error GoTo TCount_Err Dim strSQL As String strSQL = "SELECT COUNT(" & Expression & ") FROM " & Domain If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria TCount = DBEngine(0)(0).OpenRecordset(strSQL, 8)(0) Exit Function TCount_Err: Select Case Err.Number Case 3061 'einer der Feldnamen (Ausdruck oder Kriterium) stimmt nicht TCount = "#Ausdruck/Kriterium" Case 3078 'Name der Tabelle oder Abfrage stimmt nicht TCount = "#Domäne" Case 3464 'Datentyp im Kriterium ist falsch TCount = "#Kriterium" Case Else 'Sonstige Fehler TCount = "#Fehler" End Select End Function
Public Function TSum(Expression As String, Domain As String, _ Optional Criteria) As Variant 'Ersatz für DSum() On Error GoTo TSum_Err Dim strSQL As String strSQL = "SELECT SUM(" & Expression & ") FROM " & Domain If Not IsMissing(Criteria) Then strSQL = strSQL & " WHERE " & Criteria TSum = DBEngine(0)(0).OpenRecordset(strSQL, 8)(0) Exit Function TSum_Err: Select Case Err.Number Case 3061 'einer der Feldnamen (Ausdruck oder Kriterium) stimmt nicht TSum = "#Ausdruck/Kriterium" Case 3075 'Summierender Ausdruck ist falsch (z.B. "*" ist n. mgl.) TSum = "#Ausdruck" Case 3078 'Name der Tabelle oder Abfrage stimmt nicht TSum = "#Domäne" Case 3464 'Datentyp im Kriterium ist falsch TSum = "#Kriterium" Case Else 'Sonstige Fehler TSum = "#Fehler" End Select End FunctionEinzelansicht
Seiten: 1