TL;DR — Eliminar una fila es una edición estructural: no vacía la fila, la quita y hace subir una posición cada fila de debajo. Ese único hecho está detrás del error de VBA más común que existe: un bucle hacia delante que elimina filas se salta cada fila que iba justo detrás de una eliminada, porque los números de fila se desplazan bajo el bucle. La solución cabe en una palabra: recorre hacia atrás (
For i = last To first Step -1). Elimina la fila entera con.EntireRow.Deletey, cuando son muchas filas dispersas, reúnelas en una solaUniony elimínalas de una vez — es más rápido y esquiva por completo el problema del desplazamiento.
' Elimina cada fila cuya columna A esté vacía — recorre de ABAJO hacia ARRIBA.
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
Dim lastRow As Long, i As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = lastRow To 2 Step -1 ' <-- hacia atrás, o te saltas filas
If Trim(ws.Cells(i, "A").Value) = "" Then ws.Rows(i).EntireRow.Delete
Next i
«Elimina estas filas» suena como la tarea más simple de la automatización de Excel, y es la
que hace tropezar a casi todo el mundo la primera vez. El motivo no es el método Delete — es
que eliminar cambia justo aquello que estás recorriendo. Acierta con la dirección del recorrido
y eliminar por condición es trivial; fállala y tu macro deja en silencio la mitad de las filas
coincidentes sin tocar. Esta guía se construye alrededor de esa única idea y, después, de los
patrones prácticos que se derivan de ella.
Lo que aprenderás
- El modelo mental — eliminar quita una fila y hace subir todo lo que está debajo
- La regla más importante — recorre hacia atrás, o un bucle hacia delante se salta filas
- Por qué
.EntireRow.Deletees el objetivo seguro, y qué hace en cambio.Deletesobre una celda - El patrón más rápido para filas dispersas — construye una
Uniony elimina una sola vez - Quitar filas en blanco y eliminar por condición sin romper las fórmulas de referencia
El modelo mental: eliminar mueve la cuadrícula, no vacía una fila
Hay dos operaciones completamente distintas que la gente llama igual, «eliminar». Pulsar
Supr vacía una celda — la fila se queda, el valor desaparece. Clic derecho ▸
Eliminar, o Rows(i).Delete en código, quita la fila — la fila deja de existir y cada fila
de debajo sube una posición para cerrar el hueco. La fila que era la 11 ahora es la 10.
Ese comportamiento de cerrar el hueco es toda la historia. Cuando eliminas la fila 10, los datos de la fila 11 pasan a estar en la fila 10. Cualquier código que diera por hecho que «la fila 11 sigue conteniendo lo que contenía hace un momento» ahora es incorrecto. Por eso eliminar filas se siente distinto de cualquier otro bucle que escribas: la dirección de los datos que aún no has procesado cambia en el instante en que eliminas. Estás editando el sistema de coordenadas mientras lo recorres.
Ten esa imagen presente — por debajo de la fila eliminada, todo se desplaza hacia arriba — y cada regla que sigue es solo una consecuencia de ella.
La regla más importante: recorre hacia atrás o te saltas filas
Este es el error, escrito tal como casi todo el mundo lo escribe la primera vez:
' INCORRECTO — un bucle hacia delante sobre filas que estás eliminando.
For i = 2 To lastRow
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
Supongamos que las filas 5 y 6 dicen ambas "DELETE". El bucle llega a i = 5, elimina la fila
5 y la fila 6 sube para convertirse en la nueva fila 5. Pero el bucle avanza ahora a i = 6 —
que es la fila que antes era la 7. La antigua fila 6 no se comprobó nunca. Dos coincidencias
contiguas, y la segunda sobrevive. Con un bloque de coincidencias, dejas atrás más o menos una
de cada dos, y el síntoma («algunas filas no se eliminaron») parece aleatorio.
La solución no cuesta nada. Recorre de abajo arriba:
' CORRECTO — elimina desde la última fila hacia la primera.
For i = lastRow To 2 Step -1
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
Yendo hacia atrás, eliminar la fila 6 hace subir las filas por debajo de la 6 — pero esas ya
las has tratado. Las filas que aún no has mirado están todas por encima de la que acabas de
eliminar, y sus números no se movieron. El desplazamiento sigue ocurriendo; solo que ocurre
detrás de ti, donde no puede hacer ningún daño. Siempre que un bucle elimine filas, va con
Step -1. Memoriza eso y la mitad de todos los errores al eliminar desaparecen.
La regla que mantiene los datos alineados: elimina la fila, no una celda
Delete está disponible en cualquier rango, y cuanto más pequeño es el rango, más peligroso
resulta. Si escribes ws.Cells(i, "A").Delete, eliminas una sola celda, y Excel sube las
celdas que están debajo de ella solo en la columna A — dejando las columnas B, C y D
exactamente donde estaban. Cada fila a partir de ese punto queda desalineada: la columna A
muestra un registro mientras B y C muestran el de debajo. No salta ningún error; tus datos
simplemente se desordenan sin avisar.
Eliminar la fila entera mantiene cada columna acompasada:
ws.Rows(i).EntireRow.Delete ' se elimina la fila 11 entera; 12, 13... suben juntas
ws.Cells(i, "A").EntireRow.Delete ' idéntico — .EntireRow asciende una celda a su fila completa
.EntireRow es el ascenso de «esta celda» a «la fila entera en la que está esta celda», y es lo
que casi siempre quieres. Reserva el Range.Delete a secas con Shift:=xlUp/xlToLeft para el
caso raro en el que de verdad pretendes mover un bloque de celdas, no quitar un registro.
El patrón más rápido y seguro: reúne una Union y elimina una sola vez
Recorrer y eliminar fila por fila funciona en cuanto recorres hacia atrás, pero en hojas grandes
es lento — cada .Delete obliga a Excel a desplazar la cuadrícula y recalcular. Hay un patrón
que es a la vez más rápido e inmune a la trampa del desplazamiento, porque hace toda la
eliminación en un solo paso: acumula en un Range cada fila que quieres quitar con Union y
luego elimina todo el conjunto al final.
Dim victims As Range, i As Long
For i = 2 To lastRow ' la dirección da igual — eliminamos después
If ws.Cells(i, "A").Value = "DELETE" Then
If victims Is Nothing Then
Set victims = ws.Rows(i)
Else
Set victims = Union(victims, ws.Rows(i))
End If
End If
Next i
If Not victims Is Nothing Then victims.EntireRow.Delete ' un solo delete, todas las filas a la vez
Como no se quita ninguna fila hasta que el bucle termina, los números de fila nunca se mueven
durante el barrido — así que aquí un bucle hacia delante es perfectamente seguro. Y un único
.Delete de un rango de varias áreas es muchísimo más rápido que cientos de eliminaciones
individuales. Mi regla general: un puñado de filas, recorre hacia atrás; cientos o miles, reúne
una Union (o filtra — mira más abajo) y elimina una sola vez. Envuelve cualquiera de las dos
en Application.ScreenUpdating = False / Calculation = xlManual y las eliminaciones grandes
pasan de segundos a instantáneas.
Filas en blanco, condiciones y la trampa de las referencias
Eliminar filas en blanco tiene una sola línea que gana a cualquier bucle — deja que Excel encuentre los blancos:
On Error Resume Next ' SpecialCells lanza 1004 si no hay celdas en blanco
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
SpecialCells(xlCellTypeBlanks) devuelve cada celda vacía de la columna A como un único rango de
varias áreas, y .EntireRow.Delete quita todas sus filas de un solo golpe. Dos advertencias: se
guía por una columna (una fila con A vacía pero B rellena también se elimina) y da error cuando
no hay blancos — de ahí la protección con On Error.
Para eliminar por condición en grandes volúmenes de datos, la jugada profesional es AutoFilter: filtra las filas que no quieres, elimina las visibles y quita el filtro. Es el enfoque más rápido de todos porque Excel se encarga de la coincidencia:
With ws.Range("A1").CurrentRegion
.AutoFilter Field:=1, Criteria1:="DELETE"
.Offset(1).SpecialCells(xlCellTypeVisible).EntireRow.Delete ' salta la fila de encabezado
End With
ws.AutoFilterMode = False
Una trampa sobrevive a todas las demás: eliminar filas desplaza las referencias. Si una
fórmula en otro sitio apunta a =A20 y eliminas la fila 5, Excel la reescribe como =A19 —
normalmente lo que quieres. Pero si eliminas la fila de la que una fórmula depende, esa fórmula
se convierte en #REF!. Eliminar filas por debajo de fórmulas vivas es la causa clásica de una
hoja llena de errores #REF!, así que antes de una eliminación masiva, averigua si algo más
adelante hace referencia a las filas que estás quitando. Encontrar dónde terminan tus datos es
una habilidad relacionada — mira VBA última fila.
Cómo ayuda ExcelMaster
El código para eliminar filas tiene unas cuantas formas silenciosas de salir mal: el bucle hacia
delante que se salta filas, el borrado de una sola celda que desalinea columnas, la llamada a
SpecialCells que se cae cuando no hay blancos, la eliminación masiva que deja #REF! detrás.
Ninguna lanza un error evidente — solo producen datos ligeramente incorrectos.
ExcelMaster te deja
describir el resultado en su lugar. Di «elimina cada fila donde la columna A esté vacía» o «quita
las filas cuyo estado sea Cancelado», y escribe el bucle en la dirección segura (o una
Union/filtro para grandes volúmenes), apunta a .EntireRow, protege los casos límite y hace
primero una copia de seguridad de la hoja. Te quedas con el libro y con el código; te ahorras la
parte en la que un Step -1 olvidado corrompe un informe sin que te enteres.
Preguntas frecuentes
¿Por qué mi bucle de VBA se salta filas al eliminar?
Porque eliminar una fila hace subir una posición cada fila de debajo, pero un bucle hacia delante
sigue incrementando. Después de eliminar la fila 5, la antigua fila 6 pasa a ser la fila 5 — y el
bucle avanza a la fila 6, saltándosela. Recorre hacia atrás en su lugar:
For i = lastRow To 2 Step -1. Así, las filas que aún no has comprobado están siempre por encima
de la eliminación, de modo que sus números nunca se mueven.
¿Cómo elimino una fila entera en VBA?
Usa .EntireRow.Delete — por ejemplo ws.Rows(11).EntireRow.Delete o
ws.Cells(11, "A").EntireRow.Delete. Ambos quitan la fila completa, así que cada columna se
mantiene alineada. Evita Cells(11, "A").Delete, que elimina una sola celda y desplaza
únicamente esa columna, desordenando el resto.
¿Cuál es la forma más rápida de eliminar muchas filas en VBA?
Para cientos o miles de filas, no elimines de una en una. O bien aplicas AutoFilter a las filas
que quieres quitar y eliminas las celdas visibles en un solo paso, o bien construyes una Union
de todas las filas objetivo durante el bucle y llamas a .EntireRow.Delete una sola vez al
final. Una única eliminación de varias filas es mucho más rápida que muchas individuales, sobre
todo con ScreenUpdating y Calculation desactivados.
¿Cómo elimino todas las filas en blanco en VBA?
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete quita en una sola
operación cada fila cuya columna A esté en blanco. Envuélvelo en On Error Resume Next /
On Error GoTo 0 porque SpecialCells lanza un error cuando no hay celdas en blanco que
encontrar.
¿Por qué obtengo errores #REF! después de eliminar filas?
Eliminar filas desplaza las referencias de celda. Las fórmulas que apuntan más allá de las
filas eliminadas se renumeran automáticamente, pero cualquier fórmula que hiciera referencia a
una celda dentro de una fila eliminada ya no puede resolverse y se convierte en #REF!. Antes
de una eliminación masiva, comprueba si otras celdas dependen de las filas que estás a punto de
quitar.
Probado en
Probado en: Excel 365 (Windows 11), VBA 7.1 — última verificación el 07/08/2026.
Guías relacionadas: VBA insertar filas y columnas · VBA ocultar columnas y filas · VBA última fila · VBA For Loop · VBA Range
