🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA For Each in Excel — eine Collection ohne Index durchlaufen (und die Fallen, die es verbirgt)

|

VBA For Each in Excel — eine Collection ohne Index durchlaufen (und die Fallen, die es verbirgt)

TL;DRFor Each item In collection durchläuft jedes Mitglied einer Collection und reicht Ihnen eines nach dem anderen — kein Zähler, kein .Count, kein Off-by-one. Nutzen Sie es, wenn Sie eine Collection haben (ein Range, die Worksheets, ein Array) und jedes Element berühren wollen. Greifen Sie nur dann zurück auf For i = 1 To N, wenn Sie den Index selbst brauchen: um rückwärts zu gehen, mit Step zu überspringen oder Elemente unterwegs zu löschen. Drei Regeln bewahren es davor, Sie zu verraten: die Schleifenvariable muss ein Objekt oder eine Variant sein, das Durchlaufen eines Arrays ist schreibgeschützt, und Sie dürfen niemals Elemente aus der Collection entfernen, die Sie gerade durchlaufen.

Dim cell As Range
Dim total As Double

For Each cell In Sheets("Data").Range("B2:B11")
    total = total + cell.Value      ' VBA reicht Ihnen jede Zelle der Reihe nach
Next cell

Debug.Print total                   ' kein i, kein .Count, keine Grenzen zum Verhauen

Die meisten Schleifen in echten Makros sagen im Grunde dasselbe: „für jede Zelle in diesem Bereich…“, „für jedes Blatt in dieser Arbeitsmappe…“, „für jeden Namen in dieser Liste…“. For Each ist VBAs Art, Ihnen diesen Satz fast wörtlich schreiben zu lassen. Das zählerbasierte For i = 1 To N kann dieselbe Idee ausdrücken, aber es überlässt Ihnen die Verwaltung des Index — Startwert, Endwert, das .Count, den Zaunpfahl. For Each nimmt Ihnen diese Buchführung ab. Der Haken: Es nimmt Ihnen den Index vollständig weg, und ein paar Operationen brauchen ihn wirklich.

Was Sie lernen

  • Das mentale Modell — For Each durchläuft Zugehörigkeit, nicht Positionen
  • Warum die Schleifenvariable ein Range, ein Worksheet oder eine Variant sein muss — niemals ein Long
  • Die Schreibschutz-Falle: einer Schleifenvariable eines Arrays etwas zuzuweisen bewirkt nichts
  • Warum das Löschen innerhalb eines For Each den Durchlauf stillschweigend beschädigt — und was Sie stattdessen tun
  • Eine klare Regel, wann Sie For Each wählen und wann Sie auf For…Next zurückfallen

Das mentale Modell: For Each durchläuft Zugehörigkeit, nicht Positionen

Eine Zählerschleife denkt in Positionen: „geh zu Fach 1, dann Fach 2, dann Fach 3.“ For Each denkt in Zugehörigkeit: „gib mir jedes Ding, das zu dieser Gruppe gehört, in welcher Reihenfolge die Gruppe sie auch hält.“ Sie sagen nie, wo ein Element ist; Sie empfangen es einfach.

Diese Verschiebung ist der Grund, warum For Each kürzer und — bei großen Bereichen — geringfügig schneller ist. Mit Cells(i, 1) muss VBA bei jeder Iteration die Adresse berechnen und die Zelle auflösen. Mit For Each cell In rng reicht Ihnen der eingebaute Enumerator der Collection jedes Mal ein bereits aufgelöstes Range-Objekt — keine Rechnerei. Sie tauschen die Indexnummer gegen einen saubereren, schnelleren Durchlauf. Alles Weitere ist eine Folge davon, diesen Index nicht zu haben.

Die Regel, die den Typ der Schleifenvariable bestimmt: Objekt oder Variant, niemals Long

Das ist das Erste, worüber Leute stolpern, denn es ist das Gegenteil einer Zählerschleife. In For i = 1 To 10 ist i ein Long. In einem For Each empfängt die Schleifenvariable ein ganzes Element aus der Collection, also muss sie dieses Element halten können:

' Bereich von Zellen -> das Element ist ein Range
Dim cell As Range
For Each cell In Range("A1:A10")
    cell.Value = cell.Value * 2
Next cell

' Worksheets -> das Element ist ein Worksheet
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
    Debug.Print ws.Name
Next ws

Deklarieren Sie Dim cell As Long für einen Bereichsdurchlauf, wirft VBA „Objekt erforderlich“ (Fehler 424) in dem Moment, in dem es versucht, ein Range in eine Zahl zu stopfen. Die Regel: der Typ der Schleifenvariable muss zu der Art von Ding passen, das die Collection hältRange für Zellen, Worksheet für Blätter, Workbook für geöffnete Arbeitsmappen.

Es gibt eine Ausnahme, und es ist die, die Leute vergessen: Arrays. Ein VBA-Array kann alles halten, also kann der Compiler den Elementtyp nicht im Voraus kennen. Ein Array mit For Each zu durchlaufen erfordert eine Variant:

Dim names As Variant
names = Array("Alice", "Bob", "Carol")

Dim n As Variant          ' MUSS eine Variant sein für einen Array-Durchlauf
For Each n In names
    Debug.Print n
Next n

Nutzen Sie dort Dim n As String, bekommen Sie den Fehler „Typen unverträglich“ (Fehler 13). Im Zweifel ist die Schleifenvariable bei einem Array eine Variant.

Die Regel, die jeden einmal erwischt: das Durchlaufen eines Arrays ist schreibgeschützt

Hier ist ein Bug, der aussieht, als müsste er funktionieren, und es nicht tut:

Dim nums As Variant
nums = Array(1, 2, 3)

Dim x As Variant
For Each x In nums
    x = x * 10            ' sieht aus, als würde es jedes Element multiplizieren...
Next x

Debug.Print nums(0), nums(1), nums(2)   ' -> 1  2  3   (UNVERÄNDERT)

Sie haben x multipliziert, nicht das Array. Wenn For Each ein Array durchläuft, ist die Schleifenvariable eine Kopie des Elements, kein lebendiger Griff darauf. Eine Zuweisung an x ändert die Kopie und wirft sie bei der nächsten Iteration weg. Das Array bewegt sich nie.

Das ist das Wichtigste, was Sie über For Each wissen müssen, denn es scheitert stillschweigend — kein Fehler, nur veraltete Daten. Die Lösung ist, auf eine Zählerschleife zurückzufallen, die das echte Element per Index anspricht:

Dim i As Long
For i = LBound(nums) To UBound(nums)
    nums(i) = nums(i) * 10     ' DAS ändert das Array wirklich
Next i

Beachten Sie die Asymmetrie: Ein Range mit For Each zu durchlaufen ist schreibbar (cell.Value = … greift durch das Range-Objekt bis zur echten Zelle durch), weil cell eine Objektreferenz ist, keine Kopie. Es sind speziell Arrays — und Elemente mit Werttyp —, die unter For Each schreibgeschützt sind. Wenn Ihre Schleife den Array-Inhalt neu schreiben muss, nutzen Sie For i = LBound To UBound.

Die Regel, die Sie auf die harte Tour lernen: niemals aus der Collection löschen, die Sie durchlaufen

For Each stützt sich auf den Enumerator der Collection, und dieser Enumerator setzt voraus, dass sich die Collection unter ihm nicht verändert. Entfernen Sie ein Element mitten im Durchlauf, verliert der Enumerator seinen Platz — er überspringt Elemente oder löst einen Fehler aus, und er sagt Ihnen nie, welche.

' KAPUTT — das Löschen verschiebt die Collection unter dem Enumerator
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
    If sh.Name Like "Temp*" Then sh.Delete   ' überspringt Blätter, unvorhersehbar
Next sh

Dieselbe Falle schnappt zu, wenn Sie Arbeitsblattzeilen löschen, Elemente aus einer Collection entfernen oder Schlüssel aus einem Dictionary innerhalb eines For Each streichen. Die Regel ist absolut: ändert die Schleife die Zugehörigkeit der Collection, nutzen Sie kein For Each. Durchlaufen Sie sie stattdessen mit einem Zähler rückwärts, sodass das Entfernen eines Elements nie die Indizes stört, die Sie noch nicht besucht haben:

' KORREKT — rückwärts zählen, damit Löschungen nicht verschieben, was übrig ist
Dim i As Long
For i = ThisWorkbook.Worksheets.Count To 1 Step -1
    With ThisWorkbook.Worksheets(i)
        If .Name Like "Temp*" Then .Delete
    End With
Next i

Das ist dieselbe Rückwärts-Iterations-Disziplin, mit der Sie Tabellenzeilen sicher löschen — siehe das Step -1-Muster in VBA For-Schleife. Der Leitgedanke: For Each ist zum Lesen und Ändern von Elementen an Ort und Stelle da; eine absteigende Zählerschleife ist zum Hinzufügen oder Entfernen da.

Wann For Each und wann For…Next

Keine der beiden Schleifen ist „besser“ — sie beantworten verschiedene Fragen. Wählen Sie danach, was die Aufgabe vom Index braucht:

  • Nutzen Sie For Each, wenn Sie eine Collection haben und jedes Mitglied in seiner natürlichen Reihenfolge berühren wollen: einen Bereich summieren, jede Zelle formatieren, jeden Blattnamen ausgeben, jedes Element einmal verarbeiten. Sauberer zu lesen, keine Grenzen zum Verhauen und schneller bei großen Bereichen.
  • Nutzen Sie For i = 1 To N, wenn Sie den Index als Wert brauchen — um in Zeile i zu schreiben, um rückwärts zu laufen (Step -1), um zu überspringen (Step 2), um Element i mit Element i+1 zu vergleichen oder um unterwegs zu löschen. Es ist auch der einzige schreibbare Weg, die Elemente eines Arrays neu zu schreiben.

