VBAマクロからWindowsのAPI(システム関数)を呼び出す

エクセル上で実行されるVBAマクロからは、Windowsに用意されているAPIを呼び出すことができます。APIとは、Windows上で動くプログラムからWindowsに用意されている各種機能を利用するためのシステム関数です。

VBAマクロからWindowsのAPIを呼び出す仕組みについては、マイクロソフトの開発者向けサイトにOffice VBA と Windows APIというページが用意されているので、これを見ながら基本的な流れを確認してみましょう。

VBAからWindows APIを呼び出すためには、まずその「場所」と「名前」を指定し、Declare文でVBAマクロの関数として宣言する必要があります。この宣言さえすれば、後は通常の関数として呼び出せるようになるわけですね。

試しに、「起動時からの経過時間をミリ秒単位で返す」Windows API「GetTickCount」をVBAから呼び出せるよう宣言してみましょう。

APIの宣言では、そのAPIがWindowsのどのライブラリ(dll)に含まれるのかを調べて指定する必要があります。GetTickCount()は、kernel32.dllに含まれるので「kernel32」を指定し、Declareで宣言しましょう。

これで、宣言したモジュールではAPIのGetTickCountが「GetTickCountという名前の関数」として利用できるようになりました。

Private Declare Function GetTickCount Lib "kernel32" () As Long

Sub test()
  MsgBox GetTickCount
End Sub

上のマクロを実行してみると、実際にAPIから返される結果が表示されますね。

次に、APIの関数に引数を渡してみましょうか。「指定番号の通知音を鳴らす」MessageBeepをVBAマクロから呼び出してみることにします。

一度宣言したAPIは、通常の関数と同じなので「数値」を渡す場合は、「型」にさえ注意すれば特に難しいことはありません。試しに引数として通常のメッセージ音を指定する「64」を指定してみました。

Private Declare Function MessageBeep Lib "user32.dll" (ByVal uType As Integer) As Integer

Sub test()
  MessageBeep(64)
End Sub

実行すると、おなじみのダイアログが出てくるときの音が鳴りましたね。

以上で、VBAマクロからWindowsのAPIを呼び出し、引数や帰り値として「数値」をやり取りする方法が確認できました。

APIと文字列やまとまった情報(構造体)をやり取りする場合も、基本的には同じなのですが、その場合は「文字列や構造体が存在するアドレス(メモリ上の番号)」を数値としてやりとりする、という点に注意しましょう。

APIが使えるようになると、WindowsでできることならVBAマクロでほとんどのことができるようになります。エクセルという一つのアプリケーションの枠を超えて一気に可能性が広がるわけですが、それは同時に「おかしな引数で呼び出したりするとシステムに障害を与えたりファイルを書き換えてしまう」可能性でもあるわけです。
Windows APIを使う場合は、機能や引数、特に「引数として渡したアドレスに情報が書き込まれるか」といった点に注意して慎重に動作確認を行うようにしてください。


エクセルVBA練習帳