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

VBA Mid, Left y Right en Excel — Extraer una subcadena por posición

|

VBA Mid, Left y Right en Excel — Extraer una subcadena por posición

Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · verificado por última vez el 09-06-2026

En resumenMid, Left y Right sacan un trozo de una cadena por posición — un punto de inicio y una longitud. Left y Right no son más que Mid fijado a un extremo:

Sub SliceDemo()
    Dim s As String
    s = "INV-2026-0042"

    Debug.Print Left(s, 3)      ' INV       <- los 3 primeros caracteres
    Debug.Print Right(s, 4)     ' 0042      <- los 4 últimos caracteres
    Debug.Print Mid(s, 5, 4)    ' 2026      <- 4 caracteres desde la posición 5
    Debug.Print Mid(s, 5)       ' 2026-0042 <- sin longitud = hasta el final
End Sub

Una cosa que memorizar antes que nada: las cadenas de VBA empiezan en la posición 1, no en 0.

El modelo mental: cortar con una regla, no por contenido

Mid es una regla. Le dices dónde empezar y cuántos caracteres tomar, y corta. No mira qué son los caracteres — cuenta posiciones. Left(s, n) es "la regla desde el principio", Right(s, n) es "la regla desde el final", y Mid(s, start, len) es el caso general del que ambas son atajos.

Esa única idea te dice exactamente cuándo son la herramienta correcta y cuándo no. Brillan cuando lo que buscas está en una posición fija y conocida — un prefijo de 3 letras, los 4 últimos dígitos, una columna de ancho fijo. Se desmoronan en cuanto el trozo puede moverse, porque una regla no se adapta. Esa es toda la tensión de este artículo, y la razón de que existan InStr y Split.

La regla de oro: empieza en 1, y ese error de índice es el bug nº 1

Viniendo de casi cualquier otro lenguaje, los dedos teclean posiciones que empiezan en 0. VBA no funciona así:

En Mid(string, start, length), start = 1 significa el primer carácter. Mid("Excel", 1, 2) es "Ex", no "xc".

Equivócate y no obtienes un error — obtienes los caracteres equivocados, desplazados en uno, lo cual es mucho peor que un fallo porque parece plausible:

Debug.Print Mid("Excel", 1, 2)   ' "Ex"  (correcto — 1 es el primer carácter)
Debug.Print Mid("Excel", 0, 2)   ' error de ejecución 5 — no hay posición 0
Debug.Print Mid("Excel", 2, 2)   ' "xc"  (empieza en el 2.º carácter)

La regla compañera: Mid sin longitud devuelve todo desde start hasta el final. No es un bug que sortear — es la forma más limpia de decir "el resto de la cadena desde aquí":

extension = Mid(filename, InStrRev(filename, ".") + 1)   ' todo lo posterior al último punto

Lo que casi nadie sabe: Mid también es una instrucción

Hay dos Mid. La función lee caracteres. La instrucción escribe caracteres en el sitio — sobrescribe parte de la cadena sin cambiar su longitud:

Dim s As String
s = "2026-00-15"
Mid(s, 6, 2) = "06"      ' sobrescribir 2 caracteres desde la posición 6
Debug.Print s            ' "2026-06-15"  <- misma longitud, parcheado en el sitio

Mid(s, 6, 2) = "06" a la izquierda de un = es la instrucción. Es más rápida que reconstruir la cadena con Left & nuevo & Right, y es la forma idiomática de parchear un campo de ancho fijo. La pega que encaja con el modelo mental: nunca cambia la longitud — si asignas un reemplazo más largo, VBA simplemente lo trunca para que quepa en la ventana. La regla no se estira.

La familia Left/Right/Mid en un bloque

Left(s, n)          ' los n primeros caracteres
Right(s, n)         ' los n últimos caracteres
Mid(s, start)       ' desde start hasta el final
Mid(s, start, len)  ' len caracteres desde start
Len(s)              ' cuántos caracteres en total (para acotar los cortes)

Left y Right no son ideas aparte — son Mid con una coordenada fija. Left(s, n) es Mid(s, 1, n). Right(s, n) es Mid(s, Len(s) - n + 1). En cuanto Mid encaja, las otras dos vienen de regalo.

La opinión: las posiciones fijas son la línea más frágil de tu macro

Mid(s, 5, 4) se lee precioso en la única fila que probaste. Luego llega un valor un carácter más corto, cada posición se desplaza, y tu extracción del "año" ahora devuelve "026-". Los cortes por posición codifican una suposición — los datos siempre tienen la forma exacta de mi muestra — que los datos reales rompen a la primera ocasión.

