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

VBA FileSystemObject en Excel — CreateObject frente a referencia, subcarpetas y por qué no abre libros

|

VBA FileSystemObject en Excel — CreateObject frente a referencia, subcarpetas y por qué no abre libros

TL;DR — El FileSystemObject (FSO) es un modelo de objetos para el disco: créalo una vez, luego recorre Files y SubFolders y lee propiedades como Size y DateLastModified. Créalo con enlace tardío para que corra en cualquier máquina — sin ninguna referencia que marcar:

Sub ListWithSizes()
    Dim fso As Object, folder As Object, file As Object
    Set fso = CreateObject("Scripting.FileSystemObject")   ' enlace tardio - no hace falta referencia
    Set folder = fso.GetFolder("C:\Reports")
    For Each file In folder.Files                          ' una coleccion real, no un cursor
        Debug.Print file.Name, file.Size, file.DateLastModified
    Next file
End Sub

Donde Dir es un built-in escueto con un único cursor oculto, el FileSystemObject trata el sistema de archivos como el resto de VBA trata un libro — como objetos con propiedades que puedes recorrer e inspeccionar. Esa mejora es lo que compras: subcarpetas, metadatos de archivo y bucles anidados seguros. El precio es un objeto que crear, y una decisión — cómo lo enlazas — que decide en silencio si tu macro corre en el ordenador de cualquier otra persona.

Lo que aprenderás

  • El modelo mental — el sistema de archivos como Folders y Files, cada uno un objeto con propiedades
  • La única decisión con la que todo el mundo tropieza — CreateObject (enlace tardío) frente a Dim … As New (enlace temprano)
  • Cómo entrar de forma recursiva en las subcarpetas, lo que Dir sencillamente no puede hacer
  • Leer metadatos — Size, DateLastModified, Name, ParentFolder
  • FileExists y FolderExists — la forma limpia de comprobar antes de actuar
  • Por qué FSO abre archivos de texto pero nunca abre un libro de Excel

El modelo mental: el disco como un modelo de objetos

En todos los demás sitios de VBA trabajas con objetos — un Workbook tiene Sheets, un Worksheet tiene un Range. El FileSystemObject extiende esa misma idea al disco:

  • un fso te da GetFolder(path) y GetFile(path)
  • una Folder tiene una colección .Files, una colección .SubFolders y un .Name
  • un File tiene .Name, .Size, .DateLastModified, .ParentFolder, .Path

Así que en lugar de sembrar un cursor y hacerlo avanzar, escribes el bucle que ya conoces — For Each file In folder.Files — y metes la mano en cada objeto para lo que necesites. No hay estado oculto, así que puedes anidar bucles con libertad (archivos dentro de subcarpetas dentro de subcarpetas) sin que nada se reinicie por debajo.

La única decisión con la que todo el mundo tropieza: CreateObject frente a New

Hay dos maneras de crear un fso, y la diferencia decide si tu macro sobrevive a que se la envíes por correo a un colega. Este es el bug número uno del FileSystemObject.

Enlace temprano — de aspecto limpio, pero frágil:

Dim fso As New FileSystemObject      ' necesita Tools > References > Microsoft Scripting Runtime

Esto compila solo si esa máquina tiene marcada la referencia Microsoft Scripting Runtime. Escríbelo en tu PC, donde la casilla está marcada, envía el archivo a alguien cuya casilla no lo está, y no compila con User-defined type not defined («tipo definido por el usuario no definido») — antes de que se ejecute una sola línea. A cambio obtienes IntelliSense, pero has atado el libro a la configuración de una máquina.

Enlace tardío — el valor por defecto portable:

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")   ' se resuelve en tiempo de ejecucion, sin referencia

CreateObject busca el componente por su nombre en tiempo de ejecución, así que no hace falta ninguna referencia y el libro corre en cualquier sitio donde esté instalado Windows Scripting (es decir, en todas partes). Pierdes el IntelliSense en tiempo de compilación; ganas una macro que sencillamente funciona cuando se distribuye. Para cualquier cosa que compartas, usa enlace tardío y declara tus variables As Object. Esa única elección elimina toda la clase de informes de «funciona en mi máquina».

