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

VBA Static Variable in Excel — ein Gedächtnis, das End Sub überlebt (und sich zu viel merkt)

|

VBA Static Variable in Excel — ein Gedächtnis, das End Sub überlebt (und sich zu viel merkt)

Kurzfassung — Schreiben Sie innerhalb einer Prozedur Static statt Dim, und die Variable behält ihren Wert, wenn die Prozedur endet: Static clicks As Long zählt jeden Aufruf, nicht nur den aktuellen. Sie ist ein privates Gedächtnis: Niemand außerhalb der Prozedur sieht sie, aber sie lebt so lange wie eine globale Variable, nämlich bis das VBA-Projekt zurückgesetzt wird. Das ist ihre Stärke und ihre Falle. Eine Static-Variable vergisst nie von selbst, also merkt sie sich auch ein Flag, das hängen geblieben ist, weil ein Fehler die Zeile übersprungen hat, die es zurücksetzen sollte, und einen Cache aus Daten, die sich inzwischen geändert haben. Nehmen Sie Static, wenn eine Prozedur das Gedächtnis allein besitzt; sobald eine andere Prozedur es lesen oder zurücksetzen muss, verlegen Sie es in ein modulweites Private.

Sub CountClicks()
    Static clicks As Long            ' bleibt zwischen den Aufrufen erhalten
    clicks = clicks + 1
    Application.StatusBar = "Clicked " & clicks & " times"
End Sub

Dies ist der zweite Teil einer dreiteiligen Reihe darüber, wo ein Wert lebt. Eine globale Variable ist für das ganze Projekt sichtbar und lebt, bis das Projekt zurückgesetzt wird. Eine Static-Variable behält diese Lebensdauer, ist aber nur für eine einzige Prozedur sichtbar. Ein optionaler Parameter hält genau einen Aufruf lang. Die Regel über alle drei hinweg: Nehmen Sie den engsten Gültigkeitsbereich, der die Aufgabe erfüllt.

Was Sie lernen

  • Das Denkmodell: Static ist lokaler Gültigkeitsbereich mit Modul-Lebensdauer
  • Static vs. Dim vs. ein modulweites Private im direkten Vergleich
  • Vier Aufgaben, die Static gut erledigt: Zähler, Umschalter, Wiedereintrittssperren, Caches
  • Die zwei Arten, wie sich eine Static-Variable zu viel merkt: hängende Flags und veraltete Caches
  • Warum sich alle Zellen, die eine Arbeitsblattfunktion aufrufen, eine Static-Variable teilen
  • Static Sub, und wann Sie eine Static-Variable aus ihrer Prozedur herausziehen

Das Denkmodell: lokaler Gültigkeitsbereich, Modul-Lebensdauer

Ein Dim innerhalb einer Prozedur ist ein Notizzettel: Er entsteht, wenn die Prozedur startet, und wird weggeworfen, wenn sie endet; der nächste Aufruf beginnt also bei null. Ein Static innerhalb einer Prozedur ist eine Schublade, zu der nur diese Prozedur einen Schlüssel hat. Die Prozedur kann etwas darin ablegen, enden und es beim nächsten Aufruf dort wiederfinden.

Deklaration Wer sie sieht Wie lange sie ihren Wert behält
Dim n As Long innerhalb einer Prozedur diese Prozedur bis die Prozedur endet
Static n As Long innerhalb einer Prozedur diese Prozedur bis das Projekt zurückgesetzt wird
Private n As Long am Anfang eines Moduls jede Prozedur des Moduls bis das Projekt zurückgesetzt wird
Public n As Long am Anfang eines Standardmoduls das ganze Projekt bis das Projekt zurückgesetzt wird

