PR

【対処方法】このプロジェクトのコードは、64ビットシステムで…【Declare,PrtSafe】

Access
この記事にはアフィリエイト広告および広告が含まれています。

今回はパソコンの入れ替え後等にVBAマクロ付きのExcelやAccessファイルを使用した際、
「このプロジェクトのコードは、64ビットシステムで使用するために更新する必要があります。
Declareステートメントの確認および更新を行い、
次にDeclareステートメントにPrtSafe 属性を設定してください。」

とエラーコードがでてしまった場合の対処方法を紹介します。

エラー

エラーの原因は?どんな状況で発生する?

Office64bitで、
Win32API(32bitのWindows API)を呼び出す
と該当のエラーメッセージがでます。
64bitと32bitでは使用できる領域が異なるため、
通常そのまま使うと何かしら問題が発生する場合があります。
よって「使っても良いか」確認の意味も込めたエラーメッセージとなります。

例えば、パソコンの入れ替えやOfficeのバージョンアップで、
Officeが32bitから64bitに変わった際
に発生します。

対処方法

対処方法は以下になります。

  • Declare文の変更(※1)
    ①PtrSafeを追加
    ②Long型を適宜PtrLong型に変更
  • API実行箇所をDeclare文の型に合わせる(引数・戻り値) 

※1 Office64bitでのDeclare文の記述方法は、
以下のとおりMicrosoft公式より公開されていますので、 コピーして使用します。

Microsoft Docs:Win32API_PtrSafe より、
Office 2010 ヘルプファイル:64 ビットのサポートが含まれる Win32API_PtrSafe
へのリンクにとび、
「Office2010Win32API_PtrSafe.exe」をダウンロード・インストール。
インストールすると、
「C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe」 に、
Win32API_PtrSafe.TXTが出来上がるので、こちらを開き、該当箇所をコピペする。

なお、Office2010より64bitが新しくできたためOffice2010となっていますが、
他バージョンでも同じように上記のURLからダウンロードします。

コード変更例

例えば、以下のようなコードを記述しているとして、どのように修正するか説明します。
コード内容としては、”user32”というWin32APIを使用し、
アクティブウィンドウの名前を取得して、出力する」という単純なものです。

Declare Function GetActiveWindow Lib "user32" () As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Sub GetWindowName()

'アクティブウインドウのハンドル取得
Dim lWindowHwnd As Long
lWindowHwnd = GetActiveWindow()

'バッファを確保
Dim sWindowName As String
sWindowName = String(256, Chr(0))

'アクティブウインドウのウインドウ名取得
Dim lWindowNameLen As Long
lWindowNameLen = GetWindowText(lWindowHwnd, sWindowName, Len(sWindowName))

'イミディエイトに出力
Debug.Print "現在アクテイブウインドウのタイトル名は"
Debug.Print sWindowName
Debug.Print "長さは" + Str(lWindowNameLen) + "です"

End Sub

もちろん、Office32bitではエラーメッセージなしで正常に動きます。

Declare文の変更

まず、Win32API_PtrSafe.TXTを開いて該当の箇所
「GetActiveWindow」「GetWindowTextA」などで検索し、コピペします。

Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr
Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long

Declare文の変更はたったこれだけです♪
注意点は、必ず「Win32API_PtrSafe.TXT」を見てコピペすることです。
バグの元なので全てのLong型をPtrLong型にしないようにしてください。

API実行箇所をDeclare文の型に合わせる(引数・戻り値)

次にAPI実行箇所については、Declare文と睨めっこしながら変更していきます。
今回の場合、GetActiveWindowの戻り値の型であり、
GetWindowTextの第一引数であるlWindowHwndを Long型からLongPtr型に変えます。
命名規則にもよりますが、変数名のルールで型名も考慮しているのであればそちらも変更します。
lWindowHwndからlpWindowHwnd

Private Sub GetWindowName()

'アクティブウインドウのハンドル取得
Dim lpWindowHwndAs LongPtr
lpWindowHwnd = GetActiveWindow()

'バッファを確保
Dim sWindowName As String
sWindowName = String(256, Chr(0))

'アクティブウインドウのウインドウ名取得
Dim lWindowNameLen As Long
lWindowNameLen = GetWindowText(lpWindowHwnd, sWindowName, Len(sWindowName))

'イミディエイトに出力
Debug.Print "現在アクテイブウインドウのタイトル名は"
Debug.Print sWindowName
Debug.Print "長さは" + Str(lWindowNameLen) + "です"

End Sub

他にも元からLong型のものがありますが、Declare文でもLong型なので変更しません。

以上で、VBAのOffice64bit対応は完了です。

補足:PtrSafeやPtrLong型について

簡単に紹介すると以下になります。

  • PtrSafe
    Office64bitで実行しても安全であると明示するキーワード
  •  
  • PtrLong型
    Office32bitではLong型に、Office64bitではLongLong形になる型

このことから、
Office64bitで使えるようにコードを書き換えても、 Office32bitで動くようになっています。

タイトルとURLをコピーしました