Subcarpetas: lo que Dir no puede hacer

La razón más clara para dejar atrás Dir es un árbol de carpetas. La colección SubFolders de FSO más un Sub recursivo recorre cualquier profundidad, algo que el único cursor de Dir hace imposible:

Sub WalkTree(folderPath As String)
    Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
    ProcessFolder fso.GetFolder(folderPath), fso
End Sub

Sub ProcessFolder(fld As Object, fso As Object)
    Dim file As Object, sub_ As Object
    For Each file In fld.Files
        If LCase(fso.GetExtensionName(file.Name)) = "xlsx" Then Debug.Print file.Path
    Next file
    For Each sub_ In fld.SubFolders          ' recurre - Dir no puede anidar asi
        ProcessFolder sub_, fso
    Next sub_
End Sub

Cada Folder lleva sus propios .Files y .SubFolders, así que el anidamiento y la recursión son seguros — no hay ningún cursor compartido que corromper. Fíjate en fso.GetExtensionName y sus hermanos (GetBaseName, BuildPath, GetParentFolderName) — ayudantes de rutas sin líos de cadenas que sustituyen al quisquilloso troceado con InStrRev.

Leer metadatos: tamaño, fecha, nombre

La otra razón para elegir FSO es que un objeto File sabe cosas sobre sí mismo que Dir nunca expone:

For Each file In folder.Files
    If file.DateLastModified < Now - 30 Then       ' mas antiguo que 30 dias
        Debug.Print file.Name & " - " & Format(file.Size / 1024, "0") & " KB"
    End If
Next file

Size, DateLastModified, DateCreated, Type, Attributes — todos a una propiedad de distancia. Filtrar «cada libro modificado esta semana» o «borra los archivos temporales de más de 10 MB» es trivial con FSO y doloroso con Dir.

FileExists y FolderExists: comprueba antes de actuar

FSO te da dos predicados sin estado que son la forma más limpia de comprobar si hay un archivo — y, lo crucial, no tienen ningún cursor oculto, así que a diferencia de Dir puedes llamarlos en cualquier sitio, incluso dentro de un bucle Dir:

If fso.FileExists("C:\Reports\March.xlsx") Then ...
If fso.FolderExists("C:\Reports\2026") Then ...

FileExists y FolderExists son distintos — Dir mezcla los dos — así que dices exactamente lo que quieres decir y nunca coincides por accidente con una carpeta cuando querías un archivo.

La trampa: FSO no abre libros

Aquí está la confusión que manda a la gente en círculos. El FileSystemObject puede crear, leer y escribir archivos de texto plano (CreateTextFile, OpenTextFile) — registros, CSV tratados como texto crudo, archivos .ini. Puede hacer CopyFile, MoveFile, DeleteFile. Lo que no puede hacer es abrir un libro de Excel:

Set wb = fso.OpenTextFile("C:\Reports\March.xlsx")   ' MAL - te da bytes XML/zip crudos, no un libro
Set wb = Workbooks.Open("C:\Reports\March.xlsx")     ' BIEN - un libro lo abre Excel, no FSO

FSO encuentra y gestiona archivos; Workbooks.Open es lo que convierte un archivo en un libro vivo del que puedes leer celdas. La macro por lotes idiomática usa ambos: FSO (o Dir) para enumerar la carpeta, luego Workbooks.Open para abrir cada resultado. Mantén los dos trabajos separados en tu cabeza y todo el patrón encaja.

El veredicto honesto: cuándo FSO le gana a Dir

