Excel VBA & SharePoint : sauvegarder un classeur (.xlsm), créer une copie « Copies » et remplacer l’original sans « Erreur 0 »

Besoin de sauvegarder automatiquement un classeur Excel macro‑activé sur SharePoint, de créer une copie dans un sous‑dossier « Copies », de remplacer l’original et de supprimer la fameuse « Erreur 0 » ? Voici une solution VBA prête à l’emploi, robuste et expliquée pas à pas.

Sommaire

Sauvegarder un classeur Excel VBA dans un autre dossier SharePoint

Vue d’ensemble de la question

Un classeur .xlsm stocké sur SharePoint exécute du code VBA. À la fin du traitement, l’utilisateur souhaite :

  1. Créer une copie de sauvegarde dans un sous‑dossier Copies du même site ;
  2. Remplacer ou remettre à jour le classeur original dans son dossier d’origine ;
  3. Gérer proprement les erreurs (y compris l’erreur 0 affichée à tort) ;
  4. Comprendre pourquoi, par moments, le dossier SharePoint n’est pas détecté alors qu’il existe.

Solution proposée (macro minimale, fonctionnelle)

Cette version répond au besoin avec le moins de dépendances possible et en conservant une logique claire.

Option Explicit

Sub MakeBackup()
Dim Home As String, OrigPath As String, BackupPath As String

```
Home       = ThisWorkbook.Path                     'Dossier courant (chemin local ou URL https)
OrigPath   = Home & "/BOB_Finalv5a.xlsm"           'Fichier de travail (macro‑activé)
BackupPath = Home & "/Copies/BOB_Finalv5a_backup.xlsm"

On Error GoTo ErrorHandler

' 1. Copie de sauvegarde : crée un duplicata sans modifier le classeur actif
ThisWorkbook.SaveCopyAs BackupPath

' 2. Ré‑enregistrement du classeur actif (ou d’un nouveau nom)
ActiveWorkbook.SaveAs Filename:=OrigPath, _
                      FileFormat:=xlOpenXMLWorkbookMacroEnabled
```

Fin:
Exit Sub                                           'Sortie propre
ErrorHandler:
If Err.Number <> 0 Then                            'Évite le MsgBox « Erreur 0 »
MsgBox "Erreur " & Err.Number & " : " & Err.Description, _
vbCritical, "Sauvegarde SharePoint"
End If
Resume Fin
End Sub 

Version robuste prête pour la prod (recommandée)

La version ci‑dessous ajoute : création sécurisée du sous‑dossier (si chemin local), nom horodaté des sauvegardes, gestion explicite des états d’Excel, neutralisation de l’« Erreur 0 », et un fallback documenté lorsque le chemin est une URL SharePoint.

Option Explicit

' ==========
' PARAMÈTRES
' ==========
Private Const WORK_NAME As String = "BOB_Finalv5a.xlsm"      'Nom "officiel" du fichier de travail
Private Const COPIES_DIR As String = "Copies"                'Sous-dossier des sauvegardes

' ==========
' POINT D'ENTRÉE
' ==========
Public Sub SaveAndBackupSharePoint()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim home As String, isUrl As Boolean
Dim origPath As String, copiesFolder As String, backupPath As String
Dim oldAlerts As Boolean, oldEvents As Boolean, oldScreen As Boolean

```
' États Excel à restaurer en fin de traitement
oldAlerts = Application.DisplayAlerts
oldEvents = Application.EnableEvents
oldScreen = Application.ScreenUpdating

On Error GoTo FAIL
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False

home = NormalizePath(wb.Path)
isUrl = IsUrlPath(home)

' Construction des chemins
origPath = CombinePath(home, WORK_NAME)
copiesFolder = CombinePath(home, COPIES_DIR)
backupPath = CombinePath(copiesFolder, StampedBackupName(WORK_NAME, "_backup"))

' 1) S’assurer que le dossier Copies existe (possible uniquement en chemin local)
If Not isUrl Then
    EnsureFolderExists copiesFolder
End If

' 2) Sauvegarde de sécurité (duplicata &quot;à froid&quot;)
wb.SaveCopyAs backupPath

' 3) Remplacer / remettre à jour l'original
SilentSaveAs wb, origPath, xlOpenXMLWorkbookMacroEnabled
```

CLEAN:
' Restauration des états Excel (toujours)
Application.DisplayAlerts = oldAlerts
Application.EnableEvents = oldEvents
Application.ScreenUpdating = oldScreen
Exit Sub

