Lektionen/Grundlagen

Arrays: statisch & dynamisch

Einsteiger10 Min. Lesezeit

Ein Array ist eine Variable, die viele Werte desselben Typs unter einem Namen speichert. Statt zehn einzelne Variablen anzulegen, hast du einen Behälter mit zehn nummerierten Fächern — auf jedes greifst du über seinen Index zu.

Statisches Array deklarieren

Bei einem statischen Array steht die Größe schon beim Deklarieren fest. Du gibst die Ober- (und optional Unter-)grenze in Klammern an:

Option Explicit

Public Sub StatischesArray()
    Dim werte(1 To 10) As Long   ' 10 Fächer: Index 1 bis 10

    werte(1) = 100
    werte(2) = 200
    werte(10) = 999

    Debug.Print werte(2)         ' 200
End Sub

Mit 1 To 10 legst du Unter- und Obergrenze explizit fest. Das ist die klarste Schreibweise, weil du sofort siehst, welche Indizes gültig sind.

0-basiert oder 1-basiert?

Schreibst du nur Dim werte(10), meint VBA nicht zehn Fächer, sondern die Indizes 0 bis 10 — also elf Fächer. Denn ohne To beginnt die Zählung standardmäßig bei 0:

Dim a(10) As Long     ' Index 0 bis 10 -> 11 Elemente!
Dim b(1 To 10) As Long ' Index 1 bis 10 -> 10 Elemente

Mit Option Base 1 ganz oben im Modul verschiebst du die Standard-Untergrenze auf 1:

Option Base 1

Public Sub MitBaseEins()
    Dim a(10) As Long     ' jetzt Index 1 bis 10
    Debug.Print LBound(a) ' 1
End Sub

Option Base 1 gilt nur für das Modul, in dem es steht, und nicht für Arrays aus Array() oder Split(). Verlass dich lieber nicht darauf, sondern schreib Grenzen mit 1 To … explizit hin — dann ist der Code überall eindeutig.

Grenzen abfragen mit UBound und LBound

UBound liefert den höchsten, LBound den niedrigsten gültigen Index. So durchläufst du ein Array, ohne die Größe fest einzutippen:

Dim werte(1 To 5) As Long
Dim i As Long

For i = LBound(werte) To UBound(werte)
    werte(i) = i * 10
Next i

Debug.Print LBound(werte)  ' 1
Debug.Print UBound(werte)  ' 5

Diese Schleife funktioniert unverändert, egal ob das Array 0- oder 1-basiert ist oder später seine Größe ändert. Genau deshalb nimmst du LBound/UBound statt fester Zahlen.

Mehrdimensionale Arrays

Ein Array kann mehrere Dimensionen haben — praktisch für Tabellen (Zeilen × Spalten). Die Indizes trennst du mit Komma:

Dim matrix(1 To 3, 1 To 2) As String  ' 3 Zeilen, 2 Spalten

matrix(1, 1) = "Meier"
matrix(1, 2) = "Berlin"
matrix(2, 1) = "Schmidt"
matrix(2, 2) = "Hamburg"

' Bei mehreren Dimensionen brauchst du die Dimensionsnummer:
Debug.Print UBound(matrix, 1)  ' 3  (erste Dimension)
Debug.Print UBound(matrix, 2)  ' 2  (zweite Dimension)

Bei UBound/LBound gibst du als zweiten Parameter die Dimension an. Ohne Angabe wird immer die erste Dimension genommen.

Dynamische Arrays mit ReDim

Oft kennst du die Größe erst zur Laufzeit — etwa die Anzahl gefundener Datensätze. Dann deklarierst du das Array mit leeren Klammern und legst die Größe später mit ReDim fest:

Public Sub DynamischesArray()
    Dim namen() As String   ' noch ohne Größe
    Dim anzahl As Long

    anzahl = 3
    ReDim namen(1 To anzahl)  ' Größe zur Laufzeit setzen

    namen(1) = "Anna"
    namen(2) = "Ben"
    namen(3) = "Carla"
End Sub

ReDim legt das Array komplett neu an. Alle bisherigen Werte gehen dabei verloren — das Array wird auf leere Standardwerte zurückgesetzt.

ReDim Preserve — Werte behalten

Willst du die vorhandenen Werte behalten und das Array nur vergrößern, hängst du Preserve an:

Dim werte() As Long
Dim i As Long

ReDim werte(1 To 3)
werte(1) = 10: werte(2) = 20: werte(3) = 30

ReDim Preserve werte(1 To 5)  ' auf 5 vergrößern, 10/20/30 bleiben
werte(4) = 40
werte(5) = 50

For i = 1 To 5
    Debug.Print werte(i)      ' 10 20 30 40 50
