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

Última fila en VBA en Excel — encuentra el final real de tus datos (y la trampa de cada método)

|

Última fila en VBA en Excel — encuentra el final real de tus datos (y la trampa de cada método)

TL;DR — Deja de codificar a mano Range("A1:A100"). Tus datos crecen y encogen, así que encuentra su borde en tiempo de ejecución. La fórmula canónica es Cells(Rows.Count, "A").End(xlUp).Row: simula pulsar Ctrl+↑ desde el fondo mismo de la columna. Usa Rows.Count, nunca un 65536 codificado a mano. Hay cuatro maneras de preguntar «¿dónde terminan los datos?» y cada una responde a una pregunta ligeramente distinta: .End(xlUp) encuentra la última celda no vacía de una columna, .End(xlDown) se detiene en el primer hueco, .UsedRange informa de más y .Find es la única de verdad a prueba de huecos. Elige el método equivocado y procesarás las filas equivocadas, sin ningún error que te avise.

Encontrar la última fila es lo más habitual que una macro necesita hacer antes de poder recorrer, copiar, ordenar o limpiar datos. Es también donde los principiantes escriben la línea más frágil de todo el procedimiento: un A2:A500 codificado a mano. Añade una fila y la macro se la salta; borra filas y procesa cientos de celdas en blanco. El VBA de verdad nunca da por supuesto el tamaño de los datos: lo mide.

Lo que aprenderás

  • La fórmula canónica Cells(Rows.Count, "A").End(xlUp).Row, descifrada pieza a pieza
  • Por qué 65536 es una mina y Rows.Count es la solución
  • El modo de fallo que se esconde en cada uno de los cuatro métodos (.End(xlUp), .End(xlDown), .UsedRange, .Find)
  • Cómo encontrar la última columna, no solo la última fila
  • Cuándo los huecos en tus datos te obligan a pasar de .End a .Find

El modelo mental: tus datos tienen un borde, y Excel no te lo entrega

Una hoja de cálculo es una cuadrícula de un millón de filas. Tus datos ocupan algún rectángulo dentro de ella, pero Excel no guarda una propiedad ordenada de «última fila» que puedas leer sin más. Así que tienes que caminar hasta el borde y preguntar dónde has aterrizado. Toda técnica fiable es alguna versión de «empieza en un punto que sabes que está más allá de los datos y luego salta de vuelta a lo último que hay de verdad».

La imagen mental de la fórmula canónica es una persona plantada en el fondo mismo de una columna que pulsa Ctrl+↑: el cursor sube volando y se detiene en la última celda con contenido. Eso es exactamente lo que hace .End(xlUp) en el código.

Sub FindLastRow()
    Dim ws As Worksheet
    Set ws = ActiveSheet

    Dim lastRow As Long
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row

    Debug.Print "Last row with data in column A: " & lastRow
End Sub

Léela de dentro hacia fuera: ws.Rows.Count es el número de filas de la hoja (1.048.576 en el Excel moderno). Cells(eso, "A") es la celda del fondo mismo de la columna A. .End(xlUp) salta hacia arriba hasta la última celda no vacía. .Row lee su número de fila. Esa única línea es el caballo de batalla, pero solo si entiendes la trampa que lleva dentro.

La regla que te salva del peor error de última fila: nunca codifiques 65536 a mano

Durante una década, los tutoriales escribían Cells(65536, 1).End(xlUp).Row, porque 65.536 era la última fila del antiguo formato .xls. Las hojas .xlsx modernas tienen 1.048.576 filas. Si tus datos pasan de la fila 65.536 y arrancas el salto hacia arriba desde la 65.536, empiezas por encima de una parte de tus datos y devuelves en silencio una última fila demasiado pequeña, cortando el bucle en mitad de la tabla.

' FRÁGIL — empieza por encima de cualquier dato que haya debajo de la fila 65536
lastRow = Cells(65536, 1).End(xlUp).Row

' CORRECTO — siempre empieza desde el verdadero fondo de ESTA hoja
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

Rows.Count lee el número real de filas de la hoja en la que se ejecute el código, así que está a prueba de futuro y de versiones. No hay ningún escenario en el que codificar el número a mano sea mejor. Convierte Cells(Rows.Count, col) en un reflejo.

La regla que ata cada método a su modo de fallo

Esta es la parte que todos los tutoriales se saltan: los cuatro métodos habituales no devuelven la misma respuesta, porque responden a preguntas distintas. Aprende el modo de fallo de cada uno y siempre sabrás cuál elegir.

.End(xlUp) — la última celda no vacía de una columna. La opción por defecto. Su punto ciego es que solo mira una columna. Si eliges una columna con un hueco donde la última fila queda vacía (pongamos que el nombre de la fila 500 está en blanco, pero su importe no), te quedas corto. Elige una columna que tengas garantizado que esté rellena en todas las filas de datos —un ID o una clave— o encuentra la última fila de toda la tabla con .Find.

.End(xlDown) — el primer hueco desde arriba. Es Ctrl+↓ desde la fila 1. No encuentra la última fila; encuentra la fila justo antes de la primera celda en blanco. Una sola celda vacía en mitad de la columna te trunca al bloque superior. No uses nunca .End(xlDown) para encontrar el final de los datos: solo para encontrar el fondo de un tramo sin interrupciones.

' A1:A10 tiene datos, A6 está en blanco, A7:A10 tiene más datos
Cells(1, 1).End(xlDown).Row     ' -> 5   (se detuvo en el hueco — INCORRECTO para «última fila»)
Cells(Rows.Count, 1).End(xlUp).Row  ' -> 10  (última fila real — CORRECTO)