Die zweite Zeile ist die einzige, die einen engen Gültigkeitsbereich mit einer langen Lebensdauer verbindet. „Bis das Projekt zurückgesetzt wird“ bedeutet hier dasselbe wie bei einer globalen Variablen: End, die Zurücksetzen-Schaltfläche, ein unbehandelter Fehler, den der Benutzer beendet, manche Codeänderungen oder das Schließen der Arbeitsmappe — alles behandelt in der Anleitung zu globalen Variablen.

Eine Static-Variable deklarieren, und der Wert beim ersten Aufruf

Static ist nur innerhalb einer Prozedur erlaubt, anstelle von Dim:

Function NextInvoiceNo() As Long
    Static lastNo As Long            ' 0 beim allerersten Aufruf
    lastNo = lastNo + 1
    NextInvoiceNo = lastNo
End Function

VBA kennt keine Initialisierung in der Deklaration, Static lastNo As Long = 1000 ist also ein Syntaxfehler. Beim ersten Aufruf enthält eine Static-Variable den leeren Wert ihres Typs — 0, "", Empty oder Nothing —, und den echten Startwert setzen Sie selbst. Kann 0 ein echter Wert sein, verfolgen Sie den ersten Aufruf mit einer zweiten Static-Variablen:

Function NextInvoiceNo() As Long
    Static lastNo As Long, started As Boolean
    If Not started Then
        lastNo = ThisWorkbook.Worksheets("Settings").Range("B3").Value
        started = True
    End If
    lastNo = lastNo + 1
    NextInvoiceNo = lastNo
End Function

Beachten Sie, was diese Fassung eingesteht: Die Static-Variable ist eine schnelle Kopie, die echte Nummer lebt in der Arbeitsmappe. Ein Zähler, der das Schließen der Datei überstehen muss, muss dorthin zurückgeschrieben werden, denn keine Variable überlebt das Projekt.

Vier Aufgaben, die Static gut erledigt

Ein Umschalter. Eine Schaltfläche, die etwas ein- und ausschaltet, muss ihren letzten Zustand kennen:

Sub ToggleGridlines()
    Static isOff As Boolean
    isOff = Not isOff
    ActiveWindow.DisplayGridlines = Not isOff
End Sub

Ein Zähler oder eine laufende Summe, die zu einer einzigen Routine gehört, wie die Rechnungsnummer oben.

Eine Wiedereintrittssperre für eine Ereignisprozedur, die das Blatt ändert, das sie überwacht. Wer innerhalb von Worksheet_Change eine Zelle schreibt, löst Worksheet_Change erneut aus; ein Static-Flag stoppt die Schleife:

Private Sub Worksheet_Change(ByVal Target As Range)
    Static busy As Boolean
    If busy Then Exit Sub
    busy = True
    On Error GoTo Done
    Target.Offset(0, 1).Value = Now  ' wuerde dieses Ereignis erneut ausloesen
Done:
    busy = False
End Sub

Ein Cache für eine Nachschlagetabelle, deren Aufbau langsam ist und die nur eine Prozedur braucht:

Function RegionOf(ByVal code As String) As String
    Static map As Object
    If map Is Nothing Then
        Dim r As Range
        Set map = CreateObject("Scripting.Dictionary")
        For Each r In ThisWorkbook.Worksheets("Regions").Range("A2:A500")
            map(r.Value) = r.Offset(0, 1).Value
        Next r
    End If
    If map.Exists(code) Then RegionOf = map(code)
End Function

Der Test If map Is Nothing erfüllt eine doppelte Aufgabe: Er baut den Cache beim ersten Aufruf auf und baut ihn neu auf, nachdem ein Zurücksetzen des Projekts ihn geleert hat. Das ist das selbstheilende Muster aus der Anleitung zu globalen Variablen, nur dass der Cache privat in der einen Funktion bleibt, die ihn verwendet.

Die Regel, die zubeißt: Eine Static-Variable vergisst nie von selbst

Jeder Static-Bug ist derselbe Bug: Der Wert hat die Situation überlebt, für die er galt.

