TL;DR —
With object … End Withte deja nombrar un objeto una vez y luego alcanzar sus miembros con un punto inicial a secas:.Value,.Font.Bold,.Interior.Color. Es menos tecleo, se lee más limpio y es de verdad más rápido, porque VBA resuelve la referencia al objeto una sola vez en lugar de en cada línea. Todo el truco vive en ese punto inicial:.Fontse enlaza con tu objetoWith; elFonta secas no — recurre a un objeto implícito (normalmente la hoja activa) y cambia en silencio lo que no debe.
With Sheets("Report").Range("A1")
.Value = "Total" ' cada punto significa: Sheets("Report").Range("A1") . ...
.Font.Bold = True
.Font.Size = 14
.Interior.Color = vbYellow
End With
Las rutas de objeto profundas están por todas partes en Excel VBA:
ThisWorkbook.Worksheets("Data").Range("A1").Font.…. Teclear ese prefijo en diez
líneas seguidas es tedioso, lento de ejecutar y difícil de leer — y si algún día
necesitas reapuntarlo a otra celda, estás editando diez sitios. With arregla las
tres cosas a la vez: enuncia el objeto en la primera línea y luego deja que cada
línea de dentro del bloque cuelgue de él con un punto. Es uno de los constructos más
simples del lenguaje y uno de los más fáciles de escribir mal por un detalle.
Lo que aprenderás
- El modelo mental —
Withsaca factor común de un prefijo repetido, como2(a+b)en álgebra - Por qué no es solo más ordenado:
Withresuelve la referencia al objeto una sola vez - La trampa del punto que falta —
Fontfrente a.Font— y por qué falla en silencio - Cómo resuelven el punto los bloques
Withanidados, y por qué deberías parar en dos - El patrón
With+For Eachque ata todo este grupo
El modelo mental: saca factor común del prefijo repetido
Piensa en With como en sacar factor común, igual que reescribes 2*a + 2*b + 2*c
como 2*(a + b + c). Lo que se repite —aquí la ruta de objeto
Sheets("Report").Range("A1")— se enuncia una vez, y se entiende que todo lo de
dentro del paréntesis está multiplicado por ello. En VBA, el «paréntesis» es
With … End With, y el «multiplicar por ello» es el punto inicial.
' Sin With — el prefijo se repite en cada línea
Sheets("Report").Range("A1").Value = "Total"
Sheets("Report").Range("A1").Font.Bold = True
Sheets("Report").Range("A1").Font.Size = 14
' Con With — enúncialo una vez y entra con el punto
With Sheets("Report").Range("A1")
.Value = "Total"
.Font.Bold = True
.Font.Size = 14
End With
Ambos hacen exactamente lo mismo. El segundo es más corto, se reapunta con una sola
edición y —como muestra la siguiente sección— de hecho se ejecuta más rápido. Todo
lo de dentro del bloque lleva de forma implícita como prefijo el objeto de la línea
With.
La regla que lo hace algo más que cosmético: el objeto se resuelve una vez
With no va solo de teclear menos. Cuando VBA ve
Sheets("Report").Range("A1").Font en diez líneas distintas, vuelve a recorrer esa
cadena entera diez veces — busca la hoja, resuelve el rango, obtiene la fuente — en
cada línea. Dentro de un bloque With, VBA resuelve el objeto una vez, al
entrar, y reutiliza esa referencia ya resuelta para cada miembro con punto.
En un par de líneas la diferencia es invisible. Dentro de un bucle sobre miles de celdas, es real:
Dim cell As Range
For Each cell In Range("A1:A10000")
With cell
.Value = .Value * 1.1 ' resuelve 'cell' una vez por iteración...
.NumberFormat = "0.00" ' ...no tres veces
.Font.Color = vbBlue
End With
Next cell
Sin el With, cada cell. vuelve a desreferenciar el objeto de rango en cada
línea; con él, esa desreferencia ocurre una vez por iteración. La regla: cuando
tocas tres o más miembros del mismo objeto —sobre todo dentro de un bucle—
envuélvelos en With. Es esa rara mejora de legibilidad que además te regala
velocidad.
La trampa que cambia el objeto equivocado: el punto inicial que falta
Este es el error que hace que With sea peligroso en vez de solo útil. El punto
inicial es lo que enlaza un miembro con el objeto With. Déjalo fuera y el miembro
no da error — se enlaza con otra cosa:
With Sheets("Report").Range("A1")
.Value = "Total"
Font.Bold = True ' ERROR: sin punto inicial — esta NO es la fuente del objeto With
End With
.Font.Bold significa Sheets("Report").Range("A1").Font.Bold. Pero Font.Bold
—sin punto— es una referencia sin cualificar. VBA la resuelve contra el contexto
implícito de la hoja activa, así que o bien obtienes un error de compilación o,
peor, das formato en silencio a una celda de la hoja que resulte estar activa. Nada
te avisa; el objeto With simplemente queda intacto mientras cambia algún otro
objeto.
La regla es mecánica y merece grabarse a fuego: dentro de un bloque With, todo
miembro que pertenezca al objeto debe empezar por un punto. Cuando revises un
bloque With, repasa el margen izquierdo — cualquier cosa que no empiece por . es
o bien una referencia deliberada a un objeto distinto o un error. (Es la misma
familia del fallo del «ActiveSheet implícito» que se trata en
VBA ActiveSheet — un Range o Cells sin cualificar se
adhiere sin ruido a la hoja que esté activa.)
La regla del anidamiento: el punto se enlaza con el With más cercano
Puedes anidar bloques With, y es de verdad útil para profundizar en un
subobjeto. Pero la regla de resolución pilla a la gente: un punto inicial siempre se
enlaza con el With más interno.
With Sheets("Report")
.Range("A1").Value = "Report" ' un punto -> la hoja
With .Range("A2").Font ' abre un With interno sobre la fuente
.Bold = True ' .Bold -> la FUENTE (la más interna), no la hoja
.Size = 12
End With
.Range("A3").Value = "Done" ' de vuelta a la hoja tras End With
End With
Dentro del bloque interno, .Bold es el de la fuente, no el de la hoja. Eso es
correcto y legible a dos niveles — pero a tres o cuatro se vuelve un juego de
adivinar qué objeto significa cada punto. La regla: anida como mucho dos bloques
With. Más profundo que eso, asigna una variable de objeto intermedia (Set fnt = .Range("A2").Font) y dale al lector un nombre en vez de una pila de puntos.
El patrón que ata el grupo: With + For Each
With y For Each son compañeros naturales. For Each te
entrega un objeto cada vez; With te deja trabajar ese objeto con limpieza sin
repetir la variable de bucle:
Dim cell As Range
For Each cell In Sheets("Data").Range("B2:B100")
With cell
If .Value < 0 Then
.Interior.Color = vbRed
.Font.Bold = True
End If
End With
Next cell
Léelo en voz alta y es casi lenguaje natural: «por cada celda, con esa celda — si
es negativa, coloréala de rojo y ponla en negrita». Esa pareja —For Each para
recorrer la colección, With para actuar sobre cada miembro— es la columna
vertebral de las macros de formato y marcado de datos sobre un
Range.
Cómo ayuda ExcelMaster
With es una cosa pequeña hecha mil veces: saca factor común del prefijo, acuérdate
del punto, no anides demasiado. Es justo la clase de cuidado mecánico que separa las
macros legibles de las frágiles — y justo la clase de cosa en la que preferirías no
pensar cuando solo quieres una hoja con formato.
ExcelMaster te deja
describir el resultado en su lugar. Di «en la hoja Datos, colorea de rojo cada valor
negativo de la columna B y ponlo en negrita», y escribe y ejecuta la lógica —
cualificando bien cada referencia a objeto, para que el error silencioso de la
«hoja equivocada» que provoca el punto que falta simplemente no pueda ocurrir.
Cuando escribas a mano una macro programada seguirás recurriendo a With tú mismo;
para la tarea cotidiana de dar formato y marcar, describir lo que quieres gana a
acertar a mano cada punto inicial.
Preguntas frecuentes
¿Qué hace la instrucción With en VBA?
With object … End With nombra un objeto una vez para que puedas acceder a sus
miembros con un punto inicial a secas (.Value, .Font.Bold) en lugar de repetir
la ruta completa del objeto en cada línea. Hace el código más corto, más fácil de
reapuntar y más rápido — porque VBA resuelve la referencia al objeto una sola vez al
entrar, no en cada línea.
¿Por qué mi bloque With no cambia el objeto correcto?
Casi siempre es un punto inicial que falta. Dentro de With obj, .Font se refiere
a obj, pero Font sin punto es una referencia sin cualificar que se enlaza con el
contexto implícito de la hoja activa — así que cambias en silencio el objeto
equivocado. Todo miembro que pertenezca al objeto With debe empezar por un punto.
¿La instrucción With hace de verdad que VBA sea más rápido?
Sí, de forma modesta, y importa dentro de los bucles. VBA resuelve el objeto de la
línea With una vez y reutiliza esa referencia para cada miembro con punto, en
lugar de volver a recorrer la cadena completa del objeto en cada línea. En dos o
tres líneas no lo notarás; a lo largo de miles de iteraciones, las desreferencias
ahorradas suman.
¿Puedo anidar instrucciones With en VBA?
Sí. Un punto inicial siempre se enlaza con el With activo más interno, así que
With .Range("A2").Font dentro de With Sheets("Report") hace que .Bold sea el
de la fuente. Es legible a dos niveles, pero anidar más hondo dificulta saber a qué
objeto se refiere cada punto — asigna una variable de objeto intermedia en vez de
anidar tres o más niveles.
¿Puedo cambiar el propio objeto With dentro del bloque?
No — la referencia With queda fija al entrar en el bloque. No puedes reasignar a
qué apunta With a mitad de camino; para trabajar sobre otro objeto, cierra el
bloque con End With y abre uno nuevo. Sí puedes leer y modificar los miembros
del objeto con libertad, solo que no reapuntar el bloque.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 01/08/2026.
Guías relacionadas: VBA For Each · VBA Collection · VBA Range · VBA ActiveSheet · VBA For Loop
