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

VBA FileSystemObject dans Excel — CreateObject contre référence, sous-dossiers, et pourquoi il n'ouvre pas les classeurs

|

VBA FileSystemObject dans Excel — CreateObject contre référence, sous-dossiers, et pourquoi il n'ouvre pas les classeurs

TL;DR — Le FileSystemObject (FSO) est un modèle objet pour le disque : créez-le une fois, puis parcourez Files et SubFolders et lisez des propriétés comme Size et DateLastModified. Créez-le en liaison tardive pour qu'il tourne sur toutes les machines — aucune référence à cocher :

Sub ListWithSizes()
    Dim fso As Object, folder As Object, file As Object
    Set fso = CreateObject("Scripting.FileSystemObject")   ' liaison tardive - aucune reference requise
    Set folder = fso.GetFolder("C:\Reports")
    For Each file In folder.Files                          ' une vraie collection, pas un curseur
        Debug.Print file.Name, file.Size, file.DateLastModified
    Next file
End Sub

Là où Dir est un mot-clé intégré et laconique doté d'un unique curseur caché, le FileSystemObject traite le système de fichiers comme le reste de VBA traite un classeur — comme des objets dotés de propriétés que vous pouvez parcourir et inspecter. C'est cette montée en gamme que vous achetez : sous-dossiers, métadonnées de fichiers, et boucles imbriquées sûres. Le prix, c'est un objet à créer, et une décision — comment vous le liez — qui détermine discrètement si votre macro tourne sur l'ordinateur de quelqu'un d'autre.

Ce que vous allez apprendre

  • Le modèle mental — le système de fichiers vu comme des dossiers et des fichiers, chacun un objet doté de propriétés
  • La décision unique qui piège tout le monde — CreateObject (liaison tardive) contre Dim … As New (liaison précoce)
  • Comment récurser dans les sous-dossiers, ce que Dir ne sait tout simplement pas faire
  • Lire les métadonnées — Size, DateLastModified, Name, ParentFolder
  • FileExists et FolderExists — la façon propre de vérifier avant d'agir
  • Pourquoi FSO ouvre les fichiers texte mais jamais un classeur Excel

Le modèle mental : le disque comme modèle objet

Partout ailleurs en VBA, vous travaillez avec des objets — un Workbook a des Sheets, un Worksheet a un Range. Le FileSystemObject étend cette même idée au disque :

  • un fso vous donne GetFolder(path) et GetFile(path)
  • un Folder a une collection .Files, une collection .SubFolders, et un .Name
  • un File a .Name, .Size, .DateLastModified, .ParentFolder, .Path

Ainsi, au lieu d'amorcer un curseur et de le faire avancer, vous écrivez la boucle que vous connaissez déjà — For Each file In folder.Files — et vous atteignez dans chaque objet ce dont vous avez besoin. Il n'y a aucun état caché, si bien que vous pouvez imbriquer les boucles librement (des fichiers dans des sous-dossiers dans des sous-dossiers) sans que rien ne se réinitialise sous vos pieds.

La décision unique qui piège tout le monde : CreateObject contre New

Il y a deux façons de fabriquer un fso, et la différence décide si votre macro survit à un envoi par courriel à un collègue. C'est le bug FileSystemObject numéro un.

Liaison précoce — d'apparence propre, mais fragile :

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

Cela compile uniquement si cette machine a la référence Microsoft Scripting Runtime cochée. Écrivez-le sur votre PC où la case est cochée, envoyez le fichier à quelqu'un dont la case ne l'est pas, et il échoue à compiler avec User-defined type not defined — avant qu'une seule ligne ne s'exécute. Vous obtenez l'IntelliSense en échange, mais vous avez lié le classeur aux réglages d'une seule machine.

Liaison tardive — le choix par défaut portable :

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")   ' resolue a l'execution, aucune reference

CreateObject recherche le composant par son nom à l'exécution, si bien qu'aucune référence n'est requise et que le classeur tourne partout où Windows Scripting est installé (c'est-à-dire partout). Vous perdez l'IntelliSense à la compilation ; vous gagnez une macro qui fonctionne simplement une fois distribuée. Pour tout ce que vous partagez, utilisez la liaison tardive et déclarez vos variables As Object. Ce seul choix supprime toute la catégorie des rapports « ça marche sur ma machine ».

Sous-dossiers : ce que Dir ne sait pas faire

La raison la plus claire de laisser Dir derrière soi, c'est une arborescence de dossiers. La collection SubFolders de FSO plus un Sub récursif parcourt n'importe quelle profondeur, ce que l'unique curseur de Dir rend impossible :

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          ' recursion - Dir ne peut pas imbriquer ainsi
        ProcessFolder sub_, fso
    Next sub_
End Sub

Chaque Folder porte ses propres .Files et .SubFolders, si bien que l'imbrication et la récursion sont sûres — il n'y a aucun curseur partagé à corrompre. Notez fso.GetExtensionName et ses semblables (GetBaseName, BuildPath, GetParentFolderName) — des utilitaires de chemin sans manipulation de chaînes qui remplacent le fastidieux découpage à coups d'InStrRev.

Lire les métadonnées : taille, date, nom

L'autre raison de choisir FSO, c'est qu'un objet File sait des choses sur lui-même que Dir n'expose jamais :

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

Size, DateLastModified, DateCreated, Type, Attributes — tous à une propriété de distance. Filtrer « chaque classeur modifié cette semaine » ou « supprimer les fichiers temporaires de plus de 10 Mo » est trivial avec FSO et pénible avec Dir.

FileExists et FolderExists : vérifier avant d'agir

FSO vous donne deux prédicats sans état qui sont la façon la plus propre de tester la présence d'un fichier — et, ce qui est crucial, ils n'ont aucun curseur caché, si bien que contrairement à Dir, vous pouvez les appeler n'importe où, même à l'intérieur d'une boucle Dir :

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

FileExists et FolderExists sont distincts — Dir confond les deux — si bien que vous dites exactement ce que vous voulez dire et ne correspondez jamais par accident à un dossier alors que vous vouliez un fichier.

Le piège : FSO n'ouvre pas les classeurs

Voici la confusion qui fait tourner les gens en rond. Le FileSystemObject peut créer, lire et écrire des fichiers texte bruts (CreateTextFile, OpenTextFile) — des journaux, des CSV traités comme du texte brut, des fichiers .ini. Il peut faire CopyFile, MoveFile, DeleteFile. Ce qu'il ne peut pas faire, c'est ouvrir un classeur Excel :

Set wb = fso.OpenTextFile("C:\Reports\March.xlsx")   ' FAUX - vous obtenez des octets XML/zip bruts, pas un classeur
Set wb = Workbooks.Open("C:\Reports\March.xlsx")     ' CORRECT - un classeur est ouvert par Excel, pas par FSO

FSO trouve et gère les fichiers ; c'est Workbooks.Open qui transforme un fichier en classeur vivant dont vous pouvez lire les cellules. La macro par lots idiomatique utilise les deux : FSO (ou Dir) pour énumérer le dossier, puis Workbooks.Open pour ouvrir chaque résultat. Gardez les deux tâches séparées dans votre tête et tout le motif s'emboîte.

Le verdict honnête : quand FSO surpasse Dir

Dir l'emporte sur un seul axe — zéro installation pour une boucle plate sur un seul dossier. Le FileSystemObject l'emporte partout ailleurs, et la décision est mécanique :

  • Besoin de sous-dossiers ? FSO — Dir ne sait pas récurser.
  • Besoin de la taille, de la date ou du type ? FSO — Dir ne renvoie qu'un nom.
  • Copier, déplacer, supprimer, ou écrire des fichiers texte ? FSO — c'est une boîte à outils complète.
  • Une boucle rapide *.xlsx sur un seul dossier sans rien ajouter ? Dir convient et il est plus court.
  • Quelle que soit la façon d'énumérer, ouvrez les classeurs avec Workbooks.Open — jamais avec FSO.

