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

VBA Add Sheet en Excel — crea una hoja y captúrala como es debido

|

VBA Add Sheet en Excel — crea una hoja y captúrala como es debido

TL;DRWorksheets.Add devuelve la hoja que acaba de crear. Captura ese valor de retorno —Set ws = Worksheets.Add(...)— y nunca tendrás que adivinar cuál es la hoja nueva. Las dos cosas que hacen tropezar a todo el mundo son la posición y el nombre: un Worksheets.Add a secas coloca la hoja a la izquierda de la hoja activa (no al final), y no puedes pasar el nombre en la llamada a Add: fijas .Name después, donde un nombre duplicado, en blanco o demasiado largo lanza el error en tiempo de ejecución 1004.

Sub AddMonthSheet()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets.Add(After:=Worksheets(Worksheets.Count))
    ws.Name = "Sep 2026"          ' <= 31 caracteres, unico, sin : \ / ? * [ ]
End Sub

Worksheets.Add es el código que hay detrás de Inicio ▸ Insertar ▸ Insertar hoja y del pequeño + que hay junto a las pestañas. Es una de las primeras cosas que hace una macro de informes, y falla siempre en los mismos dos sitios: la hoja aparece donde no esperabas, o la línea que la renombra revienta. Ambos problemas desaparecen en cuanto tratas Add como una fábrica que te entrega la hoja terminada, en lugar de como un comando que te deja a ti la tarea de ir a buscarla.

Lo que aprenderás

  • El modelo mental — Add devuelve la hoja nueva, así que captúrala y deja de usar ActiveSheet
  • La única regla que evita casi todos los fallos — asigna el valor de retorno a una variable Worksheet
  • Por qué un Add a secas coloca la hoja a la izquierda, y cómo lo arreglan Before y After
  • Por qué no puedes nombrar la hoja dentro de Add, y las reglas que hacen que .Name lance 1004
  • Cómo añadir una hoja solo si no existe ya

El modelo mental: Add te entrega la hoja

Worksheets.Add no es un comando de disparar y olvidar. Es una función que crea una hoja y devuelve una referencia a ella. El error más común con diferencia es tirar esa referencia a la basura:

Worksheets.Add                    ' la hoja nueva se crea... y luego se pierde
Worksheets(Worksheets.Count).Name = "Data"   ' adivinando donde acabo

La segunda línea es una conjetura. Da por hecho que la hoja nueva es la última, cosa que por defecto no es cierta, así que renombra la pestaña equivocada. Todo lo que viene después —escribir encabezados, dar formato, añadir fórmulas— apunta entonces a una hoja elegida por azar. Captura el valor de retorno en su lugar y las conjeturas desaparecen para siempre:

Dim ws As Worksheet
Set ws = Worksheets.Add
ws.Name = "Data"                  ' esta es sin ambiguedad la hoja que acabas de crear

Una vez que ws contiene el objeto de verdad, la posición deja de importar para la corrección: puedes poner la hoja donde te apetezca y tu código sigue hablando con la correcta.

La regla que más importa: asigna el valor de retorno

Toda rutina fiable que añade una hoja empieza igual: Set ws = Worksheets.Add(...). Esta es la regla que elimina una categoría entera de fallos, porque las dos alternativas frágiles se rompen en condiciones de lo más normales:

  • ActiveSheet después de Add normalmente apunta a la hoja nueva, pero no si un evento, un Calculate u otra línea movieron el foco antes. Es una convención, no una garantía.
  • Sheets(Sheets.Count) da por hecho que la hoja nueva es la última, lo cual solo es cierto si la añadiste ahí.

El valor de retorno es la única referencia que siempre es correcta, de inmediato, sin importar dónde acabó la hoja ni qué se ejecute a continuación. Trata «añadir una hoja» y «quedarte con la hoja» como un único paso indivisible.

La posición: Before, After y por qué el valor por defecto cae a la izquierda

Worksheets.Add acepta los argumentos Before:= y After:= —una hoja delante de la cual insertar, o detrás—. Pasa como mucho uno. Sin ninguno, Excel inserta la hoja nueva justo antes de la hoja activa, cosa que sorprende a casi todo el mundo la primera vez: la gente espera «el final» y en cambio la pestaña aparece en mitad del libro.

Para añadir al final —la posición que de verdad quieren la mayoría de las macros—, ancla a la última hoja con After:

Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count))   ' siempre la ultima
Set ws = Worksheets.Add(Before:=Worksheets(1))                 ' siempre la primera

Worksheets(Worksheets.Count) es el modismo para «la última hoja de cálculo». Fíjate en que cuenta hojas de cálculo, no todas las hojas: si el libro también tiene hojas de gráfico, Sheets.Count y Worksheets.Count no coinciden. En la duda, posiciona de forma explícita; nunca te fíes del valor por defecto de izquierda-de-la-activa en código que van a leer otras personas.

El nombre es donde Add revienta

No hay ningún argumento Name en Add. Creas la hoja y luego fijas .Name sobre el objeto que capturaste. Ese segundo paso es donde vive el error en tiempo de ejecución 1004, porque Excel impone reglas estrictas a los nombres de hoja, y son las mismas reglas tanto si estás nombrando una hoja recién creada como si estás renombrando una vieja:

  • 31 caracteres como máximo
  • Debe ser único dentro del libro (sin distinguir mayúsculas) — un duplicado es el fallo número uno
  • No puede estar en blanco
  • No puede contener : \ / ? * [ ]

