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

VBA Check If File Exists — Dir contre FileSystemObject.FileExists, et le piège à l'intérieur d'une boucle Dir

|

VBA Check If File Exists — Dir contre FileSystemObject.FileExists, et le piège à l'intérieur d'une boucle Dir

TL;DR — Deux façons correctes, une pour chaque boîte à outils. Dir est la ligne unique quand vous êtes loin de toute boucle Dir ; FileSystemObject.FileExists est le choix par défaut sûr parce qu'il n'a aucun état caché :

' Integre, une ligne - mais partage l'unique curseur global de Dir :
If Dir("C:\Reports\March.xlsx") <> "" Then MsgBox "It's there"

' Sans etat, plus clair, distingue fichier et dossier - le choix par defaut le plus sur :
Dim fso As Object: Set fso = CreateObject("Scripting.FileSystemObject")
If fso.FileExists("C:\Reports\March.xlsx") Then MsgBox "It's there"

« Ce fichier existe-t-il ? » est la question de fichier la plus recherchée en VBA, parce que l'alternative — ouvrir un fichier qui n'est pas là — lève l'erreur d'exécution 1004 et arrête net une macro sans surveillance. La bonne nouvelle, c'est que la vérification tient en une ligne. Le hic, c'est que la ligne unique évidente, Dir, porte le même curseur caché qui anime une boucle Dir — si bien que l'endroit où vous l'appelez compte autant que la façon dont vous l'appelez.

Ce que vous allez apprendre

  • Le mauvais réflexe — « ouvre-le et piège l'erreur » — et pourquoi c'est la pire option
  • Les deux bonnes réponses — Dir et FileSystemObject.FileExists
  • Le piège qui définit ce sujet — le test Dir réinitialise une boucle Dir
  • Comment Dir gère mal un chemin de dossier ou une barre oblique inverse finale
  • FileExists contre FolderExists — dites exactement ce que vous voulez dire
  • Pourquoi « vérifier puis ouvrir » exige encore un garde-fou d'erreur (la minuscule course, et le correctif pratique)

Le mauvais réflexe : ouvre-le et attrape l'erreur

Le raccourci tentant est de sauter la vérification entièrement et de laisser l'échec vous prévenir :

On Error Resume Next
Set wb = Workbooks.Open(path)        ' s'il est absent, 1004 se declenche et est avale
On Error GoTo 0
If wb Is Nothing Then MsgBox "Not found"

