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

VBA Comprobar si un Archivo Existe — Dir frente a FileSystemObject.FileExists (y la trampa dentro de un bucle Dir)

|

VBA Comprobar si un Archivo Existe — Dir frente a FileSystemObject.FileExists (y la trampa dentro de un bucle Dir)

TL;DR — Dos formas correctas, una para cada juego de herramientas. Dir es el one-liner cuando no estás ni cerca de un bucle Dir; FileSystemObject.FileExists es el valor por defecto seguro porque no tiene estado oculto:

' Built-in, una linea - pero comparte el unico cursor global de Dir:
If Dir("C:\Reports\March.xlsx") <> "" Then MsgBox "It's there"

' Sin estado, mas claro, distingue archivo de carpeta - el valor por defecto mas seguro:
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\Reports\March.xlsx") Then MsgBox "It's there"

«¿Existe este archivo?» es la pregunta sobre archivos más buscada en VBA, porque la alternativa — abrir un archivo que no está ahí — lanza el error 1004 en tiempo de ejecución y detiene en seco una macro desatendida. La buena noticia es que la comprobación es un one-liner. La trampa es que el one-liner obvio, Dir, arrastra el mismo cursor oculto que impulsa un bucle Dir — así que dónde lo llamas importa tanto como cómo.

Lo que aprenderás

  • El reflejo equivocado — «simplemente ábrelo y atrapa el error» — y por qué es la peor opción
  • Las dos respuestas correctas — Dir y FileSystemObject.FileExists
  • La trampa que define este tema — la comprobación con Dir reinicia un bucle Dir
  • Cómo Dir maneja mal una ruta de carpeta o una barra invertida final
  • FileExists frente a FolderExists — di exactamente lo que quieres decir
  • Por qué «comprobar y luego abrir» todavía necesita una protección de errores (la pequeña carrera, y el arreglo práctico)

El reflejo equivocado: abrirlo y atrapar el error

El atajo tentador es saltarse la comprobación por completo y dejar que el fallo te lo diga:

On Error Resume Next
Set wb = Workbooks.Open(path)        ' si no esta, salta el 1004 y se lo traga
On Error GoTo 0
If wb Is Nothing Then MsgBox "Not found"

Esto funciona, pero es la peor de las tres opciones. Es lento (Excel de verdad intenta abrir el archivo), se traga errores no relacionados — un archivo corrupto, un problema de permisos, un archivo bloqueado, todos parecen idénticos a «no existe» — y se apoya en On Error Resume Next, que esconde bugs cuando se deja encendido. Comprobar la existencia es barato y preciso; renunciar a ello para apoyarte en un manejador de errores cambia una respuesta limpia por una turbia. Comprueba primero.

Las dos respuestas correctas

Dir — el one-liner del built-in. Sin comodín, Dir simplemente comprueba una ruta y devuelve el nombre del archivo si está ahí o "" si no:

If Dir("C:\Reports\March.xlsx") <> "" Then   ' "" significa no encontrado

Corto, sin referencias, sin objeto. Su única desventaja es el cursor compartido (siguiente sección).

FileSystemObject.FileExists — el valor por defecto sin estado. Un predicado de verdad que devuelve True/False y no toca ningún estado global:

Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\Reports\March.xlsx") Then ...

Se lee como lo que hace, distingue archivos de carpetas y — la razón por la que es el valor por defecto más seguro — puedes llamarlo en cualquier sitio, incluso en mitad de un bucle Dir, sin efectos secundarios. Usa enlace tardío (CreateObject) para que corra en cualquier máquina; ver VBA FileSystemObject.

La trampa que define este tema: comprobación con Dir dentro de un bucle Dir

Esta es la razón por la que las dos comprobaciones no son intercambiables, y es el mismo comportamiento de cursor oculto que gobierna Dir. Dir mantiene una sola posición de búsqueda a nivel de módulo. Llamar a Dir(path) para comprobar un archivo inicia una búsqueda nueva — borrando la posición de la que dependía tu bucle de enumeración:

