Steuerelemente zur Laufzeit debuggen

Wenn Sie ein Abonnement des Magazins 'Access im Unternehmen' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Steuerelemente zur Laufzeit debuggen

Wenn im Formular oder in den enthaltenen Steuerelementen zur Laufzeit merkwürdige Werte angezeigt werden oder die Elemente nicht wie gewünscht reagieren, kann das verschiedene Ursachen haben. Viele davon lassen sich am einfachsten aufdecken, wenn Sie die Werte und Eigenschaften auslesen, während das Formular in der Formularansicht geöffnet ist. Doch das ist nicht ganz einfach, denn es erfordert eine Menge Tipparbeit – und oft die genaue Kenntnis der Formular-, Unterformular- oder Steuerelementnamen. Wir zeigen eine Methode, die das Abfragen der Eigenschaftswerte erheblich vereinfacht.

Die Standardmethode

Sind wir mal ehrlich: Wenn Sie den Wert der Eigenschaft eines Steuerelements eines geöffneten Formulars ermitteln wollen, geht man üblicherweise über das Direktfenster und ermittelt den gesuchten Wert mit der Debug.Print-Anweisung.

Schauen Sie sich beispielsweise das Formular aus Bild 1 an. Es enthält einige Kombinationsfelder, die natürlich – wie es in einer professionel gestalteten Anwendung der Fall sein sollte – nicht die Primärschlüsselwerte der gebundenen Datenherkunft, sondern die für den Benutzer wichtigen Werte wie den Kundennamen, den Namen des Sachbearbeiters oder auch im Unterformular den Namen des Artikels anzeigen. Nun kommt es vor, dass Sie sich fragen, welches Formular Sie dort gerade überhaupt geöffnet haben. Wenn es das einzige Formular ist, können Sie dies mit dem ersten Eintrag der Forms-Auflistung herausfinden:

Formular und Unterformular zur Verwaltung von Bestellungen

Bild 1: Formular und Unterformular zur Verwaltung von Bestellungen

  Forms(0).Name
frmBestellungen

Sind mehrere Formular geöffnet, hilft dies nicht weiter, denn Sie kennen ja den Index des zu untersuchenden Formulars nicht. In diesem Fall greifen Sie einfach über die Eigenschaft ActiveForm des Screen-Objekts auf das Formular zu und lassen sich dessen Namen ausgeben:

  Screen.ActiveForm.Name
frmBestellungen

Auf diese Weise haben Sie schon einmal den Namen des Formulars herausgefunden. Damit können Sie nun gezielt auf dieses Formular und seine Eigenschaften, wie zum Beispiel Name, zugreifen (was zugegebenermaßen wenig Sinn macht, da wir den Namen ja schon kennen – aber es ist ja nur ein Beispiel!):

  Forms!frmBestellungen.Name
frmBestellungen

Sie können damit natürlich auch etwa die Datenherkunft des Formulars ausgeben lassen:

  Forms!frmBestellungen.Recordsource
tblBestellungen

Auf die gleiche Weise greifen Sie auch auf die übrigen Eigenschaften des Formulars zu.

Steuerelemente ansprechen

Nun gehen wir einen Schritt weiter und kümmern uns um die Steuerelemente. Wenn Sie nicht wissen, wie ein Steuerelement heißt, können Sie sich in einer Schleife die Steuerelementnamen ausgeben lassen:

Public Sub Steuerelementnamen()
     Dim ctl As Control
     For Each ctl In Forms!frmBestellungen.Controls
         Debug.Print ctl.Name
     Next ctl
End Sub

Dies gibt die Namen aller Steuerelemente im Direktfenster aus. Wenn Sie das gewünschte Steuerelement gefunden haben, können Sie wie folgt darauf zugreifen – in diesem Beispiel auf das Steuerelement BestellungID:

  Forms!frmBestellungen.Controls("BestellungID").Value
  10248 

Das entspricht der folgenden Syntax mit dem Ausrufezeichen:

  Forms!frmBestellungen!BestellungID
10248

Aktivierbare Steuerelemente ansprechen

Bei den Steuerelementen, die aktivierbar sind, also denen Sie den Fokus etwa per Mausklick zuweisen können, gibt es noch eine einfachere Methode, beispielsweise den Namen zu ermitteln. Dazu verwenden Sie eine weitere Eigenschaft des Screen-Objekts, nämlich ActiveControl. Wenn Sie einmal das Steuerelement zur Anzeige des Feldes BestellungID per Mausklick aktivieren und dann im Direktfenster die folgende Anweisung absetzen, erhalten Sie ebenfalls den Namen dieses Steuerelements:

  Screen.ActiveControl.Name
