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

VBA Copy File dans Excel — FileCopy, FileSystemObject.CopyFile, et pourquoi il ne peut pas copier un classeur ouvert

|

VBA Copy File dans Excel — FileCopy, FileSystemObject.CopyFile, et pourquoi il ne peut pas copier un classeur ouvert

TL;DRFileCopy source, destination copie un fichier en une ligne, n'exige aucune référence, et écrase en silence ce qui se trouve déjà à la destination. Le piège qui attrape tout le monde : il ne peut pas copier un fichier ouvert — y compris le classeur depuis lequel vous exécutez la macro. Les deux chemins doivent être complets, nom de fichier compris, et le dossier de destination doit déjà exister :

Sub BackupReport()
    ' Les deux arguments sont des chemins COMPLETS, nom de fichier inclus de chaque cote
    FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"   ' ecrase Backup en silence
End Sub

Une fois qu'une macro a trouvé les fichiers sur lesquels travailler, la chose suivante qu'elle fait d'ordinaire, c'est d'agir sur eux — et la plus douce de ces actions est d'en copier un quelque part de sûr avant que quoi que ce soit d'autre n'y touche. C'est aussi là que les débutants heurtent leur premier mur : FileCopy fonctionne parfaitement sur un fichier fermé, puis échoue avec error 70 à l'instant où vous le pointez sur un classeur ouvert. Comprenez pourquoi, et vous choisirez toujours le bon des trois outils de copie.

Ce que vous allez apprendre

  • Le modèle mental — quel outil de copie vous faut-il dépend de savoir si le fichier est ouvert
  • Pourquoi FileCopy écrase sans avertissement — l'inverse de l'instruction Name
  • Pourquoi FileCopy échoue avec error 70 sur un classeur ouvert, et quoi utiliser à la place
  • Pourquoi les deux arguments doivent être des chemins complets et le dossier de destination doit déjà exister
  • Quand passer à FileSystemObject.CopyFile pour les caractères génériques et un indicateur d'écrasement explicite
  • Comment copier le classeur actuellement ouvert avec SaveCopyAs, et comment copier-puis-Kill devient un déplacement

Le modèle mental : trois outils de copie pour trois situations

Il n'y a pas de commande unique « copier un fichier » en VBA — il y en a trois, et elles ne sont pas interchangeables. La question qui désigne la bonne est toujours la même : le fichier est-il ouvert, et avez-vous besoin de caractères génériques ?

  • FileCopy source, destination — l'instruction intégrée. Aucune référence, aucun objet. Copie un fichier fermé, écrase la destination en silence. C'est votre choix par défaut pour les fichiers posés sur le disque.
  • FileSystemObject.CopyFile source, destination[, overwrite] — la version modèle objet. Même tâche, mais elle accepte les caractères génériques (*.xlsx), prend un indicateur d'écrasement explicite, et possède un frère CopyFolder pour des arborescences entières.
  • workbook.SaveCopyAs path — la seule façon correcte de copier un classeur actuellement ouvert. Elle écrit un instantané sur le disque sans perturber le fichier vivant.

Tout ce qui suit découle de ces trois outils et des situations auxquelles ils appartiennent. Choisissez en demandant d'abord « est-il ouvert ? », puis « me faut-il un motif ? ».

FileCopy écrase en silence — l'inverse de Name

FileCopy ne demande jamais rien. Si quelque chose existe déjà à la destination, c'est remplacé sans invite et sans erreur. Cela compte parce que l'instruction sœur pour le disque, Name, fait exactement l'inverse — elle refuse d'écraser et lève une erreur. Deux instructions intégrées, deux réponses contradictoires à « et si la destination existe ? » :

FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"   ' remplace Backup\March.xlsx, sans avertissement

Si un écrasement silencieux est ce que vous voulez (rafraîchir une sauvegarde), c'est commode. Si ce n'est pas le cas — si cette sauvegarde était l'unique copie d'hier — vous devez protéger la destination vous-même avant d'appeler FileCopy :

If Dir("C:\Backup\March.xlsx") = "" Then                    ' ne copier que si rien ne s'y trouve
    FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"
End If

Ce test d'existence d'une ligne fait l'objet de la vérification de l'existence d'un fichier ; ici, il fait la différence entre une sauvegarde sûre et une sauvegarde détruite.

Le piège de l'erreur 70 : FileCopy ne peut pas copier un fichier ouvert

C'est le bug FileCopy numéro un. L'instruction demande à Windows un accès en lecture exclusif sur la source et un accès en écriture exclusif sur la destination. Un classeur ouvert est verrouillé par Excel, donc :

