Home > Artikel > Ausgabe 5/2018 > Steuerelemente per VBA referenzieren

Steuerelemente per VBA referenzieren

Achtung: Sie sind nicht angemeldet. Wenn Sie Abonnent sind und sich anmelden, lesen Sie den kompletten Artikel, laden das PDF herunter oder probieren die Beispieldatenbank aus (sofern vorhanden).

Wenn Sie Formulare und Steuerelemente programmieren wollen, müssen Sie wissen, wie Sie diese referenzieren. Nicht immer geschieht dies vom Klassenmodul des Formulars selbst aus – manchmal wollen Sie vielleicht auch von anderen Formularen auf die Steuer­elemente eines anderen Formulars zugreifen oder auch von einer VBA-Prozedur in eine Standardmodul. Dieser Artikel zeigt, wie Sie die Unterformulare und Steuer­elemente eines Formulars referenzieren und auf diese zugreifen.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1805_FormsControlsVBARead.accdb.

Innerhalb des Formulars

Im Artikel Formulare per VBA referenzieren haben Sie bereits erfahren, dass ein Formular ein Klassenmodul erhält, sobald Sie Ereignisprozeduren für das Formular oder die enthaltenen Steuer­elemente anlegen. In diesem Klassenmodul können Sie mit dem Schlüsselwort Me auf das Formular und seine Eigenschaften zugreifen, während Sie von außen auf andere Art auf das Formular zugreifen müssen. Für den Zugriff auf die in einem Formular enthaltenen Elemente wie Unterformulare oder andere Steuer­elemente gelten daher auch verschiedene Regeln, auch wenn Sie letztendlich auf das gleiche Element zugreifen wollen. Allerdings können wir das entschärfen, indem wir die Regeln dafür nochmal zusammenfassen. Wenn Sie also auf Steuer­elemente in einem Formular zugreifen wollen, verwenden Sie abhängig vom Ausgangspunkt die folgenden Referenzen für das Formular:

Im eigenen Klassenformular:

Me...

Von außen:

Forms!...

Forms("")...

Etwas komplizierter wird es noch, wenn sich die zu referenzierenden Steuer­elemente in einem Unterformular befinden – dazu jedoch später mehr.

Über den Namen auf ein Steuer­element zugreifen

Die einfachste Methode, auf ein Steuer­element zuzugreifen, ist die über den Namen des Steuerelements. Dazu fügen wir dem Beispielformular frmBeispiel zwei Schaltflächen hinzu, von denen die zweite den Namen der ersten Schaltfläche ausgeben soll (siehe Bild 1). In der Ereignisprozedur, die durch die zweite Schaltfläche ausgelöst wird, referenzieren wir die erste Schaltfläche dann über die Syntax mit dem Ausrufezeichen und geben den Namen per MsgBox aus:

Schaltfläche zum Ermitteln des Namens einer anderen Schaltfläche

Bild 1: Schaltfläche zum Ermitteln des Namens einer anderen Schaltfläche

Private Sub cmdNameEinesSteuerelements_Click()

MsgBox Me!cmdNameAnzeigen.Name

End Sub

Die zweite Möglichkeit ist die Angabe des Steuerelementnamens als Parameter des Me-Schlüsselworts:

MsgBox Me("cmdNameAnzeigen").Name

Dies ist allerdings auch nur möglich, weil die Auflistung Controls die Standardeigenschaft des mit dem Schlüsselwort Me referenzierten Objekts, in diesem Fall des Formulars, ist. Die ausgeschriebene Form dieser Schreibweise bezieht die Controls-Auflistung dann explizit mit ein:

MsgBox Me.Controls("cmdNameAnzeigen").Name

Dabei fällt mir ein, dass man mal prüfen könnte, welchen Typ das Schlüsselwort Me eigentlich hat. Ist es Form? Nein: Es handelt sich um die Code behind-Klasse des Formulars selbst:

Debug.Print TypeName(Me)

Form_frmBeispiel

