過去2つの記事で 32ビット版の7-zip32.dllを使用たZIPファイルの作成方法と活用法について解説してきました。最近 Office Excel が64ビット版の環境でもVBAでZIPファイルを扱いたいという複数の要望がありました。
64ビット版の環境では「7-zip64.dll」を使うことでZIPファイルを操作できるようになります。今回はその方法について解説していきたいと思います。
はじめに
7-zip32.dll の場合、64ビット版の環境で 7-zip32.dllの呼び出しを実行した場合「コンパイルエラー」メッセージ(下の画像)が表示されます。
64ビット版の環境で32ビットの記述のままではAPIの呼び出しを行うことはできません。
しかも「7-zip32.dll」は 64ビットでは動作しません。64ビット版の環境では「7-zip32.dll」ではなく「7-zip64.dll」を使う必要があります。
【この記事でわかることは】
・Excel が64ビット版の環境でもZIPファイルを作成できるようにする方法
・32ビットと64ビットどちらの環境でも動作できるようにする方法
7-zip64.dll を利用させていただきます
64ビット版の「7-zip64.dll」は、綾川 鞠乃介 氏のHP「http://ayakawa.o.oo7.jp/index.html」
から “7-zip64.dll ver 9.22.00.02 私家版” をダウンロードできます。
http://ayakawa.o.oo7.jp/soft/ntutil.html#7z ←ここのページにあります。
7-zip64.dllを使うための準備
ダウンロードしてきたファイル「7z922002_64.zip」を解凍します。
複数(5個)のファイルが同梱されていますが、その中の「7-zip64.dll」をWindowsのシステムフォルダ「C:\Windows\System32」にコピーしてください。
しかし、セキュリティー強化環境によってはSystem32ディレクトリに入れることが出来ない(管理者権限がない等)場合もあります。その対処法としてDLLを実行するExcelファイルと同じディレクトリに入れておき「ActiveWorkbook.Path」でPath変更しておくことで利用可能にすることができます。
'7-Zip.dllのパス設定(Systmに無い場合のため)
ChDrive ThisWorkbook.path 'ドライブ変更
ChDir ThisWorkbook.path 'パス変更
64ビット用のDLL参照宣言(7-zip64APIを使うための宣言)
「7-zip32.DLL」のAPI宣言を流用して「7-zip64.DLL」用に変更します。
'7-zip64.DLLのAPI宣言
'[PtrSafe]キーワードの追加と戻り値の[Long]を → [LongPtr]に変更
'[hWnd]ウィンドウハンドルのデータ型を[Long]から[LongPtr]に変更
'[szCmdLine]コマンド文字列,[szOutput]結果を返すバッファ,[dwSize]バッファのサイズ
'戻り値 正常終了= 0 エラー時 <> 0
Private Declare PtrSafe Function SevenZip Lib "7-zip64.DLL" ( _
ByVal hWnd As LongPtr, ByVal szCmdLine As String, _
ByVal szOutput As String, ByVal dwSize As Long) As Long
コメントにも入れていますが変更点は次の3つです。
・ Declareステートメントに「PtrSafe」キーワードを追加
・ 呼び出し名を「7-zip32.DLL」を → 「7-zip64.DLL」に変更
・ [hWnd] のデータ型「Long」を → 「LongPtr」に変更
Declareステートメントを使ってAPI 呼び出しを行う場合「PtrSafe」キーワードを追加してVBAのコンパイルエラーを回避することができます。しかし、引数や戻り値のデータ型が異なったり、呼び出し名が違う場合は、動作中に重大なエラーが発生する可能性があります。引数や戻り値のデータ型は個々に確認して適切に変更する必要があります。何でもかんでも Long を「LongPtr」にすれば良いというものではありません。
修飾子 | PtrSafe | Declare ステートメントが 64 ビットと互換性があることを示します。 この属性は 64 ビット システムでは必須です。 |
データ型 | LongPtr | ポインターおよびハンドラーには LongPtr を使用します。 32ビット環境では Long、64ビット環境では LongLong に変換されます。 |
64ビットと32ビットの両方に対応させる
条件付きコンパイル定数というのが2つあります。
・VBA7 という定数は、Excelのバージョンが2007以前か2010以降かを区別できます。
・Win64 という定数は、実行しているExcelが64ビットなのか32ビットなのかを区別出来ます。
今回の場合は、Excelが64ビットなのか32ビットなのかでAPI宣言を分けたいので Win64 を使います。2007以前の場合は64ビットのExcelは無いので VBA7 は使いません。
条件付きコンパイル定数を使って分岐
Option Explicit
'条件付きコンパイル定数でAPI宣言を分岐
#if Win64 then
'7-zip64.DLLのAPI宣言
'[PtrSafe]キーワードの追加と戻り値の[Long]を → [LongPtr]に変更
'[hWnd]ウィンドウハンドルのデータ型を[Long]から[LongPtr]に変更
'[szCmdLine]コマンド文字列,[szOutput]結果を返すバッファ,[dwSize]バッファのサイズ
'戻り値 正常終了= 0 エラー時 <> 0
Private Declare PtrSafe Function SevenZip Lib "7-zip64.DLL" ( _
ByVal hWnd As LongPtr, ByVal szCmdLine As String, _
ByVal szOutput As String, ByVal dwSize As Long) As Long
#else
'7-zip32.DLLのAPI宣言
'[hWnd]ウィンドウハンドル,[szCmdLine]コマンド文字列
'[szOutput]結果を返すバッファ,[dwSize]バッファのサイズ
'戻り値 正常終了= 0 エラー時 <> 0
Private Declare Function SevenZip Lib "7-zip32.DLL" ( _
ByVal hWnd As Long, ByVal szCmdLine As String, _
ByVal szOutput As String, ByVal dwSize As Long) As Long
#end if
こんな感じです。
「7-zip64.dll」と「7-zip32.dll」の両方をシステムフォルダに入れておくようにしてください。
Win32APIの64ビット対応
VBAで Declare を使って Win32API の呼び出しを行う場合の考え方は、今回の「7-zip64.dll」と同じです。具体例は示しませんが一応簡単に解説しておきます。
PtrSafe キーワードを Declare ステートメントに追加しても、Declare ステートメントの対象として 64 ビットが明示的に指定されるだけです。64 ビットのデータを格納する必要があるステートメント内のすべてのデータ型 (戻り値およびパラメーター) について、64 ビットの整数には LongLong、ポインターとハンドルには LongPtr を使用して、64 ビットのデータを保持するように変更する必要があります。
https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/the-code-in-this-project-must-be-updated-for-use-on-64-bit-systems?source=recommendations
API 呼び出しの Declareステートメントにとりあえず「PtrSafe」キーワードを追加するだけではいけません。(これだけで済む場合もあります。ちゃんと確認したうえでならOKです)
データ型 Long を全部「LongPtr」に変えればいいのではと思いがちですが、これもいけません。LongをLongLongに入れることはできますが、LongLongをLongに入れることはできません。確保したメモリ領域外に書き込もうとすればクラッシュする場合があります!
では、どうすればよいでしょうか?
この修正を正しく行うには、Win32API_ptrsafe.txt 内を検索し該当のものをコピペして使いましょう。下の引用のとおりTypeメンバーの型宣言なども含まれていますので併せて修正します。
Win32API_ptrsafe.txt については次の引用のとおりです。
Win32API_PtrSafe.txtには、次のものが含まれます。
https://learn.microsoft.com/ja-jp/office/troubleshoot/office-suite-issues/win32api_ptrsafe-with-64-bit-support?source=recommendations
· 元のWin32API.txt ファイルに含まれていたWindows API 関数の 32 ビット (x86) および 64 ビット (x64) 互換の Declare ステートメント。
· 指定された Declare ステートメントで使用される定数のグローバル定数宣言。
· 指定された Declare ステートメントで使用されるユーザー定義型 (構造体) の型宣言。Win32API_PtrSafe.txtをダウンロードするには、Office 2010 ヘルプ ファイル: Win32API_PtrSafe 64 ビット サポートの Web ページからファイル Office2010Win32API_PtrSafe.exeにアクセスします。
ダウンロード “Office2010Win32API_PtrSafe.exe” では、”Win32API_PtrSafe.txt”、”using Win32API_PtrSave.xps”、”UsingWin32API_PtrSafe.docx” がインストールされます。 後者の 2 つのファイルには、VBA コードを記述するときにWin32API_PtrSafe.txtの内容を使用するための重要な情報が含まれています。
目的の Win32API_PtrSafe.txt はインストール先のフォルダ
「C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe」内にインストールされています。
APIを呼び出す側の引数や戻り値のデータ型についても修正が必要な場合があります。
必要に応じて、API関数の Declare文の型(引数・戻り値)に合わせて呼び出す側のデータ型を変更します。
まとめ(おわりに)
・64ビット版ExcelでZIPファイルを操作できるようにするため
7-zip64.dll を使えるようにする方法を解説しました。
・今までの解説記事で Win32API を使っている部分については、今後時間をみて
修正していくようにしたいと思います。
ZIPファイル関連記事サンプルを追加登録しました
今後の記事について
今回の記事はいかがだったでしょうか。お役に立てたなら幸いです(^^;
【今後の記事内容はどうしようかなぁ・・・】
記事の更新頻度がスローダウンしていますが、週1回は更新したいと思っていますが…
ご期待ください(^^)/