【入門編】Visio VBAにおける安全なトランザクション擬似処理:処理失敗時にUndo(元に戻す)を一括実行して図面を原状回復する設計 – Visio VBA解析バイブル

スポンサーリンク

こんにちは! Visioの自動化の世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めてみたものの、「なんだか難しそうだな」「エラーが起きたときにごちゃごちゃになって怖いな」と感じていませんか?

大丈夫、安心してください。今日ここでお伝えする「安全なトランザクション擬似処理」のテクニックをマスターすれば、あなたのVBAコードは見違えるほど堅牢になり、プロのエンジニアが書くような信頼性の高いシステムへと生まれ変わります。

ここをクリアすれば、Visio VBAの基本はバッチリですよ。さあ、一緒に扉を開けていきましょう!

なぜVisio VBAには「トランザクション(安全装置)」が必要なのか?

マクロを使って、何百個もの図形(シェイプ)を一括で配置したり、色を変えたりする処理を書いたとします。
もし、その処理の「真ん中あたり」で予期せぬエラー(ゼロ除算やオブジェクトが見つからない等)が発生したらどうなるでしょうか?

  • 最悪のシナリオ: 図面の半分だけが書き換わり、もう半分は古いまま。どこまで処理が進んだのか分からない「半端な状態(不整合データ)」で図面が保存されてしまう……。

こんな事故が起きたら、ユーザーはパニックになりますよね。業務システムや大事な設計図を扱う現場において、これは絶対に許されない失敗です。

データベースの世界には、処理が成功したら確定(コミット)、失敗したら全部なかったことにする(ロールバック)という「トランザクション」という概念があります。
実は、Visioが標準で持っている`Application.Undo`(元に戻す)の仕組みをVBAから巧みに操ることで、このトランザクションの安全装置を完全に再現することができるのです。

Visio VBAの基本:オブジェクトモデルの繋がりを理解する

まずは、Visio VBAの骨組みを軽くおさらいしておきましょう。Visioのオブジェクトは、以下のような「マトリョーシカ構造(階層構造)」になっています。

Application (Visioアプリ全体)
┗ Documents (開いているファイルたち)
┗ Document (いま操作している特定の図面)
┗ Pages (ページたち)
┗ Page (特定のページ)
┗ Shapes (図形たち)
┗ Shape (個別の図形)

VBAで図面を操作するということは、この階層を上から順に辿って、「ここのページの、この図形をこうする!」と命令していく作業に他なりません。

【実践】エラー時に一括で元に戻す!安全設計テンプレートコード

それでは本題です。大量の図形変更を行う際に、エラーが起きたら一発で元の状態に巻き戻す(Undoする)実践的なコードのテンプレートを公開します。

開発の現場で、そのままコピペしてベースとして使えるよう、隅々にまでコメントを仕込んでおきました。

Sub SafeTransactionSample()
Dim vsoApp As Visio.Application
Set vsoApp = Visio.Application

Dim lScopeID As Long
Dim blnSuccess As Boolean

‘ 初期化
blnSuccess = False

‘ —————————————————-
‘ 1. 【超重要】Undoスコープ(変更の単位)を開始する
‘ —————————————————-
‘ BeginUndoScopeは、ここから実行される一連の操作を「ひとまとめのグループ」として記録します。
lScopeID = vsoApp.BeginUndoScope(“一括シェイプ生成処理”)

‘ エラーハンドリング(エラーが起きたらErrorHandlerラベルへジャンプ)
On Error GoTo ErrorHandler

‘ ====================================================
‘ 2. メインの処理(ここに大量の図形操作を書く)
‘ ====================================================
Dim vsoPage As Visio.Page
Set vsoPage = vsoApp.ActivePage

Dim i As Long
For i = 1 to 100
‘ 例:100個の長方形を並べる処理
Dim vsoShape As Visio.Shape
Set vsoShape = vsoPage.DrawRectangle(i 0.5, i 0.5, (i 0.5) + 1, (i 0.5) + 1)

‘ 【わざとエラーを起こすテスト用コード】
‘もしiが50になったら、強制的にエラーを発生させてみる
If i = 50 Then Err.Raise 9999, , “途中で意図しないエラーが発生しました!”

vsoShape.Text = “No.” & i
Next i
‘ ====================================================

‘ 3. ここまでエラーなく来たら「成功」とみなす
blnSuccess = True

CleanUp:
‘ —————————————————-
‘ 4. スコープの終了処理
‘ —————————————————-
If blnSuccess Then
‘ 正常終了:スコープを正常に閉じる(変更が確定する)
vsoApp.EndUndoScope lScopeID, True
MsgBox “処理が正常に完了しました。”, vbInformation
Else
‘ 異常終了:スコープを破棄し、自動的に「Undo(元に戻す)」を発動させる!
vsoApp.EndUndoScope lScopeID, False
MsgBox “途中でエラーが発生したため、変更をすべて元に戻しました。”, vbExclamation
End If

Exit Sub

ErrorHandler:
‘ エラー発生時はここに飛んでくる
blnSuccess = False
‘ 必要に応じてエラーログなどをここに記録
MsgBox “エラー番号: ” & Err.Number & vbCrLf & “内容: ” & Err.Description, vbCritical

‘ 後片付け(CleanUpへ飛ぶ)
Resume CleanUp
End Sub

コードの核心:なぜこれで安全になるのか?

このコードのミソは、`BeginUndoScope``EndUndoScope` のペアにあります。

1. `vsoApp.BeginUndoScope(“処理名”)` を呼び出した瞬間から、Visioは「ユーザーがCTRL+Zを押したときにどこまで戻すか」の境界線を引き始めます。
2. 処理が順調にいけば、最後に `EndUndoScope lScopeID, True` (第二引数に `True`)を渡し、「このグループの変更を確定するよ」とVisioに伝えます。
3. もし途中で `On Error GoTo` によりエラーが起きた場合、フラグ (`blnSuccess`) を `False` にした上で、`EndUndoScope lScopeID, False` (第二引数に `False`)を実行します。

この `False` を指定した瞬間に、Visioのエンジンは「このスコープ内でやった変更、全部ナシ!」と判断し、一瞬でコード実行前の状態へと図面を綺麗に巻き戻してくれるのです。

陥りやすい罠とエンジニアの知見

実務でこのパターンを使うとき、初心者がやりがちな落とし穴がいくつかあります。プロの知見として共有しておきますね。

  • 画面のチラつきを防ぐために `ScreenUpdating` を併用する

大量の図形を操作するとき、画面がパチパチと切り替わると処理が遅くなります。処理の最初に `vsoApp.ScreenUpdating = False` を入れ、終了時(あるいはエラー時)に `True` に戻すと、爆速かつスマートに動作します。

  • スコープのネスト(入れ子)に注意する

VBAの別のプロシージャ(関数)を呼び出す際、その中でも `BeginUndoScope` を使っていると、Undoの階層が複雑になり、期待通りに巻き戻せなくなることがあります。大規模な自動化では、トランザクションの起点を「一番外側の司令塔プロシージャ」に絞るのが美しい設計です。

まとめ

いかがでしたか?
「マクロが途中でコケたら、図面がグチャグチャになっておしまい……」という恐怖は、もう今日で終わりです。

`BeginUndoScope` と `EndUndoScope` を適切に配置するだけで、あなたの書くVBAマクロは、市販の業務ソフト並みに堅牢で安全なものにレベルアップします。

「ここをクリアすれば、Visio VBAの基本はバッチリですよ!」
自信を持って、次の自動化チャレンジへ進んでください。あなたの開発ライフを応援しています!

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