Für weitere Experimente fügen wir dem Formular noch ein Textfeld namens txtBeispiel hinzu sowie eine weitere Schaltfläche namens cmdTextfeldAusgeben (siehe Bild 2). Den Inhalt des Textfeldes legen wir in einer Ereignisprozedur fest, die beim Laden des Formulars ausgelöst wird:

Neues Textfeld zum Experimentieren

Bild 2: Neues Textfeld zum Experimentieren

Private Sub Form_Load()

Me!txtBeispiel = "Beispieltext"

End Sub

Warum Ausrufezeichen und kein Punkt?

Theoretisch kommen Sie in den meisten Fällen auch ohne Fehler aus, wenn Sie zwischen Formularbezeichner (also etwa Me oder Forms!) und Steuerelementname den Punkt als Trennzeichen angeben. Warum aber verwenden wir hier so beharrlich das Ausrufezeichen? Dieses sollten Sie immer dann nutzen, wenn Sie Elemente von Auflistungen referenzieren, die Sie selbst angelegt haben beziehungsweise anlegen können – also etwa Formulare (Forms!) oder Steuer­elemente in Formularen (Forms!!).

Zugriff auf Textfelder von verschiedenen Stellen

Wenn wir vom Formular selbst – in diesem Fall über die Schaltfläche cmdTextfeldAusgeben – auf den Inhalt dieses Textfeldes zugreifen wollen, verwenden wir, wie oben gelernt, das Schlüsselwort Me sowie das Ausrufezeichen und den Namen des Textfeldes:

Private Sub cmdTextfeldAusgeben_Click()

MsgBox Me!txtBeispiel

End Sub

Tatsächlich ist dies wiederum eine Kurzform. Wir geben ja nicht das Textfeld txtBeispiel aus, sondern den Inhalt dieses Textfeldes. Die Kurzform funktioniert deshalb, weil die Eigenschaft Value des Textfeldes die Standardeigenschaft der Textfeld-Klasse ist. Ohne diese Kurzform müssten Sie also mit dem folgenden Asudruck arbeiten:

MsgBox Me!txtBeispiel.Value

Woher wissen wir so etwas? Dies erfahren wir beispielsweise im Objektkatalog, den Sie über den Menüeintrag Ansicht|Objektkatalog öffnen (siehe Bild 3). In der Liste der Eigenschaften finden Sie zum Beispiel für das Textfeld (TextBox) ein spezielles Icon für die Eigenschaft Value. Unten finden Sie dann den Text Standardelement von Access.TextBox – das ist eindeutig.

Standardeigenschaft einer Klasse im Objektkatalog

Bild 3: Standardeigenschaft einer Klasse im Objektkatalog

Das waren nun zwei Kurzform. Genau wie beim Referenzieren von Formularen können Sie aber auch noch über die Schreibweise mit Klammern auf die Steuer­elemente eines Formulars zugreifen. Die erste Variante nimmt den Namen des Formulars entgegen:

Debug.Print Me("txtBeispiel").Value

Das war wiederum die Kurzform für die Variante mit der Controls-Auflistung:

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

Und wenn Sie den Index-Wert des Steuerelements kennen, können Sie auch noch einen numerischen Wert angeben:

Debug.Print Me.Controls(2).Value

Zugriff auf das aktive Steuerelement

Im Artikel zum Thema Formulare haben Sie die Eigenschaft ActiveForm des Screen-Objekts kennengelernt, mit der Sie das aktive Formular referenzieren konnten. Ein Pendand zu dieser Eigenschaft gibt es auch für Steuer­elemente. Wenn Sie also das aktuell aktive Steuer­element ermitteln wollen, nutzen Sie die Eigenschaft ActiveControl des Screen-Objekts:

Debug.Print Screen.ActiveControl.Name

