【VBA】Win32 APIを活用したミリ秒単位の処理計測とマクロ高速化手法

Tech

【ビジネスロジック設計】

  1. 目的:VBAにおける1秒未満の精密な処理時間計測と、実務的な高速化テンプレートの提供。

  2. 手法:Win32 API (GetTickCount) を活用し、標準の Timer 関数(秒単位)以上の分解能(ミリ秒単位)を確保。

  3. 構成:宣言部(64bit対応)、計測ラッパー、高速化設定、主処理の4層構造。

  4. 品質管理:エラーハンドリングによる「設定戻し忘れ」の防止を組み込む。

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

【VBA】Win32 APIを活用したミリ秒単位の処理計測とマクロ高速化手法

【背景と目的】

大量データ処理時、標準のTimer関数では分解能が不足し、正確なボトルネック特定が困難です。APIを用いた高精度計測で最適化の基盤を構築します。

【処理フロー図】

graph TD
A["計測開始: GetTickCount"] --> B["画面更新/自動計算の停止"]
B --> C["メイン処理: 配列操作・計算等"]
C --> D["画面更新/自動計算の再開"]
D --> E["計測終了: GetTickCount"]
E --> F["実行時間(ms)の算出と出力"]

【実装: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 ExecuteOptimizedProcess()
    Dim startTime As Long
    Dim endTime As Long
    Dim executionTime As Long

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

    ' 2. 高速化設定の適用
    Call FastMode(True)

    On Error GoTo ErrorHandler

    ' ------------------------------------------------
    ' 3. メイン処理(例:大量の配列処理)
    ' ------------------------------------------------
    Dim i As Long
    Dim tempArray(1 To 1000000) As Long

    For i = 1 To 1000000
        tempArray(i) = i * 2 ' ダミー処理
    Next i
    ' ------------------------------------------------

    ' 4. 高速化設定の解除
    Call FastMode(False)

    ' 5. 計測終了と結果表示
    endTime = GetTickCount()
    executionTime = endTime - startTime

    MsgBox "処理が完了しました。" & vbCrLf & _
           "実行時間: " & executionTime & " ms", vbInformation, "計測結果"

    Exit Sub

ErrorHandler:
    Call FastMode(False)
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

''' <summary>
''' エクセル動作の高速化/通常化を切り替える
''' </summary>
Private Sub FastMode(ByVal isOn As Boolean)
    With Application
        If isOn Then
            .ScreenUpdating = False         ' 画面更新停止
            .Calculation = xlCalculationManual ' 自動計算停止
            .EnableEvents = False           ' イベント抑止
            .DisplayStatusBar = False       ' ステータスバー更新停止
        Else
            .ScreenUpdating = True
            .Calculation = xlCalculationAutomatic
            .EnableEvents = True
            .DisplayStatusBar = True
        End If
    End With
End Sub

【技術解説】

  1. GetTickCountの優位性: VBA標準のTimer関数は単精度浮動小数点型で、分解能は約1/64秒(約15.6ms)ですが、GetTickCountはシステムタイマーから直接ミリ秒単位の整数を取得するため、より精密なプロファイリングが可能です。

  2. PtrSafeと条件付きコンパイル: Office 2010以降の64bit版ExcelでAPIを動かすにはPtrSafeキーワードが必須です。#If VBA7を使用することで、古いバージョンとの互換性を維持しています。

  3. FastModeサブルーチン: ScreenUpdatingCalculationの停止は、セルへの書き込みが多い処理において劇的な(数倍〜数十倍)速度向上をもたらします。

【注意点と運用】

  • 49日問題: GetTickCountは戻り値が Long 型(32bit符号付き整数)の範囲に依存するため、Windowsを連続起動して約49.7日経過すると値が0にリセットされます。サーバー用途でない限り問題ありません。

  • エラー時の復旧: 処理中にエラーで中断した場合、画面更新停止などが維持されると操作不能に見えるため、必ず On Error GoTo で設定を元に戻す処理(FastMode(False))を通過させてください。

  • APIの限界: さらに高精度(マイクロ秒単位)が必要な場合は QueryPerformanceCounter APIを使用しますが、通常の業務自動化であれば GetTickCount で十分です。

【まとめ】

  1. ミリ秒計測でコード内の「本当に遅い箇所」を定量的に特定する。

  2. 高速化設定(三種の神器)をセットで適用し、描画と計算のオーバーヘッドを削る。

  3. エラーハンドリングを徹底し、設定変更によるユーザー側の不具合を防止する。

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

コメント

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