Das hängende Flag. Nehmen Sie die Wiedereintrittssperre oben und löschen Sie die Zeile On Error GoTo Done. Jetzt beendet jeder Fehler nach busy = True — eine geschützte Zelle oder ein Typkonflikt — die Prozedur, bevor busy = False läuft. Das Flag bleibt True, und von da an steigt die erste Zeile jedes Mal aus: Die Ereignisprozedur ist stillschweigend tot, bis das Projekt zurückgesetzt wird. Der Benutzer sieht ein Blatt, das sich nicht mehr aktualisiert, ohne jede Fehlermeldung. Ein Sperr-Flag muss auf jedem Ausgangsweg zurückgesetzt werden, und genau deshalb springt die Fehlerbehandlung zu der Zeile, die es zurücksetzt. Die EnableEvents-Anleitung behandelt die andere übliche Sperre, mit derselben Regel.

Der veraltete Cache. RegionOf baut seine Tabelle einmal auf. Fügt jemand danach eine Region auf dem Blatt hinzu, antwortet die Funktion weiter aus der alten Tabelle, den ganzen Tag, weil ihr nichts sagt, dass sich die Daten geändert haben. Und nichts außerhalb der Funktion kann es ihr sagen, denn die Static-Variable ist von außen unsichtbar. Das ist die eigentliche Grenze von Static: Sie können sie nicht aus einer anderen Prozedur zurücksetzen.

Die UDF-Überraschung: Alle Zellen teilen sich eine Static-Variable

Eine Static-Variable gehört zur Prozedur, nicht zu der Stelle, von der aus sie aufgerufen wurde. Bei einer Arbeitsblattfunktion heißt das: Alle Zellen, die sie aufrufen, teilen sich eine einzige Variable:

Function CallCount() As Long
    Static n As Long
    n = n + 1
    CallCount = n
End Function
' =CallCount() in A1, A2 und A3 ergibt nicht 1, 1, 1 -
' sondern drei verschiedene Zahlen, in Berechnungsreihenfolge

Excel bestimmt die Berechnungsreihenfolge und kann jede Zelle jederzeit neu berechnen; eine UDF, deren Ergebnis von einer Static-Variablen abhängt, liefert also Ergebnisse, die sich von selbst ändern. Die Function-Anleitung erklärt, warum eine Arbeitsblattfunktion nur von ihren Argumenten abhängen sollte. Ein Static-Cache in einer UDF, wie die Tabelle in RegionOf, ist in Ordnung, denn er ändert, wie schnell die Antwort kommt, nicht, wie sie lautet. Ein Static-Zähler oder eine laufende Summe in einer UDF ist ein Bug.

Static Sub, und Static in einer UserForm

Steht Static vor der Prozedur, wird jede lokale Variable darin statisch:

Static Sub Tally()
    Dim total As Double              ' ebenfalls statisch, wegen Static Sub
    total = total + 1
End Sub

Das gibt es, aber meiden Sie es. Wer den Code liest, sieht Dim und erwartet eine frische Variable, und das eine Schlüsselwort oben, das etwas anderes sagt, übersieht man leicht. Kennzeichnen Sie stattdessen die einzelnen Variablen, die ein Gedächtnis brauchen.

Static-Variablen in den Prozeduren einer UserForm leben nur so lange, wie das Formular geladen bleibt. Nach Unload beginnt das nächste Show mit frischen Werten — dieselbe Lebensdauer wie die der anderen Variablen des Formulars, siehe UserForm-Anleitung.

Die Abwägung: Static, bis eine zweite Prozedur es braucht

Static ist der engste Weg, einer Prozedur ein Gedächtnis zu geben, und eng ist gut: Nichts anderes kann den Wert versehentlich ändern, und die Deklaration steht direkt neben dem Code, der sie verwendet. Meine Regel: Nehmen Sie Static, wenn genau eine Prozedur das Gedächtnis liest und schreibt und nichts anderes es je leeren muss. Sobald eine zweite Prozedur es sehen muss oder Sie eine „Aktualisieren“-Schaltfläche brauchen, die einen Cache leert, verlegen Sie die Variable als Private an den Anfang des Moduls und ergänzen eine kleine Prozedur, die sie zurücksetzt:

Private mMap As Object

Sub ResetRegionCache()
    Set mMap = Nothing               ' die naechste Abfrage baut ihn neu auf
End Sub

So bleibt der Gültigkeitsbereich so eng, wie es der neue Bedarf erlaubt, und Sie vermeiden den Sprung direkt zu einer globalen Public-Variablen.

Wie ExcelMaster hilft

Static-Bugs wirken wie Geister: eine Ereignisprozedur, die ohne sichtbaren Grund nicht mehr auslöst, eine Nachschlagefunktion, die die gerade eingefügte Zeile ignoriert, eine UDF, deren Zahlen sich bei jeder Neuberechnung des Blatts verschieben.

ExcelMaster lässt Sie beschreiben, was sich das Makro merken soll — etwa „nummeriere jede neue Rechnung ab der zuletzt verwendeten Nummer“. Es wählt den richtigen Ort für dieses Gedächtnis — eine Static-Variable, eine modulweite Variable mit Zurücksetzen-Prozedur oder eine Zelle in der Arbeitsmappe — und ergänzt die Fehlerbehandlung, die verhindert, dass ein Sperr-Flag hängen bleibt.

Häufig gestellte Fragen

Was bedeutet Static in VBA?

Static deklariert innerhalb einer Prozedur eine Variable, die ihren Wert behält, nachdem die Prozedur geendet hat. Der nächste Aufruf sieht den Wert, den der letzte hinterlassen hat. Nur diese Prozedur sieht die Variable, und der Wert geht verloren, wenn das VBA-Projekt zurückgesetzt oder die Arbeitsmappe geschlossen wird.

Was ist der Unterschied zwischen Static und Dim in VBA?

Eine Dim-Variable innerhalb einer Prozedur beginnt bei jedem Aufruf leer und verschwindet, wenn die Prozedur endet. Eine Static-Variable beginnt nur beim ersten Aufruf leer und behält ihren Wert zwischen den Aufrufen. Beide sind nur innerhalb ihrer Prozedur sichtbar.

Wie behalte ich den Wert einer Variablen zwischen zwei Makroläufen?

Deklarieren Sie sie mit Static innerhalb der Prozedur, wenn nur diese Prozedur sie braucht, oder als Private am Anfang des Moduls, wenn mehrere Prozeduren sie brauchen. Beide behalten den Wert, bis das Projekt zurückgesetzt wird. Soll er auch nach dem Schließen der Arbeitsmappe erhalten bleiben, speichern Sie ihn in einer Zelle oder einem definierten Namen.

Kann ich einer Static-Variablen einen Startwert geben?

Nicht in der Deklaration: VBA kennt keine Initialisierung, Static n As Long = 5 ist also ein Syntaxfehler. Die Variable beginnt als 0, "", Empty oder Nothing. Setzen Sie den Startwert beim ersten Aufruf und merken Sie sich mit einer zweiten Static-Variablen vom Typ Boolean, ob der erste Aufruf schon stattgefunden hat.

Wie setze ich eine Static-Variable zurück?

Nur die Prozedur, die sie deklariert, kann sie ändern; geben Sie dieser Prozedur also einen Weg, sie zurückzusetzen, oder verlegen Sie die Variable als Private auf Modulebene und ergänzen Sie eine kleine Prozedur zum Zurücksetzen. Ein Zurücksetzen des gesamten VBA-Projekts leert sie ebenfalls, zusammen mit allen anderen modulweiten und öffentlichen Variablen.

Getestet in

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

Verwandte Anleitungen: VBA Global Variable · VBA Optional Parameter · VBA Dim · VBA Function · VBA Worksheet Change · VBA EnableEvents · VBA Dictionary · VBA UserForm