Resumen (TL;DR) — Una hoja tiene tres asas y solo una es segura.
Sheets("Jan")usa el nombre de la pestaña: el usuario puede renombrarla y tu macro muere con «subíndice fuera del intervalo».Sheets(1)usa la posición: arrastra una pestaña y tu macro escribe en silencio en la hoja equivocada.Sheet1(el CodeName, fijado en el VBE) es la que el usuario no puede tocar desde Excel, así que nunca se rompe. Captura una referencia una sola vez —Set ws = ThisWorkbook.Worksheets("Data")— y deja de usar.Select/.Activate.
Una hoja está un nivel por debajo del libro: el libro contiene hojas, una hoja contiene rangos. El dolor recurrente no es usar una hoja, sino nombrarla. Si te equivocas en la referencia, tu macro o se cae a gritos o, peor, escribe en la pestaña equivocada sin un solo error.
Qué aprenderás
- Las tres formas de referenciar una hoja y cuáles dos te traicionan
- Por qué el CodeName es el asa a prueba de balas (y dónde fijarlo)
- La diferencia entre
SheetsyWorksheets(no son sinónimos) - Por qué
.Selecty.Activateson hábitos de la grabadora de macros, no código real
El modelo mental: tres asas, dos de ellas se mueven
Una hoja es un objeto que puedes tomar de tres maneras. Dos de esas asas están atadas a cosas que controla el usuario — el nombre de la pestaña y el orden de las pestañas — así que se mueven bajo tus pies. La tercera, el CodeName, está atada a algo que solo tú controlas desde el VBE.
Sub ThreeWaysToGrabASheet()
' 1) Por NOMBRE de pestaña — el usuario puede renombrarla -> se rompe
Debug.Print Worksheets("Jan").Name
' 2) Por ÍNDICE (posición) — el usuario puede reordenar -> hoja equivocada en silencio
Debug.Print Worksheets(1).Name
' 3) Por CODENAME — fijado en el VBE, invisible al usuario -> a prueba de balas
Debug.Print Sheet1.Name ' "Sheet1" es el CodeName, no el texto de la pestaña
End Sub
Por qué importa: las asas #1 y #2 dependen del comportamiento del usuario. Alguien renombra «Jan» como «January» o la arrastra detrás de «Feb», y tu macro o lanza error de ejecución 9 («subíndice fuera del intervalo») o — mucho más peligroso — sigue corriendo y edita la pestaña equivocada. El asa #3 es inmune porque el CodeName vive en el código, no en la pestaña.
La regla: fija un CodeName o captura la referencia una vez
El modo de fallo es usar un asa móvil en lo profundo de tu macro. La solución es clavar la hoja una vez, arriba, y luego hablar solo con esa variable.
Sub SafeSheetReference()
' Captura la referencia una vez — calificada hasta el libro
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("Data")
' De aquí en adelante, todo pasa por ws. Sin «activo», sin volver a buscar.
ws.Range("A1").Value = "Report"
ws.Range("A2:A100").ClearContents
Debug.Print ws.UsedRange.Rows.Count
End Sub
Para hacer el nombre mismo irrompible, dale a la hoja un CodeName: en el VBE,
selecciona la hoja bajo Microsoft Excel Objects, abre la ventana Propiedades (F4)
y fija (Name). Ahora puedes escribir Set ws = SalesData y renombrar la pestaña en
Excel no cambia nada. El juicio: si una macro debe sobrevivir a que otros usen el
archivo, referencia las hojas por CodeName — los nombres de pestaña son contenido del
usuario, no código.
Sheets vs. Worksheets — no es la misma colección
Esto hace tropezar a casi todos. Worksheets son solo las hojas de cuadrícula.
Sheets es todo lo que tiene pestaña, incluidas las hojas de gráfico. Itera
sobre la colección equivocada y darás con una hoja de gráfico que no tiene .Range,
y te caes.
Sub SheetsVsWorksheets()
' Worksheets: SOLO hojas de cuadrícula — seguras para .Range / .Cells
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
ws.Range("A1").Value = "Auditado"
Next ws
' Sheets: cuadrícula MÁS hojas de gráfico — .Range en una de gráfico = caída
Debug.Print ThisWorkbook.Worksheets.Count ' solo cuadrículas
Debug.Print ThisWorkbook.Sheets.Count ' cuadrículas + gráficos
End Sub
La regla práctica: si tu bucle toca celdas, itera Worksheets, nunca Sheets.
Recurre a Sheets solo cuando de verdad necesites hojas de gráfico en la mezcla.
Deja de usar .Select y .Activate
La grabadora de macros escribe Sheets("Data").Select y luego
Range("A1").Select porque solo puede grabar lo que hiciste clic. El código real
se salta el clic por completo: habla directamente con el objeto hoja. Seleccionar es
lento, parpadea la pantalla y (porque cambia el ActiveSheet) prepara justamente los
errores de hoja equivocada de arriba.
' Estilo grabadora — selecciona, luego actúa sobre la selección (frágil)
Sheets("Data").Select
Range("A1").Select
Selection.Value = 100
' Código real — una línea, sin selección, sin depender de ActiveSheet
ThisWorkbook.Worksheets("Data").Range("A1").Value = 100
Casi nunca necesitas seleccionar una hoja para leerla o escribirla. Por qué «activo» es una trampa de entrada lo ves en VBA ActiveSheet.
Cómo ayuda ExcelMaster
La mayoría del VBA multihoja existe para barajar datos entre pestañas de forma periódica. ExcelMaster lo hace desde una descripción en lenguaje natural — «copia las filas limpias de Data a la pestaña Summary y actualiza los totales» — sin referencias de hoja que nombrar mal. Te saltas toda la clase de error de «subíndice fuera del intervalo».
VBA sigue ganándose su lugar en la automatización permanente dentro del libro. Pero para el cotidiano «mueve esto de aquella pestaña a esta», describirlo es más rápido y no se rompe cuando alguien renombra una hoja.
Preguntas frecuentes
¿Por qué obtengo «subíndice fuera del intervalo» al referenciar una hoja?
El nombre de pestaña que pasaste no existe — normalmente porque alguien renombró la hoja, o hay un espacio sobrante o un error de tipeo. Referencia por CodeName (fijado en el VBE), que el usuario no puede cambiar, o envuelve la búsqueda y verifica que la hoja exista primero.
¿Qué es un CodeName de hoja y dónde lo fijo?
El CodeName es el nombre interno que usa VBA (Sheet1, Sheet2, …), visible en el
Explorador de Proyectos del VBE. Fíjalo en la ventana Propiedades (F4) → (Name). A
diferencia del nombre de pestaña, el usuario no puede cambiarlo desde Excel, así que
es el asa más fiable.
¿Cuál es la diferencia entre Sheets y Worksheets en VBA?
Worksheets contiene solo hojas de cuadrícula estándar. Sheets contiene todos los
tipos de hoja, incluidas las de gráfico. Si tu código usa .Range o .Cells, itera
Worksheets — una hoja de gráfico no tiene celdas y se cae.
¿Necesito Seleccionar o Activar una hoja para editarla?
No. ThisWorkbook.Worksheets("Data").Range("A1").Value = 1 funciona sin seleccionar
nada. .Select/.Activate son artefactos de la grabadora de macros que ralentizan
la macro y crean errores de hoja equivocada.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — verificado por última vez el 13/06/2026.
Guías relacionadas: VBA Workbook · VBA ActiveSheet · VBA Range · VBA For Loop · VBA Dictionary