.UsedRange — el recuadro delimitador que Excel guarda en caché. ws.UsedRange no son tus datos; son todas las celdas que Excel ha tocado alguna vez, incluidas las que solo llevan formato, y no encoge cuando borras filas hasta que se guarda o se recalcula el libro. Informa de más, así que un bucle sobre UsedRange puede arrastrarse por cientos de filas fantasma. Además, no empieza necesariamente en la fila 1 (mira las preguntas frecuentes). Trata UsedRange como «más o menos toda la hoja», nunca como un número preciso de última fila.

.Find — el único método a prueba de huecos. Buscar hacia atrás la última celda que contenga cualquier cosa, en cualquier sitio de la hoja es inmune a los blancos internos y a la columna que elijas:

Function LastDataRow(ws As Worksheet) As Long
    Dim c As Range
    Set c = ws.Cells.Find(What:="*", After:=ws.Cells(1, 1), _
                          LookIn:=xlFormulas, SearchOrder:=xlByRows, _
                          SearchDirection:=xlPrevious)
    If c Is Nothing Then
        LastDataRow = 0            ' hoja vacía
    Else
        LastDataRow = c.Row
    End If
End Function

.Find es verboso y tienes que gestionar el caso Nothing (una hoja vacía), pero es la respuesta correcta cuando tus datos tienen bordes irregulares o huecos internos. LookIn:=xlFormulas encuentra celdas con una fórmula aunque ahora mismo dé como resultado ""; xlValues las ignora, así que elige a conciencia.

El criterio de decisión: qué método y cuándo

  • Lista limpia de una sola columna o tabla con una columna clave sólidaCells(Rows.Count, keyCol).End(xlUp).Row. Rápido, legible y correcto.
  • Datos con filas en blanco internas o un borde derecho irregular.Find(What:="*", SearchDirection:=xlPrevious). A prueba de huecos.
  • «Qué tamaño tiene, más o menos, todo lo que hay en esta hoja, para poder limpiarla».UsedRange. Informar de más es inofensivo cuando estás borrando.
  • Nunca uses .End(xlDown) para la última fila, y nunca leas UsedRange.Rows.Count como si fuera el número de la última fila.

Encontrar también la última columna

El mismo truco del salto funciona en horizontal. Empieza en la celda del extremo derecho de tu fila de encabezados y pulsa Ctrl+← desde el código:

Dim lastCol As Long
lastCol = Cells(1, Columns.Count).End(xlToLeft).Column

Con los dos números puedes construir el rango de datos exacto sin codificar nada a mano:

Dim rng As Range
Set rng = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol))

De eso se trata todo: una vez que sabes encontrar los bordes, no vuelves a teclear una dirección fija nunca más. Para construir un rango que se salte la fila de encabezados, combina esto con Offset y Resize; para tomar el bloque contiguo en una sola llamada, mira UsedRange frente a CurrentRegion.

Cómo ayuda ExcelMaster

Casi toda pregunta del tipo «encontrar la última fila» es en realidad un paso hacia un objetivo mayor: recorrer esta columna y marcar duplicados, copiar filas nuevas a otra hoja, sumar por grupo. ExcelMaster toma ese objetivo en lenguaje natural —«por cada fila de la tabla de pedidos, copia las no terminadas a la hoja Pendientes»— y escribe por ti las cuentas del rango, encontrando los bordes de los datos de la forma robusta en lugar de dar por supuesto un tamaño fijo.

Seguirás escribiendo .End(xlUp) a mano dentro de una macro que se ejecuta de forma programada. Pero para la tarea cotidiana de «procesa las filas que haya hoy», describir el resultado gana a acertar cada vez con Rows.Count y con el manejo de huecos.

Preguntas frecuentes

¿Cuál es la mejor forma de encontrar la última fila en VBA?

Para una tabla con una columna clave que siempre esté rellena, usa Cells(Rows.Count, keyColumn).End(xlUp).Row. Imita Ctrl+↑ desde el fondo de la hoja y es rápido y legible. Si tus datos tienen filas en blanco internas o un borde irregular, usa en su lugar Cells.Find(What:="*", SearchDirection:=xlPrevious).Row, porque .End puede detenerse en un hueco.

¿Por qué debería usar Rows.Count en lugar de 65536?

65536 era la última fila del antiguo formato .xls. Las hojas .xlsx modernas tienen 1.048.576 filas, así que arrancar el salto hacia arriba en la 65.536 empieza por encima de cualquier dato que haya debajo de ese punto y devuelve una última fila demasiado pequeña. Rows.Count siempre refleja el tamaño real de la hoja actual.

¿Por qué UsedRange da una última fila incorrecta?

UsedRange es un recuadro delimitador en caché de todas las celdas que Excel ha tocado alguna vez, incluidas las que solo tienen formato, y no encoge cuando borras datos hasta que se guarda el archivo. Además, puede no empezar en la fila 1, así que UsedRange.Rows.Count es un recuento, no el número de la última fila. Usa .End(xlUp) o .Find para obtener una última fila precisa.

¿Cómo encuentro la última columna en VBA?

Refleja en horizontal la fórmula de la última fila: Cells(1, Columns.Count).End(xlToLeft).Column. Salta desde la celda del extremo derecho de la fila de encabezados de vuelta a la última columna con contenido.

¿Cómo encuentro la última fila cuando la columna tiene celdas en blanco?

.End(xlUp) solo inspecciona una columna, así que un blanco en la última fila de datos de esa columna hace que se quede corto. O lo apuntas a una columna que esté siempre rellena (un ID), o usas Cells.Find(What:="*", SearchDirection:=xlPrevious).Row, que encuentra la última celda con contenido en cualquier parte de la hoja sin importar los huecos.

Probado en

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

Guías relacionadas: VBA Offset · VBA UsedRange frente a CurrentRegion · VBA Range · VBA For Loop