FileCopy ThisWorkbook.FullName, "C:\Backup\live.xlsx"   ' error 70 - "Permission denied"

échoue immédiatement — et le fichier que vous voulez le plus sauvegarder (celui dans lequel vous travaillez) est précisément celui qui est ouvert. Le même error 70 apparaît si la destination est ouverte, en lecture seule, ou si vous n'avez pas les droits sur le dossier. Il y a deux issues correctes :

  • Si c'est votre classeur, utilisez SaveCopyAs — il copie le fichier vivant sans le fermer (section suivante).
  • Si c'est un autre classeur que vous avez ouvert par code, Close-le d'abord, puis FileCopy le fichier sur le disque.

Ne « corrigez » jamais un error 70 avec On Error Resume Next — cela masque un fichier verrouillé comme une non-copie silencieuse, et votre sauvegarde n'a tout simplement jamais lieu.

Les deux arguments sont des chemins complets — et le dossier doit exister

Deux règles structurelles piègent les gens à répétition :

La destination est un chemin complet, pas un dossier. FileCopy ne déduit pas le nom de fichier à partir de la source.

FileCopy "C:\Reports\March.xlsx", "C:\Backup\"              ' error 75 - erreur d'acces chemin/fichier
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"    ' correct - nommez-le explicitement

Le dossier de destination doit déjà exister. FileCopy ne créera pas C:\Backup\ pour vous. Si le dossier risque d'être absent, créez-le d'abord avec MkDir — et rappelez-vous que MkDir lui-même lève une erreur si le dossier existe déjà, alors protégez-le :

If Dir("C:\Backup", vbDirectory) = "" Then MkDir "C:\Backup"
FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx"

FileSystemObject.CopyFile : caractères génériques et un indicateur d'écrasement explicite

Quand vous devez copier beaucoup de fichiers d'un coup, ou que vous voulez que l'écrasement soit une décision plutôt qu'un défaut silencieux, passez au FileSystemObject :

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")        ' liaison tardive - tourne sur toute machine
fso.CopyFile "C:\Reports\*.xlsx", "C:\Backup\"              ' caracteres generiques : tous les .xlsx d'un coup
fso.CopyFile "C:\Reports\March.xlsx", "C:\Backup\March.xlsx", False   ' Overwrite:=False -> erreur si le fichier existe

Trois choses que FileCopy ne sait pas faire et que CopyFile sait faire : correspondre à un motif de caractères génériques, prendre un indicateur d'écrasement pour qu'un fichier existant lève error 58 au lieu de disparaître en silence, et — avec CopyFolder — copier une arborescence de dossiers entière. Notez que la forme dossier-de-destination est permise ici (un \ final signifie « dans ce dossier »), ce qui explique pourquoi CopyFile s'associe naturellement à une source à caractères génériques. Il ne peut toujours pas copier un fichier ouvert, cependant — cette limite appartient à Windows, pas à l'outil.

Copier le classeur ouvert avec SaveCopyAs — et copier-puis-Kill est un déplacement

Pour le classeur vivant, la réponse n'est pas du tout une copie de système de fichiers — c'est une méthode de classeur :

ThisWorkbook.SaveCopyAs "C:\Backup\March-" & Format(Now, "yyyymmdd-hhnnss") & ".xlsx"

SaveCopyAs écrit une copie sur le disque et laisse l'original ouvert et intact — pas de error 70, pas de fermeture, aucun changement au chemin propre du classeur. C'est l'appel de sauvegarde correct au sein de toute longue macro, et il est traité aux côtés de Save et SaveAs dans le guide de sauvegarde d'un classeur.

Enfin, une identité utile : un déplacement est une copie suivie d'une suppression. Quand vous ne pouvez pas utiliser Name — par exemple pour déplacer un fichier vers un lecteur différent, ce que Name refuse — vous vous rabattez sur copier-puis-supprimer :

FileCopy "C:\Reports\March.xlsx", "D:\Archive\March.xlsx"   ' copier vers l'autre lecteur
Kill "C:\Reports\March.xlsx"                                ' puis supprimer l'original

Ce Kill est définitif et n'a aucune annulation, alors faites-le seulement après avoir confirmé que la copie est bien arrivée.

Le verdict honnête : choisissez selon « est-il ouvert ? » puis « me faut-il un motif ? »

