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

VBA UBound in Excel — Array-Größe mit UBound und LBound (und der Off-by-One-Fehler)

|

VBA UBound in Excel — Array-Größe mit UBound und LBound (und der Off-by-One-Fehler)

Kurzfassung — In VBA zählen Sie ein Array nicht, Sie fragen es. UBound(a) gibt den höchsten gültigen Index zurück; LBound(a) den niedrigsten. Arrays sind standardmäßig nullbasiert, also hält Dim a(9) zehn Elemente mit den Indizes 0 bis 9UBound ist 9, nicht 10. Dieser Off-by-One-Fehler ist der mit Abstand häufigste Schleifenfehler. Die Schleife, die immer übersteht, lautet For i = LBound(a) To UBound(a), und die wahre Länge ist UBound(a) - LBound(a) + 1. Ein Array hat kein .Length und kein .Count.

Sub LoopSafely()
    Dim a() As String
    a = Split("red,green,blue", ",")   ' Split liefert ein 0-basiertes Array

    Dim i As Long
    For i = LBound(a) To UBound(a)      ' funktioniert unabhaengig von den Grenzen
        Debug.Print i, a(i)            ' 0 red / 1 green / 2 blue
    Next i

    Debug.Print "count = " & (UBound(a) - LBound(a) + 1)   ' 3
End Sub

UBound ist der Weg, die Form eines Arrays zu lesen, und der Partner von ReDim: Sie dimensionieren das Array und fragen dann, welche Größe dabei herauskam. Bekommen Sie die Grenzen falsch, überspringen Sie entweder das letzte Element oder laufen über das Ende hinaus in Laufzeitfehler 9. Weil verschiedene Quellen Ihnen Arrays mit unterschiedlichen Startindizes reichen, ist die Gewohnheit des Fragens — statt 0 oder 1 anzunehmen — das, was Schleifen korrekt hält.

Was Sie lernen

  • Was UBound und LBound zurückgeben und warum ein Array keine .Length-Eigenschaft hat
  • Warum VBA-Arrays standardmäßig nullbasiert sind und woher der Off-by-One-Fehler kommt
  • Die Schleife, die immer funktioniert: For i = LBound(a) To UBound(a)
  • Die wahre Array-Länge: UBound(a) - LBound(a) + 1
  • Die Größe jeder Dimension eines 2D-Arrays mit UBound(a, 2) ermitteln
  • Warum UBound auf einem leeren dynamischen Array Fehler 9 auslöst und wie Sie ihn absichern

UBound und LBound: fragen, nicht zählen

UBound (obere Grenze) gibt den größten Index zurück, den Sie legal verwenden dürfen; LBound (untere Grenze) gibt den kleinsten. Zusammen beschreiben sie die Form des Arrays. VBA-Arrays haben bewusst kein .Length und kein .Count — die Grenzen sind die maßgebliche Quelle, und Sie lesen sie zur Laufzeit:

Dim a(1 To 5) As Long
Debug.Print LBound(a)   ' 1
Debug.Print UBound(a)   ' 5

Warum fragen statt sich merken? Weil das Array, über das Sie iterieren, oft anderswo dimensioniert wurde — durch ein ReDim, durch Split, durch das Einlesen eines Bereichs — und die Größe, die Sie zu haben glauben, fest zu verdrahten ist genau der Weg, wie Schleifen aus dem Tritt mit der Wirklichkeit geraten.

Standardmäßig nullbasiert: wo der Off-by-One-Fehler wohnt

Sofern Sie nichts anderes sagen, beginnt ein VBA-Array bei Index 0. Dim a(9) gibt Ihnen also nicht neun Elemente — es gibt Ihnen zehn, mit den Indizes 0 bis 9:

Dim a(9) As Long        ' zehn Elemente: a(0) .. a(9)
Debug.Print LBound(a)   ' 0
Debug.Print UBound(a)   ' 9  <- nicht 10

Das ist die Wurzel des klassischen Fehlers. For i = 1 To UBound(a) überspringt still a(0); For i = 0 To 10 läuft einen Schritt zu weit und trifft «Subscript out of range». Sie können mit Option Base 1 für ein ganzes Modul einsbasierte Arrays erzwingen oder mit Dim a(1 To 10) ausdrückliche Grenzen deklarieren — aber die eigentliche Lösung ist, den Start gar nicht mehr zu raten.

Die Schleife, die immer funktioniert

Schreiben Sie die Schleife anhand der eigenen Grenzen des Arrays, und sie ist korrekt, egal wie das Array deklariert wurde oder woher es kam:

Dim i As Long
For i = LBound(a) To UBound(a)
    ' ... a(i) verwenden ...
Next i

Diese eine Gewohnheit räumt die ganze Familie der Off-by-One-Fehler aus. Sie funktioniert für ein nullbasiertes Split-Ergebnis, ein einsbasiertes Range.Value-Array, ein Option Base 1-Modul und ein ausdrückliches Dim a(5 To 12) gleichermaßen. Verdrahten Sie nie 0 oder 1 als Start einer Array-Schleife fest, wenn LBound Ihnen die Wahrheit gratis nennt.

Array-Länge: UBound minus LBound plus eins

Weil ein Array bei jedem beliebigen Index beginnen kann, ist seine Länge nicht einfach UBound + 1. Die Formel, die immer stimmt, lautet:

Dim n As Long
n = UBound(a) - LBound(a) + 1

