【実務・中級編】進捗状況のリアルタイム表示:大容量処理時のDoEvents活用とステータスバー更新の実装 – Visio VBA解析バイブル

スポンサーリンク

Visioを「フリーズ」させない:数千シェイプを掌握する進捗表示の極意

業務自動化の現場でVisioを扱うとき、多くのエンジニアが直面する壁がある。「数百ページの図面、数千のシェイプを処理するとVisioが応答なし(Not Responding)になる」という問題だ。

これを「Visioの仕様だから仕方ない」と諦めていないか?
それは甘えだ。ユーザーにとって、処理中にアプリがフリーズすることは「バグっている」のと同義である。今回は、Visio VBAの内部構造を理解し、洗練された進捗表示を実装する「プロの作法」を伝授する。

1. なぜ「フリーズ」が起きるのか?

Visioのレンダリングエンジンは、単一スレッドで動作している。VBAで`Shapes`コレクションをループさせ、色を変えたりテキストを流し込んだりすると、Visioのメインループは「描画更新」という優先順位の高いタスクを後回しにする。その結果、OSは「このアプリは固まった」と判断し、タイトルバーに「応答なし」を表示する。

これを防ぐ鍵は、「メインループを強制的に解放し、OSに描画と入力を委譲する」こと。これが`DoEvents`の真髄だ。

2. 堅牢な進捗表示の実装パターン

ただ`DoEvents`を叩けばいいわけではない。過度な呼び出しはパフォーマンスを著しく低下させる。「1%進むごとに更新する」といった適切な粒度で制御するのが、ハイパフォーマンスなツール開発の定石だ。

プロダクション環境に耐えうる実装例

このコードは、処理対象のシェイプ数を事前にカウントし、ステータスバーを更新しつつ、描画負荷を最小限に抑える設計となっている。

‘ @description: 大容量処理における進捗表示付きシェイプ処理のテンプレート
Public Sub ProcessShapesWithProgress()
Dim shp As Visio.Shape
Dim pg As Visio.Page
Dim totalShapes As Long
Dim currentCount As Long
Dim lastPercent As Integer

‘ 1. 事前カウント(パフォーマンスのため、一度だけ実行)
totalShapes = GetTotalShapeCount()

‘ 2. ステータスバーの初期化
Application.StatusBar = “処理を開始しています…”

For Each pg In ActiveDocument.Pages
For Each shp In pg.Shapes
‘ — ここに本来の処理を記述 —
‘ 例: shp.Cells(“FillForegnd”).Formula = “RGB(255,0,0)”
‘ —————————–

currentCount = currentCount + 1

‘ 3. 進捗の更新(1%刻みで実行することでオーバーヘッドを抑制)
Dim currentPercent As Integer
currentPercent = Int((currentCount / totalShapes) 100)

If currentPercent > lastPercent Then
Application.StatusBar = “進捗: ” & currentPercent & “% (” & currentCount & “/” & totalShapes & “)”
DoEvents ‘ ここでOSに制御を戻し、描画と入力を受け付ける
lastPercent = currentPercent
End If
Next shp
Next pg

Application.StatusBar = “完了しました。”
End Sub

Private Function GetTotalShapeCount() As Long
‘ 処理対象の全シェイプ数を取得するロジック
Dim count As Long
‘ 省略:各ページのShapes.Countを合計する処理
GetTotalShapeCount = count
End Function

3. 実務で「陥りがちな罠」への対策

1. `DoEvents`の悪用を防げ

`DoEvents`は便利だが、魔法ではない。ループの1回ごとに実行すれば、処理速度は劇的に低下する。前述の通り、「`lastPercent`」という変数で前回更新時と比較し、変化があったときだけ叩くのが、計算コストとユーザー体験の黄金比だ。

2. データベース・ファイル連携時の注意

Visioから外部データ(ExcelやDB)を読み書きしながら処理する場合、`DoEvents`中にユーザーが「閉じる」ボタンを押す可能性がある。このとき、未保存のDB接続やファイルハンドルが残るとメモリリークやデータの不整合を招く。

  • 対策: `Global`変数等で「処理中フラグ」を立て、処理完了までユーザーの操作を制限するか、`Try-Catch`相当の例外処理(`On Error Resume Next`を適切に活用したエラーハンドリング)を必ず実装すること。

3. ステータスバーの「後始末」

`Application.StatusBar`は、処理終了後に必ず空文字に戻すか、`False`(Visioの自動制御に戻す)に設定すること。これを忘れると、ユーザーは「永遠に処理中」という不安を抱えたままVisioを使い続けることになる。

4. 最後に:アーキテクトからの助言

ツール開発において、コードが動くことは「スタート地点」に過ぎない。
本当に優れた自動化ツールとは、「ユーザーにストレスを与えず、あたかもVisioに元から備わっている機能であるかのように振る舞うもの」だ。

`DoEvents`を使いこなすということは、君がマシンの計算リソースと、ユーザーの心理的リソースの両方をコントロールする指揮官になるということだ。ぜひ、この実装を自身のツールに組み込み、ワンランク上のエンジニアリングを見せてほしい。

質問があればいつでも歓迎する。ただし、基本動作を理解した上で、更なる最適化を求める者のみに限定させてもらう。

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