TL;DR — Escribe
Staticen lugar deDimdentro de un procedimiento y la variable conserva su valor cuando el procedimiento termina:Static clicks As Longcuenta todas las llamadas, no solo la actual. Es una memoria privada: nadie fuera del procedimiento puede verla, pero vive tanto como una global, hasta que el proyecto VBA se restablece. Esa es su fuerza y su trampa. Una Static nunca olvida por sí sola, así que también recuerda un indicador que se quedó atascado cuando un error se saltó la línea que lo limpiaba, y una caché construida con datos que han cambiado desde entonces. Usa Static cuando un solo procedimiento es dueño de la memoria; en cuanto otro procedimiento necesite leerla o restablecerla, pásala a unPrivatede módulo.
Sub CountClicks()
Static clicks As Long ' se conserva entre llamadas
clicks = clicks + 1
Application.StatusBar = "Clicked " & clicks & " times"
End Sub
Esta es la segunda parte de una serie de tres artículos sobre dónde vive un valor. Una variable global es visible para todo el proyecto y vive hasta que el proyecto se restablece. Una variable Static mantiene esa duración pero solo es visible para un procedimiento. Un parámetro Optional dura una sola llamada. La regla para las tres: elige el ámbito más estrecho que haga el trabajo.
Lo que aprenderás
- El modelo mental: Static es ámbito local con duración de módulo
- Static frente a Dim frente a un Private de módulo, lado a lado
- Cuatro trabajos que Static hace bien: contadores, interruptores, protecciones contra reentrada, cachés
- Las dos formas en que una Static recuerda demasiado: indicadores atascados y cachés caducadas
- Por qué todas las celdas que llaman a una función de hoja comparten una sola Static
- Static Sub, y cuándo sacar una Static de su procedimiento
El modelo mental: ámbito local, duración de módulo
Un Dim dentro de un procedimiento es un borrador: se crea cuando arranca el procedimiento y se tira cuando
termina, así que la siguiente llamada empieza de cero. Un Static dentro de un procedimiento es un cajón del
que solo este procedimiento tiene la llave. El procedimiento puede dejar algo dentro, terminar y encontrarlo
ahí en la siguiente llamada.
| Declaración | Quién puede verla | Cuánto conserva su valor |
|---|---|---|
Dim n As Long dentro de un procedimiento |
ese procedimiento | hasta que termina el procedimiento |
Static n As Long dentro de un procedimiento |
ese procedimiento | hasta que el proyecto se restablece |
Private n As Long en la parte superior de un módulo |
todos los procedimientos del módulo | hasta que el proyecto se restablece |
Public n As Long en la parte superior de un módulo estándar |
todo el proyecto | hasta que el proyecto se restablece |
La segunda fila es la única que combina un ámbito estrecho con una vida larga. «Hasta que el proyecto se
restablece» significa lo mismo que para una global: End, el botón Restablecer, un error no controlado que el
usuario finaliza, algunas ediciones de código o cerrar el libro, todo ello cubierto en la
guía de variables globales.
Declarar una Static, y el valor de la primera llamada
Static solo se permite dentro de un procedimiento, en lugar de Dim:
Function NextInvoiceNo() As Long
Static lastNo As Long ' 0 en la primerisima llamada
lastNo = lastNo + 1
NextInvoiceNo = lastNo
End Function
VBA no tiene inicializadores, así que Static lastNo As Long = 1000 es un error de sintaxis. En la primera
llamada una Static contiene el valor vacío de su tipo, 0, "", Empty o Nothing, y el valor inicial real
lo pones tú. Cuando 0 podría ser un valor legítimo, controla la primera llamada con una segunda Static:
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
Fíjate en lo que reconoce esa versión: la Static es una copia rápida y el número real vive en el libro. Un contador que debe sobrevivir al cierre del archivo tiene que volver a escribirse ahí, porque ninguna variable sobrevive al proyecto.
Cuatro trabajos que Static hace bien
Un interruptor. Un botón que activa y desactiva algo necesita saber su último estado:
Sub ToggleGridlines()
Static isOff As Boolean
isOff = Not isOff
ActiveWindow.DisplayGridlines = Not isOff
End Sub
Un contador o un total acumulado que pertenece a una sola rutina, como el número de factura de antes.
Una protección contra reentrada para un controlador de eventos que modifica la hoja que está vigilando.
Escribir en una celda dentro de Worksheet_Change vuelve a disparar Worksheet_Change; un indicador Static
corta el bucle:
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 ' volveria a disparar este evento
Done:
busy = False
End Sub
Una caché para una búsqueda que es lenta de construir y que solo necesita un procedimiento:
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
La comprobación If map Is Nothing cumple una doble función: construye la caché en la primera llamada y la
reconstruye después de que un restablecimiento del proyecto la haya vaciado. Es el patrón autorreparable de la
guía de variables globales, con la caché privada de la única función que la
usa.
La regla que muerde: una Static nunca olvida por sí sola
Todos los errores con Static son el mismo error: el valor sobrevivió a la situación en la que era válido.
El indicador atascado. Toma la protección contra reentrada de antes y borra la línea On Error GoTo Done.
Ahora cualquier error después de busy = True, una celda protegida o una falta de coincidencia de tipos,
termina el controlador antes de que se ejecute busy = False. El indicador se queda en True y, a partir de
ahí, la primera línea sale siempre: el controlador de eventos está muerto en silencio hasta que el proyecto se
restablece. El usuario ve una hoja que dejó de actualizarse, sin ningún mensaje de error. Un indicador de
protección debe limpiarse en todas las rutas de salida, y por eso el controlador de errores salta a la línea
que lo limpia. La guía de EnableEvents cubre la otra protección habitual, con la
misma regla.
La caché caducada. RegionOf construye su mapa una sola vez. Si después alguien añade una región a la
hoja, la función sigue respondiendo con el mapa antiguo durante todo el día, porque nada le dice que los datos
cambiaron. Y nada fuera de la función puede decírselo, porque la Static es invisible desde fuera. Ese es el
verdadero límite de Static: no puedes restablecerla desde otro procedimiento.
La sorpresa de las UDF: todas las celdas comparten una sola Static
Una Static pertenece al procedimiento, no al lugar desde el que se llamó. En una función de hoja eso significa que todas las celdas que la llaman comparten una sola variable:
Function CallCount() As Long
Static n As Long
n = n + 1
CallCount = n
End Function
' =CallCount() en A1, A2 y A3 no da 1, 1, 1 -
' da tres numeros distintos, en el orden de calculo
Excel decide el orden de cálculo y puede recalcular cualquier celda en cualquier momento, así que una función
definida por el usuario (UDF) cuya respuesta depende de una Static da resultados que cambian solos. La
guía de Function explica por qué una función de hoja debe depender solo de sus
argumentos. Una caché Static dentro de una UDF, como el mapa de RegionOf, está bien, porque cambia lo
rápido que llega la respuesta y no cuál es. Un contador Static o un total acumulado dentro de una UDF es
un error.
Static Sub, y Static en un UserForm
Poner Static delante del procedimiento convierte en estáticas todas sus variables locales:
Static Sub Tally()
Dim total As Double ' tambien estatica, por el Static Sub
total = total + 1
End Sub
Existe, pero evítalo. Quien lee ve Dim y da por hecho una variable nueva, y la única palabra clave de arriba
que dice lo contrario es fácil de pasar por alto. Marca una a una las variables que necesitan memoria.
Las variables Static en los procedimientos de un UserForm solo duran mientras el formulario siga cargado.
Después de Unload, el siguiente Show empieza con valores nuevos, la misma duración que las demás variables
del formulario en la guía de UserForm.
El criterio: Static hasta que un segundo procedimiento la necesite
Static es la forma más estrecha de dar memoria a un procedimiento, y estrecho es bueno: nada más puede cambiar
el valor por accidente, y la declaración está justo al lado del código que la usa. Mi regla: usa Static
cuando exactamente un procedimiento lee y escribe la memoria y nada más necesita nunca limpiarla. En cuanto
un segundo procedimiento tenga que verla, o necesites un botón de «actualizar» que vacíe una caché, pasa la
variable a la parte superior del módulo como Private y añade un pequeño procedimiento que la restablezca:
Private mMap As Object
Sub ResetRegionCache()
Set mMap = Nothing ' la siguiente busqueda la reconstruye
End Sub
Así el ámbito se mantiene tan estrecho como permite la nueva necesidad, y evitas saltar directamente a una
global Public.
Cómo ayuda ExcelMaster
Los errores con Static parecen fantasmas: un controlador de eventos que deja de dispararse sin motivo visible, una búsqueda que ignora la fila que acabas de añadir, una UDF cuyos números cambian cada vez que la hoja se recalcula.
ExcelMaster te deja describir lo que debe recordar la macro, por ejemplo «numera cada factura nueva a partir de la última usada». Elige el lugar adecuado para esa memoria —una Static, una variable de módulo con restablecimiento o una celda del libro— y añade el control de errores que impide que un indicador de protección se quede atascado.
Preguntas frecuentes
¿Qué significa Static en VBA?
Static declara una variable dentro de un procedimiento que conserva su valor cuando el procedimiento
termina. La siguiente llamada ve el valor que dejó la anterior. Solo ese procedimiento puede ver la variable,
y el valor se pierde cuando el proyecto VBA se restablece o se cierra el libro.
¿Qué diferencia hay entre Static y Dim en VBA?
Una variable Dim dentro de un procedimiento empieza vacía en cada llamada y desaparece cuando el
procedimiento termina. Una variable Static solo empieza vacía en la primera llamada y conserva su valor
entre llamadas. Ambas son visibles únicamente dentro de su procedimiento.
¿Cómo conservo el valor de una variable entre ejecuciones de una macro?
Declárala con Static dentro del procedimiento si solo ese procedimiento la necesita, o como Private en la
parte superior del módulo si la necesitan varios. Las dos conservan el valor hasta que el proyecto se
restablece. Para conservarlo después de cerrar el libro, guárdalo en una celda o en un nombre definido.
¿Puedo dar un valor inicial a una variable Static?
No en la declaración: VBA no tiene inicializadores, así que Static n As Long = 5 es un error de sintaxis. La
variable empieza como 0, "", Empty o Nothing. Asigna un valor inicial en la primera llamada, usando una
segunda Static de tipo Boolean para saber si la primera llamada ya se produjo.
¿Cómo restablezco una variable Static?
Solo el procedimiento que la declara puede cambiarla, así que dale a ese procedimiento una forma de
restablecerla, o pasa la variable a nivel de módulo como Private y añade un pequeño procedimiento de
restablecimiento. Restablecer todo el proyecto VBA también la vacía, junto con todas las demás variables de
módulo y públicas.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 01/10/2026.
Guías relacionadas: VBA Global Variable · VBA Optional Parameter · VBA Dim · VBA Function · VBA Worksheet Change · VBA EnableEvents · VBA Dictionary · VBA UserForm