Dies liefert beispielsweise den Namen des aktiven Steuerelements. Was geschieht hier beispielsweise, wenn derzeit kein Formular, sondern etwa eine Tabelle den Fokus hat? Dann liefert Screen.ActiveControl den Namen des Feldes der Tabelle, das gerade markiert ist! Im Falle der Tabelle tblBeispiel unserer Beispieldatenbank sieht der Aufruf im Direktbereich etwa wie folgt aus:

Debug.Print Screen.ActiveControl.Name

ID

Können wir darüber auch auf den Namen der Tabelle zugreifen? Ja, auch das gelingt:

Debug.Print Screen.ActiveControl.Parent.Name

tblBeispiel

Dadurch angespornt lassen wir auch gleich noch den mit TypeName ermittelten Typ dieses Tabellenobjekts ausgeben:

Debug.Print TypeName(Screen.ActiveControl.Parent)

T_tblBeispiel

Dies ist dann also das Pendant zu dem Typ Form_..., der für ein Formular zurückgeliefert wird.

Wenn Sie also etwa per Code über Screen.Active­Control auf ein Steuer­element eines Formulars zugreifen wollen, sollten Sie zuvor mit Screen.ActiveForm sicherstellen, dass auch gerade ein Formular den Fokus hat.

Steuer­elemente durchlaufen

Sie haben nun schon gesehen, dass es eine Auflistung namens Controls gibt, mit der Sie Steuer­elemente referenzieren können. Für Auflistungen können Sie auch die Anzahl der enthaltenen Elemente bestimmen und Sie können die Elemente in verschiedenen Schleifentypen durchlaufen.

Wir fügen dem Formular zwei weitere Schaltflächen hinzu. Die erste heißt cmdSteuerelementeDurchlaufenForNext und löst die folgende Ereignisprozedur aus:

Private Sub cmdSteuerelementeDurchlaufenForNext_Click()

Dim intCount As Integer

Dim i As Integer

intCount = Me.Controls.Count

For i = 0 To intCount - 1

Debug.Print Me.Controls(i).Name

Next i

End Sub

Dies ist die Variante zum Durchlaufen der enthaltenen Steuer­elemente, bei der wir zuerst die Anzahl der Steuerelemente ermitteln und dann eine For...Next-Schleife entsprechend der Anzahl der Steuer­elemente durchlaufen. Innerhalb der Schleife referenzieren wir dabei das jeweilige Steuer­element über den Index.

Da dieser 0-basiert ist, beginnt die Schleife bei 0 und wir legen den Endpunkt der Schleife auf intCount - 1 fest. intCount ermitteln wir zuvor über die Eigenschaft Count der Controls-Auflistung.

Die zweite Variante lösen wir mit der Schaltfläche cmSteuerelementeDurchlaufenForEach aus. Diese hat einen etwas eleganteren Ansatz: Sie durchläuft die Controls-Auflistung mit einer For Each-Schleife. Diese füllt die Elemente der Auflistung dann automatisch in die hinter For Each angegebene Variable, hier die Variable ctl vom Datentyp Control.

Control ist ein allgemeiner Datentyp, den Sie mit allen möglichen Steuerelementen füllen können. Innerhalb der Schleife gibt die Prozedur dann den Namen des mit ctl referenzierten Steuerelements aus:

Private Sub cmdSteuerelementeDurchlaufenForEach_Click()

Dim ctl As Control

For Each ctl In Me.Controls

Debug.Print ctl.Name

Next ctl

End Sub

Steuerelementtypen

Wenn Sie sich die Auswahl der für die Klasse Control verfügbaren Eigenschaften, Methoden und Ereignisse ansehen (etwas per IntelliSense wie in Bild 4), scheint dies nur eine Teilmenge der für die verschiedenen Steuerelementtypen verfügbaren Member zu sein – in der Tat sind es nur rund 40. Schauen Sie sich dann etwas im Objektkatalog die Eigenschaften des Steuerelements TextBox an, finden Sie schon circa 160 Eigenschaften. Da scheint es logisch, dass Sie für volle Flexibilität auf das Steuer­element mit dem spezifischen Datentyp zugreifen wollen. Wenn Sie gezielt auf einzelne Steuer­elemente zugreifen, wissen Sie natürlich, welchen Typ das jeweilige Steuer­element hat. Sie können es dann direkt mit dem passenden Datentyp deklarieren – beispielsweise wie folgt:

