64ビット環境で実行する VBA マクロでは、戻り値の型を明示的に宣言する必要があります。

概要

一部のコールバック関数を使用して、microsoft Visual Basic for Applications (VBA) の一部の Api を64ビットバージョンの Microsoft Office で宣言するコードを実行しようとすると、コードが失敗します。 ただし、このコードは、32ビットバージョンの Microsoft Office では失敗しません。 この問題は、戻り値の型が64ビットの VBA アプリケーションで明示的に宣言されている必要があるために発生します。 

メモ戻り値の型が明示的に宣言されていない場合、値はバリアント型 (Variant) のデータ型を使用して処理されます。

詳細

「概要」セクションに記載されているこの問題をテストするには、次の手順を実行します。

  1. Word 文書を64ビット版の Microsoft Word 2010 で開きます。
  2. VBA エディターを開くには、リボンの [開発] タブの [ Visual Basic ] をクリックします。
  3. VBA エディターで新しいモジュールを作成するには、次の手順を実行します。
    1. VBA エディターの左上の領域に配置されているプロジェクトツリー で、このドキュメントを右クリックします。
    2. [挿入] を選択し、[モジュール] をクリックします。
    3. 新しいモジュールノードがプロジェクトツリーの下に表示され、新しいモジュールの [VBA コード] ウィンドウが開きます。
    4. 次のコードをコピーして、新しいモジュールの VBA コードウィンドウにコードを貼り付けます。
Option Explicit
Dim iCounter As Integer
Dim lngTimerID As Long
Dim BlnTimer As Boolean

Declare PtrSafe Function SetTimer Lib "user32" (ByVal hwnd As Long, _
 ByVal nIDEvent As Long, _
 ByVal uElapse As Long, _
 ByVal lpTimerFunc As LongPtr) As Long

Declare PtrSafe Function KillTimer Lib "user32" (ByVal hwnd As Long, _
 ByVal nDEvent As Long) As Long

Sub TimerProc(ByVal hwnd As Long, _
 ByVal uMsg As Long, _
 ByVal idEvent As Long, _
 ByVal dwTime As Long)
iCounter = iCounter + 1
End Sub 

Private Sub ToggleTimer()
 If BlnTimer = False Then
 lngTimerID = SetTimer(0, 0, 200, AddressOf TimerProc)
 If lngTimerID = 0 Then
 MsgBox "Timer not created. Ending program"
 Exit Sub
 End If
 BlnTimer = True
 Else 
lngTimerID = KillTimer(0, lngTimerID)
 If lngTimerID = 0 Then
MsgBox "Could not kill the timer"
 End If
 BlnTimer = False
 MsgBox " Timer Count " & iCounter
 End If

End Sub

Sub Macro1()
 ToggleTimer
End Sub   
  1. コードを実行するには、[VBA エディターで実行] をクリックするか、[実行 ] メニューから [ Sub\User フォームの実行] コマンドを選択します。 次に、表示されるダイアログボックスで、[ Macro1 の実行] をクリックします。 
  2. その後、次のようなコードを Sub プロシージャから Function プロシージャに変更します。
Sub TimerProc(ByVal hwnd As Long, _
 ByVal uMsg As Long, _
 ByVal idEvent As Long, _
 ByVal dwTime As Long)

iCounter = iCounter + 1
End Sub
After you have changed the Sub procedure to a Function procedure, the code resembles the following:

Function TimerProc(ByVal hwnd As Long, _
 ByVal uMsg As Long, _
 ByVal idEvent As Long, _
 ByVal dwTime As Long)

iCounter = iCounter + 1
End Function   
  1. コードをもう一度実行すると、次のエラーが表示されます。

Microsoft Word は、情報を回復しようとしています。 この処理には数分間かかる場合があります。

戻り値の型を Variant データ型にすることはできません。 この制限は、64ビット環境で実行する、VBA のコールバック関数にのみ適用されます。 この制限は、外部 API メソッドを呼び出すための Declare ステートメントには適用されません。 32ビット環境で実行される VBA では、Variant データ型と Sub プロシージャを使用して、Void 値を返す可能性のある API コールバック、16ビットの整数データ型、または32ビットである Long データ型を返す Function プロシージャを使用できます。 そのため、前述の手順では、VBA でコードを32ビット環境で実行した場合にエラーは発生しません。 この問題は、VBA で64ビット環境で実行するポインターが変更されたために発生します。 そのため、コールバック関数は、64ビット環境で正しい戻り値の型を使用して明示的に宣言する必要があります。 この動作を行うには、前述の例に示した TimerProc が Sub プロシージャとして宣言されている必要がありますが、Function プロシージャではありません。