FAIL:
' Capture immédiate des infos d'erreur
Dim n As Long, d As String: n = Err.Number: d = Err.Description
Err.Clear
' Restauration des états Excel
Application.DisplayAlerts = oldAlerts
Application.EnableEvents = oldEvents
Application.ScreenUpdating = oldScreen
' Éviter le piège "Erreur 0"
If n <> 0 Then
MsgBox "Erreur " & n & " : " & d & vbCrLf & _
"Chemin: " & home & vbCrLf & _
"Dossier Copies détecté comme " & IIf(isUrl, "URL SharePoint", "chemin local") & ".", _
vbCritical, "Sauvegarde SharePoint"
End If
Resume CLEAN
End Sub

' ==========
' UTILITAIRES
' ==========
Private Sub SilentSaveAs(ByVal wb As Workbook, ByVal filePath As String, ByVal ff As XlFileFormat)
' Enregistre sans boîtes de dialogue parasites (remplace l’original si même nom)
wb.SaveAs Filename:=filePath, FileFormat:=ff, CreateBackup:=False
End Sub

Private Function NormalizePath(ByVal p As String) As String
' Harmonise les séparateurs pour faciliter les concaténations
NormalizePath = Trim$(Replace(p, "", "/"))
End Function

Private Function CombinePath(ByVal base As String, ByVal leaf As String) As String
If Right$(base, 1) = "/" Then
CombinePath = base & leaf
Else
CombinePath = base & "/" & leaf
End If
End Function

Private Function IsUrlPath(ByVal p As String) As Boolean
Dim L As String: L = LCase$(Trim$(p))
IsUrlPath = (Left$(L, 8) = "https://" Or Left$(L, 7) = "http://")
End Function

Private Function StampedBackupName(ByVal originalName As String, ByVal suffix As String) As String
' Insère un horodatage avant l’extension pour garder un historique propre
Dim base As String, ext As String, dotPos As Long
dotPos = InStrRev(originalName, ".")
If dotPos > 0 Then
base = Left$(originalName, dotPos - 1)
ext = Mid$(originalName, dotPos)               ' .xlsm, .xlsx, ...
Else
base = originalName
ext = ""
End If
StampedBackupName = base & "_" & Format(Now, "yyyymmdd_hhnnss") & suffix & ext
End Function

Private Sub EnsureFolderExists(ByVal logicalFolder As String)
' Crée le dossier "Copies" si le classeur est ouvert depuis un chemin local synchronisé.
' Note: en URL SharePoint (https), MkDir ne fonctionne pas ; le dossier doit exister côté site/synchro.
Dim p As String: p = ToLocalFsPath(logicalFolder)
If p = "" Then Exit Sub  ' rien à faire pour les URL
Dim parts() As String, i As Long, build As String
parts = Split(Replace(p, "", "/"), "/")           ' Travailler avec des segments
If UBound(parts) < 0 Then Exit Sub
If InStr(parts(0), ":") = 0 And Left$(p, 2) <> "\" Then Exit Sub ' sécurité

```
build = IIf(Left$(p, 2) = "\\", "\\" & parts(2), parts(0)) ' init partiel
If Left$(p, 2) = "\\" Then
    ' UNC (rare en OneDrive/SharePoint mais toléré)
    build = "\\" & parts(2)
    For i = 3 To UBound(parts)
        build = build & "\" & parts(i)
        If Dir(build, vbDirectory) = "" Then MkDir build
    Next i
Else
    ' Disque local (chemin OneDrive synchronisé typique)
    build = parts(0)
    For i = 1 To UBound(parts)
        build = build & "\" & parts(i)
        If Dir(build, vbDirectory) = "" Then MkDir build
    Next i
End If
```

End Sub

Private Function ToLocalFsPath(ByVal logicalPath As String) As String
' Si le chemin est une URL https, renvoie chaîne vide (MkDir impossible)
' Sinon, remplace les "/" par le séparateur local pour Dir/MkDir.
If IsUrlPath(logicalPath) Then
ToLocalFsPath = ""     ' on laissera SaveCopyAs gérer côté Office/SharePoint
Else
ToLocalFsPath = Replace(logicalPath, "/", Application.PathSeparator)
End If
End Function 

Pourquoi deux méthodes ? SaveCopyAs vs SaveAs

  • SaveCopyAs fabrique un duplicata « à froid » du fichier, sans toucher au classeur actif. Idéal pour une copie de sauvegarde.
  • SaveAs remplace le fichier courant et change l’identité du classeur en mémoire (son FullName). C’est la bonne méthode pour remettre à jour l’original (ou repartir avec un nouveau nom).
  • Pour un classeur macro‑activé, utilisez xlOpenXMLWorkbookMacroEnabled. Pour un .xlsx standard : xlOpenXMLWorkbook.