Copier un fichier est trivial jusqu'à ce que le fichier soit ouvert ou que la destination compte déjà. Quatre règles gardent la chose correcte :

  • Fichier fermé, copie uniqueFileCopy — le plus court, aucune installation, mais il écrase en silence, alors protégez la destination quand le fichier existant compte.
  • Beaucoup de fichiers ou une vraie décision d'écrasementfso.CopyFile avec un caractère générique et l'indicateur Overwrite.
  • Le classeur ouvertSaveCopyAs, jamais FileCopy — c'est toute la réponse à error 70.
  • Chemins complets, dossier existant → nommez explicitement le fichier de destination et faites MkDir du dossier d'abord.

À l'instant où FileCopy vous donne un error 70, cessez de vous tourner vers On Error et posez la vraie question : ce fichier est-il ouvert ? S'il est à vous, SaveCopyAs ; si c'en est un autre, fermez-le d'abord.

Comment ExcelMaster aide

Choisir entre FileCopy, fso.CopyFile et SaveCopyAs — et se souvenir que seul le dernier peut toucher un classeur ouvert, que la destination a besoin d'un chemin complet, et que le dossier doit exister au préalable — représente beaucoup de cérémonie pour « juste faire une copie », et le mauvais choix échoue avec un error 70 cryptique à l'exécution.

ExcelMaster écrit la bonne copie pour la situation. Décrivez la tâche — « sauvegarde ce classeur avec un horodatage avant que j'écrase quoi que ce soit », ou « copie chaque .xlsx de ce dossier dans une archive » — et il produit l'appel correct : SaveCopyAs pour le fichier vivant, fso.CopyFile avec un caractère générique pour un lot, la protection MkDir pour un dossier manquant, et un copier-puis-Kill quand vous vouliez vraiment un déplacement inter-lecteurs. Vous décrivez le résultat ; il choisit l'outil qui ne lèvera pas error 70.

Questions fréquentes

Comment copier un fichier en VBA ?

Utilisez l'instruction intégrée FileCopy source, destination, où les deux arguments sont des chemins complets incluant le nom de fichier — par exemple FileCopy "C:\Reports\March.xlsx", "C:\Backup\March.xlsx". Elle n'exige aucune référence et copie un fichier fermé, mais elle écrase la destination en silence et le dossier de destination doit déjà exister. Pour copier beaucoup de fichiers d'un coup, utilisez FileSystemObject.CopyFile avec une source à caractères génériques.

Pourquoi VBA FileCopy donne-t-il l'erreur 70 Permission denied ?

Parce que le fichier source ou destination est ouvert ou verrouillé. FileCopy a besoin d'un accès exclusif, et Excel verrouille tout classeur ouvert — copier le classeur depuis lequel vous exécutez échoue donc toujours avec error 70. Pour copier le classeur actuellement ouvert, utilisez plutôt ThisWorkbook.SaveCopyAs path ; pour copier un autre classeur que vous avez ouvert par code, Close-le d'abord, puis FileCopy le fichier sur le disque.

Comment copier un fichier vers un autre dossier en VBA ?

Donnez à FileCopy une destination dans ce dossier, sous forme de chemin complet avec le nom de fichier : FileCopy "C:\In\a.xlsx", "C:\Out\a.xlsx". Le dossier de destination doit déjà exister — FileCopy ne le créera pas, alors protégez avec If Dir("C:\Out", vbDirectory) = "" Then MkDir "C:\Out" d'abord. Pour une destination sous forme de dossier seul comme "C:\Out\", utilisez fso.CopyFile plutôt que FileCopy.

VBA FileCopy écrase-t-il un fichier existant ?

Oui — en silence, sans invite et sans erreur. C'est l'inverse de l'instruction Name, qui refuse d'écraser. Si vous ne voulez pas remplacer un fichier existant, testez-le d'abord avec Dir(path) = "" ou fso.FileExists(path), ou utilisez fso.CopyFile source, destination, False pour qu'une destination existante lève error 58 au lieu de disparaître.

Comment copier le classeur ouvert actuel en VBA ?

Utilisez ThisWorkbook.SaveCopyAs "C:\Backup\copy.xlsx". SaveCopyAs écrit un instantané sur le disque tout en laissant l'original ouvert et inchangé, si bien qu'il évite le error 70 que FileCopy donne sur un fichier ouvert. C'est la façon standard de prendre une sauvegarde horodatée au sein d'une longue macro, et il ne modifie pas le chemin enregistré propre du classeur.

Testé dans

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

Guides associés : VBA Delete File · VBA Rename File · VBA Dir · VBA FileSystemObject · VBA Save Workbook