name = Dir(folder & "*.xlsx")
Do While name <> ""
    If Dir(folder & "done\" & name) = "" Then    ' <- reinicia el cursor - el bucle se rompe
        Process folder & name
    End If
    name = Dir()          ' ahora avanza la busqueda de "done\", no la de *.xlsx
Loop

El Dir interno vuelve a sembrar el motor, así que el bucle se salta archivos, los repite o no termina nunca. La regla es absoluta: dentro de un bucle Dir, nunca llames a Dir para comprobar otro archivo — usa fso.FileExists en su lugar. No tiene ningún cursor que perturbar. Esta única interacción es la razón por la que «¿qué comprobación de existencia?» no es cuestión de gustos: si hay una enumeración Dir en cualquier punto de la ruta de llamadas, la respuesta es FileExists.

Cómo Dir maneja mal las carpetas y las barras invertidas finales

Incluso fuera de un bucle, Dir tiene dos casos límite que FileExists evita, porque Dir se construyó para coincidir con nombres, no para responder un sí/no limpio sobre un archivo:

  • Una ruta de carpeta. Dir("C:\Reports") puede devolver "Reports" — coincidiendo con la carpeta — así que una prueba de «el archivo existe» pasa para algo que es un directorio. fso.FileExists("C:\Reports") devuelve correctamente False (es una carpeta), y fso.FolderExists responde la pregunta de la carpeta por separado.
  • Una barra invertida final. Dir("C:\Reports\") comprueba la existencia de la carpeta, no de un archivo dentro de ella. Fácil de encontrártelo cuando construyes rutas por concatenación y dejas un separador perdido.

Por defecto Dir también se salta los archivos ocultos y de sistema, así que un archivo que existe de verdad pero está oculto se informa como ausente a menos que pases el atributo vbHidden. FileExists no tiene ninguna de estas ambigüedades — responde «hay un archivo exactamente en esta ruta», y punto.

Comprobar y luego abrir: la pequeña carrera, el arreglo práctico

Una advertencia honesta: entre el instante en que compruebas y el instante en que abres, otro proceso podría borrar o bloquear el archivo. En la práctica esta brecha de «tiempo de comprobación frente a tiempo de uso» es diminuta y rara vez importa — pero el patrón correcto no es elegir entre la comprobación y la protección de errores, es usar ambas:

If Not fso.FileExists(path) Then
    MsgBox "File not found: " & path       ' el caso esperado y comun - un mensaje limpio
    Exit Sub
End If
On Error GoTo OpenFailed                    ' el caso raro - bloqueado, corrupto, permisos
Set wb = Workbooks.Open(path)

La comprobación de existencia maneja el caso ordinario de «no está ahí» con un mensaje claro en lugar de una caída; el manejador de errores atrapa los fallos genuinamente excepcionales que la comprobación no puede predecir. Esa es la forma robusta para cualquier Workbooks.Open en un trabajo automatizado.

Relacionado: ¿el libro ya está abierto?

Un primo cercano de «¿existe el archivo?» es «¿ya está abierto en Excel?», y es una pregunta distinta con una respuesta distinta — recorrer Workbooks por nombre, sin tocar el disco:

Function IsOpen(fileName As String) As Boolean
    Dim wb As Workbook
    On Error Resume Next
    Set wb = Workbooks(fileName)     ' por nombre de archivo, p.ej. "March.xlsx"
    On Error GoTo 0
    IsOpen = Not wb Is Nothing
End Function

La existencia es sobre el disco; «ya abierto» es sobre la colección Workbooks en memoria. Abrir un archivo que ya está abierto no lo recarga — Excel simplemente activa la copia en memoria — así que una macro por lotes que podría ejecutarse dos veces debería comprobar esto antes de llamar a Workbooks.Open.

El veredicto honesto: qué comprobación, cuándo

  • Por defecto, fso.FileExists. No tiene estado, se lee con claridad, distingue el archivo de la carpeta y — el punto decisivo — es la única comprobación segura si hay un bucle Dir en juego.
  • Usa el one-liner de Dir solo para una prueba rápida y aislada donde no haya ninguna enumeración Dir en marcha y quieras cero preparación.
  • Nunca sustituyas la comprobación por un abrir-y-atrapar a secas; es más lento y esconde errores de verdad.
  • Empareja la comprobación con una protección de errores alrededor de la apertura — la comprobación para el caso común, el manejador para el raro.

Acierta con esto y el fallo de archivo número uno — un 1004 sobre una ruta que no está ahí — se convierte en un mensaje limpio de una línea que tu macro desatendida puede registrar y superar.

Cómo ayuda ExcelMaster

La comprobación de existencia parece trivial hasta que llegas a las partes que no lo son — el cursor de Dir que una comprobación perdida reinicia, la ruta de carpeta con la que una prueba de archivo coincide por error, la carrera que significa que todavía necesitas una protección de errores. Acertar con todo ello para cada archivo que toca una macro por lotes es un montón de fontanería cuidadosa.

ExcelMaster se encarga. Describe el trabajo — «para cada informe esperado, si el archivo está ahí impórtalo, si no regístralo como ausente y sigue» — y escribe comprobaciones con fso.FileExists que nunca perturban tu bucle de carpeta, empareja cada Workbooks.Open con un manejador de errores, y comprueba si un libro ya está abierto antes de reabrirlo. Tú describes el resultado; él hace las comprobaciones correctas y sin efectos secundarios.

Preguntas frecuentes

¿Cómo compruebo si un archivo existe en VBA?

Dos buenas formas. El one-liner del built-in es If Dir("C:\path\file.xlsx") <> "" ThenDir devuelve el nombre si el archivo existe y "" si no. La forma más clara y sin estado es CreateObject("Scripting.FileSystemObject").FileExists(path), que devuelve True/False y puede llamarse en cualquier sitio. Prefiere FileExists, y nunca compruebes con Dir dentro de un bucle Dir.

¿Por qué mi comprobación de archivo con Dir rompe mi bucle Dir?

Porque Dir mantiene un único cursor de búsqueda oculto. Llamar a Dir(otraRuta) para comprobar un archivo inicia una búsqueda nueva y borra la posición de la que depende tu bucle de enumeración, así que el bucle se salta archivos, los repite o corre para siempre. Dentro de un bucle Dir, usa fso.FileExists para comprobar otros archivos — no tiene estado compartido.

¿Debo usar Dir o FileSystemObject para comprobar que un archivo existe?

Usa FileSystemObject.FileExists como valor por defecto — no tiene estado, distingue archivos de carpetas, y es seguro de llamar dentro de un bucle Dir. Usa el one-liner de Dir solo para una comprobación rápida y aislada donde no haya ninguna enumeración Dir en marcha y no quieras preparación. Ver VBA FileSystemObject.

¿Dir devuelve verdadero para una carpeta?

Puede. Dir("C:\Reports") puede devolver "Reports", coincidiendo con la carpeta, así que una prueba ingenua de «el archivo existe» pasa para un directorio. Y Dir("C:\Reports\") con una barra invertida final comprueba la carpeta, no un archivo dentro de ella. FileSystemObject.FileExists evita ambos respondiendo estrictamente sobre un archivo, con FolderExists para la pregunta de la carpeta.

¿Cómo compruebo si un libro ya está abierto en VBA?

Esa es una pregunta distinta — es sobre memoria, no sobre disco. Recorre la colección Workbooks por nombre de archivo: Set wb = Workbooks("March.xlsx") dentro de un bloque On Error Resume Next, luego comprueba Not wb Is Nothing. Abrir un archivo que ya está abierto no lo recarga, así que una macro que podría ejecutarse dos veces debería comprobar esto antes de llamar a Workbooks.Open.

Probado en

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

Guías relacionadas: VBA Dir · VBA FileSystemObject · VBA Open Workbook · VBA On Error · VBA Close Workbook