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

概要

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

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

詳細情報

「概要」セクションで説明されているこの問題をテストするには、次の手順に従います。

  1. 64 ビット バージョンのMicrosoft Word 2010で Word 文書を開きます。
  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 エディターで実行] をクリックするか、[実行] メニューの[サブユーザー フォームの実行] コマンドを選択します。 次に、表示されるダイアログ ボックスで [ マクロ 1 の実行 ] をクリックします。 
  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 データ型を使用する Function プロシージャと、Void 値を返す API コールバックの Sub プロシージャ、16 ビットの整数データ型、または 32 ビットの Long データ型を使用できます。 したがって、前述の手順では、VBA で 32 ビット環境でコードを実行してもエラーは発生しません。 この問題は、64 ビット環境で実行する VBA のポインターの変更が原因で発生します。 そのため、コールバック関数は、64 ビット環境で正しい戻り値の型を使用して明示的に宣言する必要があります。 この動作では、前述の例にある TimerProc を、Function プロシージャではなく Sub プロシージャとして宣言する必要があります。