<p><!-- STYLESHEET_ID: VBA_WIN32_PERF_001 -->
<!-- GEN_DATE: 2024-05-23 -->
<!-- TECH_AREA: Office Automation / Win32 API --></p>
<p>本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">Win32 API「GetTickCount」によるVBA処理時間の高精度計測と高速化実装</h1>
<h3 class="wp-block-heading">【背景と目的】</h3>
<p>VBA標準の<code>Timer</code>関数は精度が約15ミリ秒と荒く、高速なループ処理のボトルネック特定には不向きです。本稿ではWin32 APIを利用し、1ミリ秒単位の計測を実現します。</p>
<h3 class="wp-block-heading">【処理フロー図】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["開始"] --> B["Win32 API 宣言"]
B --> C["計測開始時のTick取得"]
C --> D["高速化設定の適用"]
D --> E["メイン処理実行"]
E --> F["高速化設定の解除"]
F --> G["計測終了時のTick取得"]
G --> H["差分計算・結果表示"]
H --> I["終了"]
</pre></div>
<h3 class="wp-block-heading">【実装:VBAコード】</h3>
<pre data-enlighter-language="generic">Option Explicit
' --- Win32 API 宣言 (64bit/32bit両対応) ---
' 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
''' <summary>
''' 高精度計測を伴うデータ処理のサンプル
''' </summary>
Public Sub ExecuteHighPrecisionTask()
Dim startTime As Long
Dim endTime As Long
Dim executionTime As Double
' 1. 計測開始
startTime = GetTickCount()
' 2. 高速化設定(画面更新停止・自動計算停止)
Call OptimizeExcel(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 OptimizeExcel(False)
' 5. 計測終了と結果算出
endTime = GetTickCount()
executionTime = (endTime - startTime) / 1000 ' 秒単位に変換
MsgBox "処理が完了しました。" & vbCrLf & _
"実行時間: " & Format(executionTime, "0.000") & " 秒", vbInformation
Exit Sub
ErrorHandler:
Call OptimizeExcel(False)
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub
''' <summary>
''' Excelの動作設定を切り替えて処理を高速化する
''' </summary>
Private Sub OptimizeExcel(ByVal enable As Boolean)
With Application
If enable Then
.ScreenUpdating = False ' 画面更新停止
.Calculation = xlCalculationManual ' 自動計算停止
.EnableEvents = False ' イベント停止
Else
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End If
End With
End Sub
</pre>
<h3 class="wp-block-heading">【技術解説】</h3>
<ol class="wp-block-list">
<li><p><strong>Win32 APIの採用理由</strong>:
VBA標準の<code>Timer</code>関数はシステム時刻に基づきますが、<code>GetTickCount</code>はシステムの稼働時間を参照するため、より高精度(1ms単位)な計測が可能です。</p></li>
<li><p><strong>PtrSafe 宣言</strong>:
<code>VBA7</code>(Excel 2010以降)および64bit環境で動作させるため、条件付きコンパイルと<code>PtrSafe</code>キーワードが必須となります。</p></li>
<li><p><strong>最適化関数の分離</strong>:
<code>ScreenUpdating</code>等の設定変更を独立したサブプロシージャ(<code>OptimizeExcel</code>)にすることで、再利用性を高め、エラー発生時の復旧漏れを防ぎます。</p></li>
</ol>
<h3 class="wp-block-heading">【注意点と運用】</h3>
<ul class="wp-block-list">
<li><p><strong>49.7日の壁</strong>: <code>GetTickCount</code>の戻り値は32bit符号付き整数の範囲を超えるため、Windowsを連続稼働させて約49.7日経過すると数値がループ(オーバーフローのようにリセット)されます。サーバーOS等で長時間稼働させる場合は注意が必要です。</p></li>
<li><p><strong>エラーハンドリング</strong>: 高速化設定(<code>ScreenUpdating = False</code>)中にマクロが中断すると、Excelの操作ができなくなる(画面が固まる)ため、必ず<code>On Error</code>句で設定を元に戻す処理を入れてください。</p></li>
<li><p><strong>さらなる精度</strong>: さらにマイクロ秒単位の精度が必要な場合は、<code>QueryPerformanceCounter</code> APIの検討が必要ですが、通常の実務改善であれば<code>GetTickCount</code>で十分です。</p></li>
</ul>
<h3 class="wp-block-heading">【まとめ】</h3>
<ol class="wp-block-list">
<li><p><strong>ボトルネックの可視化</strong>: 1ms単位で計測することで、どの処理が遅いのかを正確に特定する。</p></li>
<li><p><strong>一括設定の定石化</strong>: 画面更新停止等の「高速化セット」をテンプレート化して適用する。</p></li>
<li><p><strong>環境互換性の確保</strong>: <code>PtrSafe</code>を用いた宣言により、組織内の多様なExcelバージョンに対応させる。</p></li>
</ol>
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
Win32 API「GetTickCount」によるVBA処理時間の高精度計測と高速化実装
【背景と目的】
VBA標準のTimer関数は精度が約15ミリ秒と荒く、高速なループ処理のボトルネック特定には不向きです。本稿ではWin32 APIを利用し、1ミリ秒単位の計測を実現します。
【処理フロー図】
graph TD
A["開始"] --> B["Win32 API 宣言"]
B --> C["計測開始時のTick取得"]
C --> D["高速化設定の適用"]
D --> E["メイン処理実行"]
E --> F["高速化設定の解除"]
F --> G["計測終了時のTick取得"]
G --> H["差分計算・結果表示"]
H --> I["終了"]
【実装:VBAコード】
Option Explicit
' --- Win32 API 宣言 (64bit/32bit両対応) ---
' 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
''' <summary>
''' 高精度計測を伴うデータ処理のサンプル
''' </summary>
Public Sub ExecuteHighPrecisionTask()
Dim startTime As Long
Dim endTime As Long
Dim executionTime As Double
' 1. 計測開始
startTime = GetTickCount()
' 2. 高速化設定(画面更新停止・自動計算停止)
Call OptimizeExcel(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 OptimizeExcel(False)
' 5. 計測終了と結果算出
endTime = GetTickCount()
executionTime = (endTime - startTime) / 1000 ' 秒単位に変換
MsgBox "処理が完了しました。" & vbCrLf & _
"実行時間: " & Format(executionTime, "0.000") & " 秒", vbInformation
Exit Sub
ErrorHandler:
Call OptimizeExcel(False)
MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub
''' <summary>
''' Excelの動作設定を切り替えて処理を高速化する
''' </summary>
Private Sub OptimizeExcel(ByVal enable As Boolean)
With Application
If enable Then
.ScreenUpdating = False ' 画面更新停止
.Calculation = xlCalculationManual ' 自動計算停止
.EnableEvents = False ' イベント停止
Else
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End If
End With
End Sub
【技術解説】
Win32 APIの採用理由:
VBA標準のTimer関数はシステム時刻に基づきますが、GetTickCountはシステムの稼働時間を参照するため、より高精度(1ms単位)な計測が可能です。
PtrSafe 宣言:
VBA7(Excel 2010以降)および64bit環境で動作させるため、条件付きコンパイルとPtrSafeキーワードが必須となります。
最適化関数の分離:
ScreenUpdating等の設定変更を独立したサブプロシージャ(OptimizeExcel)にすることで、再利用性を高め、エラー発生時の復旧漏れを防ぎます。
【注意点と運用】
49.7日の壁: GetTickCountの戻り値は32bit符号付き整数の範囲を超えるため、Windowsを連続稼働させて約49.7日経過すると数値がループ(オーバーフローのようにリセット)されます。サーバーOS等で長時間稼働させる場合は注意が必要です。
エラーハンドリング: 高速化設定(ScreenUpdating = False)中にマクロが中断すると、Excelの操作ができなくなる(画面が固まる)ため、必ずOn Error句で設定を元に戻す処理を入れてください。
さらなる精度: さらにマイクロ秒単位の精度が必要な場合は、QueryPerformanceCounter APIの検討が必要ですが、通常の実務改善であればGetTickCountで十分です。
【まとめ】
ボトルネックの可視化: 1ms単位で計測することで、どの処理が遅いのかを正確に特定する。
一括設定の定石化: 画面更新停止等の「高速化セット」をテンプレート化して適用する。
環境互換性の確保: PtrSafeを用いた宣言により、組織内の多様なExcelバージョンに対応させる。
ライセンス:本記事のテキスト/コードは特記なき限り
CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
コメント