Incumple cualquiera de ellas y .Name = ... lanza 1004. El detonante más común es volver a ejecutar una macro que ya creó "Data" una vez: la segunda ejecución choca. Como las reglas son idénticas para crear y para renombrar, vale la pena blindar el nombre en un único sitio:

Function SafeName(nm As String) As String
    nm = Left$(nm, 31)
    Dim bad As Variant, ch As Variant
    For Each ch In Array(":", "\", "/", "?", "*", "[", "]")
        nm = Replace(nm, ch, "-")
    Next ch
    SafeName = nm
End Function

Eso resuelve la longitud y los caracteres ilegales; la unicidad la resuelves comprobando antes, que es la siguiente sección.

Añade solo si no existe ya

No hay un Exists integrado para las hojas, así que la colisión al reejecutar es cosa tuya evitarla. Comprueba la colección por nombre antes de añadir, y reutiliza la hoja si ya está ahí:

Function GetOrAddSheet(nm As String) As Worksheet
    Dim ws As Worksheet
    For Each ws In ThisWorkbook.Worksheets
        If StrComp(ws.Name, nm, vbTextCompare) = 0 Then
            Set GetOrAddSheet = ws          ' reutiliza la que ya existe
            Exit Function
        End If
    Next ws
    Set GetOrAddSheet = ThisWorkbook.Worksheets.Add(After:=Worksheets(Worksheets.Count))
    GetOrAddSheet.Name = nm                 ' libre para nombrar - sabemos que no esta en uso
End Function

Este es el patrón que hace idempotente una macro que añade hojas —segura de ejecutar dos veces— en lugar de una que funciona la primera vez y lanza 1004 para siempre a partir de ahí. El criterio: nunca llames a Add y a .Name a ciegas en una rutina que podría ejecutarse más de una vez; busca primero el nombre, y o reutiliza o crea.

Cómo te ayuda ExcelMaster

Añadir una hoja parece una sola línea y esconde tres decisiones —capturar el valor de retorno, elegir una posición y producir un nombre legal y único—, y equivocarse en cualquiera de ellas falla en silencio (renombra la pestaña equivocada) o a gritos (error 1004 en la segunda ejecución).

ExcelMaster te deja decir lo que quieres —«añade una hoja mensual al final con el nombre del mes actual, y reutilízala si ya existe»— y escribe la captura Set ws = Worksheets.Add(After:=...), añade en el sitio correcto, sanea el nombre según las reglas de 31 caracteres y de caracteres ilegales, y comprueba primero la colección para que una segunda ejecución reutilice la hoja en vez de reventar. Tú conservas el libro y el código.

Preguntas frecuentes

¿Cómo añado una hoja y le pongo nombre en VBA?

Captura el valor de retorno y fija .Name sobre él: Set ws = Worksheets.Add(After:=Worksheets(Worksheets.Count)) y luego ws.Name = "Data". No hay ningún argumento Name en el propio Add. El nombre debe tener 31 caracteres o menos, ser único en el libro, no estar en blanco y no contener : \ / ? * [ ], o .Name lanza el error en tiempo de ejecución 1004.

¿Por qué mi hoja nueva aparece en la posición equivocada?

Porque un Worksheets.Add a secas inserta la hoja justo antes de la hoja activa, no al final. Contrólalo con Before:= o After:=. Para añadir al final, usa Worksheets.Add(After:=Worksheets(Worksheets.Count)); para ponerla primera, usa Worksheets.Add(Before:=Worksheets(1)).

¿Por qué obtengo el error 1004 al añadir o nombrar una hoja?

Casi siempre es una violación de las reglas de nombres, y normalmente un duplicado. Los nombres de hoja deben ser únicos, así que volver a ejecutar una macro que ya creó "Data" choca en la segunda ejecución. Los nombres también deben tener 31 caracteres o menos, no estar en blanco y no contener : \ / ? * [ ]. Comprueba el nombre en la colección antes de añadir, y sanea la cadena primero.

¿Cómo añado una hoja solo si no existe ya?

No hay ningún método Exists, así que recorre la colección Worksheets y compara nombres con StrComp(ws.Name, nm, vbTextCompare) = 0. Si encuentras una coincidencia, reutiliza esa hoja; si no, llama a Add y ponle nombre. Envolver esto en una función GetOrAddSheet hace que la macro sea segura de ejecutar repetidamente.

¿Cómo añado una hoja justo al final del libro?

Ancla a la última hoja de cálculo: Worksheets.Add(After:=Worksheets(Worksheets.Count)). Worksheets(Worksheets.Count) es la última hoja de cálculo, así que insertar después de ella añade al final. Usa Sheets.Count en lugar de Worksheets.Count solo si quieres deliberadamente contar también las hojas de gráfico.

Probado en

Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 14/09/2026.

Guías relacionadas: VBA Copy Sheet · VBA Delete Sheet · VBA Worksheets · VBA Worksheet · VBA ThisWorkbook