<p>[METADATA: PROMPT_ENGINEERING_DRAFT_VBA_PERFORMANCE_MONITOR]
本記事は<strong>Geminiの出力をプロンプト工学で整理した業務ドラフト(未検証)</strong>です。</p>
<h1 class="wp-block-heading">VBA処理のボトルネックを特定する:GetTickCountを用いたミリ秒単位のパフォーマンス計測</h1>
<h3 class="wp-block-heading">【背景と目的】</h3>
<p>マクロの実行速度低下は業務効率を著しく損なうため、ミリ秒単位で正確に処理時間を計測し、改修すべき箇所を特定する手法を確立します。</p>
<h3 class="wp-block-heading">【処理フロー図】</h3>
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid"><pre class="mermaid">
graph TD
A["計測開始"] --> B["開始時刻を取得 GetTickCount"]
B --> C["画面更新停止・計算停止"]
C --> D["メイン処理実行"]
D --> E["画面更新再開・計算再開"]
E --> F["終了時刻を取得 GetTickCount"]
F --> G["差分算出と結果出力"]
G --> H["終了"]
</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
Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else
Declare Function GetTickCount Lib "kernel32" () As Long
#End If
''' <summary>
''' 高精度な処理計測を行うサンプルマクロ
''' </summary>
Sub PerformanceMeasureSample()
Dim startTime As Long
Dim endTime As Long
Dim totalTime As Double
Dim i As Long
Dim dataArray As Variant
' 1. 開始時刻の記録
startTime = GetTickCount()
' 2. エクセル動作の最適化 (高速化の定石)
With Application
.ScreenUpdating = False ' 画面描画停止
.Calculation = xlCalculationManual ' 自動計算停止
.EnableEvents = False ' イベント抑止
End With
' --- メイン処理ここから ---
' 例:10万行のセル処理を想定し、配列を使用して高速化
ReDim dataArray(1 To 100000, 1 To 1)
For i = 1 To 100000
' 仮の処理内容
dataArray(i, 1) = i * 2
Next i
' シートへ一括書き出し
ActiveSheet.Range("A1").Resize(100000, 1).Value = dataArray
' --- メイン処理ここまで ---
' 3. エクセル動作の復元
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
' 4. 終了時刻の記録と結果表示
endTime = GetTickCount()
totalTime = (endTime - startTime) / 1000 ' 秒単位に変換
MsgBox "処理が完了しました。" & vbCrLf & _
"実行時間: " & Format(totalTime, "0.000") & " 秒", vbInformation, "計測結果"
End Sub
</pre>
<h3 class="wp-block-heading">【技術解説】</h3>
<ol class="wp-block-list">
<li><p><strong>Win32 API <code>GetTickCount</code></strong>: VBA標準の <code>Timer</code> 関数は精度が約1/64秒(15.6ms)程度であり、かつ午前0時にリセットされる制約があります。一方、<code>GetTickCount</code> はミリ秒単位(1ms)の精度を持ち、連続稼働する環境でも安定した計測が可能です。</p></li>
<li><p><strong>PtrSafe 宣言</strong>: Office 64bit版の普及に伴い、API宣言には <code>PtrSafe</code> キーワードが必須です。また、条件付きコンパイル(<code>#If VBA7</code>)を用いることで旧バージョンとの互換性を維持しています。</p></li>
<li><p><strong>配列処理による高速化</strong>: セルへの個別アクセスは処理を著しく遅延させます。本コードのように「メモリ上の配列(<code>dataArray</code>)」で計算を完結させ、最後に一括してセルへ書き戻す手法が実務上最も有効な高速化対策です。</p></li>
</ol>
<h3 class="wp-block-heading">【注意点と運用】</h3>
<ul class="wp-block-list">
<li><p><strong>符号の反転(オーバーフロー)</strong>: <code>GetTickCount</code> はシステム起動から約49.7日(2の32乗ミリ秒)経過すると、内部値がリセットされマイナスになる可能性があります。サーバー機など長期間再起動しない端末での計測には注意が必要です。</p></li>
<li><p><strong>副作用の管理</strong>: <code>ScreenUpdating</code> 等を停止した際、エラーが発生すると設定が停止したままになるため、実際の開発では <code>On Error GoTo</code> 等を用いて必ず復元処理を通るように設計してください。</p></li>
<li><p><strong>QueryPerformanceCounter</strong>: さらに微細な(マイクロ秒単位)精度が必要な場合は、より複雑な <code>QueryPerformanceCounter</code> APIを使用しますが、通常の業務改善には <code>GetTickCount</code> で十分です。</p></li>
</ul>
<h3 class="wp-block-heading">【まとめ】</h3>
<ul class="wp-block-list">
<li><p><strong>定量的評価</strong>: 勘ではなく、ミリ秒単位のデータに基づいてコードのボトルネックを特定する。</p></li>
<li><p><strong>環境互換性</strong>: 64bit版Officeを想定し、必ず <code>PtrSafe</code> 対応のAPI宣言を行う。</p></li>
<li><p><strong>最適化の併用</strong>: 計測だけでなく、配列化や画面更新停止などの「高速化ロジック」をセットで実装する。</p></li>
</ul>
[METADATA: PROMPT_ENGINEERING_DRAFT_VBA_PERFORMANCE_MONITOR]
本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。
VBA処理のボトルネックを特定する:GetTickCountを用いたミリ秒単位のパフォーマンス計測
【背景と目的】
マクロの実行速度低下は業務効率を著しく損なうため、ミリ秒単位で正確に処理時間を計測し、改修すべき箇所を特定する手法を確立します。
【処理フロー図】
graph TD
A["計測開始"] --> B["開始時刻を取得 GetTickCount"]
B --> C["画面更新停止・計算停止"]
C --> D["メイン処理実行"]
D --> E["画面更新再開・計算再開"]
E --> F["終了時刻を取得 GetTickCount"]
F --> G["差分算出と結果出力"]
G --> H["終了"]
【実装:VBAコード】
Option Explicit
' --- Win32 API 宣言 (64bit/32bit両対応) ---
' GetTickCountはWindows起動後の経過時間をミリ秒単位で返します
#If VBA7 Then
Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else
Declare Function GetTickCount Lib "kernel32" () As Long
#End If
''' <summary>
''' 高精度な処理計測を行うサンプルマクロ
''' </summary>
Sub PerformanceMeasureSample()
Dim startTime As Long
Dim endTime As Long
Dim totalTime As Double
Dim i As Long
Dim dataArray As Variant
' 1. 開始時刻の記録
startTime = GetTickCount()
' 2. エクセル動作の最適化 (高速化の定石)
With Application
.ScreenUpdating = False ' 画面描画停止
.Calculation = xlCalculationManual ' 自動計算停止
.EnableEvents = False ' イベント抑止
End With
' --- メイン処理ここから ---
' 例:10万行のセル処理を想定し、配列を使用して高速化
ReDim dataArray(1 To 100000, 1 To 1)
For i = 1 To 100000
' 仮の処理内容
dataArray(i, 1) = i * 2
Next i
' シートへ一括書き出し
ActiveSheet.Range("A1").Resize(100000, 1).Value = dataArray
' --- メイン処理ここまで ---
' 3. エクセル動作の復元
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
' 4. 終了時刻の記録と結果表示
endTime = GetTickCount()
totalTime = (endTime - startTime) / 1000 ' 秒単位に変換
MsgBox "処理が完了しました。" & vbCrLf & _
"実行時間: " & Format(totalTime, "0.000") & " 秒", vbInformation, "計測結果"
End Sub
【技術解説】
Win32 API GetTickCount: VBA標準の Timer 関数は精度が約1/64秒(15.6ms)程度であり、かつ午前0時にリセットされる制約があります。一方、GetTickCount はミリ秒単位(1ms)の精度を持ち、連続稼働する環境でも安定した計測が可能です。
PtrSafe 宣言: Office 64bit版の普及に伴い、API宣言には PtrSafe キーワードが必須です。また、条件付きコンパイル(#If VBA7)を用いることで旧バージョンとの互換性を維持しています。
配列処理による高速化: セルへの個別アクセスは処理を著しく遅延させます。本コードのように「メモリ上の配列(dataArray)」で計算を完結させ、最後に一括してセルへ書き戻す手法が実務上最も有効な高速化対策です。
【注意点と運用】
符号の反転(オーバーフロー): GetTickCount はシステム起動から約49.7日(2の32乗ミリ秒)経過すると、内部値がリセットされマイナスになる可能性があります。サーバー機など長期間再起動しない端末での計測には注意が必要です。
副作用の管理: ScreenUpdating 等を停止した際、エラーが発生すると設定が停止したままになるため、実際の開発では On Error GoTo 等を用いて必ず復元処理を通るように設計してください。
QueryPerformanceCounter: さらに微細な(マイクロ秒単位)精度が必要な場合は、より複雑な QueryPerformanceCounter APIを使用しますが、通常の業務改善には GetTickCount で十分です。
【まとめ】
定量的評価: 勘ではなく、ミリ秒単位のデータに基づいてコードのボトルネックを特定する。
環境互換性: 64bit版Officeを想定し、必ず PtrSafe 対応のAPI宣言を行う。
最適化の併用: 計測だけでなく、配列化や画面更新停止などの「高速化ロジック」をセットで実装する。
ライセンス:本記事のテキスト/コードは特記なき限り
CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
コメント