Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · última verificación el 07/06/2026
En resumen — Un Sub (subrutina) es un bloque de acciones con nombre que se ejecuta al llamarlo y no devuelve nada. La macro que ejecutas desde el cuadro Macros es un Sub. Se llama por su nombre, con o sin la palabra clave Call:
Sub SaludarUsuario() ' un Sub: una serie de acciones con nombre, sin valor de retorno
MsgBox "¡Hola!"
End Sub
Sub EjecutarInforme()
SaludarUsuario ' lo llamas — sin Call, sin paréntesis
Call SaludarUsuario ' resultado idéntico, solo la sintaxis Call más antigua
End Sub
Llamar mal a un Sub lleva a «Error de compilación: se esperaba =» o «se esperaba: fin de la instrucción» — el error de Sub más común. Todo esta guía gira en torno al porqué.
El modelo mental: un Sub es un verbo que llamas por su nombre
Piensa en un Sub como una acción con nombre — un verbo. DarFormatoInforme, ExportarFacturas, EliminarFilasViejas. Defines los pasos una vez, les das un nombre y, desde entonces, ejecutas esos pasos desde cualquier sitio diciendo el nombre.
Lo que casi ningún tutorial cuenta: en VBA no existe un tipo «macro» aparte. Cuando grabas una macro o eliges una en Programador → Macros, en realidad ejecutas un simple Sub — en concreto un Sub público sin argumentos. «Macro» es solo la palabra amable que Excel muestra a los usuarios; por debajo es un Sub. En cuanto eso encaja, todo el proyecto VBA deja de parecer magia y pasa a ser una lista de acciones con nombre que conectas entre sí.
La única regla: cómo lo llamas decide los paréntesis
Esta es la regla que explica casi todos los errores de principiante:
' Sin argumentos — las tres son válidas:
SaludarUsuario
Call SaludarUsuario
Call SaludarUsuario()
' CON argumentos — solo estas dos son válidas:
EscribirLog "informe.txt", 3 ' ✅ llamada directa: SIN paréntesis, argumentos por comas
Call EscribirLog("informe.txt", 3) ' ✅ con Call: paréntesis OBLIGATORIOS
EscribirLog("informe.txt", 3) ' ❌ Error de compilación: se esperaba =
La última línea falla porque, sin Call, VBA lee EscribirLog( … ) como «evalúa EscribirLog y usa su valor de retorno» — pero un Sub no tiene valor de retorno, y "informe.txt", 3 tampoco es una sola expresión. Los paréntesis pertenecen a Call, no a la llamada directa. Es exactamente la lógica de la regla de los paréntesis de MsgBox: los paréntesis solo aparecen cuando se usa un valor.
En una frase: llamada directa → sin paréntesis; palabra clave Call → paréntesis. Elige un estilo y mantenlo. El VBA moderno suele prescindir de Call.
Una macro es un Sub público — Private lo oculta
Que tu Sub aparezca en el cuadro Macros depende de una sola palabra delante:
Public Sub CierreMensual() ' aparece en la lista de Macros (Alt+F8) — esto es «una macro»
PrepararDatos ' llama a un ayudante que el usuario nunca ve
ConstruirResumen
End Sub
Private Sub PrepararDatos() ' oculto de la lista de Macros — solo un ayudante
' ...
End Sub
Public (lo predeterminado para un Sub simple) significa «cualquiera puede llamarlo y mostrarlo al usuario». Private significa «solo el código de este módulo lo llama». Usa Private para los pequeños Subs ayudantes que hacen un paso cada uno — mantiene limpio el cuadro Macros y señala «esto no es un punto de entrada». Un Sub con argumentos también desaparece de la lista automáticamente, porque Excel no puede saber qué pasarle.
Meter datos: los argumentos
Un Sub se vuelve reutilizable en cuanto deja de fijar valores a fuego y empieza a recibirlos:
Sub ResaltarFila(filaObjetivo As Long, indiceColor As Long)
Rows(filaObjetivo).Interior.ColorIndex = indiceColor
End Sub
Sub MarcarVencidas()
ResaltarFila 5, 3 ' fila 5 en rojo
ResaltarFila 9, 6 ' fila 9 en amarillo
End Sub
Cómo viajan esos argumentos — si el Sub llamado puede cambiar la variable que pasaste — es una trampa que merece su propia página. El valor predeterminado en VBA es ByRef, así que el original puede modificarse a tus espaldas. Mira ByRef vs ByVal para la trampa detrás de «¿por qué cambió mi contador tras esa llamada?».
Los procedimientos de evento son Subs — y deben serlo
Cada evento de hoja o de libro que hayas escrito es un Sub, sin alternativa:
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("A:A")) Is Nothing Then
MsgBox "Se editó la columna A."
End If
End Sub
Excel los llama cuando algo ocurre (cambia una celda, se abre el libro) y no lee ningún valor de retorno — así que solo pueden ser Subs, nunca Functions. Esa asimetría hace nítida la frontera Sub/Function: si quien llama no quiere respuesta, es un Sub.
La opinión: un Sub, una tarea
El camino más rápido a un VBA inmantenible es el Sub Main() de 300 líneas que importa, limpia, calcula, da formato y envía — todo de un tirón. Divídelo en Subs con nombre que hagan una cosa cada uno:
Public Sub EjecutarFlujo()
ImportarDatos
LimpiarDatos
ConstruirInforme
EnviarInforme
End Sub
Ahora EjecutarFlujo se lee como un índice, cada paso se prueba por separado y, cuando el envío falla, arreglas EnviarInforme sin desplazarte por 250 líneas ajenas. El nombre de un Sub es documentación que no puede quedar obsoleta — se ejecuta. Es el único hábito que separa el VBA que sobrevive un año del VBA que nadie se atreve a tocar.
Errores frecuentes de Sub (y la solución)
| Síntoma | Causa | Solución |
|---|---|---|
| «se esperaba =» al llamar | Paréntesis en una llamada directa: MiSub(a, b) |
Quitar los paréntesis (MiSub a, b) o añadir Call: Call MiSub(a, b) |
| La macro no aparece en Alt+F8 | El Sub es Private, o tiene argumentos |
Hacerlo Public sin argumentos, o llamarlo desde un wrapper sin argumentos |
| «Nombre ambiguo detectado» | Dos Subs con el mismo nombre en un módulo | Renombrar uno — los nombres deben ser únicos por módulo |
| El Sub se ejecuta pero «no pasa nada» | Un Sub donde hacía falta un valor de retorno | Usar una Function cuando quien llama necesita respuesta |
| Argumento cambiado de forma inesperada | El ByRef predeterminado dejó que el Sub mutara la variable |
Declarar el parámetro ByVal — ver ByRef vs ByVal |
| «Sub o Function no definido» | Errata, o el Sub está en otro módulo/libro | Revisar la ortografía; calificar con el módulo/libro si hace falta |
Cuando la propia macro es lo difícil — descríbela y ya
Dividir el trabajo en Subs limpios es buena ingeniería, pero sigue siendo fontanería que hay que escribir y mantener. Si la lógica es «importa estos tres archivos, cuádralos por el ID de pedido, marca las diferencias y envíalas a contabilidad», el trabajo real no es dónde cortar los Subs — es el código de dentro. ExcelMaster Agent te deja decir eso en español sencillo y escribe todo el flujo por ti — sin Sub, sin Call, sin mantenimiento. Prueba gratis →
Guías relacionadas
- VBA Function en Excel — Valores de retorno y funciones personalizadas
- VBA ByRef vs ByVal — Por qué tu variable cambió tras una llamada
- VBA MsgBox en Excel — Sí/No, botones y la regla de los paréntesis
- VBA Bucle For en Excel — 8 ejemplos reales
Preguntas frecuentes
¿Qué es un Sub en VBA?
Un Sub (subrutina) es un bloque de código VBA con nombre que ejecuta acciones y no devuelve ningún valor. Se define con Sub Nombre() … End Sub y se ejecuta llamando a su nombre. Las macros que ejecutas desde el cuadro Macros de Excel son Subs.
¿Qué diferencia hay entre un Sub y una macro?
Ninguna a nivel técnico. «Macro» es solo el nombre de cara al usuario de un Sub público sin argumentos — el único tipo que aparece en la lista de Programador → Macros (Alt+F8). Toda macro es un Sub; no todo Sub se muestra como macro.
¿Cómo se llama a un Sub en VBA?
De dos formas equivalentes: escribir el nombre solo — MiSub (o MiSub arg1, arg2 con argumentos, sin paréntesis) — o usar la palabra clave Call — Call MiSub(arg1, arg2) (paréntesis obligatorios). No pongas paréntesis en una llamada directa con varios argumentos: es un error de compilación.
¿Por qué MiSub(a, b) da error de compilación?
Sin la palabra clave Call, VBA interpreta los paréntesis como «usa el valor de retorno de este Sub», pero un Sub no tiene, y a, b no es una sola expresión. Quita los paréntesis (MiSub a, b) o añade Call (Call MiSub(a, b)).
¿Cuál es la diferencia entre Sub y Function en VBA?
Un Sub hace trabajo y no devuelve nada; una Function hace trabajo y devuelve un valor a quien la llama. Usa una Function cuando quien llama necesita una respuesta (y cuando quieras usarla como fórmula de hoja); un Sub para todo lo demás.
¿Qué significa Private Sub en VBA?
Private Sub hace que el procedimiento solo sea invocable desde el mismo módulo y lo oculta del cuadro Macros. Úsalo para ayudantes que no deben ejecutarse directamente por el usuario. Los procedimientos de evento como Worksheet_Change son Private Sub por esa razón.