Points essentiels et bonnes pratiques

PointExplications / Astuces
Chemin SharePointDeux cas : URL https (ex. https://.../Shared Documents/...) ou chemin local synchronisé OneDrive (ex. C:\Users\...\SharePoint\...). Dans les deux cas, construire les chemins avec « / » en VBA est robuste ; convertir en « \ » uniquement pour Dir/MkDir.
SaveCopyAs vs SaveAsSaveCopyAs n’affecte pas l’état du classeur ouvert ; SaveAs bascule le nom et peut déclencher des alertes (format, coexistence). D’où l’usage de DisplayAlerts = False et de la procédure SilentSaveAs.
Type de fichierMacro‑activé : xlOpenXMLWorkbookMacroEnabled.xlsm. Sans macro : xlOpenXMLWorkbook.xlsx. Alignez extension et FileFormat pour éviter le message « Certaines fonctionnalités seront perdues ».
Gestion d’erreurÉvitez la « Erreur 0 » : capturez Err.Number / Err.Description dès l’entrée dans le gestionnaire, Err.Clear, restaurez l’état d’Excel, puis affichez le message seulement si Err.Number ≠ 0. Terminez toujours sur une étiquette « CLEAN ».
Dossier introuvableCauses fréquentes : synchro OneDrive incomplète, droits insuffisants, caractères non valides, chemin trop long ou langue de la bibliothèque (ex. « Shared Documents » vs « Documents partagés »). Solutions : forcer/attendre la synchro, corriger le libellé, réduire la profondeur, créer le dossier côté SharePoint/OneDrive.
Nom horodatéPréférez un suffixe yyyymmdd_hhnnss pour tracer l’historique des sauvegardes (ex. MonFichier_20250927_101530_backup.xlsm).
Ne pas confondre ThisWorkbook / ActiveWorkbookSi la macro vit dans l’add‑in ou un autre classeur, ciblez explicitement le bon Workbook. Dans les exemples, on prend ThisWorkbook pour éviter les surprises.
Conflits de versionSi le fichier est ouvert ailleurs, SaveAs peut échouer (partage/co‑création). Dans ce cas, conservez SaveCopyAs comme sauvegarde certaine et traitez la remise à jour plus tard ou notifiez l’utilisateur.

Quand le dossier SharePoint n’est « pas détecté »

Vous observez que Dir(copiesFolder, vbDirectory) ou MkDir échoue alors que le dossier existe bien dans le site ? Voici les pièges les plus courants et comment les résoudre :

  • Bibliothèque non synchronisée localement : en URL https, MkDir n’a aucun effet. Créez le dossier « Copies » directement via l’interface SharePoint/OneDrive, ou activez la synchro OneDrive de la bibliothèque.
  • Nom local différent : selon la langue, la bibliothèque s’appelle « Shared Documents », « Documents partagés », « Dokumente », etc. Ne forcez pas un libellé ; récupérez le ThisWorkbook.Path et concaténez.
  • Caractères interdits dans le nom de dossier/fichier (ex. :*?"<>|) ou dièses (#) et % dans l’URL mal encodée. Remplacez les caractères problématiques ou laissez Excel gérer l’encodage côté URL.
  • Chemins trop longs : au‑delà de ~260 caractères sur certains systèmes/outils, des erreurs 75/76 peuvent apparaître. Raccourcissez l’arborescence ou renommez des dossiers.
  • Droits SharePoint insuffisants : vous voyez le dossier mais ne pouvez pas écrire. Vérifiez au minimum l’autorisation « Édition » sur la bibliothèque.
  • OneDrive en pause : le chemin local existe, mais la synchro est stoppée → la sauvegarde locale réussit, la publication côté cloud prendra effet quand la synchro reprendra.

Tableau de dépannage : erreurs fréquentes

Erreur (VBA)Signification typiqueCause probablePiste de correction
0Aucune erreur (valeur par défaut)Gestionnaire appelé sans erreur effectiveTester Err.Number ≠ 0 avant MsgBox ; utiliser le patron CLEAN/FAIL.
52Bad file name or numberChemin mal formé, caractères interditsNettoyer les noms ; vérifier l’extension/format.
53File not foundLe fichier source n’existe pas (rare avec SaveCopyAs)Contrôler ThisWorkbook.FullName ; vérifier les accès.
70Permission deniedFichier verrouillé, droit d’écriture absentFermer les instances concurrentes ; vérifier les droits.
75Path/File access errorChemin inaccessible (réseau), longueur excessiveRaccourcir les segments ; vérifier la connexion.
76Path not foundDossier non existant (surtout en URL https)Créer le dossier côté SharePoint ou synchroniser localement.
1004Application-defined or object-defined errorFormats incohérents, prompts bloquants, co‑éditionDisplayAlerts = False, aligner FileFormat/extension, fermer les co‑éditeurs.
-2147024894Système : fichier introuvableSegment d’URL ou de chemin erronéTracer les chemins complets, corriger le segment fautif.

Bonnes pratiques de structuration du code

  • Toujours encapsuler les modifications d’état (DisplayAlerts, EnableEvents, ScreenUpdating) et les restaurer dans le bloc finally (CLEAN).
  • Centraliser la construction des chemins (NormalizePath, CombinePath) pour éviter les doubles séparateurs ou les erreurs de langue.
  • Horodater systématiquement les sauvegardes pour un historique traçable sans écrasement silencieux.
  • Ne pas forcer la création de dossiers en URL https : cela ne fonctionne pas en natif en VBA. Créez‑les via l’interface du site ou synchronisez.
  • Éviter les noms avec #, %, & dans les segments d’URL si vous composez manuellement des chemins web.

FAQ express

Peut‑on utiliser des barres « / » sous Windows ?
Oui, Excel tolère / dans les chemins lors des opérations d’enregistrement. Pour les appels Dir/MkDir, on convertit en \ côté système de fichiers.

Faut‑il préférer l’URL https ou le chemin synchronisé ?
Le chemin synchronisé OneDrive est souvent plus rapide et plus fiable pour les opérations automatiques (création de dossiers, tests Dir). L’URL https convient très bien à SaveCopyAs/SaveAs mais ne permet pas MkDir en VBA.

Comment gérer un fichier ouvert par un autre utilisateur ?
Conservez la sauvegarde (SaveCopyAs) et différer le SaveAs (ou informer l’utilisateur). En co‑édition, Excel peut empêcher le remplacement direct.

Pourquoi ai‑je un message « perte de fonctionnalités » ?
Extension et FileFormat ne correspondent pas (ex. .xlsx avec un FileFormat macro‑activé). Alignez‑les.

Variantes utiles (extraits prêts à copier)

Forcer un nom de sauvegarde distinct par utilisateur

Dim userTag As String
userTag = Environ$("Username")
backupPath = CombinePath(copiesFolder, "BOB_Finalv5a_" &amp; userTag &amp; "_" &amp; _
                         Format(Now, "yyyymmdd_hhnnss") &amp; "_backup.xlsm")
ThisWorkbook.SaveCopyAs backupPath

Basculer le format en .xlsx (si vous purgez les macros au préalable)

' Après avoir supprimé les modules si nécessaire :
SilentSaveAs ThisWorkbook, CombinePath(home, "BOB_Finalv5a.xlsx"), xlOpenXMLWorkbook

Contrôler rapidement l’existence du dossier (chemin local)

Function FolderExistsLocal(ByVal logicalFolder As String) As Boolean
    If IsUrlPath(logicalFolder) Then Exit Function
    FolderExistsLocal = (Dir(ToLocalFsPath(logicalFolder), vbDirectory) &lt;&gt; "")
End Function

Checklist d’implémentation

  • Ouvrez le classeur .xlsm depuis SharePoint (URL) ou depuis un dossier synchronisé OneDrive.
  • Collez le module « Version robuste » ci‑dessus dans Module1.
  • Adaptez uniquement WORK_NAME et, si besoin, COPIES_DIR.
  • Créez le sous‑dossier Copies côté site si vous travaillez en URL https pure.
  • Exécutez SaveAndBackupSharePoint. Vérifiez l’apparition du fichier horodaté dans Copies et la remise à jour de l’original.

Sécurité & gouvernance

  • Macros signées : en environnement Microsoft 365, les macros non approuvées peuvent être bloquées (Mark of the Web). Signez le projet ou placez le fichier dans un emplacement approuvé.
  • Conformité : si des versions majeures, métadonnées ou approbations sont requises, envisagez une orchestration via des flux (Power Automate) ou l’API Graph au lieu de VBA pur.

Résumé opérationnel

La combinaison SaveCopyAs (copie sûre, hors‑ouverture) + SaveAs (remise à jour contrôlée) fournit un flux fiable pour des sauvegardes sur SharePoint. En normalisant les chemins, en gérant proprement les erreurs et en respectant la différence URL vs chemin synchronisé, on élimine les faux positifs (dont l’« Erreur 0 ») et on automatise la sauvegarde sans intervention manuelle.


Annexe : macro complète tout‑en‑un (coller/tourner)

Si vous préférez un seul bloc prêt à coller :

Option Explicit

Private Const WORK_NAME As String = "BOB_Finalv5a.xlsm"
Private Const COPIES_DIR As String = "Copies"

Public Sub BackupAndReplace()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim home As String, isUrl As Boolean
Dim origPath As String, copiesFolder As String, backupPath As String
Dim a As Boolean, e As Boolean, s As Boolean
a = Application.DisplayAlerts: e = Application.EnableEvents: s = Application.ScreenUpdating

```
On Error GoTo KO
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False

home = NormalizePath(wb.Path)
isUrl = IsUrlPath(home)
origPath = CombinePath(home, WORK_NAME)
copiesFolder = CombinePath(home, COPIES_DIR)
backupPath = CombinePath(copiesFolder, StampedBackupName(WORK_NAME, "_backup"))

If Not isUrl Then EnsureFolderExists copiesFolder

wb.SaveCopyAs backupPath
SilentSaveAs wb, origPath, xlOpenXMLWorkbookMacroEnabled
```

OK:
Application.DisplayAlerts = a
Application.EnableEvents = e
Application.ScreenUpdating = s
Exit Sub

KO:
Dim n As Long, d As String: n = Err.Number: d = Err.Description
Err.Clear
Application.DisplayAlerts = a
Application.EnableEvents = e
Application.ScreenUpdating = s
If n <> 0 Then MsgBox "Erreur " & n & " : " & d, vbCritical, "Sauvegarde SharePoint"
Resume OK
End Sub

' ==== Utilitaires de chemin et de sauvegarde ====
Private Sub SilentSaveAs(ByVal wb As Workbook, ByVal filePath As String, ByVal ff As XlFileFormat)
wb.SaveAs Filename:=filePath, FileFormat:=ff, CreateBackup:=False
End Sub

Private Function NormalizePath(ByVal p As String) As String
NormalizePath = Trim$(Replace(p, "", "/"))
End Function

Private Function CombinePath(ByVal base As String, ByVal leaf As String) As String
CombinePath = IIf(Right$(base, 1) = "/", base & leaf, base & "/" & leaf)
End Function

Private Function IsUrlPath(ByVal p As String) As Boolean
Dim L As String: L = LCase$(Trim$(p))
IsUrlPath = (Left$(L, 8) = "https://" Or Left$(L, 7) = "http://")
End Function

Private Function StampedBackupName(ByVal originalName As String, ByVal suffix As String) As String
Dim base As String, ext As String, dotPos As Long
dotPos = InStrRev(originalName, ".")
If dotPos > 0 Then
base = Left$(originalName, dotPos - 1)
ext = Mid$(originalName, dotPos)
Else
base = originalName
ext = ""
End If
StampedBackupName = base & "_" & Format(Now, "yyyymmdd_hhnnss") & suffix & ext
End Function

Private Sub EnsureFolderExists(ByVal logicalFolder As String)
Dim p As String: p = ToLocalFsPath(logicalFolder)
If p = "" Then Exit Sub

```
Dim parts() As String, i As Long, build As String
parts = Split(Replace(p, "\", "/"), "/")
If UBound(parts) &lt; 0 Then Exit Sub

If Left$(p, 2) = "\\" Then
    build = "\\" & parts(2)
    For i = 3 To UBound(parts)
        build = build &amp; "\" &amp; parts(i)
        If Dir(build, vbDirectory) = "" Then MkDir build
    Next i
Else
    build = parts(0)
    For i = 1 To UBound(parts)
        build = build &amp; "\" &amp; parts(i)
        If Dir(build, vbDirectory) = "" Then MkDir build
    Next i
End If
```

End Sub

Private Function ToLocalFsPath(ByVal logicalPath As String) As String
If IsUrlPath(logicalPath) Then
ToLocalFsPath = ""
Else
ToLocalFsPath = Replace(logicalPath, "/", Application.PathSeparator)
End If
End Function 

En bref

  • Construisez toujours les chemins à partir de ThisWorkbook.Path ;
  • Utilisez SaveCopyAs pour la sauvegarde, SaveAs pour la remise à jour ;
  • Supprimez l’affichage de la fausse « Erreur 0 » avec le patron CLEAN/FAIL ;
  • Créez le dossier Copies côté site si vous travaillez en URL https ;
  • Horodatez les fichiers de sauvegarde pour un historique clair.

En appliquant ce modèle et ces recommandations, la sauvegarde automatisée vers un dossier SharePoint distinct devient fiable, traçable et silencieuse pour l’utilisateur final.

Sommaire