TL;DR — No hay una palabra clave
Regexen VBA. Creas el objeto VBScript RegExp, ya sea con enlace tardío medianteCreateObject("VBScript.RegExp")o con enlace temprano vía una referencia. No hace nada hasta que fijas sus propiedades:.Pattern, y las dos que vienen con el valor poco útil por defecto —.Global = False(solo la primera coincidencia) y.IgnoreCase = False(distingue mayúsculas). Luego elige el verbo correcto:.Testdevuelve un Boolean,.Replacedevuelve una cadena (las retrorreferencias son$1, no\1), y.Executedevuelve una colección de coincidencias cuyos grupos capturados viven en.SubMatches— no en.Value.
Sub RegexBasics()
Dim re As Object
Set re = CreateObject("VBScript.RegExp") ' enlace tardio - no necesita referencia
re.Pattern = "PO-(\d+)" ' un grupo captura los digitos
re.Global = True ' encuentra TODAS las coincidencias, no solo la primera
re.IgnoreCase = True ' sin distinguir mayusculas
Dim m As Object
For Each m In re.Execute("po-17 and PO-9004")
Debug.Print m.Value ' PO-17 luego PO-9004 (la coincidencia completa)
Debug.Print m.SubMatches(0) ' 17 luego 9004 (el grupo capturado)
Next m
End Sub
Lo que aprenderás
- El modelo mental — regex es un objeto que creas, no una palabra clave
- Enlace tardío frente a añadir la referencia, y el error de compilación que sigue
- Por qué
Global = Falsesignifica que solo obtienes la primera coincidencia - Qué devuelve cada uno de
Test,ReplaceyExecute - Por qué extraer un valor significa ir más allá de
Match.ValuehastaSubMatches - Qué admite el sabor de patrones de VBScript, y qué no
El modelo mental: regex es un objeto que creas, no una palabra clave
Viniendo de casi cualquier otro lenguaje, esperas un operador o una función regex. VBA no tiene ninguno.
Lo que tiene es un componente COM — la biblioteca VBScript Regular Expressions — que instancias,
conectas con propiedades y luego llamas. Así que el modelo mental no es «llamar a una función» sino
«configurar un objeto y luego hacerle una pregunta». Cada frustración de abajo es en realidad «se me
olvidó fijar una propiedad antes de preguntar».
Eso también te dice cuándo vale la pena usarlo. RegExp es el peso pesado en lo alto de la escalera, por
encima del operador Like y del simple
InStr. Pagas un coste de preparación — crearlo, fijar
el patrón, accionar los interruptores — y a cambio obtienes recuentos de repetición, alternancia y lo único
que los otros no pueden hacer: sacar las piezas capturadas de la coincidencia.
Cómo prepararlo: enlace tardío frente a una referencia
Dos formas de obtener el objeto, y la elección tiene consecuencias reales:
' Enlace tardio - portatil, no necesita referencia, se resuelve en tiempo de ejecucion
Dim re As Object
Set re = CreateObject("VBScript.RegExp")
' Enlace temprano - anade primero la referencia, luego esto compila
' Tools -> References -> "Microsoft VBScript Regular Expressions 5.5"
Dim re As New RegExp
El enlace temprano te da IntelliSense y llamadas ligeramente más rápidas, pero solo compila si la
referencia está marcada — y si envías el libro a alguien a quien le falta la referencia, obtiene un error
de compilación User-defined type not defined en la línea As New RegExp antes de que se ejecute una
sola instrucción. El enlace tardío (As Object + CreateObject) no tiene nada de esa fragilidad: se
resuelve en tiempo de ejecución y viaja sin una referencia. Para cualquier cosa que distribuyas, prefiere
el enlace tardío — la portabilidad vale más que perder IntelliSense.
Trampa 1: Global está apagado, así que solo obtienes la primera coincidencia
.Global vale False por defecto, y ese único valor por defecto causa los dos informes de «regex está
roto» más comunes:
re.Pattern = "\d+"
re.Global = False ' el valor por defecto
Debug.Print re.Replace("a1 b2 c3", "#") ' "a# b2 c3" <- solo se reemplaza la PRIMERA serie
Debug.Print re.Execute("a1 b2 c3").Count ' 1 <- solo se encuentra la PRIMERA coincidencia
re.Global = True
Debug.Print re.Replace("a1 b2 c3", "#") ' "a# b# c#" <- ahora todas
Debug.Print re.Execute("a1 b2 c3").Count ' 3
Si un reemplazo solo tocó la primera aparición, o una búsqueda encontró una coincidencia cuando puedes ver
tres, esta es casi siempre la causa. Fija .Global = True siempre que quieras decir «en todas partes». Su
vecina .IgnoreCase vale False por defecto de la misma manera, así que un patrón que claramente debería
coincidir con texto de distinto caso y no lo hace suele ser uno al que le falta re.IgnoreCase = True.
Trampa 2: Test, Replace y Execute devuelven tres cosas distintas
El objeto expone tres verbos, y confundir sus tipos de retorno es el segundo gran tropiezo:
re.Test(s)devuelve un Boolean — ¿coincide el patrón en algún lugar? Úsalo como validador, el primo con potencia de regex deLike.re.Replace(s, replacement)devuelve una String — la entrada con cada coincidencia (siGlobal) reemplazada. Las retrorreferencias en el reemplazo usan un signo de dólar:$1es el primer grupo capturado. Escribir\1inserta una barra invertida y un uno literales, un fallo frecuente para quien llega de otros lenguajes.re.Execute(s)devuelve una MatchCollection — una colección de objetosMatchque recorres para inspeccionar o extraer.
re.Pattern = "(\d{4})-(\d{2})"
Debug.Print re.Test("2026-09") ' True
Debug.Print re.Replace("2026-09", "$2/$1") ' "09/2026" - $1, $2 son los grupos
Elige el verbo por la respuesta que necesitas: un sí o no es Test, una cadena transformada es Replace,
y cualquier cosa donde quieres el texto coincidente o sus piezas es Execute.
Trampa 3: para extraer, ve más allá de Value hasta SubMatches
Esta es la que hace a la gente dar vueltas. Cada Match de .Execute tiene un .Value — el texto
coincidente completo — y una colección .SubMatches que contiene los grupos capturados, las partes
que envolviste en paréntesis:
re.Pattern = "Invoice #(\d+) dated (\d{4}-\d{2}-\d{2})"
re.Global = True
Dim m As Object
For Each m In re.Execute("Invoice #4471 dated 2026-09-04")
Debug.Print m.Value ' Invoice #4471 dated 2026-09-04 (la coincidencia completa)
Debug.Print m.SubMatches(0) ' 4471 (primer grupo)
Debug.Print m.SubMatches(1) ' 2026-09-04 (segundo grupo)
Debug.Print m.FirstIndex ' 0 (posicion de inicio base cero en la entrada)
Next m
Si quieres el número, quieres m.SubMatches(0), no m.Value — leer .Value y preguntarte por qué sigue
conteniendo el texto que lo rodea es el fallo de extracción número uno. SubMatches es de base cero, y un
grupo que no participó en la coincidencia vuelve como una cadena vacía, así que protégete con re.Test(s)
(o el .Count de la colección) antes de indexar en él.
El sabor VBScript: qué admite y qué no el lenguaje de patrones
El regex de VBA es el sabor VBScript (RegExp 5.5), no PCRE, y las carencias hacen tropezar a cualquiera
con experiencia de regex en otro sitio. Admite el kit de todos los días: \d \w \s y sus negaciones, los
cuantificadores * + ? {n} {n,m}, la alternancia a|b, los grupos ( ), las clases de caracteres [ ]
y los anclajes ^ $ (con .MultiLine decidiendo si esos significan línea o cadena entera). No admite
lookbehind, grupos de captura con nombre ni grupos atómicos o posesivos — los patrones que se apoyan en
esos simplemente no compilarán como esperas.
Un alivio específico de VBA: como la barra invertida no es un carácter de escape dentro de los
literales de cadena de VBA, escribes los patrones directamente — "\d{4}", no "\\d{4}". Nada de doble
escape, a diferencia de C#, Java o JSON. El único doblado que necesitas es para una comilla literal, que es
el propio "" de VBA.
La opinión: regex vale la ceremonia solo para estructura de verdad
RegExp es la herramienta de texto más potente de VBA y la que más a menudo se usa demasiado pronto. Crear
el objeto, fijar el patrón y acordarse de Global e IgnoreCase es ceremonia de verdad, y para una forma
fija o un simple sí o no es ceremonia que no necesitas — Like es una línea legible e
InStr es más rápido para «contiene este literal».
La línea que hay que trazar es estructura que debes desmontar. Cuando el patrón tiene repetición variable,
alternancia de verdad o — la decisiva — un grupo que necesitas extraer, regex es la única herramienta
de la caja que lo hace, y se gana su sueldo: un número de pedido sacado de una línea de asunto, las partes
de una marca de tiempo desordenada, cada correo en un bloque de texto. Úsalo ahí, prefiere el enlace tardío
para que viaje, fija Global e IgnoreCase a propósito, y lee SubMatches para las piezas. En cualquier
punto por debajo de eso, baja de nuevo por la escalera.
Cuando el análisis es el objetivo — describe el trabajo en su lugar
Incluso cuando regex es la herramienta correcta, el patrón rara vez es el objetivo — «saca cada número de
factura y su fecha de esta columna y divídelos en dos campos» lo es. Y un patrón VBScript con grupos de
captura, más el bucle sobre Execute, más la contabilidad de SubMatches, más los casos borde donde una
fila no coincide en absoluto, es mucha maquinaria frágil alrededor de una sola intención.
ExcelMaster te deja describir el
resultado en español llano — «extrae el número de factura y la fecha de la columna B a las columnas C y D,
marca las filas sin coincidencia» — y genera Python que hace la extracción con un motor de regex de verdad,
respalda tu archivo primero e informa de las filas que no pudo analizar. Tú describes qué sacar; él se
encarga del patrón, los grupos y los fallos.
Preguntas frecuentes
¿Cómo uso regex en VBA?
Crea el objeto VBScript RegExp, fija sus propiedades y luego llama a un método. La forma portable es el
enlace tardío: Set re = CreateObject("VBScript.RegExp"), luego re.Pattern = "\d+", re.Global = True,
re.IgnoreCase = True, y por último re.Test(s), re.Replace(s, repl) o re.Execute(s) según quieras un
Boolean, una cadena nueva o las coincidencias.
¿Por qué mi regex de VBA solo reemplaza la primera coincidencia?
Porque .Global vale False por defecto. Con Global apagado, tanto .Replace como .Execute se
detienen tras la primera coincidencia. Fija re.Global = True antes de llamarlos para actuar sobre cada
coincidencia de la cadena.
¿Cómo extraigo un grupo capturado en regex de VBA?
Recorre re.Execute(s) y lee Match.SubMatches. SubMatches(0) es el primer grupo entre paréntesis,
SubMatches(1) el segundo, y así (de base cero). Match.Value es el texto coincidente completo, no el
grupo — leer .Value cuando querías un grupo es el error de extracción más común.
¿Necesito añadir una referencia para usar regex en VBA?
Solo para el enlace temprano. Dim re As New RegExp requiere la referencia «Microsoft VBScript Regular
Expressions 5.5» en Tools -> References, y no compila, con User-defined type not defined, si falta. El
enlace tardío — Dim re As Object con CreateObject("VBScript.RegExp") — no necesita ninguna referencia y
es la mejor opción para los libros que compartes.
¿Qué sabor de regex usa VBA, y admite lookbehind?
VBA usa el sabor VBScript (RegExp 5.5). Admite \d \w \s, cuantificadores, alternancia, grupos, clases de
caracteres y anclajes ^ $, y retrorreferencias de reemplazo con $1. No admite lookbehind ni grupos de
captura con nombre. Además, como la barra invertida no es especial dentro de los literales de cadena de
VBA, escribes "\d{4}" directamente sin doble escape.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 04/09/2026.
Guías relacionadas: VBA Like · VBA IsNumeric · VBA InStr · VBA Replace · VBA Split