BestellungID

Auf den enthaltenen Wert oder andere Eigenschaften greifen Sie auf diesem Wege zu:

  Screen.ActiveControl.Value
  10248 

Nicht sichtbare Werte ermitteln

Aber warum sollte man überhaupt auf den Wert eines Steuerelements zugreifen, wenn man diesen sowieso im Formular selbst ablesen kann? Nun: Es gibt ja auch Steuerelemente, die ihren eigentlichen Inhalt nicht offenbaren – zum Beispiel die Kombinationsfelder dieses Beispielformulars, die allesamt nicht den Wert der gebundenen Spalte anzeigen (also den Feldwert des Feldes der Datenherkunft des Formulars, an das sie gebunden sind), sondern den Wert einer anderen Spalte der Datensatzherkunft des Kombinationsfeldes. Um die KundeID des Kunden aus dem Kombinationsfeld KundeID zu ermitteln, geben Sie folglich ein:

  Forms!frmBestellungen!KundeID
  90 

Diese Information können Sie dem Kombinationsfeld sonst nicht entlocken. Sie können natürlich auch auf den Inhalt der übrigen Spalten der Datensatzherkunft des Kombinationsfeldes zugreifen:

  Forms!frmBestellungen!KundeID.Column(1)
Wilman Kala

Noch sinnvoller ist dies natürlich, wenn die Datensatzherkunft des Kombinationsfeldes noch weitere Felder enthält, die nicht eingeblendet sind. Mit der Eigenschaft Column stehe ich übrigens auf Kriegsfuß – ich gebe immer Columns ein, da ich denke, dass diese Eigenschaft, der man ja einen Index übergibt, eine Auflistung sein und dementsprechend im Plural angegeben werden müsste. Deshalb wäre es praktisch, wenn man hier mit IntelliSense arbeiten könnte – aber der VBA-Editor erkennt an dieser Stelle nicht den Typ des Objekts KundeID und blendet somit auch nicht dessen Eigenschaften und Methoden ein. Später schauen wir uns allerdings eine Möglichkeit an, auch über das Direktfenster auf solche Informationen per IntelliSense zuzugreifen.

Unterformular-Steuerelement referenzieren

Nun stürzen wir uns allerdings erstmal auf das Unterformular. Hier entsteht oft das Missverständnis, dass das Unterformular-Steuerelement, das ja quasi nur ein Rahmen für das eigentliche, als Unterformular angegebene Formular ist, als Formular angesprochen wird.

Das Unterformular-Steuerelement hat jedoch ganz andere Eigenschaften als das darin enthaltene Formular, und Sie können auch nicht direkt über das Unterformular-Steuerelement auf die enthaltenen Steuerelemente des Unterformulars zugreifen. Zur Verdeutlichung haben wir das Unterformular-Steuerelement, das beim Hineinziehen des Unterformulars in den Entwurf des Hauptformulars unpraktischerweise den gleichen Namen erhält wie das Unterformular selbst (hier sfmBestellungen), umbenannt, und zwar in sfmBestellungen_UFD (für Unterformular-Control, s. Bild 2).

Umbenennen des Unterformulare-Steuerelements

Bild 2: Umbenennen des Unterformulare-Steuerelements

Nun können wir zunächst wie folgt auf das Unterformular-Steuerelement zugreifen und uns zum Beispiel die beiden Felder ausgeben lassen, über welche die Synchronisation zwischen den Datensätzen aus Haupt- und Unterformular hergestellt wird:

  Forms!frmBestellungen!sfmBestellungen_UFC.LinkChildFields
BestellungID
  Forms!frmBestellungen!sfmBestellungen_UFC.LinkMasterFields
BestellungID

Den Namen dieser beiden Eigenschaften müsste man zu diesem Zweck auch erst mal kennen beziehungsweise ermitteln. Das Unterformular-Steuerelement ist übrigens eines der Steuerelemente, dem Sie nicht den Fokus zuweisen können. Sie können also auch nicht mit Screen.ActiveControl darauf zugreifen.

Unterformular referenzieren

Wenn Sie dann auf das im Unterformular-Steuerelement selbst enthaltene Unterformular zugreifen wollen, müssen Sie noch die Eigenschaft Form hinzufügen – hier ermitteln wir den Namen des Unterformulars:

  Forms!frmBestellungen!sfmBestellungen_UFC.Form.Name
sfmBestellungen

