J'ai une application VBA développée dans Excel 2007 et qui contient le code suivant pour permettre l'accès à la fonction ShellExecute
à partir de Shell32.dll
:
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
J'ai d'abord dit:
Apparemment, l'application ne le fera pas compiler sur une version 64 bits de Windows (toujours en utilisant Office 2007 32 bits). JE supposons que c'est parce que le La déclaration
Declare
doit être mise à jour.J'ai lu l'introduction d'Office 2010 un nouveau runtime VBA (VB7), et que cela a de nouveaux mots-clés qui peuvent être utilisés dans l'instruction
Declare
pour l'autoriser pour fonctionner correctement sous Windows 64 bits . VB7 a également un nouveau compilateur prédéfini constantes à prendre en charge conditionnel compilation où soit l'ancien ou nouvelle déclaration sera utilisée, en fonction de l'application fonctionne sous Windows 32 ou 64 bits.Cependant, depuis que je suis coincé avec Office 2007 J'ai besoin d'une solution alternative . Quelles sont mes options? (Je préférerais vraiment Ne pas avoir à publier 2 Versions séparées de mon application si Dans la mesure du possible).
Cependant, selon la réponse de David ci-dessous, je me suis trompé sur les circonstances dans lesquelles ma déclaration Declare
ne fonctionnera pas. Les seules circonstances dans lesquelles cela ne fonctionnera pas sont Office 2010 64 bits sur Windows 64 bits. Ainsi, Office 2007 n'est pas un problème.
J'ai déjà rencontré ce problème sur des personnes utilisant mes outils internes sur de nouvelles machines 64 bits avec Office 2010.
tout ce que je devais faire était de changer les lignes de code comme ceci:
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
Pour ça:
#If VBA7 Then
Private Declare PtrSafe 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
#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
#End If
Vous voudrez bien sûr vous assurer que la bibliothèque que vous utilisez est disponible sur les deux machines, mais jusqu'à présent, rien de ce que j'ai utilisé n'a posé de problème.
Notez que dans l’ancien VB6, PtrSafe n’est même pas une commande valide. Il apparaît donc en rouge comme si vous aviez une erreur de compilation, mais cela ne produira jamais une erreur car le compilateur ignorera la première partie le bloc if.
Les applications utilisant le code ci-dessus se compilent et fonctionnent parfaitement sous Office 2003, 2007 et 2010 32 bits et 64 bits.
Office 2007 est uniquement en version 32 bits, il n'y a donc aucun problème. Vos problèmes ne se posent qu’avec Office 64 bits, qui comporte à la fois des versions 32 et 64 bits.
Vous ne pouvez pas espérer prendre en charge les utilisateurs avec Office 2010 64 bits avec Office 2007 uniquement. La solution consiste à mettre à niveau.
Si la seule Declare
que vous avez est cette ShellExecute
, vous n'aurez plus grand-chose à faire une fois que vous aurez mis la main sur Office 64 bits, mais ce n'est pas vraiment viable de prendre en charge les utilisateurs lorsque vous ne pouvez pas exécuter le programme que vous envoyez! Pensez-vous simplement à ce que vous feriez quand ils rapporteront un bogue?
j'ai trouvé ce code (notez que certains Long
sont remplacés par LongPtr
):
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
Utilisez PtrSafe et voyez comment cela fonctionne dans Excel 2010.
Correction d'une faute de frappe du livre "Microsoft Excel 2010 Programmation énergétique avec VBA".
#If vba7 and win64 then
declare ptrsafe function ....
#Else
declare function ....
#End If
val (application.version)> 12.0 ne fonctionnera pas car Office 2010 existe en version 32 et 64 bits
En fait, pour vérifier la plate-forme 32 bits ou 64 bits, vous devez utiliser la constante Win64 définie dans toutes les versions de VBA (versions 16 bits, 32 bits et 64 bits).
#If Win64 Then
' Win64=true, Win32=true, Win16= false
#ElseIf Win32 Then
' Win32=true, Win16=false
#Else
' Win16=true
#End If
Source: Aide VBA sur les constantes du compilateur
Pour écrire pour toutes les versions d'Office, utilisez une combinaison des nouvelles constantes de compilateur conditionnelles VBA7 et Win64.
VBA7
détermine si le code est exécuté dans la version 7 de l'éditeur VB (version VBA livrée dans Office 2010+).
Win64
détermine quelle version (32 bits ou 64 bits) d'Office est en cours d'exécution.
#If VBA7 Then
'Code is running VBA7 (2010 or later).
#If Win64 Then
'Code is running in 64-bit version of Microsoft Office.
#Else
'Code is running in 32-bit version of Microsoft Office.
#End If
#Else
'Code is running VBA6 (2007 or earlier).
#End If
Voir Article de support Microsoft pour plus de détails.
Ce travail pour moi:
#If VBA7 And Win64 Then
Private Declare PtrSafe Function ShellExecuteA Lib "Shell32.dll" _
(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
#Else
Private Declare Function ShellExecuteA Lib "Shell32.dll" _
(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
#End If
Merci Jon49 pour la perspicacité.
Cette réponse est probablement fausse fausse le contexte. Je pensais que VBA fonctionnait maintenant sur le CLR, mais ce n'est pas le cas. Dans tous les cas, cette réponse peut être utile à quelqu'un. Ou pas.
Si vous exécutez le mode Office 2010 32 bits, il est identique à Office 2007. (Le "problème" concerne Office qui s'exécute en mode 64 bits). C'est le bitness du contexte d'exécution (VBA/CLR) qui est important ici et le bitness du VBA/CLR chargé dépend du bitness du processus de l'hôte.
Entre les appels 32/64 bits, les problèmes les plus évidents sont l'utilisation de long
ou int
(taille constante dans le CLR) au lieu de IntPtr
(taille dynamique en fonction du nombre de bits) pour "types de pointeur".
La fonction ShellExecute a une signature de:
HINSTANCE ShellExecute(
__in_opt HWND hwnd,
__in_opt LPCTSTR lpOperation,
__in LPCTSTR lpFile,
__in_opt LPCTSTR lpParameters,
__in_opt LPCTSTR lpDirectory,
__in INT nShowCmd
);
Dans ce cas, il est important que HWND soit IntPtr
(car un HWND est un "HANDLE" qui est void*
/"void pointer") et non long
. Voir pinvoke.net ShellExecute à titre d'exemple. (Bien que certaines "solutions" soient louches sur pinvoke.net, c'est un bon endroit pour commencer dans la recherche).
Bonne codage.
En ce qui concerne toute "nouvelle syntaxe", je n'en ai aucune idée.