Ein nützliches Indiz: Wenn Sie sich dabei ertappen, .Count aufzurufen und Ihr eigenes i zu basteln, nur um collection(i) zu erreichen, wollten Sie wahrscheinlich For Each. Wenn Sie nach dem Element vor oder nach dem aktuellen greifen oder Elemente entfernen, brauchen Sie den Zähler.

Wie ExcelMaster hilft

Die Schleife wählen, die Schleifenvariable richtig typisieren, daran denken, dass Arrays schreibgeschützt sind und Löschungen rückwärts laufen müssen — genau diese Art mechanischen Urteilsvermögens steht zwischen „Ich weiß, was ich will“ und „das Makro macht es richtig.“

ExcelMaster lässt Sie stattdessen das Ziel nennen. Sagen Sie „markiere im Blatt Orders jede Zeile, in der der Status Overdue ist“ oder „lösche jedes Blatt, dessen Name mit Temp beginnt“, und es schreibt und führt die Logik aus — wählt For Each, wo ein schlichter Durchlauf richtig ist, und einen absteigenden Zähler, wo Elemente entfernt werden, sodass der Bug mit der Löschreihenfolge nie passiert. Wenn Sie doch ein Makro nach Zeitplan von Hand schreiben, wählen Sie die Schleife weiterhin selbst. Für die alltägliche „Erledige das einfach mit den heutigen Daten“-Aufgabe schlägt das Beschreiben des Ergebnisses das fehlerfreie Beherrschen jeder Enumerator-Regel von Hand.

Häufig gestellte Fragen

Was ist der Unterschied zwischen For Each und For…Next in VBA?

For Each durchläuft eine Collection nach Zugehörigkeit — es reicht Ihnen jedes Element in der natürlichen Reihenfolge der Collection, und Sie verwalten nie einen Index. For i = 1 To N ist zählerbasiert — Sie steuern den Index, also können Sie mit Step -1 rückwärts gehen, mit Step 2 überspringen oder Element i+1 erreichen. Nutzen Sie For Each für einen geraden Durchlauf über ein Range, Worksheets oder ein Array; nutzen Sie For…Next, wenn Sie den Index brauchen, Elemente löschen wollen oder Array-Elemente neu schreiben müssen.

Warum bekomme ich „Objekt erforderlich“ (Fehler 424) in einer For-Each-Schleife?

Fast immer, weil die Schleifenvariable mit dem falschen Typ deklariert ist — meist ein Long oder String, wenn die Collection Objekte hält. For Each cell In Range(...) braucht Dim cell As Range, und For Each ws In Worksheets braucht Dim ws As Worksheet. Durchlaufen Sie ein VBA-Array, muss die Schleifenvariable eine Variant sein.

Kann ich Array-Werte innerhalb einer For-Each-Schleife ändern?

Nein. Wenn For Each ein Array durchläuft, ist die Schleifenvariable eine Kopie jedes Elements, also ändert eine Zuweisung daran die Kopie, nicht das Array — ohne Fehler. Um das Array zu ändern, nutzen Sie eine Zählerschleife: For i = LBound(arr) To UBound(arr) und weisen Sie arr(i) zu. Ein Range mit For Each zu durchlaufen ist schreibbar, weil die Schleifenvariable eine lebendige Objektreferenz auf die Zelle ist.

Wie durchlaufe ich mit For Each jede Zelle in einem Bereich?

Deklarieren Sie die Schleifenvariable als Range und durchlaufen Sie den Bereich direkt: For Each cell In Range("A1:B10"). VBA läuft die Zellen Zeile für Zeile ab. Für einen großen Block ist das schneller als verschachtelte Cells(i, j)-Schleifen, aber der schnellste Weg von allen ist, den Bereich in einem Zug in ein Array zu lesen (arr = Range("A1:B10").Value) und das Array zu durchlaufen — siehe VBA Array.

Warum überspringt das Löschen von Zeilen oder Blättern innerhalb von For Each manche davon?

Weil For Each sich auf einen Enumerator stützt, der voraussetzt, dass sich die Zugehörigkeit der Collection nicht ändert, während Sie sie durchlaufen. Das Löschen eines Elements verschiebt alles danach, und der Enumerator verliert seinen Platz — überspringt stillschweigend Elemente. Löschen Sie niemals innerhalb eines For Each. Nutzen Sie eine Zählerschleife, die abwärts zählt (For i = .Count To 1 Step -1), sodass Entfernungen die noch nicht erreichten Elemente nicht stören.

Getestet in

Getestet mit: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 01.08.2026.

Verwandte Anleitungen: VBA For-Schleife · VBA Collection · VBA With · VBA Array · VBA Dictionary