Consigne

Passer des macros VBA en 64 bits : PtrSafe, LongPtr, Declare et #If VBA7

Dans Office 64 bits, chaque instruction Declare doit porter le mot-clé PtrSafe, sinon le projet ne compile pas. Ajouter PtrSafe ne suffit pas : les paramètres et valeurs de retour qui portent un handle ou un pointeur doivent passer en LongPtr. Pour garder un seul code qui tourne aussi sur les anciennes versions, encadrez les déclarations par #If VBA7.

Publié le 27 octobre 2026 · 6 min · par Antoine Despres, Consigne

Pourquoi vos macros cassent en 64 bits

Le VBA d'avant Office 2010 (VBA 6 et antérieurs) visait implicitement le 32 bits : un handle de fenêtre ou un pointeur tenait dans un Long, sur 4 octets. En 64 bits, ces valeurs occupent 8 octets. Les ranger dans un Long les tronque, ce qui peut, selon Microsoft, écraser de la mémoire, produire des résultats faux ou faire planter l'application.

Office 2010 a introduit VBA7, qui ajoute ce qu'il faut pour écrire un code valable en 32 et en 64 bits. Le sujet est devenu courant parce que l'architecture installée par défaut a changé :

Version d'OfficeArchitecture installée par défaut
Office 2010, 2013, 201632 bits (le 64 bits se choisit à l'installation)
Office 2019, Microsoft 36564 bits

Seul le code exécuté dans un Office 64 bits doit être modifié. Le code VBA ordinaire (cellules, plages, boucles, formulaires MSForms) n'est pas concerné : ce sont les appels à l'API Windows, et quelques composants 32 bits, qui cassent.

Le symptôme : une erreur de compilation à l'ouverture

Dans un Office 64 bits, un module qui contient un Declare sans PtrSafe ne compile pas. Le message complet, dans la version anglaise d'Office, est :

The code in this project must be updated for use on 64-bit systems.
Please review and update Declare statements and then mark them with the PtrSafe attribute.

Pour l'utilisateur, le classeur ou le document affiche une erreur de compilation, souvent dès l'ouverture quand une macro s'y lance automatiquement.

PtrSafe, LongPtr, LongLong : ce que fait chaque mot-clé

ÉlémentRôleDisponible
PtrSafedéclare que le Declare est prévu pour le 64 bits ; obligatoire en Office 64 bitsVBA7 (Office 2010 et suivants)
LongPtrtype des pointeurs et handles : devient Long en 32 bits, LongLong en 64 bitsVBA7
LongLongentier signé sur 64 bitsOffice 64 bits uniquement
CLngPtr, CLngLngconversions vers LongPtr et LongLongVBA7 ; CLngLng en 64 bits uniquement
VBA7constante de compilation, vraie dans l'éditeur VBA7Office 2010 et suivants
Win64constante de compilation, vraie dans un Office 64 bitsVBA7

LongPtr n'est pas un vrai type : c'est un alias résolu à la compilation. C'est précisément ce qui permet d'écrire une seule déclaration valable sur les deux architectures.

Corriger un Declare, étape par étape

Prenons l'exemple donné par Microsoft. La déclaration d'origine :

Declare Function GetActiveWindow Lib "user32" () As Long

Ajouter seulement PtrSafe fait disparaître l'erreur de compilation, mais laisse un handle tronqué : c'est le cas le plus dangereux, parce que le code semble fonctionner.

' Compile, mais reste faux en 64 bits
Declare PtrSafe Function GetActiveWindow Lib "user32" () As Long

La version correcte type le handle renvoyé en LongPtr :

Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr

La méthode à suivre pour chaque Declare :

  1. Ajoutez PtrSafe après Declare.
  2. Repérez les paramètres et la valeur de retour qui portent un handle (hWnd, hDC, hInstance, hKey…) ou un pointeur (lp…, adresses mémoire) : passez-les en LongPtr.
  3. Laissez en Long les entiers qui restent sur 32 bits dans l'API (tailles, indicateurs, codes de retour). Microsoft recommande LongPtr pour les pointeurs et les handles, pas pour tout.
  4. Suivez ces valeurs dans le code : les variables qui reçoivent le handle, les champs des structures Type passées à l'API, les variables locales intermédiaires doivent aussi devenir LongPtr.

Un exemple typique, avec un handle en retour et deux chaînes en paramètres :

Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
    (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr

Sub Exemple()
    Dim h As LongPtr
    h = FindWindow(vbNullString, "Calculatrice")
End Sub

Garder un seul code pour 32 et 64 bits : #If VBA7

Si certains postes ont encore un Office antérieur à 2010, le mot-clé PtrSafe et le type LongPtr n'y existent pas. La compilation conditionnelle sépare les deux mondes :

#If VBA7 Then
    Private Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
#Else
    Private Declare Function GetActiveWindow Lib "user32" () As Long
#End If

Dans la plupart des parcs, #If VBA7 suffit : LongPtr s'adapte tout seul à l'architecture. Réservez #If Win64 aux cas où la logique doit réellement différer entre 32 et 64 bits, par exemple pour manipuler des valeurs LongLong, qui n'existent pas en 32 bits :

#If Win64 Then
    Dim compteur As LongLong
#Else
    Dim compteur As Long
#End If

Si tous vos postes ont Office 2010 ou plus récent, la branche #Else est inutile : une déclaration PtrSafe avec des LongPtr fonctionne en 32 comme en 64 bits.

Ce que PtrSafe ne règle pas

Certaines dépendances n'ont tout simplement pas de version 64 bits. Le catalogue de règles d'Inventaire VBA en relève plusieurs familles :

DépendanceSymptôme en 64 bitsRemplacement possible
MSCOMCTL (ListView, TreeView), MSCOMCT2 (DTPicker), contrôle Calendarcontrôle ou référence « manquant » dans le formulairecontrôle MSForms, saisie de date maison, bibliothèque 64 bits
Script Control (MSScriptControl)référence manquanteréécriture en VBA ou appel à PowerShell
Microsoft.Jet.OLEDB.4.0, DAO 3.6, pilotes ODBC « .mdb » et « .xls »connexion impossibleMicrosoft.ACE.OLEDB.12.0 et la bibliothèque « Microsoft Office Access database engine Object Library »

Ces cas demandent plus de travail qu'un Declare : un formulaire à refaire, une connexion à retester avec les données réelles.

Méthode pour un parc entier

  1. Inventorier tous les fichiers à macros (.xlsm, .xlsb, .xlam, .xls, .docm, .dotm…) sur les partages, pas seulement ceux que l'on connaît.
  2. Chercher les lignes Declare sans PtrSafe, puis les Declare PtrSafe dont un handle ou un pointeur est encore en Long.
  3. Repérer les références et contrôles 32 bits ainsi que les chaînes de connexion Jet.
  4. Corriger en priorité les fichiers utilisés par plusieurs services, et les copies d'un même outil en une seule fois.
  5. Tester sur un poste 64 bits chaque fonction qui appelle l'API Windows : un handle tronqué ne se voit pas à la compilation.

Trouver les macros concernées dans un parc

Inventaire VBA fait les étapes 1 à 3 : il lit les fichiers Office des partages sans ouvrir Office, sans exécuter de macro ni rien envoyer sur le réseau, et liste fichier par fichier les Declare sans PtrSafe, les handles déclarés en Long, les contrôles 32 bits et les accès Jet ou DAO 3.6, avec la ligne en cause. Il traite aussi les signatures V3, le nouvel Outlook et VBScript. C'est une analyse statique : il ne sait pas quelles versions d'Office sont installées sur vos postes, et la détection des handles en Long repose sur les noms des paramètres (hWnd, lp…), donc à relire. La correction du code reste à faire.

Sources

Autres guides