Um auf die im Unterformular enthaltenen Steuerelemente zuzugreifen, können Sie einfach wieder den Steuerelementnamen entweder über die Controls-Auflistung referenzieren oder direkt per Ausrufezeichen-Syntax:

  Forms!frmBestellungen!sfmBestellungen_UFC.Form.BestellungID
  10248 

In diesem Fall greifen wir auf ein Feld der Datenherkunft zu, das selbst gar nicht als Steuerelement abgebildet ist. Woran erkennen Sie, dass Sie ein Feld der Datenherkunft referenzieren und dass es kein Steuerelement ist? Sie können versuchen, etwa die Eigenschaft Name oder DefaultValue abzufragen. Das führt zu der Fehlermeldung aus Bild 3. Greifen wir lieber auf ein echtes Steuerelement zu, beispielsweise um die ArtikelID des Artikels der ersten Bestellposition im Unterformular zu erhalten. Erstmal geben wir den Namen aus, um zu prüfen, ob wir auch auf das Steuerelement zugreifen:

Fehler beim Zugriff auf die Eigenschaft DefaultValue eines Feldes

Bild 3: Fehler beim Zugriff auf die Eigenschaft DefaultValue eines Feldes

  Forms!frmBestellungen!sfmBestellungen_UFC.Form.ArtikelID.Name
ArtikelID

Danach holen wir uns die ArtikelID:

  Forms!frmBestellungen!sfmBestellungen_UFC.Form. ArtikelID.Value
  11 

Übrigens können Sie so auch nur auf die Werte des jeweils aktivierten Datensatzes im Unterformular zugreifen. Wenn beispielsweise der erste Datensatz markiert ist und Sie wollen die ArtikelID für den zweiten Datensatz einer Bestellung erhalten, müssen Sie diesen Datensatz zunächst im Unterformular markieren.

Wenn Sie diesen Datensatz im Unterformular markieren, können Sie aber auch gleich auf das Kombinationsfeld zur Auswahl der Artikel klicken, um die folgende, viel einfachere Anweisung zu nutzen:

  Screen.ActiveControl.Value
  42 

Dennoch: Es stört schon etwas, dass man immer noch die Eigenschaften selbst eintippen muss und dass kein IntelliSense zur Verfügung steht. Wie Sie dies hinzufügen können, schauen wir uns im Folgenden an.

Eigene Debugging-Klasse

Um unser Ziel zu erreichen, bedarf es der Programmierung einer kleinen Klasse mit speziellen Eigenschaften.

Diese Klasse fügen Sie über den Menübefehl Einfügen|Klassenmodul des VBA-Editors hinzu und nennen sie Debugger. Dann exportieren Sie die Klasse über den Kontextmenü-Befehl des neuen Eintrags im Projekt-Explorer in eine Textdatei (s. Bild 4). Entfernen Sie die soeben erstellte Klasse dann mit dem Kontextmenü-Eintrag Entfernen von Debugger ... und antworten Sie auf die nun erscheinende Meldung mit Nein.

Exportieren des Klassenmoduls

Bild 4: Exportieren des Klassenmoduls

Nun ändern Sie in einem Texteditor Ihrer Wahl die gespeicherte Textdatei mit der Klasse wie in Bild 5. Dabei stellen Sie die Werte für die beiden Eigenschaften VB_Creatable und VB_PredeclaredID auf True ein:

Geänderte Version des Klassenmoduls

Bild 5: Geänderte Version des Klassenmoduls

Attribute VB_Creatable = True
Attribute VB_PredeclaredId = True

Nun importieren Sie die Datei wieder in das VBA-Projekt – am einfachsten, indem Sie es einfach aus dem Windows Explorer in den Projekt-Explorer ziehen. Aber was bewirkt diese Änderung nun? Das lässt sich schnell erklären, wenn Sie eine kleine Beispielmethode wie die folgende zu der Klasse hinzufügen:

Public Sub Test()
     MsgBox "Test erfolgreich"
End Sub

Sie können nun im Direktfenster einfach den folgenden Ausdruck eingeben, um die Klasse zu instanzieren und die Methode Test zu nutzen:

Debugger.Test

Dies zeigt dann das erwartete Meldungsfenster an. Nun wollen wir unsere Debugger-Klasse zunächst mit den Funktionen ausstatten, die auch die Screen-Klasse bietet – zum Beispiel mit dem Zugriff auf das aktive Formular über die Eigenschaft Screen.ActiveForm. Dazu fügen wir der Klasse die folgende Property Get-Methode hinzu:

Public Property Get ActiveForm()
     Set ActiveForm = _
         Screen.ActiveForm

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.