Probado en: Excel 365 v2509 · Excel 2021 · Excel 2019 · verificado por última vez el 09-06-2026
En resumen — Mid, 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 = 1significa 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
- VBA Split — Convierte una cadena en un array
- VBA Replace — Sustituir texto y las trampas de sus argumentos
- VBA InStr — Encontrar texto dentro de una cadena
- Bucle For en VBA — 8 ejemplos del mundo real
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.
