Faire cohabiter du code VBA 32 bits et 64 bits

Depuis Office 2010, Access peut exister en version 32 bits ou 64 bits, selon votre version de Windows. Ceci a un impact sur votre code VBA, lorsque vous utilisez des bibliothèques (DLL) externes. Dans un article précédent, on a vu comment adapter les déclarations de fonctions API de 32 bits en 64 bits.

Mais comment faire si votre base doit tourner à la fois sur une machine 32 bits et sur un ordinateur 64 bits ? Vous ne souhaitez pas corriger toutes vos déclarations API à chaque fois !

La solution

La solution passe par la compilation conditionnelle. Kezako ?

En VBA, il existe des directives particulières, à taper dans le code, pour compiler celui-ci en fonction de critères précis. Le principe consiste à dire quelque chose comme :

Si     Access ou Windows est en version 64 bits
Alors  Utiliser les déclarations API 64 bits
Sinon  Utiliser les déclarations API 32 bits

La syntaxe générale est la suivante :

Comme vous le voyez, ça ressemble à un If / End If Visual Basic, mais cette fois la condition a un impact sur le code qui sera compilé.

Quelques constantes utiles

Pour permettre de détecter la version de VBA ou de Windows, Microsoft fournit quelques constantes système :

  • WIN64 vaut Vrai (True) si Windows est en 64 bits, et Faux (False) sinon.
  • VBA7 vaut Vrai si la version d’Office est 2010 ou plus, et Faux sinon.
  • D’autres constantes existent encore, comme VBA6, WIN32, WIN16, mais elles ne nous serviront pas ici.
  • Il est également possible de définir vos propres constantes, de cette manière :

Les déclarations API en 64 bits sont compatibles avec Access 2010, qu’il soit 32 ou 64 bits. Ça veut dire qu’il suffit de vérifier si on est en VBA7 pour déclarer une API 64 bits. On progresse ! Maintenant, il est possible de d’écrire des tests de ce genre dans notre code VBA :

Ou accessoirement, avec nos propres constantes (mais ça n’est pas le sujet de cet article) :

Exemple pratique

Concrètement, reprenons le cas de la fonction API ShellExecute, qui permet d’ouvrir un fichier quelconque dans son application par défaut, sans connaître celle-ci. Par exemple, un document .xlsx s’ouvrira dans Excel, un .pdf s’ouvrira dans Acrobat Reader, à moins que vous ayez installé un autre lecteur de PDF (comme Sumatra PDF).

La déclaration API de cette fonction a changé en version 64 bits (voyez l’article précédent). Pour faire cohabiter les versions 32 et 64 bits dans une même base de données, écrivez ceci :

Vous aimerez aussi...

5 réponses

  1. Philippe dit :

    Bonjour,
    je suis d’accord avec les solutions que vous proposez.
    Cependant, cela ne fonctionne pas avec Gdiplus.dll
    Auriez vous une idée ?

    Par avance, merci de vos réponses.

  2. Didier Granier dit :

    Bonjour Monsieur Inisan,
    Effectivement ce sera mieux

  3. Hervé Inisan dit :

    Didier Granier > Effectivement, ça marche comme ça. Mais je mettrais plutôt toute la procédure ShellExec entière dans le #If / #End If. Le fait de déplacer uniquement la variable dans ce bloc la transforme en variable globale, ce qui n’est pas utile ici.

    Ouala !

  4. Didier Granier dit :

    Merci pour cet article

    Je viens de faire le test et il faut rajouter la déclaration de la variable lngRes dans les déclaration des API Windows pour que cela fonctionne avec la Procédure Function ShellExec(…).
    Il faut également supprimer la ligne
    Dim lngRes as Long
    dans la Procédure Function ShellExec(…).

    ‘ — DECLARATION API WINDOWS
    #If VBA7 Then
    Private Declare PtrSafe Function ShellExecute _
    Lib « shell32.dll » _
    Alias « ShellExecuteA » ( _
    ByVal hwnd As LongPtr, ByVal lpOperation As String, _
    ByVal lpFile As String, ByVal lpParameters As String, _
    ByVal lpDirectory As String, ByVal nShowCmd As Long) _
    As LongPtr

    Dim lngRes As LongPtr

    #Else
    Private Declare Function ShellExecute _
    Lib « shell32.dll » _
    Alias « ShellExecuteA » ( _
    ByVal hwnd As Long, ByVal lpOperation As String, _
    ByVal lpFile As String, ByVal lpParameters As String, _
    ByVal lpDirectory As String, ByVal nShowCmd As Long) _
    As Long

    Dim lngRes As Long

    #End If

    ‘ —
    ‘ OUVRIR/IMPRIMER UN DOCUMENT A PARTIR DE SON CHEMIN
    ‘ —
    ‘ Entrée : strFichier <- Nom du fichier à ouvrir/imprimer.
    ‘ strOperation <- Opération sur le fichier.
    ‘ explore, find, open, print
    ‘ strParametres <- Paramètres à transmettre au programme,
    ‘ lorsque strFichier est un .exe.
    ‘ strDossier <- Dossier d’exécution par défaut (pour un .exe).
    ‘ awsAffichage <- Mode d’affichage de la fenêtre.

    Public Function ShellExec( _
    ByVal STRfichier As String, _
    Optional ByVal strOperation As String = « Open », _
    Optional ByVal awsAffichage As VbAppWinStyle = VbAppWinStyle.vbNormalFocus, _
    Optional ByVal strParametres As String = «  », _
    Optional ByVal STRdossier As String = «  ») _
    As Boolean

    ‘ Dim lngRes As Long
    lngRes = ShellExecute(Access.hWndAccessApp, strOperation, _
    STRfichier, strParametres, STRdossier, awsAffichage)

    ShellExec = (lngRes < 0) Or (lngRes > 32)
    End Function

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *