Excel : réparer les liens hypertexte qui deviennent des chemins absolus (AppData\Roaming\Microsoft\Excel)

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.

Sommaire

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ômeCe que vous voyezRacine du problème
Liens vers des sous‑dossiers cassésChemins 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ésCliquer envoie vers un dossier, pas vers une feuilleHyperlink Base défini sur un chemin réel (ex. R:\Stuff) qui influence certains liens
Comportement variable entre postesLe même classeur fonctionne chez X mais pas chez YDiffé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é)

  1. Ouvrez Fichier › Options › Options avancées.
  2. Dans la section Général, cliquez sur Options Web….
  3. Allez à l’onglet Fichiers.
  4. Décochez Mettre à jour les liens lors de l’enregistrement.
  5. 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 de Hyperlink 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) &gt; 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 &lt;&gt; 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) &gt; 0 Then
                oldAddr = shp.Hyperlink.Address
                newAddr = oldAddr
                If IsAppDataExcelPath(newAddr) Then
                    newAddr = StripAppDataExcelPrefix(newAddr)
                End If
                newAddr = Replace$(newAddr, "/", "\")
                If newAddr &lt;&gt; 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) &gt; 0 Then
                ' Déjà interne : rien à faire
            ElseIf InStr(1, h.Address, "[", vbTextCompare) &gt; 0 _
               And InStr(1, h.Address, "]", vbTextCompare) &gt; 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 en A2.

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 :

SituationValeur Hyperlink BasePourquoi
Dossier des ressources = dossier du classeur.Neutre, ne casse pas les liens internes
Ressources dans un sous‑dossier fixelaisser vide + chemins relatifs dans les liensPlus 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

  1. Ouvrir le classeur, désactiver l’option incriminée, enregistrer et fermer.
  2. Rouvrir : vérifier que les liens externes restent relatifs (pas de AppData).
  3. Contrôler quelques liens internes (#Feuille!A1) et externes (dans Effects\Lovell).
  4. 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) &gt; 0 Then
            newSub = Mid$(newAddr, InStrRev(newAddr, "]") + 1)
            ' uniquement si la sous-adresse ressemble à Feuille!Cellule
            If InStr(1, newSub, "!", vbTextCompare) &gt; 0 Then
                newAddr = ""
            End If
        End If

        If newAddr &lt;&gt; oldAddr Or newSub &lt;&gt; 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) &gt; 0 Then
                newSub = Mid$(newAddr, InStrRev(newAddr, "]") + 1)
                If InStr(1, newSub, "!", vbTextCompare) &gt; 0 Then newAddr = ""
            End If
            If newAddr &lt;&gt; oldAddr Or newSub &lt;&gt; 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)

BesoinSyntaxe recommandéeExemple
Aller à une feuille#Feuille!A1 (SubAddress seul)#Résumé!B2
Ouvrir un fichier à côté du classeurChemin relatif à partir du dossier du classeurDocs\Notice.pdf
Ouvrir un fichier sur le réseauChemin 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)

  1. Désactivez Mettre à jour les liens lors de l’enregistrement.
  2. Laissez Hyperlink Base vide (ou .).
  3. Exécutez FixAllHyperlinksInWorkbook ou CorrigerTousLesLiens pour nettoyer les adresses.
  4. Remplacez les liens internes ambigus par #Feuille!Cellule.
  5. 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.

Sommaire