TL;DR —
Range("A1").Valueliest oder schreibt eine Zelle. Worauf es ankommt, ist, was bei vielen Zellen passiert:arr = Range("A1:C1000").Valueliest den ganzen Block in einem einzigen Aufruf in ein 1-basiertes, 2D-Variant-Array, undRange("A1:C1000").Value = arrschreibt ihn in einem Aufruf zurück. Zellen einzeln anzufassen —Cells(i, j).Valuein einer Schleife — überquert bei jedem Lesen die Grenze von VBA nach Excel, und genau diese Grenzüberquerung, nicht die Rechnung, macht große Schleifen langsam.
Dim v As Variant
v = Range("A1").Value ' eine Zelle in eine Variable lesen
Range("B1").Value = v * 1.08 ' eine Zelle schreiben
Dim arr As Variant
arr = Range("A1:A10000").Value ' 10.000 Zellen in EINEM Aufruf lesen -> 2D-Array
' ... arr im Speicher verarbeiten ...
Range("C1:C10000").Value = arr ' alle in EINEM Aufruf zurueckschreiben
Werte lesen und schreiben ist das Erste, was jeder in VBA tut, und für eine einzelne Zelle ist es genau
so einfach, wie es aussieht. Die Idee, auf der diese Anleitung aufbaut, zeigt sich in dem Moment, in dem
Sie mehr als eine Zelle haben: .Value auf einem Range ist nicht ein Wert, sondern ein Block — ein
zweidimensionales Array —, und diesen Block in einem einzigen Aufruf zu bewegen statt Zelle für Zelle, ist
der Unterschied zwischen einem Makro, das sich sofort anfühlt, und einem, das hängt. Halten Sie das
fest, und sowohl die Geschwindigkeitsregeln als auch die kleinen Typfallen fügen sich zusammen.
Was Sie lernen
- Das mentale Modell —
.Valueist ein Block, und ein Range liefert ein 2D-Variant-Array - Die wichtigste Regel — lesen und schreiben Sie den ganzen Block in einem Roundtrip, nicht Zelle für Zelle
- Warum das Array 1-basiert und 2D ist, selbst für eine einzelne Spalte
- Der Sonderfall einzelne Zelle — eine Zelle ist ein Skalar, kein Array
.Valueist die Standard-Eigenschaft — die Abkürzung, und warum Sie sich nicht darauf verlassen sollten- Ein Wert-Zuweisen ersetzt, was in der Zelle war, Formel eingeschlossen
Das mentale Modell: .Value ist ein Block
Für eine Zelle ist .Value ein einzelner Wert, den Sie lesen oder zuweisen:
Dim name As String
name = Range("A1").Value ' Skalar rein
Range("A2").Value = "Total" ' Skalar raus
Für einen Range aus vielen Zellen ist .Value das ganze Gitter auf einmal. Lesen Sie es in einen
Variant, und Sie erhalten ein zweidimensionales Array; weisen Sie ihm ein zweidimensionales Array zu,
und Sie setzen jede Zelle in einem Zug:
Dim block As Variant
block = Range("A1:C100").Value ' block ist jetzt ein 100 x 3 Variant-Array
Das wichtige Wort ist einmal. Jedes Mal, wenn Ihr Code .Value liest oder schreibt, überquert er die
Grenze zwischen der VBA-Engine und der Excel-Anwendung — ein relativ teurer Sprung. Eine Zelle ist ein
Sprung; ein ganzer Block, in ein Array gelesen, ist auch nur ein Sprung. Genau diese eine Tatsache — ein
Range ist ein Block, den Sie in einer einzigen Überquerung bewegen können — treibt die Performance-Regel
weiter unten an und ist das Wertvollste, was man über .Value wissen kann.
Die wichtigste Regel: den Array-Roundtrip nutzen, nicht die Zellen durchlaufen
Hier dieselbe Aufgabe auf zwei Arten. Eine Spalte durchgehen, jeden Wert um 8 % erhöhen und daneben schreiben.
Der langsame Weg fasst Excel bei jeder Iteration an:
Dim i As Long
For i = 1 To 10000
Cells(i, 3).Value = Cells(i, 1).Value * 1.08 ' 2 Ueberquerungen pro Zeile = 20.000 Spruenge
Next i
Der schnelle Weg überquert insgesamt zweimal und erledigt die Arbeit im Speicher:
Dim src As Variant, out() As Variant, i As Long
src = Range("A1:A10000").Value ' 1 Sprung rein
ReDim out(1 To UBound(src, 1), 1 To 1)
For i = 1 To UBound(src, 1)
out(i, 1) = src(i, 1) * 1.08 ' reines VBA - kein Excel beteiligt
Next i
Range("C1:C10000").Value = out ' 1 Sprung raus
Die Rechnung ist identisch; die Schleife ist gleich lang. Der einzige Unterschied ist, dass die zweite Version 10.000 Zellen in einem Aufruf liest und 10.000 in einem Aufruf schreibt, während die erste 20.000 einzelne Fahrten über die VBA-zu-Excel-Grenze macht. Auf echten Daten ist die Array-Version regelmäßig zigmal schneller — oft der Unterschied zwischen „sofort" und „der Sanduhr zusehen". Für einen noch größeren Gewinn koppeln Sie das mit dem Abschalten von Neuberechnung und Bildschirmaktualisierung während des Schreibens; siehe VBA Calculation und VBA ScreenUpdating. Die Grenzüberquerung ist der Preis, und der Array-Roundtrip ist der Weg, ihn nicht mehr pro Zelle zu zahlen.
Warum das Array 1-basiert und 2D ist
Das Variant-Array, das Sie aus einem Range erhalten, überrascht die Leute zweimal. Erstens ist es
immer 1-basiert, unabhängig von jeder Option Base-Einstellung — arr(1, 1) ist die Zelle oben
links. Zweitens ist es immer zweidimensional, selbst wenn der Range eine einzelne Spalte oder eine
einzelne Zeile ist:
Dim col As Variant
col = Range("A1:A5").Value ' eine einzelne Spalte
Debug.Print col(3, 1) ' NICHT col(3) - es ist (Zeile, Spalte)
Ein einspaltiger Range ist ein 5-mal-1-Array, Sie indexieren ihn also col(Zeile, 1); ein einzeiliger
Range ist 1-mal-5, indexiert row(1, Spalte). col(3) statt col(3, 1) zu schreiben, löst
„Subscript out of range" aus und ist der häufigste Fehler, wenn man zum ersten Mal auf Arrays umsteigt.
Wenn Sie wirklich ein 1D-Array aus einer einzelnen Spalte wollen, hüllen Sie das Lesen in
Application.Transpose — aber beachten Sie, dass Transpose seine eigenen Grenzen hat (es deckelt bei rund
65.536 Elementen und wandelt Typen um), sodass für große oder gemischte Daten das schlichte 2D-Array
sicherer ist. Siehe VBA Array für die Arbeit mit dem Ergebnis.
Der Sonderfall der einzelnen Zelle
Es gibt einen Grenzfall, der Array-Code kaputtmacht: Ist der Range eine einzelne Zelle, liefert
.Value einen schlichten Skalar, kein 1-mal-1-Array.
Dim v As Variant
v = Range("A1").Value ' A1 allein -> ein Skalar, nicht v(1, 1)
' v(1, 1) loest hier einen Fehler aus
Code also, der rng.Value in ein Array liest und dann arr(1, 1) indexiert, funktioniert für einen
mehrzelligen rng, fliegt aber auf, wenn rng zufällig eine Zelle ist. Kann eine Range-Größe bis auf
eine Zelle schrumpfen, erzwingen Sie entweder eine Mindestgröße oder prüfen rng.Cells.Count > 1, bevor
Sie das Ergebnis als Array behandeln. Es ist eine kleine Inkonsistenz in Excels Objektmodell, aber sie
verursacht echte „läuft auf dem großen Blatt, scheitert auf dem kleinen"-Bugs.
.Value ist die Standard-Eigenschaft — die Abkürzung und ihr Risiko
.Value ist die Standard-Eigenschaft eines Range, was bedeutet, dass Excel Sie es weglassen lässt:
x = Range("A1") ' funktioniert - implizit .Value
Range("A1") = 42 ' funktioniert - implizit .Value
Es liest sich sauber, und viel Code macht es so. Das Risiko ist, dass die Abkürzung verbirgt, welche
Operation Sie meinen. Set rng2 = Range("A1") weist das Range-Objekt zu; x = Range("A1") weist
dessen Wert zu — die An- oder Abwesenheit von Set ändert die Bedeutung stillschweigend. Und
If Range("A1") = Range("B1") vergleicht Werte, was ein Leser erwartet oder eben nicht, wenn der Code
nichts über Werte sagt. Die Gewohnheit, die sich lohnt: schreiben Sie .Value ausdrücklich, wenn Sie
den Wert meinen. Es kostet sechs Zeichen und beseitigt eine ganze Klasse von „meinten sie die Zelle oder
ihren Inhalt"-Mehrdeutigkeit — besonders rund um Set, behandelt in VBA Range.
Ein Wert-Zuweisen ersetzt die Formel
Eine letzte Sache, über die Leute stolpern, die Werte und Formeln mischen: .Value in eine Zelle zu
schreiben überschreibt, was auch immer dort war, eine Formel eingeschlossen.
Range("D2").Formula = "=B2*C2" ' D2 ist jetzt eine lebende Formel
Range("D2").Value = 100 ' D2 ist jetzt die statische Zahl 100 - die Formel ist weg
Das ist meist genau das, was Sie wollen — so „wandeln Sie eine Formel in ihr Ergebnis um" in einer
einzelnen Zelle (weisen Sie den Wert über sich selbst zurück). Aber es bedeutet, dass Sie einen Wert nicht
anstupsen können, ohne die Formel zu zerstören, die ihn erzeugt hat. Wenn Sie eine lebende Formel in der
Zelle brauchen, weisen Sie .Formula zu, nicht .Value — die beiden sind verschiedene Gesichter
derselben Zelle, behandelt in VBA Formula. Und wenn es Ihnen auf die genaue
Zahl ankommt, die Sie zurücklesen — Geld, Datumsangaben, lange Dezimalzahlen —, beginnt die Wahl zwischen
.Value und .Value2 zu zählen, was das Thema von VBA Value vs Value2 vs Text ist.
Wie ExcelMaster hilft
Die .Value-Fehler, die echte Zeit kosten, sind keine Tippfehler — es sind die langsame
Zelle-für-Zelle-Schleife auf einem großen Blatt, das arr(3), das arr(3, 1) hätte sein sollen, der
Array-Code, der auf einem einzelligen Range bricht, und das implizite .Value, das stillschweigend das
Falsche verglich. Jeder davon läuft; er läuft nur falsch oder langsam.
ExcelMaster schreibt
standardmäßig die schnelle, korrekte Fassung. Bitten Sie es, „Spalte A um 8 % in Spalte C
hochzurechnen", und es liest den Block in ein Variant-Array, verarbeitet ihn im Speicher und schreibt ihn
in einer einzigen Zuweisung zurück — mit Neuberechnung und Bildschirmaktualisierung rund um das Schreiben
geregelt. Es indexiert das 2D-Array korrekt, sichert den Sonderfall einzelne Zelle ab und schreibt
.Value ausdrücklich, sodass der Code sagt, was er meint. Sie beschreiben die Transformation; es schreibt
den Roundtrip, der im Nu läuft, statt einer Schleife, die kriecht.
Häufig gestellte Fragen
Wie hole ich einen Zellwert in Excel VBA?
Lesen Sie die Value-Eigenschaft eines Range: x = Range("A1").Value oder x = Cells(1, 1).Value. Für
viele Zellen auf einmal lesen Sie den ganzen Range in einen Variant — arr = Range("A1:C100").Value —,
was ein 1-basiertes, zweidimensionales Array (arr(Zeile, Spalte)) ergibt. Einen Block in ein Array zu
lesen, ist weit schneller, als jede Zelle in einer Schleife zu lesen, weil jeder einzelne
.Value-Zugriff von VBA nach Excel überquert.
Wie schreibe ich einen Wert in eine Zelle in VBA?
Weisen Sie Value zu: Range("A1").Value = 42 oder Cells(1, 1).Value = "Total". Um viele Zellen auf
einmal zu schreiben, bauen Sie ein 2D-Variant-Array und weisen es einem Range gleicher Form zu:
Range("A1:A100").Value = arr. Das schreibt alle 100 Zellen in einer einzigen Operation statt in einer
Schleife, was auf großen Ranges dramatisch schneller ist.
Warum ist mein VBA-Range-Wert ein 2D-Array?
Weil ein mehrzelliger Range ein Gitter ist, ist sein .Value ein zweidimensionales Array, indexiert als
arr(Zeile, Spalte) und immer 1-basiert — selbst eine einzelne Spalte ist ein N-mal-1-Array, Sie
indexieren es also arr(3, 1), nicht arr(3). Mit einem einzigen Index zu indexieren, löst
„Subscript out of range" aus. Eine einzelne Zelle ist die Ausnahme: Range("A1").Value liefert einen
schlichten Skalar, kein 1-mal-1-Array.
Warum ist das Lesen von Zellen in einer VBA-Schleife so langsam?
Jeder Cells(i, j).Value-Zugriff überquert die Grenze zwischen der VBA-Engine und der Excel-Anwendung,
und dieser Sprung ist der teure Teil — nicht die Rechnung. Eine Schleife über 10.000 Zeilen, die jede
Zelle liest und schreibt, macht 20.000 Überquerungen. Den Range in ein Array zu lesen, es im Speicher zu
verarbeiten und das Array zurückzuschreiben, macht nur zwei Überquerungen, weshalb es oft zigmal
schneller ist.
Was ist der Unterschied zwischen .Value und einfach Range("A1") in VBA?
.Value ist die Standard-Eigenschaft eines Range, also wird x = Range("A1") als
x = Range("A1").Value behandelt. Sie lesen für Werte gleich, aber .Value wegzulassen verbirgt Ihre
Absicht: Set rng = Range("A1") weist das Range-Objekt zu, während x = Range("A1") dessen Wert
zuweist, und der Unterschied ist nur das Schlüsselwort Set. .Value ausdrücklich zu schreiben, macht
den Code eindeutig.
Getestet in
Getestet in: Excel 365 (Windows 11), VBA 7.1 — zuletzt geprüft am 31.08.2026.
Verwandte Anleitungen: VBA Range · VBA Cells · VBA Formula · VBA Value vs Value2 vs Text · VBA Array