Next i

Wichtig: Bei einem mehrdimensionalen Array darf ReDim Preserve nur die letzte Dimension ändern. Versuchst du eine andere zu ändern, gibt es Laufzeitfehler 9 ("Index außerhalb des gültigen Bereichs"). Und: Preserve kopiert bei jedem Aufruf das ganze Array. In einer engen Schleife ist das langsam — vergrößere lieber in größeren Schritten.

Array() — schnell befüllen

Mit der Funktion Array() erzeugst du ein Array direkt aus einer Werteliste. Das Ziel muss dabei ein Variant sein:

Dim tage As Variant
tage = Array("Mo", "Di", "Mi", "Do", "Fr")

Debug.Print tage(0)   ' Mo  (Array() ist immer 0-basiert)
Debug.Print tage(4)   ' Fr

Array() ignoriert Option Base 1 und beginnt immer bei 0.

Split() — Text in ein Array zerlegen

Split zerteilt einen String an einem Trennzeichen und liefert ein 0-basiertes String-Array zurück. Sehr nützlich für CSV-Zeilen oder zusammengesetzte Schlüssel:

Dim zeile As String
Dim felder() As String
Dim i As Long

zeile = "Meier;Berlin;1985"
felder = Split(zeile, ";")

For i = LBound(felder) To UBound(felder)
    Debug.Print i & ": " & felder(i)
Next i
' 0: Meier
' 1: Berlin
' 2: 1985

Das Gegenstück ist Join(felder, ";"), das aus einem Array wieder einen String mit Trennzeichen baut.

Über ein Array iterieren

Du kannst ein Array mit einer klassischen For-Schleife über den Index oder mit For Each ohne Index durchlaufen:

Dim farben As Variant
Dim f As Variant

farben = Array("rot", "grün", "blau")

' Variante 1: mit Index
Dim i As Long
For i = LBound(farben) To UBound(farben)
    Debug.Print farben(i)
Next i

' Variante 2: For Each (nur Lesen, kein Schreiben ins Array)
For Each f In farben
    Debug.Print f
Next f

For Each ist kürzer, aber du kannst damit die Elemente nur lesen, nicht überschreiben. Zum Ändern brauchst du den Index.

Erase — Array leeren

Erase setzt ein Array zurück. Bei einem dynamischen Array wird der Speicher komplett freigegeben — danach musst du erneut ReDim aufrufen. Bei einem statischen Array bleiben die Fächer erhalten, ihre Werte werden nur zurückgesetzt (Zahlen auf 0, Strings auf ""):

Dim dyn() As Long
ReDim dyn(1 To 3)
Erase dyn            ' Array ist jetzt wieder "leer", braucht neues ReDim

Dim stat(1 To 3) As Long
stat(1) = 99
Erase stat           ' stat(1) ist wieder 0, Array behält 3 Fächer

Typische Fehler

Index außerhalb des gültigen Bereichs (Laufzeitfehler 9) ist der Klassiker. Er entsteht, wenn du auf einen Index zugreifst, den es nicht gibt:

Dim a(1 To 3) As Long
a(4) = 10        ' Fehler 9: Index 4 existiert nicht
a(0) = 10        ' Fehler 9: Untergrenze ist 1, nicht 0

Häufige Ursachen und wie du sie vermeidest:

UrsacheLösung
Off-by-one (0 vs 1)Grenzen mit 1 To … explizit setzen
Feste Zahl statt GrenzeLBound/UBound in Schleifen nutzen
Zugriff vor ReDimDynamisches Array erst dimensionieren
Preserve auf falscher DimensionNur letzte Dimension ändern

Ein leeres, noch nicht dimensioniertes dynamisches Array hat übrigens gar keine gültigen Grenzen — ein UBound darauf löst ebenfalls Fehler 9 aus. Wenn du unsicher bist, kannst du das vorher prüfen, z. B. über einen Zähler, den du beim Befüllen mitführst.

Zusammengefasst

  • Dim a(1 To 10) As Long ist ein statisches Array; ohne To beginnt der Index bei 0.
  • Option Base 1 verschiebt die Standard-Untergrenze, gilt aber nicht für Array()/Split() — Grenzen lieber explizit schreiben.
  • Dynamische Arrays mit ReDim dimensionieren; ReDim Preserve behält Werte, darf aber nur die letzte Dimension ändern.
  • LBound/UBound machen Schleifen unabhängig von der konkreten Größe; Array() und Split() liefern fertige (0-basierte) Arrays.
  • Der häufigste Fehler ist "Index außerhalb des gültigen Bereichs" (Fehler 9) — meist ein Off-by-one bei den Grenzen.
Nächste Lektion
Collections & Dictionary