TL;DR —
Dirno 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 aDirdentro 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 —
Dires un iterador con estado disfrazado de función - La única regla con la que todo el mundo tropieza — no volver a llamar a
Dirnunca en mitad de un bucleDir - Por qué
Dirdevuelve solo el nombre del archivo, y tienes que anteponer la carpeta tú mismo - El comodín (
*.xlsx) y cómoDirmaneja el «sin coincidencias» ("", no un error) - Por qué
Dirno 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.xlsxde la carpetaDir("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 únicoDirdentro del bucle no lleva argumento. - Antepón la carpeta —
Dirdevuelve nombres;folder & namereconstruye la ruta. - Dos pasadas cuando mutas — reúne los nombres en un array, luego abre/mueve/borra.
- Echa mano del
FileSystemObjecten 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