Mi regla: usa Left/Right/Mid solo cuando la posición sea genuinamente fija — un formato que controlas, una exportación de ancho fijo, un código con una disposición garantizada. En cuanto la frontera depende del contenido (el texto antes del primer espacio, la parte tras el guion, el trozo entre dos marcas), deja de fijar números. Encuentra la frontera con InStr y pásala a Mid, o usa Split si hay un delimitador limpio:

' Frágil: supone que el guion está siempre en la posición 4
code = Left(s, 3)

' Robusto: encuentra el guion, corta ahí — funciona sea cual sea la longitud
code = Left(s, InStr(s, "-") - 1)

La segunda versión es una función más larga y sobrevive al contacto con la realidad. Ese trato casi siempre vale la pena.

Cuándo usar cuál

Quieres… Usa Cuidado con
Los N primeros caracteres Left(s, n) N mayor que Len(s) solo devuelve toda la cadena (seguro)
Los N últimos caracteres Right(s, n) Igual — no da error si N es demasiado grande
N caracteres desde una posición fija Mid(s, start, n) start empieza en 1; start = 0 da error
Todo desde una posición en adelante Mid(s, start) Omite por completo el argumento de longitud
Sobrescribir caracteres en el sitio Mid(s, start, n) = "…" Nunca cambia la longitud — lo que sobra se descarta
Un trozo cuya posición puede moverse InStr + Mid, o Split No fijes el número

Errores comunes con Mid/Left/Right (y su solución)

Síntoma Causa Solución
Resultado desplazado un carácter Trataste start como base 0 start = 1 es el primer carácter
"Llamada a procedimiento o argumento no válido" (error 5) Mid(s, 0, …) o longitud negativa start ≥ 1, longitud ≥ 0
La extracción se rompe en valores más cortos Posición fija Mid(s, 5, 4) Localiza la frontera con InStr primero
La instrucción Mid no alargó la cadena Es a propósito — sobrescribe en el sitio Reconstruye con Left & nuevo & Right para cambiar la longitud
Left(s, 50) devolvió toda la cadena N excedió la longitud Comportamiento esperado; acota con Len(s) si hace falta

Cuando la lógica de troceo se adueña del trabajo — describe el resultado

Sacar el número de factura de una celda son dos líneas. Sacarlo de 40.000 filas que llegan en tres formatos ligeramente distintos — unas con guion, otras sin él, otras con un prefijo de más — es una maraña de InStr, Mid, comprobaciones de longitud y planes B que entierra la intención real. ExcelMaster Agent te deja decir "extrae el año de 4 dígitos del código de factura, sea cual sea el formato que lo rodea" y genera Python que maneja las variantes y respalda tu libro primero — sin error de índice, sin posiciones fijas. Pruébalo gratis →

Guías relacionadas

Preguntas frecuentes

¿Cuál es la diferencia entre Mid, Left y Right en VBA? Las tres extraen una subcadena por posición. Left(s, n) toma los n primeros caracteres, Right(s, n) los n últimos, y Mid(s, start, len) toma len caracteres a partir de start. Left y Right son casos especiales de Mid fijados a un extremo de la cadena.

¿VBA Mid empieza en 0 o en 1? En 1. Mid("Excel", 1, 2) devuelve "Ex" — la posición 1 es el primer carácter. Usar 0 como inicio lanza el error de ejecución 5. Este desfase de índice es el bug de Mid más común para quien viene de lenguajes con base 0.

¿Cómo obtengo todo a partir de una posición con Mid? Omite el argumento de longitud: Mid(s, start) devuelve la subcadena desde start hasta el final. Combinado con InStr, Mid(s, InStr(s, "-") + 1) te da todo lo posterior al primer guion.

¿Qué es la instrucción Mid en VBA? Mid(s, start, length) = "texto" a la izquierda de una asignación sobrescribe caracteres en el sitio, sin cambiar la longitud de la cadena. Es más rápida que reconstruirla e ideal para parchear campos de ancho fijo — pero un reemplazo más largo que la ventana se trunca.

¿Por qué mi extracción con Mid falla en algunas filas? Casi siempre por una posición fija que supone que todos los valores tienen la misma longitud. Cuando la frontera depende del contenido y no de un desplazamiento fijo, localízala con InStr y pásala a Mid, o usa Split si hay un delimitador.