Dans certains classeurs, les liens vers des fichiers situés dans des sous‑dossiers se « déforment » après enregistrement et réouverture : ils pointent soudain vers AppData\Roaming\Microsoft\Excel\...
et ne fonctionnent plus. Voici la cause, le correctif durable et des scripts VBA pour réparer le lot.
Vue d’ensemble de la question
Le cas typique ressemble à ceci :
- Le classeur contient des liens internes vers des feuilles (ex.
#Feuil1!A1
), et des liens externes vers des sous‑dossiers à côté du classeur (ex.Effects\Lovell
). - Après fermeture puis réouverture, les liens externes deviennent des chemins absolus du type :
C:\Users\<Utilisateur>\AppData\Roaming\Microsoft\Excel\Effects\Lovell
- Le fait de définir la propriété Hyperlink Base sur le dossier du classeur (ex.
R:\Stuff
) corrige les liens externes, mais casse alors les liens internes, qui se mettent à pointer vers un dossier inexistant.
Ce que l’on constate vs ce qui se passe vraiment
Symptôme | Ce que vous voyez | Racine du problème |
---|---|---|
Liens vers des sous‑dossiers cassés | Chemins réécrits en AppData\Roaming\Microsoft\Excel\... | Paramètre Mettre à jour les liens lors de l’enregistrement qui force une réécriture « absolue » |
Liens internes déréglés | Cliquer envoie vers un dossier, pas vers une feuille | Hyperlink Base défini sur un chemin réel (ex. R:\Stuff ) qui influence certains liens |
Comportement variable entre postes | Le même classeur fonctionne chez X mais pas chez Y | Différences de mappage réseau, de valeur Hyperlink Base ou d’option Excel |
La cause exacte
Excel dispose d’un réglage hérité des « Options Web ». Lorsqu’il est activé, Mettre à jour les liens lors de l’enregistrement tente d’« aider » en convertissant les chemins relatifs en chemins absolus basés sur son dossier de travail. Dans de nombreux environnements Windows, ce dossier de travail résout vers C:\Users\<Utilisateur>\AppData\Roaming\Microsoft\Excel\
. Résultat : votre Effects\Lovell
devient absolu et inutilisable.
Parallèlement, la propriété Hyperlink Base peut agir comme un préfixe implicite. Si vous la définissez sur R:\Stuff
, Excel l’ajoute parfois au lien—y compris à des liens qui devraient rester internes au classeur—avec des effets de bord indésirables.
Correctif durable (recommandé)
- Ouvrez Fichier › Options › Options avancées.
- Dans la section Général, cliquez sur Options Web….
- Allez à l’onglet Fichiers.
- Décochez Mettre à jour les liens lors de l’enregistrement.
- Enregistrez, fermez puis rouvrez le classeur. Les liens externes restent relatifs et les liens internes (
#Feuille!A1
) ne sont plus affectés.
Paramétrage conseillé de « Hyperlink Base »
Dans la majorité des cas, laissez cette propriété vide. Si vous devez l’utiliser (archives, modèles réutilisés, etc.), mettez une valeur minimale :
.
(un point) : cela signifie « dossier du classeur ». C’est le choix le plus neutre.- Vérifiez que vos liens internes utilisent
#Feuille!A1
(champ SubAddress), indépendant deHyperlink Base
.
Réparer un classeur déjà corrompu
Si des centaines ou milliers de liens pointent vers AppData\Roaming\Microsoft\Excel
, le plus rapide est un traitement automatisé. Toujours faire une copie de sauvegarde avant.
Méthode express : Rechercher/Remplacer global
Pour des liens du type C:\Users\<Utilisateur>\AppData\Roaming\Microsoft\Excel\Effects\Lovell\...
, on peut retirer le préfixe parasite :
Sub CorrigerLiens_AppData_ActiveFeuille()
Dim h As Hyperlink
For Each h In ActiveSheet.Hyperlinks
If InStr(1, h.Address, "AppData\Roaming\Microsoft\Excel\", vbTextCompare) > 0 Then
h.Address = Replace$(h.Address, _
"C:\Users\<Utilisateur>\AppData\Roaming\Microsoft\Excel\", "")
End If
Next h
End Sub
Adaptez le chemin à votre environnement (nom d’utilisateur, lecteur, etc.). Cette macro traite les liens de la feuille active. Pour un classeur entier et avec journalisation, préférez la version « pro » ci‑dessous.
Méthode robuste : traitement sur tout le classeur + journal
Ce script passe partout (cellules, formes, graphiques), normalise les séparateurs, supprime le préfixe AppData\Roaming\Microsoft\Excel\
s’il est présent et consigne chaque changement dans un onglet Hyperlink_Fix_Log.
Option Explicit
Private Function IsAppDataExcelPath(ByVal s As String) As Boolean
If Len(s) = 0 Then Exit Function
Dim t As String: t = LCase$(s)
IsAppDataExcelPath = (InStr(t, "appdata\roaming\microsoft\excel") > 0) _
Or (InStr(t, "appdata/roaming/microsoft/excel/") > 0)
End Function
Private Function StripAppDataExcelPrefix(ByVal s As String) As String
Dim t As String
t = Replace$(s, "C:\Users\AppData\Roaming\Microsoft\Excel", "", 1, -1, vbTextCompare)
t = Replace$(t, "C:/Users//AppData/Roaming/Microsoft/Excel/", "", 1, -1, vbTextCompare)
StripAppDataExcelPrefix = t
End Function
Private Sub LogChange(wsLog As Worksheet, ByVal wsName As String, _
ByVal targetType As String, ByVal oldAddr As String, ByVal newAddr As String)
With wsLog
Dim r As Long
r = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Cells(r, 1).Value = Now
.Cells(r, 2).Value = wsName
.Cells(r, 3).Value = targetType
.Cells(r, 4).Value = oldAddr
.Cells(r, 5).Value = newAddr
End With
End Sub
Public Sub FixAllHyperlinksInWorkbook()
Dim ws As Worksheet, wsLog As Worksheet
Dim h As Hyperlink, oldAddr As String, newAddr As String
Dim appSC As Boolean, ev As Long, sw As Boolean
```
' Préliminaires
On Error Resume Next
Set wsLog = ThisWorkbook.Worksheets("Hyperlink_Fix_Log")
If wsLog Is Nothing Then
Set wsLog = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
wsLog.Name = "Hyperlink_Fix_Log"
wsLog.Range("A1:E1").Value = Array("Horodatage", "Feuille", "Type", "Ancienne adresse", "Nouvelle adresse")
wsLog.Range("A1:E1").Font.Bold = True
End If
On Error GoTo 0
' Accélérations
appSC = Application.ScreenUpdating: Application.ScreenUpdating = False
ev = Application.EnableEvents: Application.EnableEvents = False
sw = Application.Calculation = xlCalculationManual: Application.Calculation = xlCalculationManual
' Boucle principale
For Each ws In ThisWorkbook.Worksheets
' 1) Liens déclarés (cellules et formes)
For Each h In ws.Hyperlinks
oldAddr = h.Address
newAddr = oldAddr
If IsAppDataExcelPath(newAddr) Then
newAddr = StripAppDataExcelPrefix(newAddr)
End If
' Normalisation simple des séparateurs
newAddr = Replace$(newAddr, "/", "\")
' N'écraser que si changement
If newAddr <> oldAddr Then
h.Address = newAddr
LogChange wsLog, ws.Name, "Hyperlink", oldAddr, newAddr
End If
Next h
' 2) Formes avec Hyperlink direct (sécurité ceinture+bretelles)
Dim shp As Shape
For Each shp In ws.Shapes
If Not shp.Hyperlink Is Nothing Then
If Len(shp.Hyperlink.Address) > 0 Then
oldAddr = shp.Hyperlink.Address
newAddr = oldAddr
If IsAppDataExcelPath(newAddr) Then
newAddr = StripAppDataExcelPrefix(newAddr)
End If
newAddr = Replace$(newAddr, "/", "\")
If newAddr <> oldAddr Then
shp.Hyperlink.Address = newAddr
LogChange wsLog, ws.Name, "Shape.Hyperlink", oldAddr, newAddr
End If
End If
End If
Next shp
Next ws
' Restaurations
Application.ScreenUpdating = appSC
Application.EnableEvents = ev
Application.Calculation = IIf(sw, xlCalculationManual, xlCalculationAutomatic)
MsgBox "Correction terminée. Consultez l'onglet 'Hyperlink_Fix_Log'.", vbInformation
```
End Sub
Remettre d’équerre les liens internes (vers des feuilles)
Un lien interne fiable ne doit pas avoir d’Address, uniquement un SubAddress de la forme Feuil1!A1
. Voici une macro qui convertit les liens internes « à l’ancienne » (qui pointent vers [Classeur.xlsx]Feuil1!A1
) en véritables liens internes :
Sub NormaliserLiensInternes()
Dim ws As Worksheet, h As Hyperlink
For Each ws In ThisWorkbook.Worksheets
For Each h In ws.Hyperlinks
' Si le SubAddress ressemble à [Classeur]Feuille!Cellule
If Len(h.SubAddress) > 0 Then
' Déjà interne : rien à faire
ElseIf InStr(1, h.Address, "[", vbTextCompare) > 0 _
And InStr(1, h.Address, "]", vbTextCompare) > 0 Then
' Extraire la partie après ] (ex. Feuil1!A1)
Dim p As Long: p = InStrRev(h.Address, "]")
h.SubAddress = Mid$(h.Address, p + 1)
h.Address = "" ' on purge l'adresse externe
End If
Next h
Next ws
End Sub
Alternative sans VBA : sécuriser avec la fonction HYPERLINK
Lorsque les liens sont sur des cellules (et non sur des formes), vous pouvez construire un chemin robuste à partir du dossier du classeur :
=HYPERLINK( SUBSTITUTE( LEFT(CELL("filename",A1), FIND("[",CELL("filename",A1))-1), "/", "\")
& "Effects\Lovell\" & A2, "Ouvrir le fichier" )
Explications :
CELL("filename")
retourne le dossier du classeur +[NomFichier.xlsx]Feuille
.LEFT(...;FIND("[")-1)
isole le dossier.- On concatène le sous‑répertoire (
Effects\Lovell\
) et, par exemple, un nom de fichier contenu enA2
.
Bonnes pratiques pour éviter la récidive
- Désactivez l’option Mettre à jour les liens lors de l’enregistrement avant d’enregistrer un modèle.
- Conservez le classeur et toutes les ressources cibles (PDF, images, etc.) dans la même arborescence que le classeur.
- Privilégiez un chemin UNC stable (
\\Serveur\Partage\
) plutôt qu’un lecteur réseau mappé (R:\
) qui varie selon les postes. - Évitez les caractères spéciaux dans les dossiers et fichiers ; préférez
-
et_
. - Pour les liens internes, utilisez
#Feuille!A1
ou SubAddress uniquement ; n’indiquez pas le nom du fichier. - En contexte OneDrive/SharePoint : conservez les cibles dans la même bibliothèque que le classeur pour garder des chemins stables.
Réglages « Hyperlink Base » : mode d’emploi prudent
Si vous devez absolument recourir à Hyperlink Base
(par exemple pour des modèles diffusés), appliquez ces règles :
Situation | Valeur Hyperlink Base | Pourquoi |
---|---|---|
Dossier des ressources = dossier du classeur | . | Neutre, ne casse pas les liens internes |
Ressources dans un sous‑dossier fixe | laisser vide + chemins relatifs dans les liens | Plus simple et robuste, pas de préfixe imposé |
Ressources sur un partage réseau | \\Serveur\Partage\ | Stable quelle que soit la lettre de lecteur |
Check‑list de validation
- Ouvrir le classeur, désactiver l’option incriminée, enregistrer et fermer.
- Rouvrir : vérifier que les liens externes restent relatifs (pas de
AppData
). - Contrôler quelques liens internes (
#Feuille!A1
) et externes (dansEffects\Lovell
). - Tester depuis un second poste (lettres réseau différentes) pour s’assurer que tout fonctionne en UNC.
FAQ rapide
Q : Pourquoi Excel choisit‑il AppData\Roaming\Microsoft\Excel
?
R : C’est un dossier de travail par défaut qu’Excel emploie quand il tente de « résoudre » un lien relatif en chemin absolu. Lorsque l’option « Mettre à jour les liens lors de l’enregistrement » est activée, il peut substituer ce préfixe parasite.
Q : Dois‑je définir Hyperlink Base
sur le dossier réel (ex. R:\Stuff
) ?
R : Non, sauf besoin impérieux. Laisser vide (ou .
) évite d’influencer des liens internes et de créer des chemins incohérents.
Q : Comment gérer des milliers de liens ?
R : Utilisez le script « tout‑en‑un » ci‑dessous ; il corrige et journalise. Conservez toujours une sauvegarde.
Q : Et si mes liens sont dans des zones de texte ou des formes ?
R : Le traitement ci‑dessus balaie aussi Worksheet.Hyperlinks et les Shapes. Si certains objets restent non traités, ajoutez un passage dédié sur les graphiques/feuilles de graphiques.
Q : Sur Mac ?
R : Le problème d’AppData
est spécifique à Windows, mais l’option « mettre à jour les liens » peut aussi réécrire des chemins. La stratégie générale reste valable : désactiver l’option et utiliser des chemins relatifs.
Script « tout‑en‑un » : corriger, normaliser, sécuriser
Ce script combine : désactivation de l’option, définition prudente d’Hyperlink Base
, correction des liens, conversion des internes en SubAddress, et rapport final. À exécuter depuis le classeur à corriger.
Option Explicit
' 1) Désactiver la réécriture des liens à l'enregistrement
Public Sub DesactiverMajLiens()
Application.Dialogs(xlDialogWebOptions).Show
' Note : l'ouverture de la boîte de dialogue permet de décocher manuellement.
End Sub
' 2) Poser une Hyperlink Base neutre (facultatif)
Public Sub SetHyperlinkBasePoint()
On Error Resume Next
ThisWorkbook.BuiltinDocumentProperties("Hyperlink Base").Value = "."
On Error GoTo 0
End Sub
' 3) Conversion généralisée
Public Sub CorrigerTousLesLiens()
Dim ws As Worksheet, h As Hyperlink, shp As Shape
Dim wb As Workbook: Set wb = ThisWorkbook
Dim log As Worksheet, r As Long
Dim oldAddr As String, newAddr As String, oldSub As String, newSub As String
```
On Error Resume Next
Set log = wb.Worksheets("Hyperlink_Report")
If log Is Nothing Then
Set log = wb.Worksheets.Add
log.Name = "Hyperlink_Report"
log.Range("A1:H1").Value = Array("Feuille","Objet","Type","Old Address","New Address","Old SubAddr","New SubAddr","Action")
log.Rows(1).Font.Bold = True
End If
On Error GoTo 0
Application.ScreenUpdating = False
For Each ws In wb.Worksheets
' a) Liens standard
For Each h In ws.Hyperlinks
oldAddr = h.Address: oldSub = h.SubAddress
newAddr = oldAddr: newSub = oldSub
' Suppression du préfixe AppData, normalisation
If IsAppDataExcelPath(newAddr) Then newAddr = StripAppDataExcelPrefix(newAddr)
newAddr = Replace$(newAddr, "/", "\")
' Conversion interne : si l'adresse contient ]Feuille!Cellule
If newSub = "" And InStr(1, newAddr, "]", vbTextCompare) > 0 Then
newSub = Mid$(newAddr, InStrRev(newAddr, "]") + 1)
' uniquement si la sous-adresse ressemble à Feuille!Cellule
If InStr(1, newSub, "!", vbTextCompare) > 0 Then
newAddr = ""
End If
End If
If newAddr <> oldAddr Or newSub <> oldSub Then
h.Address = newAddr
h.SubAddress = newSub
r = log.Cells(log.Rows.Count, 1).End(xlUp).Row + 1
log.Cells(r, 1).Value = ws.Name
log.Cells(r, 2).Value = "Hyperlink"
log.Cells(r, 3).Value = IIf(Len(newAddr) = 0, "Interne", "Externe")
log.Cells(r, 4).Value = oldAddr
log.Cells(r, 5).Value = newAddr
log.Cells(r, 6).Value = oldSub
log.Cells(r, 7).Value = newSub
log.Cells(r, 8).Value = "Corrigé"
End If
Next h
' b) Formes
For Each shp In ws.Shapes
If Not shp.Hyperlink Is Nothing Then
oldAddr = shp.Hyperlink.Address: oldSub = shp.Hyperlink.SubAddress
newAddr = oldAddr: newSub = oldSub
If IsAppDataExcelPath(newAddr) Then newAddr = StripAppDataExcelPrefix(newAddr)
newAddr = Replace$(newAddr, "/", "\")
If newSub = "" And InStr(1, newAddr, "]", vbTextCompare) > 0 Then
newSub = Mid$(newAddr, InStrRev(newAddr, "]") + 1)
If InStr(1, newSub, "!", vbTextCompare) > 0 Then newAddr = ""
End If
If newAddr <> oldAddr Or newSub <> oldSub Then
shp.Hyperlink.Address = newAddr
shp.Hyperlink.SubAddress = newSub
r = log.Cells(log.Rows.Count, 1).End(xlUp).Row + 1
log.Cells(r, 1).Value = ws.Name
log.Cells(r, 2).Value = shp.Name
log.Cells(r, 3).Value = IIf(Len(newAddr) = 0, "Interne", "Externe")
log.Cells(r, 4).Value = oldAddr
log.Cells(r, 5).Value = newAddr
log.Cells(r, 6).Value = oldSub
log.Cells(r, 7).Value = newSub
log.Cells(r, 8).Value = "Corrigé (Shape)"
End If
End If
Next shp
Next ws
Application.ScreenUpdating = True
MsgBox "Traitement terminé. Vérifiez l’onglet 'Hyperlink_Report'.", vbInformation
```
End Sub
Modèles de liens fiables (à copier/coller)
Besoin | Syntaxe recommandée | Exemple |
---|---|---|
Aller à une feuille | #Feuille!A1 (SubAddress seul) | #Résumé!B2 |
Ouvrir un fichier à côté du classeur | Chemin relatif à partir du dossier du classeur | Docs\Notice.pdf |
Ouvrir un fichier sur le réseau | Chemin UNC | \\Srv-Fichiers\Projets\P123\Devis.docx |
Lien dynamique en formule | =HYPERLINK( DossierClasseur & "SousDossier\Fichier.ext" ; "Texte" ) | Voir l’exemple avec CELL("filename") ci‑dessus |
Procédure de mise au propre (résumé opérationnel)
- Désactivez Mettre à jour les liens lors de l’enregistrement.
- Laissez Hyperlink Base vide (ou
.
). - Exécutez FixAllHyperlinksInWorkbook ou CorrigerTousLesLiens pour nettoyer les adresses.
- Remplacez les liens internes ambigus par
#Feuille!Cellule
. - Enregistrez, fermez et rouvrez. Contrôlez avec la check‑list.
Points d’attention avancés
- AutoSave/Co‑édition : sur des bibliothèques cloud, évitez de mélanger des chemins locaux et web dans un même classeur.
- Héritage de modèles : si vous partez d’un modèle déjà paramétré, vérifiez et purgez Hyperlink Base et l’option de mise à jour des liens avant d’y ajouter vos propres liens.
- Mappages réseau : un lien relatif restera portable, alors qu’un lien absolu en
R:\
ne le sera pas. Préférez\\Serveur\Partage\...
. - Formes & images : beaucoup de liens « cliquables » sont posés sur des formes ; ne les oubliez pas dans les scripts.
- Caractères spéciaux : gardez des noms simples (
a‑z
, chiffres,-
,_
). Évitez les accents et espaces non‑cassants dans les chemins.
Conclusion
Si vos liens hypertexte Excel se transforment en chemins absolus sous AppData\Roaming\Microsoft\Excel
, le coupable est presque toujours l’option Mettre à jour les liens lors de l’enregistrement. Désactivez‑la, privilégiez les liens internes via #Feuille!Cellule
et des chemins relatifs/UNC pour l’externe. Les macros fournies vous permettent de réparer massivement un classeur déjà touché et de repartir sur des bases saines.