Für ein nullbasiertes Array aus zehn ist das 9 - 0 + 1 = 10; für Dim a(1 To 10) ist es 10 - 1 + 1 = 10. Nutzen Sie die volle Formel, dann ist es egal, welche Basis das Array verwendet. (Die Leute suchen nach einer „VBA array length"-Eigenschaft; es gibt keine — dieser Ausdruck ist die Antwort.)

2D-Arrays: eine Grenze pro Dimension

Bei einem mehrdimensionalen Array nehmen UBound und LBound ein zweites Argument — welche Dimension Sie abfragen. UBound(a, 1) ist die erste Dimension (Zeilen), UBound(a, 2) die zweite (Spalten):

Dim g(1 To 3, 1 To 4) As Long   ' 3 Zeilen, 4 Spalten
Debug.Print UBound(g, 1)        ' 3  (Zeilen)
Debug.Print UBound(g, 2)        ' 4  (Spalten)

Dim r As Long, c As Long
For r = LBound(g, 1) To UBound(g, 1)
    For c = LBound(g, 2) To UBound(g, 2)
        ' ... g(r, c) verwenden ...
    Next c
Next r

Ein blankes UBound(g) ohne Dimensionsnummer gibt die erste Dimension zurück. Das zählt am meisten, wenn Sie ein Blatt in ein Array einlesen, denn Range.Value reicht Ihnen stets ein einsbasiertes 2D-Array — UBound(a, 1) und UBound(a, 2) zu fragen ist der Weg, herauszufinden, wie viele Zeilen und Spalten Sie tatsächlich bekommen haben.

Das leere dynamische Array absichern

Ein dynamisches Array, das deklariert, aber nie mit ReDim dimensioniert wurde (oder eines, das mit Erase geleert wurde), hat überhaupt keine Grenzen, und ein UBound darauf löst Laufzeitfehler 9 aus, «Subscript out of range»:

Dim a() As Long
Debug.Print UBound(a)   ' Fehler 9 - das Array hat noch keine Groesse

Besteht auch nur die Chance, dass das Array leer ist — etwa weil es aus einem Filter kam, der nichts traf —, sichern Sie es vor der Schleife ab. Ein kleiner Helfer hält den aufrufenden Code sauber:

Function IsAllocated(a As Variant) As Boolean
    On Error Resume Next
    IsAllocated = (LBound(a) <= UBound(a))
    On Error GoTo 0
End Function

Dann If IsAllocated(a) Then For i = LBound(a) To UBound(a) .... Das ist der Array-Vetter davon, ein Objekt mit Is Nothing abzusichern, bevor Sie es verwenden.

Wie ExcelMaster hilft

UBound ist eine kleine Funktion mit einer großen Aufgabe — einer Schleife genau zu sagen, wo sie aufhören soll — und die Fehler drumherum (0 oder 1 annehmen, das leere Array vergessen, eine Länge fest verdrahten) sind genau die, die ein Makro die letzte Zeile überspringen oder an einem Randfall abstürzen lassen.

ExcelMaster lässt Sie die Aufgabe beschreiben — „zieh den benutzten Bereich in ein Array, summiere jede Spalte, schreib die Summen darunter" — und iteriert von LBound bis UBound auf der richtigen Dimension, berechnet die Länge korrekt und sichert ein Array ab, das leer zurückgekommen sein könnte, sodass das Makro in der ersten Zeile, der letzten Zeile und im leeren Fall stimmt. Sie behalten die Arbeitsmappe und den Code.

Häufig gestellte Fragen

Was macht UBound in VBA?

UBound gibt den höchsten gültigen Index eines Arrays zurück — die größte Zahl, die Sie in den Klammern verwenden dürfen. Für Dim a(1 To 5) ist UBound(a) gleich 5; für ein nullbasiertes Dim a(9) ist es 9. Kombinieren Sie es mit LBound, das den niedrigsten Index zurückgibt, um über ein Array zu iterieren, ohne seine Größe fest zu verdrahten.

Wie ermittle ich die Länge eines Arrays in VBA?

Ein VBA-Array hat keine .Length- oder .Count-Eigenschaft. Berechnen Sie die Anzahl als UBound(a) - LBound(a) + 1. Die volle Formel ist nötig, weil ein VBA-Array bei Index 0, 1 oder jeder ausdrücklichen unteren Grenze beginnen kann, sodass UBound + 1 nur für nullbasierte Arrays stimmt.

Warum bekomme ich den Fehler Subscript out of range mit UBound?

Meist, weil das Array leer ist — ein dynamisches Array, das mit Dim a() deklariert, aber nie mit ReDim dimensioniert wurde, oder eines, das mit Erase geleert wurde, hat keine Grenzen, sodass UBound Laufzeitfehler 9 auslöst. Sichern Sie es mit einem kleinen IsAllocated-Helfer ab, bevor Sie iterieren. Sie sehen Fehler 9 auch, wenn eine Schleife über UBound hinausläuft, etwa For i = 0 To 10 bei einem nullbasierten Array aus zehn Elementen.

Sind VBA-Arrays nullbasiert oder einsbasiert?

Standardmäßig nullbasiert: Dim a(9) hält zehn Elemente mit den Indizes 0 bis 9. Sie können ein Modul mit Option Base 1 einsbasiert machen oder mit Dim a(1 To 10) ausdrückliche Grenzen setzen. Von Split und Array zurückgegebene Arrays sind nullbasiert; ein aus Range.Value gelesenes Array ist einsbasiert. Weil es variiert, iterieren Sie mit LBound bis UBound, statt etwas anzunehmen.

Wie finde ich die Größe eines 2D-Arrays in VBA?

Übergeben Sie die Dimensionsnummer als zweites Argument: UBound(a, 1) für die erste Dimension (Zeilen) und UBound(a, 2) für die zweite (Spalten), mit LBound(a, 1) und LBound(a, 2) für die unteren Grenzen. So lesen Sie die Form eines 2D-Arrays, das Range.Value zurückgibt.

Getestet in

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

Verwandte Anleitungen: VBA ReDim · VBA 2D Arrays · VBA Array · VBA For Loop · VBA Split