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

VBA Dir en Excel — recorre los archivos de una carpeta, y el iterador con estado que te muerde

|

VBA Dir en Excel — recorre los archivos de una carpeta, y el iterador con estado que te muerde

TL;DRDir no es una función normal. La primera llamada pasa una ruta y obtiene el nombre del primer archivo que coincide; cada llamada posterior no pasa nada y obtiene el siguiente nombre, hasta que devuelve "". Así que el bucle tiene esta forma — y nunca debes volver a llamar a Dir dentro de él:

Sub ListWorkbooks()
    Dim folder As String, name As String
    folder = "C:\Reports\"
    name = Dir(folder & "*.xlsx")      ' primera llamada: siembra la busqueda
    Do While name <> ""
        Debug.Print folder & name      ' Dir devuelve solo el NOMBRE - antepon la carpeta
        name = Dir()                   ' sin argumento: la SIGUIENTE coincidencia
    Loop
End Sub

En cuanto tu macro tiene que procesar muchos archivos — consolidar doce libros regionales, importar cada CSV de una carpeta de entrada — echas mano de Dir. Es el built-in que no necesita referencias ni preparación. Pero esconde un diseño con el que casi todo el mundo tropieza: Dir recuerda dónde se quedó, de forma global, y una segunda búsqueda borra esa memoria en silencio. Entiende ese único hecho y todos los bugs de «me saltó la mitad de los archivos» desaparecen.

Lo que aprenderás

  • El modelo mental — Dir es un iterador con estado disfrazado de función
  • La única regla con la que todo el mundo tropieza — no volver a llamar a Dir nunca en mitad de un bucle Dir
  • Por qué Dir devuelve solo el nombre del archivo, y tienes que anteponer la carpeta tú mismo
  • El comodín (*.xlsx) y cómo Dir maneja el «sin coincidencias» ("", no un error)
  • Por qué Dir no puede entrar en subcarpetas — y qué usar en su lugar
  • Por qué deberías reunir los nombres en un array primero, y luego abrir/mover/borrar los archivos

El modelo mental: Dir es un iterador, no una consulta

La mayoría de las funciones dan la misma respuesta cada vez que las llamas con la misma entrada. Dir no. Mantiene un único cursor oculto, a nivel de módulo, sobre una búsqueda de una carpeta:

  • Dir("C:\Reports\*.xlsx") — el argumento inicia una búsqueda nueva y devuelve la primera coincidencia.
  • Dir() — sin argumento avanza la misma búsqueda y devuelve la siguiente coincidencia.
  • Cuando no queda nada, Dir() devuelve una cadena vacía "".

Piénsalo como un cursor que siembras una vez y luego haces avanzar. El bucle Do While name <> "" de arriba es la forma canónica: siembra con la ruta, luego llama al Dir() sin argumentos al final de cada pasada. Ese es el patrón entero, y es la forma que deberías memorizar.

La regla con la que todo el mundo tropieza: no llames a Dir dentro de un bucle Dir

Como solo hay un cursor oculto, llamar a Dir con un argumento en cualquier punto dentro del bucle inicia una búsqueda completamente nueva y tira tu posición. Este es el bug número uno de Dir, y es sutil porque parece de lo más razonable:

name = Dir(folder & "*.xlsx")
Do While name <> ""
    If Dir(folder & "flag.txt") <> "" Then   ' <- DESASTRE: reinicia el cursor
        Process folder & name
    End If
    name = Dir()          ' ahora esto continua la busqueda de "flag.txt", no la de *.xlsx
Loop

El Dir(folder & "flag.txt") interno reinicia el motor con un patrón distinto. Cuando el bucle llama entonces a Dir(), avanza esa búsqueda — así que o procesas los archivos equivocados, o te saltas la mayoría de tus archivos .xlsx, o giras para siempre. La regla es absoluta: dentro de un bucle Dir, el único Dir que puedes llamar es el Dir() sin argumentos. Si necesitas comprobar otro archivo a mitad del bucle, usa FileSystemObject.FileExists en su lugar — no tiene ningún cursor compartido que corromper.

Dir devuelve el nombre, no la ruta

Dir te entrega el nombre desnudo del archivo — March.xlsx, no C:\Reports\March.xlsx. Olvidar esto es el segundo error más común, porque lo siguiente que sueles hacer es abrir el archivo:

Set wb = Workbooks.Open(name)             ' error 1004 - "March.xlsx" no es una ruta completa
Set wb = Workbooks.Open(folder & name)    ' correcto - reconstruye la ruta completa

