VBA: Punkt oder Ausrufezeichen

Unter VBA gibt es Gelegenheiten, wo man zwischen zwei Elemente entweder einen Punkt oder ein Aufrufezeichen setzen kann, zum Beispiel bei gebundenen Steuerelementen in der Form Me.Vorname oder rst!Vorname. Im Gegensatz dazu stehen beispielsweise die Elemente eines Recordsets – hier können wir nur rst!Vorname verwenden, rst.Vorname führt zu einem Fehler. Ganz kompliziert wird es, wenn wir gebundene Steuerelemente auch noch umbenennen. Dann können wir auf den Wert des Steuerelements sowohl über Me!Vorname, Me.Vorname, Me!txtVorname oder Me.txtVorname zugreifen. Und manchmal führt die Syntax mit dem Punkt zu ernsthaften Verwirrungen, weshalb man in manchen Fällen auf jeden Fall die Ausrufezeichen-Syntax nutzen sollte.

Wir fangen mal vorn an: Von Punkten und Ausrufezeichen bleibt man solange verschont, wie man nicht per VBA auf den Inhalt von Steuerelementen oder Feldern zugreifen möchte. Das Problem daran ist: Ohne das ist man dabei recht eingeschränkt. Das Gute ist: Wenn man einmal an die Stelle gelangt ist, wo man Objektbezüge über Punkte und/oder Ausrufezeichen herstellt, kann man nicht viel falsch machen – und wo es dabei Stolpersteine gibt, erläutern wir in diesem Beitrag.

Punkte und Ausrufezeichen in Recordsets und ähnlichen Elementen

Wir beginnen dort, wo der Einsatz eindeutig geregelt ist. Wenn man beispielsweise eine Schleife programmieren möchte, mit der man die Datensätze eines Recordsets durchläuft, möchte man auf die Felder dieses Recordsets zugreifen. Das Recordset bietet einige Eigenschaften und Methoden an, die man wie bei allen Objekten mit der Punkt-Syntax adressieren kann, also indem man den Namen der Objektvariablen, meist rst, eingibt und dann einen Punkt setzt, um per IntelliSense die möglichen Elemente zu sehen. Das Ergebnis ist eine Liste wie in Bild 1.

Nutzung des Punktes für die Anzeige von Elementen per IntelliSense

Bild 1: Nutzung des Punktes für die Anzeige von Elementen per IntelliSense

Darüber findet man beim Recordset alle möglichen Einträge, aber nicht die Felder des Recordsets. Diese können wir auch nicht über die Punkt-Syntax referenzieren. rst.KategorieID funktioniert also nicht, sondern wirft den Fehler Methode oder Datenobjekt nicht gefunden. Stattdessen nutzen wir an dieser Stelle in der kürzesten Form das Ausrufezeichen, also beispielsweise rst!KategorieID. Wir haben hier keine IntelliSense-Unterstützung, aber immerhin liefert dies den Wert des Feldes für den jeweiligen Datensatz. Im Detail sieht das wie im folgenden Beispiel aus:

Public Sub PunktOderAusrufezeichen()
     Dim db As DAO.Database
     Dim rst As DAO.Recordset
     Set db = CurrentDb
     Set rst = db.OpenRecordset("tblKategorien", dbOpenDynaset)
     Do While Not rst.EOF
         Debug.Print rst!KategorieID, rst!Kategorie
         rst.MoveNext
     Loop
End Sub

Wie wir hier sehen, werden die Eigenschaften und Methoden, also EOF oder MoveNext, mit der Punkt-Syntax verwendet. Wir haben in diesem Fall also eine eindeutige Aufteilung: Eigenschaften und Methoden erreichen wir mit einem Punkt, die Felder mit dem Ausrufezeichen.

Warum aber können wir die Felder überhaupt mit dem Ausrufezeichen adressieren? Weil es sich bei den Feldern um Elemente einer Auflistung handelt, genau genommen sogar um die einer Auflistung mit benutzerdefinierten Elementen, und weil das Ausrufezeichen in diesem Fall als Abkürzung für eine ausführlichere Schreibweise verwendet werden kann. rst!KategorieID steht nämlich eigentlich für ein Element der Fields-Auflistung des Recordset-Objekts:

Debug.Print rst.Fields("KategorieID")

Und auch das ist noch nicht die ganze Wahrheit, denn rst.Fields(“Kategorie”) können wir auch nur verwenden, weil man die Standardeigenschaft eines Elements immer weglassen kann. Eigentlich heißt der Ausdruck nämlich wie folgt, und dabei ist Value die Standardeigenschaft des Field-Objekts, das wir mit Fields(“KategorieID”) referenzieren:

Debug.Print rst.Fields("KategorieID").Value

Das Beispiel finden Sie im Modul mdlPunktUndAusrufezeichenInRecordset.

Eigenschaften und Felder in Formular- und Berichtsmodulen

Eine andere Situation finden wir vor, wenn wir die Klassenmodule von Formularen oder Berichten betrachten, die an eine Datensatzquelle wie eine Tabelle oder Abfrage gebunden sind – und hier speziell bei den Steuerelementen und den Feldern der Datensatzquelle.

Binden wir ein Formular an eine Tabelle wie tblKategorien, welche die beiden Felder KategorieID und Kategorie enthält, und fügen wir diese beiden Felder zum Detailbereich des Formularentwurfs hinzu, können wir beispielsweise in der VBA-Ereignisprozedur, die durch eine Schaltfläche ausgelöst wird, wie folgt auf die Werte der gebundenen Felder zugreifen:

Debug.Print Me.KategorieID, Me.KategorieID

Wir nutzen also einfach mit Me den Verweis auf das Klassenmodul selbst und können dann nach Eingabe des Punktes nicht nur auf die Eigenschaften und Methoden des Formulars zugreifen, sondern auch auf die Feldnamen der Datensatzquelle des Formulars.

Noch besser: Obwohl es sich hier nicht um eingebaute Eigenschaften der Formularklasse handelt, können wir IntelliSense nutzen, um darauf zuzugreifen – siehe Bild 2! Warum ist das überhaupt möglich? Der Hintergrund ist, dass Access beim Hinzufügen einer Datensatzquelle zu einem Formular automatisch für jedes Feld eine eigene Eigenschaft zum Klassenmodul des Formulars hinzufügt. Deshalb werden diese auch per IntelliSense angezeigt. Wir können hier aber auch, genau wie beim Recordset-Objekt, über die Ausrufezeichen-Syntax auf die Felder zugreifen. Das sieht so aus:

Zugriff per Punkt und IntelliSense auf die Felder der Datensatzherkunft

[

Bild 2: Zugriff per Punkt und IntelliSense auf die Felder der Datensatzherkunft

Debug.Print Me!KategorieID, Me!Kategorie

Auch hier haben wir es, genau wie beim Recordset, wieder mit einer Abkürzung zu tun, diesmal allerdings nicht für die Fields-Auflistung, sondern für die Controls-Auflistung. Weiter unten unter Was macht das Ausrufezeichen eigentlich genau? erläutern wir, warum wir mit dem Ausrufezeichen einmal die Fields– und einmal die Controls-Auflistung abkürzen können.

Für das Feld KategorieID würde ein etwas weniger verkürzter Ausdruck also wie folgt aussehen:

Debug.Print Me.Controls("KategorieID")

Und auch hier ist Value die Standardeigenschaft, sodass wir schließlich bei der folgenden ausführlichen Variante landen:

Debug.Print Me.Controls("KategorieID").Value

Soweit, so gut: Wir können also sowohl mit der Punkt- als auch mit der Ausrufezeichen-Syntax auf die Steuerelemente eines Formulars zugreifen.

Schauen wir uns nun die Eigenschaften der gebundenen Felder an, die wir über die Feldliste zum Formular hinzugefügt haben, dann sehen wir, dass der Ausdruck KategorieID sowohl als Steuerelementname als auch für die Eigenschaft Steuerelementinhalt angegeben wird (siehe Bild 3). Worauf greifen wir also eigentlich genau zu, wenn wir Me.KategorieID oder Me!KategorieID referenzieren?

Name und Steuerelementinhalt sind identisch.

Bild 3: Name und Steuerelementinhalt sind identisch.

Wir fügen der Prozedur für die Schaltfläche zwei Zeilen hinzu, um den Typ der mit Punkt und Ausrufezeichen angesprochenen Elemente zu ermitteln:

Debug.Print "Typename ''Me.KategorieID'': " _
     & TypeName(Me.KategorieID)
Debug.Print "Typename ''Me!KategorieID'': " _
     & TypeName(Me!KategorieID)

Das Ergebnis sieht wie folgt aus:

Typename ''Me.KategorieID'': TextBox
Typename ''Me!KategorieID'': TextBox

Wir greifen also in beiden Fällen auf das Steuerelement zu, welches durch die implizit angegebene Standardeigenschaft wiederum über das für Steuerelementinhalt angegebene Feld den Wert für den aktuellen Datensatz ermittelt.

Den Beispielcode finden Sie im Klassenmodul des Formulars frmKategorien.

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