TL;DR —
For Each item In collectiondurchlä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 (einRange, dieWorksheets, ein Array) und jedes Element berühren wollen. Greifen Sie nur dann zurück aufFor i = 1 To N, wenn Sie den Index selbst brauchen: um rückwärts zu gehen, mitStepzu überspringen oder Elemente unterwegs zu löschen. Drei Regeln bewahren es davor, Sie zu verraten: die Schleifenvariable muss ein Objekt oder eineVariantsein, 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 Eachdurchläuft Zugehörigkeit, nicht Positionen - Warum die Schleifenvariable ein
Range, einWorksheetoder eineVariantsein muss — niemals einLong - Die Schreibschutz-Falle: einer Schleifenvariable eines Arrays etwas zuzuweisen bewirkt nichts
- Warum das Löschen innerhalb eines
For Eachden Durchlauf stillschweigend beschädigt — und was Sie stattdessen tun - Eine klare Regel, wann Sie
For Eachwählen und wann Sie aufFor…Nextzurü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ält — Range 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 Zeileizu schreiben, um rückwärts zu laufen (Step -1), um zu überspringen (Step 2), um Elementimit Elementi+1zu 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
