Home > Artikel > Ausgabe 10/2011 > For Each-Schleifen

For Each-Schleifen

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).

Die For...Next-Schleife ist Ihnen längst bekannt. Etwas weniger oft nutzt man die For Each-Schleife. Der Hauptgrund ist, dass diese nur mit Auflistungen zusammenarbeitet, also mit Objekten, die meiste mehrere gleichartige Objekte zusammenfassen. Beispiele sind die Formulare einer Datenbank oder die Steuerelemente eines Formulars. Anhand dieser Beispiele lernen Sie in diesem Beitrag die Verwendung von For Each-Schleifen kennen.

Beispieldatenbank

Die Beispiele dieses Artikels finden Sie in der Datenbank 1110_ForEach.mdb.

Jeder nur einmal!

Die For Each-Schleife ist bestens dazu geeignet. Elemente von Auflistungen unter VBA zu durchlaufen. Auflistungen? Was für Auflistungen? Nun: In objektorientierten Sprachen, wie es auch VBA teilweise ist, gibt es nicht nur Objekte mit bestimmten Eigenschaften (wie Formulare, Steuerelemente, Datenbanken oder Tabellen), sondern auch Objekte, die den Zugriff auf solche Elemente etwa über die Angabe eines Indexes erlauben.

Offene Formulare durchlaufen

Wenn Sie beispielsweise einmal wissen möchten, welche Formulare aktuell in Ihrer Datenbank geöffnet sind, hilft Ihnen eine For Each-Schleife weiter. Die Auflistung AllForms des CurrentProject-Objekts liefert die notwendigen Daten. Mit der folgenden Anweisung können Sie etwa im Direktfenster die Anzahl der Formulare der aktuellen Datenbank abfragen:

  CurrentProject.AllForms.Count

4

Nun wollen Sie aber alle Formulare durchlaufen und deren Namen ausgeben. Um dies innerhalb einer For Each-Schleife durchzuführen, brauchen Sie zunächst einmal eine Objektvariable als Laufvariable. In diesem Fall verwenden Sie dazu ein Objekt des Typs AccessObject:

Dim frm As AccessObject

Wie finden Sie den Typ heraus? Ganz einfach: Öffnen Sie den Objektkatalog von Access mit der Tastenkombination F2, suchen Sie dort nach der Auflistungsklasse (hier AllForms) und klicken Sie auf die Eigenschaft, die so aussieht, als ob sie einen Verweis auf eines der enthaltenen Elemente zurückliefern könnte – in diesem Fall also Item. Ganz unten erfahren Sie dann, dass Item den Typ AccessObject besitzt (siehe Bild 1).

Der Objektkatalog hilft, den Typ eines Auflistungsobjekts zu ermitteln.

Bild 1: Der Objektkatalog hilft, den Typ eines Auflistungsobjekts zu ermitteln.

Damit können Sie dann die For Each-Schleife zusammensetzen, die wie folgt aussieht:

For Each frm In CurrentProject.AllForms

     Debug.Print frm.Name

Next frm

Diese Schleife durchläuft alle Elemente der AllForms-Auflistung und weist das jeweils aktuelle Element der Variablen frm zu. Damit können Sie dann innerhalb der Schleife anstellen, was Sie möchten. Gut, es gibt eine Ausnahme: das Löschen der enthaltenen Elemente geht auf diese Weise schief.

Geöffnete Formulare durchlaufen

Viele Objekte können Sie auf verschiedene Arten durchlaufen. Wenn Sie beispielsweise nur die aktuell geöffneten Elemente referenzieren möchten, nutzen Sie die Forms-Auflistung und durchlaufen alle darin enthaltenen Objekte des Typs Form. Das sieht dann so aus:

Dim frm As Form

For Each frm In Forms

     Debug.Print frm.Name

Next frm

Alternative mit For...Next

