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

Source : https://consignestudio.fr/guides/macros-vba-64-bits-ptrsafe-longptr/ · publié le 2026-10-27 · Antoine Despres, Consigne

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.

## 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'Office | Architecture installée par défaut |
|---|---|
| Office 2010, 2013, 2016 | 32 bits (le 64 bits se choisit à l'installation) |
| Office 2019, Microsoft 365 | 64 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 :

```text
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ément | Rôle | Disponible |
|---|---|---|
| `PtrSafe` | déclare que le `Declare` est prévu pour le 64 bits ; obligatoire en Office 64 bits | VBA7 (Office 2010 et suivants) |
| `LongPtr` | type des pointeurs et handles : devient `Long` en 32 bits, `LongLong` en 64 bits | VBA7 |
| `LongLong` | entier signé sur 64 bits | Office 64 bits uniquement |
| `CLngPtr`, `CLngLng` | conversions vers `LongPtr` et `LongLong` | VBA7 ; `CLngLng` en 64 bits uniquement |
| `VBA7` | constante de compilation, vraie dans l'éditeur VBA7 | Office 2010 et suivants |
| `Win64` | constante de compilation, vraie dans un Office 64 bits | VBA7 |

`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 :

```vb
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.

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

La version correcte type le handle renvoyé en `LongPtr` :

```vb
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 :

```vb
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
```

> Un `LongLong` ne se convertit pas implicitement en `Long` : Microsoft l'interdit pour éviter de tronquer un pointeur. Si une variable `Long` reçoit encore un handle, le compilateur 64 bits vous le signalera ; ne le faites pas taire avec un `CLng`.

## 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 :

```vb
#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 :

```vb
#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épendance | Symptôme en 64 bits | Remplacement possible |
|---|---|---|
| MSCOMCTL (ListView, TreeView), MSCOMCT2 (DTPicker), contrôle Calendar | contrôle ou référence « manquant » dans le formulaire | contrôle MSForms, saisie de date maison, bibliothèque 64 bits |
| Script Control (MSScriptControl) | référence manquante | réécriture en VBA ou appel à PowerShell |
| `Microsoft.Jet.OLEDB.4.0`, DAO 3.6, pilotes ODBC « *.mdb » et « *.xls » | connexion impossible | `Microsoft.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.

> Le mot de passe d'un projet VBA protégé sera nécessaire pour corriger le code dans l'éditeur. Retrouvez-le avant de planifier la correction.

## Trouver les macros concernées dans un parc

[Inventaire VBA](https://consignestudio.fr/macros-vba-64-bits-inventaire/) 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

- [Microsoft Learn, 64-bit Visual Basic for Applications overview](https://learn.microsoft.com/office/vba/language/concepts/getting-started/64-bit-visual-basic-for-applications-overview)
- [Microsoft Learn, PtrSafe keyword](https://learn.microsoft.com/office/vba/language/reference/user-interface-help/ptrsafe-keyword)
- [Microsoft Learn, LongPtr data type](https://learn.microsoft.com/office/vba/language/reference/user-interface-help/longptr-data-type)
- [Microsoft Learn, The code in this project must be updated for use on 64-bit systems](https://learn.microsoft.com/en-us/office/vba/Language/Reference/User-Interface-Help/the-code-in-this-project-must-be-updated-for-use-on-64-bit-systems)
- Inventaire VBA, catalogue des règles B64-001 à B64-004 (src/regles.mjs)
- Textes relus le 2026-10-27
