Excel 2007で開発されたVBAアプリケーションがあり、ShellExecute
関数へのアクセスを許可する次のコードが含まれています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
私はもともと言った:
どうやら、アプリケーションは64ビットバージョンのWindows(まだ32ビットのOffice 2007を使用)ではコンパイルされません。これは、
Declare
宣言を更新する必要があるためだと思います。Office 2010が新しいVBAランタイム(VB7)を導入したこと、およびこれに
Declare
ステートメントで使用できる新しいキーワードがあり、64ビットWindowsで適切に動作できることを読みました。 VB7には、アプリケーションが32ビットWindowsで実行されているか64ビットWindowsで実行されているかに応じて、古い宣言または新しい宣言が使用される条件付きコンパイルをサポートする新しい定義済みコンパイラ定数もあります。ただし、Office 2007にこだわっているため、代替ソリューションが必要です。私のオプションは何ですか? (可能な限り、アプリケーションの2つの別個のバージョンをリリースする必要はありません)。
ただし、以下のデイビッドの回答によると、Declare
ステートメントが機能しない状況については間違っていました。動作しない唯一の状況は、Windows 64ビット上のOffice 2010 64ビットです。したがって、Office 2007は問題ではありません。
Office 2010を搭載した新しい64ビットマシンで社内ツールを使用している人々で、この問題に既に遭遇しています。
私がしなければならなかったのは、次のようなコード行を変更することだけでした。
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
これに:
#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
もちろん、使用しているライブラリが両方のマシンで使用可能であることを確認する必要がありますが、これまでのところ、私が使用したことは問題になりませんでした。
古いVB6では、PtrSafeは有効なコマンドではないため、コンパイルエラーがあるかのように赤で表示されますが、コンパイラは最初の部分をスキップするため、実際にはエラーを表示しません。 ifブロック。
上記のコードを使用するアプリケーションは、32ビットおよび64ビットのOffice 2003、2007、2010で完全にコンパイルおよび実行されます。
Office 2007は32ビットのみなので、問題はありません。問題は、32ビットバージョンと64ビットバージョンの両方があるOffice 64ビットでのみ発生します。
Office 2007のみを使用している場合、64ビットOffice 2010でユーザーをサポートすることは望みません。解決策はアップグレードすることです。
唯一のDeclare
がShellExecute
である場合、64ビットのOfficeを取得すればすることはあまりありませんが、可能な場合にユーザーをサポートすることは現実的ではありません。出荷するプログラムを実行しないでください!彼らがバグを報告したときにあなたが何をするかを考えてください。
私はこのコードを見つけました(いくつかのLong
が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
PtrSafeを使用して、Excel 2010での動作を確認してください。
本「Microsoft Excel 2010 Power Programming with VBA」の誤植を修正しました。
#If vba7 and win64 then
declare ptrsafe function ....
#Else
declare function ....
#End If
val(application.version)> 12. Office 2010には32ビットバージョンと64ビットバージョンの両方があるため動作しません
実際には、32ビットまたは64ビットプラットフォームをチェックする正しい方法は、VBAのすべてのバージョン(16ビット、32ビット、および64ビットバージョン)で定義されているWin64定数を使用することです。
#If Win64 Then
' Win64=true, Win32=true, Win16= false
#ElseIf Win32 Then
' Win32=true, Win16=false
#Else
' Win16=true
#End If
ソース:コンパイラ定数に関するVBAヘルプ
Officeのすべてのバージョンを記述するには、新しいVBA7とWin64の条件付きコンパイラ定数の組み合わせを使用します。
VBA7
は、コードがVBエディター(Office 2010+で出荷されたVBAバージョン))のバージョン7で実行されているかどうかを判別します。
Win64
は、実行しているOfficeのバージョン(32ビットまたは64ビット)を決定します。
#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
詳細については、 Microsoftサポート記事 を参照してください。
私のためのこの仕事:
#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
洞察力についてJon49に感謝します。
この答えは、コンテキストが間違っている可能性があります。 VBAは最近CLRで実行されると思いますが、そうではありません。いずれにせよ、この返信はsomeoneにとって有用かもしれません。か否か。
Office 2010 32ビットモードを実行する場合、Office 2007と同じです(「問題」はOfficeが64ビットモードで実行されていることです)。ここで重要なのは実行コンテキスト(VBA/CLR)のビット数であり、ロードされたVBA/CLRのビット数はホストプロセスのビット数に依存します。
32/64ビットコール間で最も問題となるのは、long
(ビット数に基づく動的なサイズ)の代わりにint
またはIntPtr
(CLRで一定サイズ)を使用することです。 )「ポインタータイプ」の場合。
ShellExecute 関数には次のシグネチャがあります。
HINSTANCE ShellExecute(
__in_opt HWND hwnd,
__in_opt LPCTSTR lpOperation,
__in LPCTSTR lpFile,
__in_opt LPCTSTR lpParameters,
__in_opt LPCTSTR lpDirectory,
__in INT nShowCmd
);
この場合、HWNDがIntPtr
であることが重要です(これは [〜#〜] hwnd [〜#〜] がvoid*
/"void pointer")であり、long
ではありません。例として pinvoke.net ShellExecute を参照してください。 (いくつかの「ソリューション」はpinvoke.netで日陰になっていますが、最初に見るのに適した場所です)。
ハッピーコーディング。
「新しい構文」に関する限り、私にはわからない。