Dir gana en un solo eje — cero preparación para un bucle plano de una sola carpeta. El FileSystemObject gana en todo lo demás, y la decisión es mecánica:

  • ¿Necesitas subcarpetas? FSO — Dir no puede recursar.
  • ¿Necesitas el tamaño, la fecha o el tipo? FSO — Dir devuelve solo un nombre.
  • ¿Copiar, mover, borrar o escribir archivos de texto? FSO — es un kit completo.
  • ¿Un bucle rápido *.xlsx de una carpeta sin nada añadido? Dir va bien y es más corto.
  • Sea como sea que enumeres, abre los libros con Workbooks.Open — nunca con FSO.

Y sea cual sea el que distribuyas, crea el objeto con CreateObject, no con New, para que corra en cualquier máquina y no solo en la tuya.

Cómo ayuda ExcelMaster

El FileSystemObject es potente precisamente porque es un modelo de objetos — pero eso significa acordarse de enlazarlo tarde para que sea portable, de recursar SubFolders para un árbol, de leer la propiedad de metadatos correcta, y de entregar cada archivo a Workbooks.Open en lugar de esperar que FSO lo abra. Pequeñas elecciones, cada una de las cuales decide en silencio si la macro corre en el PC de la siguiente persona.

ExcelMaster toma esas decisiones por ti. Describe la tarea — «recorre cada subcarpeta bajo Reports, encuentra los libros modificados este mes y copia sus totales en un resumen» — y escribe un recorrido FSO de enlace tardío con el bucle recursivo de SubFolders, el filtro de DateLastModified, y un Workbooks.Open / Close correspondiente para cada acierto. Tú describes el resultado; él conecta el modelo de objetos correctamente a la primera.

Preguntas frecuentes

¿Qué es el FileSystemObject en VBA?

El FileSystemObject (FSO) es un componente de Windows Scripting que expone el sistema de archivos como un modelo de objetos — objetos Folder y File con colecciones (Files, SubFolders) y propiedades (Name, Size, DateLastModified). Lo creas con CreateObject("Scripting.FileSystemObject") y lo usas para enumerar, copiar, mover, borrar y leer archivos de texto. A diferencia de Dir, no tiene ningún cursor oculto, así que los bucles se anidan de forma segura.

¿CreateObject o Dim As New FileSystemObject — cuál debo usar?

Usa Set fso = CreateObject("Scripting.FileSystemObject") (enlace tardío). No necesita ninguna referencia y corre en cualquier máquina. Dim fso As New FileSystemObject (enlace temprano) requiere que la referencia Microsoft Scripting Runtime esté marcada en Tools ▸ References, así que un libro que compila en tu PC falla con User-defined type not defined en el de un colega. El enlace tardío es el valor por defecto portable para cualquier cosa que distribuyas.

¿Cómo recorro las subcarpetas con el FileSystemObject?

Obtén la carpeta con fso.GetFolder(path), recorre su colección .SubFolders, y llama a la misma rutina de forma recursiva sobre cada subcarpeta. Como cada Folder tiene sus propios .Files y .SubFolders, la recursión es segura — no hay estado compartido que reiniciar. Esto es exactamente lo que Dir no puede hacer.

¿Puede el FileSystemObject abrir un libro de Excel?

No. FSO abre y escribe archivos de texto (OpenTextFile, CreateTextFile) y puede copiar, mover o borrar cualquier archivo, pero no puede abrir un libro. Úsalo para encontrar archivos, luego abre cada uno con Workbooks.Open. fso.OpenTextFile sobre un .xlsx devuelve bytes crudos, no un libro.

¿Cómo obtengo el tamaño o la fecha de modificación de un archivo en VBA?

Usa el FileSystemObject: fso.GetFile(path).Size devuelve los bytes y .DateLastModified devuelve la marca de tiempo. Dentro de un bucle de carpeta, lee file.Size y file.DateLastModified directamente en cada objeto File. Dir no puede darte ninguno de los dos — devuelve solo el nombre — que es una de las razones principales para preferir FSO para cualquier cosa más allá de un listado plano.

Probado en

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

Guías relacionadas: VBA Dir · VBA Check If File Exists · VBA Open Workbook · VBA Save Workbook · VBA On Error