Eigenschaften der Control-Klasse

Bild 4: Eigenschaften der Control-Klasse

Dim txtBeispiel As TextBox

Was aber, wenn Sie etwa alle Steuer­elemente durchlaufen wollen, aber dennoch die spezifischen Eigenschaften der jeweiligen Steuer­elemente nutzen wollen? In diesem Fall müssen wir zuerst herausfinden, um welchen Steuerelementtyp es sich bei dem jeweiligen Objekt handelt.

Steuerelementtyp in einer Schleife ermitteln

Den Steuerelementtyp ermitteln Sie mit einer Eigenschaft, die interessanterweise gar nicht für die Control-Klasse angegeben ist – nämlich ControlType. Die folgende Prozedur, ausgelöst durch eine neue Schaltfläche namens cmdSteuerelementtypErmitteln, liefert jeweils einen Zahlenwert für die Steuer­elementtypen:

Private Sub cmdSteuerelementtypErmitteln_Click()

Dim ctl As Control

For Each ctl In Me.Controls

Debug.Print ctl.ControlType

Next ctl

End Sub

Woher kommt aber die Eigenschaft ControlType und warum können wir diese nutzen, aber nicht per Intelli­Sense auswählen? Die Eigenschaft steht, soviel verrät der Objektkatalog wie in Bild 5, für alle im Objektkatalog bekannten Steuer­elemente zur Verfügung, aber nicht für die Control-Klasse. Die Control-Klasse kann aber alle Eigenschaften der verschiedenen Steuerelementklassen nutzen, die einer Variablen des Datentyp Control zugewiesen werden können.

Die Eigenschaft ControlType gibt es für alle Steuer­elemente.

Bild 5: Die Eigenschaft ControlType gibt es für alle Steuer­elemente.

Die Suche nach der Eigenschaft ControlType im Objektkatalog lieferte auch noch den Typ acControlType. Dieser enthält alle Konstanten für die verschiedenen Steuerelementtypen (siehe Bild 6). Wenn Sie eines der Elemente anklicken, erscheint unten auch der Zahlenwert für die jeweilige Konstante. Das Problem ist nur: Dieser Zahlenwert wird auch zurückgeliefert, wenn Sie die Eigenschaft ControlType etwa im Direktfenster ausgeben lassen. Und damit können Sie nicht viel anfangen, wenn Sie die Zahlenwerte nicht alle auswendig können. Also stellen wir eine kleine Hilfsfunktion zur Verfügung, welche den Zahlenwert für einen Steuerelementtyp als Parameter erwartet und diesen in einer Select Case-Bedingung mit den möglichen Werten des Typs acControlType abgleicht und die Bezeichnung in die Variable strType schreibt. Der Wert dieser Variablen wird dann schließlich als Funktionsergebnis zurückgegeben:

Konstanten für die verschiedenen Steuerelementtypen

Bild 6: Konstanten für die verschiedenen Steuerelementtypen

Public Function ControlType(intControlType As AcControlType) As String

Dim strType As String

Select Case intControlType

Case acAttachment

strType = "Attachment"

Case acBoundObjectFrame

strType = "BoundObjectFrame"

Case acChart

strType = "Chart"

Case acCheckBox

strType = "CheckBox"

Case acComboBox

strType = "ComboBox"

Case acCommandButton

strType = "CommandButton"

Sie haben das Ende des frei verfügbaren Teil dieses Artikels erreicht!

Wenn Sie mehr lesen und auf viele weitere Artikel zugreifen möchten, melden Sie sich als Abonnent unter Login an. Falls nicht, bestellen Sie doch einfach ein Jahresabonnement!