Ça marche, mais c'est la pire des trois options. C'est lent (Excel tente réellement d'ouvrir le fichier), ça avale les erreurs sans rapport — un fichier corrompu, un problème de permissions, un fichier verrouillé ressemblent tous à « absent » — et ça s'appuie sur On Error Resume Next, qui masque les bugs quand on le laisse activé. Tester l'existence est peu coûteux et précis ; y renoncer pour s'appuyer sur un gestionnaire d'erreurs échange une réponse nette contre une réponse trouble. Vérifiez d'abord.

Les deux bonnes réponses

Dir — la ligne unique intégrée. Sans caractère générique, Dir teste simplement un chemin et renvoie le nom de fichier s'il est là ou "" s'il ne l'est pas :

If Dir("C:\Reports\March.xlsx") <> "" Then   ' "" signifie introuvable

Court, aucune référence, aucun objet. Sa seule faiblesse est le curseur partagé (section suivante).

FileSystemObject.FileExists — le choix par défaut sans état. Un véritable prédicat qui renvoie True/False et ne touche à aucun état global :

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

Il se lit comme ce qu'il fait, distingue les fichiers des dossiers, et — la raison pour laquelle c'est le choix par défaut le plus sûr — vous pouvez l'appeler n'importe où, y compris au milieu d'une boucle Dir, sans effet de bord. Utilisez la liaison tardive (CreateObject) pour qu'il tourne sur toutes les machines ; voir VBA FileSystemObject.

Le piège qui définit ce sujet : le test Dir dans une boucle Dir

C'est la raison pour laquelle les deux tests ne sont pas interchangeables, et c'est le même comportement de curseur caché qui gouverne Dir. Dir conserve une position de recherche à l'échelle du module. Appeler Dir(path) pour tester un fichier lance une nouvelle recherche — effaçant la position sur laquelle votre boucle d'énumération comptait :

name = Dir(folder & "*.xlsx")
Do While name <> ""
    If Dir(folder & "done\" & name) = "" Then    ' <- reinitialise le curseur - la boucle casse
        Process folder & name
    End If
    name = Dir()          ' avance desormais la recherche "done\", pas la recherche *.xlsx
Loop

Le Dir interne ré-amorce le moteur, si bien que la boucle saute des fichiers, les répète, ou ne finit jamais. La règle est absolue : à l'intérieur d'une boucle Dir, n'appelez jamais Dir pour vérifier un autre fichier — utilisez fso.FileExists à la place. Il n'a aucun curseur à perturber. Cette seule interaction est la raison pour laquelle « quel test d'existence ? » n'est pas une affaire de goût : si une énumération Dir se trouve quelque part sur le chemin d'appel, la réponse est FileExists.

Comment Dir gère mal les dossiers et les barres obliques inverses finales

Même hors d'une boucle, Dir a deux cas limites que FileExists évite, parce que Dir a été conçu pour faire correspondre des noms, pas pour répondre par un oui/non net à propos d'un fichier :

  • Un chemin de dossier. Dir("C:\Reports") peut renvoyer "Reports" — en correspondant au dossier — si bien qu'un test « le fichier existe » passe pour quelque chose qui est un répertoire. fso.FileExists("C:\Reports") renvoie correctement False (c'est un dossier), et fso.FolderExists répond séparément à la question du dossier.
  • Une barre oblique inverse finale. Dir("C:\Reports\") teste l'existence du dossier, pas d'un fichier à l'intérieur. Facile à déclencher quand vous construisez des chemins par concaténation et laissez un séparateur parasite.

Par défaut, Dir ignore aussi les fichiers cachés et système, si bien qu'un fichier qui existe vraiment mais qui est caché se déclare comme absent, à moins que vous ne passiez l'attribut vbHidden. FileExists n'a aucune de ces ambiguïtés — il répond à « y a-t-il un fichier exactement à ce chemin », point final.

Vérifier puis ouvrir : la petite course, le correctif pratique

Une réserve honnête : entre l'instant où vous vérifiez et l'instant où vous ouvrez, un autre processus pourrait supprimer ou verrouiller le fichier. En pratique, cet écart « moment de la vérification / moment de l'usage » est minuscule et compte rarement — mais le motif correct n'est pas de choisir entre la vérification et le garde-fou d'erreur, c'est d'utiliser les deux :

If Not fso.FileExists(path) Then
    MsgBox "File not found: " & path       ' le cas courant et attendu - un message propre
    Exit Sub
End If
On Error GoTo OpenFailed                    ' le cas rare - verrouille, corrompu, permissions
Set wb = Workbooks.Open(path)

La vérification d'existence gère le cas ordinaire « il n'est pas là » avec un message clair au lieu d'un plantage ; le gestionnaire d'erreurs attrape les échecs véritablement exceptionnels que la vérification ne peut pas prévoir. C'est la forme robuste pour tout Workbooks.Open dans une tâche automatisée.

Connexe : le classeur est-il déjà ouvert ?

Un proche cousin de « le fichier existe-t-il » est « est-il déjà ouvert dans Excel », et c'est une question différente avec une réponse différente — parcourir Workbooks par nom, sans toucher au disque :

Function IsOpen(fileName As String) As Boolean
    Dim wb As Workbook
    On Error Resume Next
    Set wb = Workbooks(fileName)     ' par nom de fichier, ex. "March.xlsx"
    On Error GoTo 0
    IsOpen = Not wb Is Nothing
End Function

L'existence concerne le disque ; « déjà ouvert » concerne la collection Workbooks en mémoire. Ouvrir un fichier déjà ouvert ne le recharge pas — Excel se contente d'activer la copie en mémoire — si bien qu'une macro par lots susceptible de tourner deux fois devrait tester ceci avant d'appeler Workbooks.Open.

Le verdict honnête : quel test, quand

  • Par défaut, fso.FileExists. Il est sans état, se lit clairement, distingue le fichier du dossier, et — le point décisif — c'est le seul test sûr si une boucle Dir est en jeu quelque part.
  • Utilisez la ligne unique Dir seulement pour un test rapide et isolé, là où aucune énumération Dir ne tourne et où vous voulez zéro installation.
  • Ne remplacez jamais la vérification par un simple ouvre-et-piège ; c'est plus lent et ça masque les vraies erreurs.
  • Associez la vérification à un garde-fou d'erreur autour de l'ouverture — la vérification pour le cas courant, le gestionnaire pour le cas rare.

Réussissez cela et le plantage de fichier numéro un — un 1004 sur un chemin qui n'est pas là — devient un message propre d'une ligne que votre macro sans surveillance peut journaliser avant de passer à la suite.

Comment ExcelMaster aide

La vérification d'existence paraît triviale jusqu'à ce que vous heurtiez les parties qui ne le sont pas — le curseur Dir qu'un test égaré réinitialise, le chemin de dossier qu'un test de fichier fait correspondre à tort, la course qui fait que vous avez encore besoin d'un garde-fou d'erreur. Réussir tout cela pour chaque fichier qu'une macro par lots touche représente beaucoup de plomberie soigneuse.

ExcelMaster s'en charge. Décrivez la tâche — « pour chaque rapport attendu, si le fichier est là importe-le, sinon journalise-le comme manquant et continue » — et il écrit des vérifications fso.FileExists qui ne perturbent jamais votre boucle de dossier, associe chaque Workbooks.Open à un gestionnaire d'erreurs, et teste si un classeur est déjà ouvert avant de le rouvrir. Vous décrivez le résultat ; il rend les vérifications correctes et sans effet de bord.

Questions fréquentes

Comment vérifier si un fichier existe en VBA ?

Deux bonnes façons. La ligne unique intégrée est If Dir("C:\path\file.xlsx") <> "" ThenDir renvoie le nom si le fichier existe et "" sinon. La façon plus claire et sans état est CreateObject("Scripting.FileSystemObject").FileExists(path), qui renvoie True/False et peut être appelée n'importe où. Préférez FileExists, et ne testez jamais avec Dir à l'intérieur d'une boucle Dir.

Pourquoi mon test de fichier Dir casse-t-il ma boucle Dir ?

Parce que Dir conserve un unique curseur de recherche caché. Appeler Dir(autreChemin) pour tester un fichier lance une nouvelle recherche et efface la position dont dépend votre boucle d'énumération, si bien que la boucle saute alors des fichiers, les répète, ou tourne sans fin. À l'intérieur d'une boucle Dir, utilisez fso.FileExists pour vérifier d'autres fichiers — il n'a aucun état partagé.

Dois-je utiliser Dir ou FileSystemObject pour vérifier qu'un fichier existe ?

Utilisez FileSystemObject.FileExists par défaut — il est sans état, distingue les fichiers des dossiers, et peut être appelé sans danger à l'intérieur d'une boucle Dir. Utilisez la ligne unique Dir seulement pour une vérification rapide et isolée, là où aucune énumération Dir ne tourne et où vous ne voulez aucune installation. Voir VBA FileSystemObject.

Dir renvoie-t-il vrai pour un dossier ?

Cela peut arriver. Dir("C:\Reports") peut renvoyer "Reports", en correspondant au dossier, si bien qu'un test naïf « le fichier existe » passe pour un répertoire. Et Dir("C:\Reports\") avec une barre oblique inverse finale teste le dossier, pas un fichier à l'intérieur. FileSystemObject.FileExists évite les deux en répondant strictement à propos d'un fichier, avec FolderExists pour la question du dossier.

Comment vérifier si un classeur est déjà ouvert en VBA ?

C'est une question différente — elle concerne la mémoire, pas le disque. Parcourez la collection Workbooks par nom de fichier : Set wb = Workbooks("March.xlsx") à l'intérieur d'un bloc On Error Resume Next, puis testez Not wb Is Nothing. Ouvrir un fichier déjà ouvert ne le recharge pas, si bien qu'une macro susceptible de tourner deux fois devrait vérifier ceci avant d'appeler Workbooks.Open.

Testé dans

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

Guides associés : VBA Dir · VBA FileSystemObject · VBA Open Workbook · VBA On Error · VBA Close Workbook