本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
【VBA】64ビット版Office対応:Win32 API(PtrSafe/LongPtr)の実装完全ガイド
【背景と目的】
32bitから64bit版Office移行時のAPIエラーを解消し、PtrSafeとLongPtrを適切に使い分けることでマクロの動作を安定させます。(61文字)
【処理フロー図】
graph TD
A["開始"] --> B{"VBAのバージョン判定"}
B -->|VBA7以上| C["PtrSafe属性を付与して宣言"]
B -->|VBA6以下| D["従来のDeclareで宣言"]
C --> E{"引数/戻り値の型判定"}
E -->|ポインタ・ハンドル| F["LongPtr型を適用"]
E -->|32bit数値| G["Long型を適用"]
F --> H["API実行"]
G --> H["API実行"]
H --> I["終了"]
【実装:VBAコード】
Option Explicit
' ============================================================
' Win32 API 宣言セクション
' VBA7 (Office 2010以降) かどうかで宣言を分岐
' ============================================================
#If VBA7 Then
' 64bit/32bit両対応の宣言
' PtrSafe: 64bit環境で実行可能であることをコンパイラに通知
' LongPtr: 実行環境に応じて 32bit(4byte) / 64bit(8byte) に自動変化
Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
#Else
' 旧バージョン(Office 2007以前)用
Declare Function GetTickCount Lib "kernel32" () As Long
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
#End If
''' <summary>
''' 高速化処理を施した、API利用による実行時間計測サンプルフロー
''' </summary>
Public Sub ExecuteOptimizedProcess()
Dim startTime As Long
Dim endTime As Long
Dim hWnd As LongPtr ' ハンドルを保持するためLongPtrを使用
' --- 高速化の開始 ---
With Application
.ScreenUpdating = False ' 画面更新停止
.Calculation = xlCalculationManual ' 自動計算停止
.EnableEvents = False ' イベント停止
End With
On Error GoTo ErrorHandler
' APIを使用した処理開始時間の取得
startTime = GetTickCount()
' APIを使用したウィンドウハンドルの取得例
' Excel自体のハンドルを探す(一例)
hWnd = FindWindow("XLMAIN", Application.Caption)
Debug.Print "Window Handle: " & hWnd
' 擬似的な重い処理(Sleep APIで待機)
' ※実務ではここに配列処理などのメインロジックが入る
Sleep 500 ' 0.5秒待機
' 終了時間の取得と計算
endTime = GetTickCount()
MsgBox "処理が完了しました。" & vbCrLf & _
"実行時間: " & (endTime - startTime) & " ms", vbInformation
CleanUp:
' --- 高速化設定の解除(必ず実行する) ---
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
Exit Sub
ErrorHandler:
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
Resume CleanUp
End Sub
【技術解説】
VBA7 定数:
VBA7は Office 2010 以降で True となる条件付きコンパイル定数です。これにより 64bit 版環境で必須となるPtrSafeキーワードを切り分けます。PtrSafe: 64bit 版 VBA で Win32 API を呼び出す際、「この Declare 文は 64bit 安全である」と宣言するために必須です。
LongPtr (Long Pointer): 最も重要なデータ型です。
32bit 環境:
Long(4byte) として動作64bit 環境:
LongLong(8byte) として動作 ウィンドウハンドル(hWnd)やポインタを扱う変数は、必ずこのLongPtrを使用しないと、64bit 環境でメモリ溢れやクラッシュの原因となります。
Long 型の維持: ミリ秒単位の時間(dwMilliseconds)など、データ構造自体が 32bit 固定のものは
LongPtrではなくLongのまま維持するのが正解です。
【注意点と運用】
型の混同に注意: 全ての
LongをLongPtrに置換してはいけません。APIの引数仕様を確認し、ハンドルやポインタのみをLongPtrに変換してください。構造体(Type)のパディング: APIに渡す構造体がある場合、64bit化によりデータのアライメント(境界)が変わることがあります。複雑な構造体の場合はバイト配列での調整が必要になるケースがあります。
参照設定の排除: Win32 API は標準の
kernel32やuser32を参照するため、追加の DLL 登録なしで配布可能です。
【まとめ】
VBA7/Win64定数を使用して、環境に応じた Declare 文を記述する。
ハンドル・ポインタを扱う引数と戻り値には必ず LongPtr を採用する。
エラーハンドリングを実装し、異常終了時も画面更新(ScreenUpdating)を必ず復旧させる。

