【ExcelVBA・マクロ】Declare Functionの使い方|Windows API宣言の基本とSleep関数で処理を待機する方法【コピペOK】

ExcelVBA

VBAには数千個もの関数が用意されていますが、「ミリ秒単位で処理を待機したい」「処理時間を正確に計測したい」といった、VBA単体では実現しづらい処理も存在します。こうした場合に使えるのが、Windowsが提供するDLL(kernel32.dllなど)の関数をVBAから直接呼び出すDeclareステートメントです。

この記事では、Declare Function(Windows API宣言)の基本的な書き方から、実務でよく使うSleep関数・GetTickCount関数の活用例、利用時の注意点まで解説します。

スポンサーリンク
スポンサーリンク

Declare Functionとは

構文は以下の通りです(VBA7以降、64bit版Officeにも対応した書き方)。

Private Declare PtrSafe Function 関数名 Lib "DLL名" (引数リスト) As 戻り値の型

注意点として、Office 2010以降で追加された64bit版のVBA(VBA7)ではPtrSafeキーワードが必須です。32bit版のOfficeしか使わない場合はPtrSafeを省略した従来の書き方もできますが、32bit・64bit両方の環境で動かしたい場合は、次のように条件付きコンパイルを使うと安全です。

#If VBA7 Then
    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

#If VBA7 Thenは、実行環境がVBA7(Office 2010以降)かどうかをコンパイル時に判定する仕組みです。これにより、同じコードを32bit・64bitどちらのOfficeでも動作させられます。

Sleep関数で処理を一定時間待機する

VBAには標準で「指定ミリ秒だけ待機する」関数がありません。Application.Waitは秒単位でしか指定できず、待機中は画面全体の操作を受け付けなくなります。Windows APIのSleep関数を使うと、ミリ秒単位で処理を待機できます。

#If VBA7 Then
    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Sub Sample_Sleep()
    Debug.Print "処理開始:" & Now
    Sleep 500 ' 500ミリ秒(0.5秒)待機する
    Debug.Print "処理再開:" & Now
End Sub

外部アプリの起動待ちや、Web APIへのリトライ間隔の調整など、秒未満の細かい待機が必要な場面で活用できます。

GetTickCount関数で処理時間を計測する

処理のパフォーマンスを確認したいときは、GetTickCount関数を使うと、Windows起動からの経過時間をミリ秒単位で取得できます。処理の前後で値を取得し、差分を計算することで処理時間を計測できます。

#If VBA7 Then
    Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else
    Private Declare Function GetTickCount Lib "kernel32" () As Long
#End If

Sub Sample_MeasureTime()
    Dim startTime As Long
    Dim endTime As Long
    Dim i As Long
    Dim total As Double

    startTime = GetTickCount()

    For i = 1 To 1000000
        total = total + i
    Next i

    endTime = GetTickCount()

    Debug.Print "処理時間:" & (endTime - startTime) & "ミリ秒"
End Sub

GetTickCountを使えば、処理時間を数値としてコード内で取得できるため、ログへの記録や、一定時間を超えたら警告を出す、といった処理にも活用できます。

Windows API利用時の注意点

Windows APIを使う際は、以下の点に注意してください。

  • Declareステートメントは標準モジュールの先頭(プロシージャの外)に書く:クラスモジュールやユーザーフォームのモジュール内には書けません。
  • 引数の型を正確に合わせる:API側の引数の型とVBA側の型が一致していないと、正しく動作しなかったり、最悪の場合Excelが強制終了したりすることがあります。
  • 32bit・64bit環境の違いを意識する:ウィンドウハンドルなど、ポインタを扱うAPIを使う場合はLongではなくLongPtr型を使う必要があります。今回紹介したSleepGetTickCountはポインタを扱わない単純な関数のため、Longのままで問題ありません。
  • 必要最小限の利用にとどめる:VBAの標準機能やApplication.Waitなどで代用できる場合は、無理にAPIを使う必要はありません。APIはあくまで「VBA単体では実現できない処理」を補うための手段と考えましょう。

まとめ

  • Declareステートメントを使うと、VBAからWindows APIのDLL関数を直接呼び出せる
  • 64bit版OfficeではPtrSafeキーワードが必須。#If VBA7 Thenで条件付きコンパイルすれば、32bit・64bit両方の環境に対応できる
  • Sleep関数を使うと、Application.Waitでは対応できないミリ秒単位の待機ができる
  • GetTickCount関数を使うと、処理時間をミリ秒単位で計測できる
  • APIの引数の型やポインタの扱いを誤ると不具合の原因になるため、必要最小限の利用にとどめ、型の対応関係を確認してから使う

Windows APIはVBA標準の関数だけでは対応しきれない処理を補ってくれる仕組みですが、使い方を誤るとExcelの動作が不安定になるリスクもあります。まずはSleepGetTickCountのようなシンプルな関数から試して、Declareステートメントの感覚をつかんでみてください。

スポンサーリンク
スポンサーリンク
ExcelVBA
シェアする
いがぴをフォローする

コメント

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