TL;DR — El
FileSystemObject(FSO) es un modelo de objetos para el disco: créalo una vez, luego recorreFilesySubFoldersy lee propiedades comoSizeyDateLastModified. 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 aDim … As New(enlace temprano) - Cómo entrar de forma recursiva en las subcarpetas, lo que
Dirsencillamente no puede hacer - Leer metadatos —
Size,DateLastModified,Name,ParentFolder FileExistsyFolderExists— 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
fsote daGetFolder(path)yGetFile(path) - una
Foldertiene una colección.Files, una colección.SubFoldersy un.Name - un
Filetiene.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 —
Dirno puede recursar. - ¿Necesitas el tamaño, la fecha o el tipo? FSO —
Dirdevuelve solo un nombre. - ¿Copiar, mover, borrar o escribir archivos de texto? FSO — es un kit completo.
- ¿Un bucle rápido
*.xlsxde una carpeta sin nada añadido?Dirva 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