Mantén siempre la cadena de la carpeta por separado y vuelve a concatenarla cuando necesites la ruta completa. Esta es también la razón por la que la variable de la carpeta termina en una barra invertida ("C:\Reports\") — para que folder & name sea una ruta válida sin separador faltante.

El comodín y el caso «sin coincidencias»

El argumento del primer Dir es una ruta más un patrón. * coincide con cualquier secuencia de caracteres, ? con un solo carácter:

  • Dir("C:\Reports\*.xlsx") — cada .xlsx de la carpeta
  • Dir("C:\Reports\Q?-2026.xlsx")Q1-2026.xlsx, Q2-2026.xlsx, …
  • Dir("C:\Reports\March.xlsx") — sin comodín, así que solo comprueba un archivo: devuelve "March.xlsx" si existe, "" si no (este es el one-liner detrás de comprobar si un archivo existe)

Si nada coincide, Dir devuelve ""no lanza un error. Por eso Do While name <> "" maneja tanto «no hay ningún archivo» como «llegué al final» con la misma prueba.

Una trampa: por defecto Dir también coincide con carpetas y se salta los archivos ocultos y de sistema. Si una subcarpeta resulta coincidir con tu patrón, también puedes recibir su nombre de vuelta. Cuando importe, pasa el atributo vbNormal explícitamente o verifica con el FileSystemObject.

Dir no puede recursar — y modificar la carpeta a mitad del bucle la corrompe

Dos límites duros te empujan fuera de Dir para cualquier cosa más allá de una lista plana:

No es recursivo. Dir recorre una carpeta. No hay ningún argumento para bajar a las subcarpetas, y no puedes anidar dos bucles Dir (un solo cursor, recuerda). Para procesar un árbol — C:\Reports\2026\Q1\..., Q2\... — necesitas el FileSystemObject, cuya colección SubFolders está hecha para la recursión.

Cambiar la carpeta mientras iteras rompe la enumeración. Si haces Kill, renombras, mueves o incluso Open y SaveAs de archivos durante un bucle Dir, estás mutando la mismísima carpeta que el cursor oculto está recorriendo. Se saltan nombres o se repiten. El arreglo es un patrón de dos pasadas — reúne primero, actúa después:

Dim names() As String, n As Long
ReDim names(1 To 1000)
Dim f As String: f = Dir(folder & "*.xlsx")
Do While f <> ""                 ' pasada 1: solo reune los nombres
    n = n + 1: names(n) = f
    f = Dir()
Loop
Dim i As Long
For i = 1 To n                   ' pasada 2: ahora es seguro abrir / mover / borrar
    Process folder & names(i)
Next i

Una vez que los nombres están en un array, el frágil cursor ha terminado y puedes hacer lo que quieras con los archivos.

El veredicto honesto: para qué sirve de verdad Dir

Dir es la herramienta correcta para exactamente un trabajo — un bucle rápido y plano sobre los archivos de una sola carpeta, sin referencias que añadir y sin objeto que crear. Para «ejecuta esta macro sobre cada .xlsx de esta carpeta», es más corto y más rápido que cualquier otra cosa. Mantenlo en eso, y sigue cuatro reglas:

  • Siembra una vez, avanza con Dir() — el único Dir dentro del bucle no lleva argumento.
  • Antepón la carpetaDir devuelve nombres; folder & name reconstruye la ruta.
  • Dos pasadas cuando mutas — reúne los nombres en un array, luego abre/mueve/borra.
  • Echa mano del FileSystemObject en cuanto necesites subcarpetas, el tamaño o la fecha de un archivo, o una segunda comprobación de existencia a mitad del bucle.

En el instante en que te descubres queriendo un segundo Dir en el mismo bucle, esa es la señal de que se te ha quedado pequeño Dir — no un bug que parchear, sino una herramienta que cambiar.

Cómo ayuda ExcelMaster

Acertar con un bucle de archivos significa sembrar Dir una vez, avanzar con la llamada sin argumentos, reconstruir las rutas completas, y saber cuándo la mutación de la carpeta obliga a un array de dos pasadas — una cantidad sorprendente de ceremonia para «solo recorrer los archivos de una carpeta», y una sola llamada Dir de más rompe todo en silencio.

ExcelMaster escribe el bucle por ti. Describe el trabajo — «abre todos los libros de esta carpeta, saca los totales y cierra cada uno» — y produce un bucle Dir correcto (o un recorrido con FileSystemObject cuando necesitas subcarpetas), con la concatenación de la carpeta, el array de dos pasadas cuando se mueven archivos, y un wb.Close correspondiente en cada iteración. Tú describes el resultado; él gestiona la memoria del iterador para que nunca te muerda.

Preguntas frecuentes

¿Cómo recorro todos los archivos de una carpeta con VBA?

Siembra Dir con una ruta y un comodín, luego avanza con el Dir() sin argumentos: name = Dir("C:\Reports\*.xlsx"), luego Do While name <> "" … name = Dir() … Loop. Dir devuelve cada nombre de archivo por turno y "" cuando la carpeta se agota. Recuerda que Dir devuelve solo el nombre, así que usa folder & name cuando necesites la ruta completa.

¿Por qué mi bucle Dir de VBA se salta archivos o se repite para siempre?

Casi siempre porque llamaste a Dir con un argumento dentro del bucle. Dir mantiene un único cursor oculto, y cualquier Dir(algunaRuta) inicia una búsqueda nueva que borra tu posición — así que el Dir() del final del bucle avanza entonces la búsqueda equivocada. Dentro de un bucle Dir, llama siempre solo al Dir() sin argumentos. Para comprobar otro archivo a mitad del bucle, usa FileSystemObject.FileExists, que no tiene estado compartido.

¿Dir de VBA busca en las subcarpetas?

No. Dir recorre una sola carpeta y no tiene recursión, y no puedes anidar dos bucles Dir porque solo hay un cursor. Para recorrer un árbol de carpetas, usa el FileSystemObject e itera su colección SubFolders de forma recursiva.

¿Cómo obtengo la ruta completa a partir de Dir en VBA?

Dir devuelve el nombre desnudo del archivo (March.xlsx), no la ruta completa. Mantén la carpeta en su propia variable (terminada en una barra invertida) y concatena: folder & name da C:\Reports\March.xlsx. Pasar el nombre desnudo a Workbooks.Open lanza el error 1004 en tiempo de ejecución.

¿Debo usar Dir o FileSystemObject para recorrer archivos?

Usa Dir para un bucle rápido y plano sobre una carpeta sin preparación. Cambia al FileSystemObject cuando necesites entrar en subcarpetas, leer el tamaño o la fecha de modificación de cada archivo, o comprobar otros archivos mientras iteras — cualquier cosa en la que el único cursor oculto de Dir se interponga en tu camino.

Probado en

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

Guías relacionadas: VBA FileSystemObject · VBA Check If File Exists · VBA Open Workbook · VBA Close Workbook · VBA For Loop