Das Gleiche gelingt auch mit einer For...Next-Schleife – die For Each-Schleife ist nur etwas eleganter. Mit For...Next sieht das Durchlaufen der Formulare wie folgt aus:

Dim i As Integer

For i = 0 To Forms.Count - 1

     Debug.Print Forms(i).Name

Next i

Und wenn Sie auch hier ein Form-Objekt nutzen möchten, füge Sie noch ein paar Zeilen hinzu:

Dim frm As Form

Dim i As Integer

For i = 0 To Forms.Count - 1

     Set frm = Forms(i)

     Debug.Print frm.Name

Next i

Warum bei 0 beginnen? Die meisten Auflistungen verwenden einen 0-basierten Index, das heißt, dass Sie das erste Element über den Wert 0 für den Index erhalten. Dementsprechend führt das Referenzieren des Elements mit dem Index, welcher der Anzahl entspricht (also beispielsweise Forms.Count), zu einem Fehler: Eine Auflistung mit vier Elementen verwendet, wenn Sie 0-basiert ist, die Index-Werte 0, 1, 2 und 3. Der Verweis auf Forms(4) funktioniert dementsprechend nicht. Gelegentlich gibt es auch Elemente, deren Indexwerte bei 1 beginnen. Hier ist dann der Wert der Count-Eigenschaft gleichzeitig der Index-Wert des letzten Elements der Auflistung. Und dies ist ein Vorteil der For Each-Schleife: Sie schert sich nicht um den Index, sondern liefert einfach alle Werte der Auflistung zurück.

Elemente löschen

Mit der Methode DeleteObject des DoCmd-Objekts können Sie Access-Objekte wie Tabellen, Abfragen, Formulare et cetera löschen. Wenn wir das in eine For Each-Schleife einbauen, um beispielsweise alle Formulare der aktuellen Datenbank zu löschen, sähe das so aus:

Dim frm As AccessObject

For Each frm In CurrentProject.AllForms

     DoCmd.DeleteObject acForm, frm.Name

Next frm

Das führt aber zu einem Fehler, was sich am Beispiel der beiden Formulare frm1 und frm2 leicht nachvollziehen lässt. Im ersten Durchlauf wird die Variable frm mit einem Verweis auf frm1 gefüllt. Dieses Formular wird mit der DeleteObject-Methode gelöscht. Dann versucht die For Each-Schleife, zum zweiten Objekt der Auflistung zu springen. Das gelingt allerdings nicht, weil nur noch ein Objekt da ist, das Objekt frm jedoch das zweite Element der Auflistung referenzieren will!

Auch in einer For...Next-Schleife wird es nicht besser. Im ersten Durchlauf würde von zwei Formularen frm1 und frm2 wiederum frm1 gelöscht, im zweiten Durchlauf versucht die Prozedur jedoch, auf das zweite Element der AllForms-Auflistung zuzugreifen. Da diese jedoch nur noch ein Element enthält, scheitert auch diese Variante:

Dim frm As AccessObject

Dim i As Integer

For i = 0 To CurrentProject.AllForms.Count - 1

     Set frm = CurrentProject.AllForms(i)

     DoCmd.DeleteObject acForm, frm.Name

Next i

Wenn Sie also alle Elemente einer Auflistung löschen wollen, müssen Sie eine For...Next-Schleife verwenden, welche die Liste der Formulare rückwärts durchläuft – vom höchsten Index (CurrentProject.AllForms.Count) zum niedrigsten (0). Um bei unserem Beispiel der zwei Formulare frm1 und frm2 zu bleiben: Im ersten Durchlauf wird das zweite Elemente der Auflistung AllForms gelöscht, im zweiten das erste – und dies gelingt, weil nach dem Löschen des zweiten Elements nur noch das erste vorhanden ist:

Dim frm As AccessObject

Dim i As Integer

For i = CurrentProject.AllForms.Count - 1 To 0 Step -1

     Set frm = CurrentProject.AllForms(i)

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!