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

VBA With en Excel — nombra el objeto una sola vez (y el punto inicial del que todo depende)

|

VBA With en Excel — nombra el objeto una sola vez (y el punto inicial del que todo depende)

TL;DRWith object … End With te 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: .Font se enlaza con tu objeto With; el Font a 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 — With saca factor común de un prefijo repetido, como 2(a+b) en álgebra
  • Por qué no es solo más ordenado: With resuelve la referencia al objeto una sola vez
  • La trampa del punto que falta — Font frente a .Font — y por qué falla en silencio
  • Cómo resuelven el punto los bloques With anidados, y por qué deberías parar en dos
  • El patrón With + For Each que 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. 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