VBA高速化の鍵:Win32 APIを用いたミリ秒単位の処理時間計測

Tech

【執筆作法:業務ドキュメント・テクニカルライティング】

  • 結論から記述する(PREP法)

  • 専門用語は平易に解説するか、文脈で補完する

  • コードブロックは「実務での再利用性」を最優先する

  • 曖昧な表現を避け、具体的な数値や型を提示する

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

VBA高速化の鍵:Win32 APIを用いたミリ秒単位の処理時間計測

【背景と目的】

VBAのボトルネック特定には、標準のTimer関数では精度が不足します。APIを活用し、ミリ秒単位で正確な実行時間を可視化・最適化します。(63文字)

【処理フロー図】

graph TD
A["計測開始:GetTickCount取得"] --> B["画面更新・自動計算の停止"]
B --> C["メイン処理:配列を用いたデータ加工等"]
C --> D["画面更新・自動計算の再開"]
D --> E["計測終了:GetTickCount取得"]
E --> F["差分計算:ミリ秒単位で結果表示"]

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 (64bit/32bit 両対応) ---
#If VBA7 Then

    ' システム起動後の経過時間をミリ秒単位で取得
    Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else

    Private Declare Function GetTickCount Lib "kernel32" () As Long
#End If

''' <summary>
''' 高速処理と精密な時間計測を両立したサンプルマクロ
''' </summary>
Public Sub MeasureProcessingTime()
    Dim startTime As Long
    Dim endTime As Long
    Dim processTime As Double

    ' 1. 計測開始
    startTime = GetTickCount()

    ' 2. 高速化設定(お約束の最適化)
    With Application
        .ScreenUpdating = False         ' 画面更新停止
        .Calculation = xlCalculationManual ' 自動計算停止
        .EnableEvents = False           ' イベント抑止
    End With

    On Error GoTo ErrorHandler

    ' 3. メイン処理(例:大量のセル転記を配列で高速化)
    Dim dataArray() As Variant
    Dim i As Long
    Const MAX_ROW As Long = 100000

    ReDim dataArray(1 To MAX_ROW, 1 To 1)
    For i = 1 To MAX_ROW
        dataArray(i, 1) = "Sample_" & i
    Next i

    ' セルへの一括書き出し
    ActiveSheet.Range("A1").Resize(MAX_ROW, 1).Value = dataArray

    ' 4. 計測終了
    endTime = GetTickCount()

    ' 5. 後処理(設定の復元)
    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
    End With

    ' 実行時間の算出 (ミリ秒 -> 秒)
    processTime = (endTime - startTime) / 1000

    MsgBox "処理が完了しました。" & vbCrLf & _
           "実行時間: " & Format(processTime, "0.000") & " 秒", vbInformation, "計測結果"

    Exit Sub

ErrorHandler:
    ' エラー時も必ず設定を戻す
    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
    End With
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

【技術解説】

  1. GetTickCountの活用: 標準の Timer 関数は「午前0時からの経過秒数」を返すため、日付をまたぐ処理や、1秒未満の精密な計測(分解能 約15.6ms)には不向きです。APIを使用することでミリ秒単位の精度が得られます。

  2. PtrSafe 宣言: 64bit版Officeでは API 宣言に PtrSafe が必須です。条件付きコンパイル(#If VBA7)を用いることで、旧環境との互換性を維持しています。

  3. 配列処理による高速化: Range オブジェクトへの個別アクセスは非常に低速です。メモリ上の配列(Variant型)で一括処理してからセルに書き戻すことで、API計測の恩恵を感じるレベルの高速化が実現します。

【注意点と運用】

  • 49.7日の壁: GetTickCount は戻り値が32ビット符号付き整数(Long)の範囲を扱うため、PCを起動し続けて約49.7日が経過すると、カウントがリセット(オーバーフロー)されます。サーバー稼働環境では注意が必要です。

  • フロー制御の徹底: ScreenUpdating などを停止した場合、エラー発生時に True に戻さないと、Excelがフリーズしたように見えます。必ず On Error GoTo で復旧処理を記述してください。

  • 高精度が必要な場合: さらに高い精度(マイクロ秒単位)が必要な場合は、QueryPerformanceCounter APIの使用を検討してください。

【まとめ】

  1. ミリ秒計測は Win32 API (GetTickCount) を使い、ボトルネックを正しく把握する。

  2. 計測の前提条件として、画面更新停止や配列処理などの高速化手法を併用する。

  3. 例外処理を組み込み、万が一の際もExcelの設定(画面更新等)を確実に復旧させる。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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