Et quel que soit celui que vous distribuez, créez l'objet avec CreateObject, pas New, pour qu'il tourne sur toutes les machines et pas seulement la vôtre.

Comment ExcelMaster aide

Le FileSystemObject est puissant précisément parce qu'il est un modèle objet — mais cela signifie penser à le lier tardivement pour la portabilité, à récurser SubFolders pour une arborescence, à lire la bonne propriété de métadonnée, et à confier chaque fichier à Workbooks.Open plutôt que d'attendre de FSO qu'il l'ouvre. De petits choix, dont chacun décide discrètement si la macro tourne sur le PC de la personne suivante.

ExcelMaster fait ces choix pour vous. Décrivez la tâche — « parcours chaque sous-dossier sous Reports, trouve les classeurs modifiés ce mois-ci, et copie leurs totaux dans une synthèse » — et il écrit un parcours FSO à liaison tardive avec la boucle récursive SubFolders, le filtre DateLastModified, et un Workbooks.Open / Close correspondant pour chaque résultat. Vous décrivez le résultat ; il assemble le modèle objet correctement du premier coup.

Questions fréquentes

Qu'est-ce que le FileSystemObject en VBA ?

Le FileSystemObject (FSO) est un composant Windows Scripting qui expose le système de fichiers comme un modèle objet — des objets Folder et File avec des collections (Files, SubFolders) et des propriétés (Name, Size, DateLastModified). Vous le créez avec CreateObject("Scripting.FileSystemObject") et l'utilisez pour énumérer, copier, déplacer, supprimer et lire des fichiers texte. Contrairement à Dir, il n'a aucun curseur caché, si bien que les boucles s'imbriquent sans danger.

CreateObject ou Dim As New FileSystemObject — lequel utiliser ?

Utilisez Set fso = CreateObject("Scripting.FileSystemObject") (liaison tardive). Il n'exige aucune référence et tourne sur n'importe quelle machine. Dim fso As New FileSystemObject (liaison précoce) exige que la référence Microsoft Scripting Runtime soit cochée sous Tools ▸ References, si bien qu'un classeur qui compile sur votre PC échoue avec User-defined type not defined sur celui d'un collègue. La liaison tardive est le choix par défaut portable pour tout ce que vous distribuez.

Comment parcourir les sous-dossiers avec le FileSystemObject ?

Obtenez le dossier avec fso.GetFolder(path), parcourez sa collection .SubFolders, et appelez la même routine récursivement sur chaque sous-dossier. Parce que chaque Folder a ses propres .Files et .SubFolders, la récursion est sûre — il n'y a aucun état partagé à réinitialiser. C'est exactement ce que Dir ne sait pas faire.

Le FileSystemObject peut-il ouvrir un classeur Excel ?

Non. FSO ouvre et écrit des fichiers texte (OpenTextFile, CreateTextFile) et peut copier, déplacer ou supprimer n'importe quel fichier, mais il ne peut pas ouvrir un classeur. Utilisez-le pour trouver les fichiers, puis ouvrez chacun avec Workbooks.Open. fso.OpenTextFile sur un .xlsx renvoie des octets bruts, pas un classeur.

Comment obtenir la taille ou la date de modification d'un fichier en VBA ?

Utilisez le FileSystemObject : fso.GetFile(path).Size renvoie les octets et .DateLastModified renvoie l'horodatage. À l'intérieur d'une boucle de dossier, lisez file.Size et file.DateLastModified directement sur chaque objet File. Dir ne peut vous donner ni l'un ni l'autre — il ne renvoie que le nom — ce qui est l'une des principales raisons de préférer FSO pour tout ce qui dépasse une liste plate.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 21/08/2026.

Guides associés : VBA Dir · VBA Check If File Exists · VBA Open Workbook · VBA Save Workbook · VBA On Error