【実務・中級編】Application.DeferRecalcとFormulaForceUを組み合わせた、数式エラー(#VALUE!)を強制上書き復旧する非常用VBA – Visio VBA解析バイブル

スポンサーリンク

【Visioの深淵】#VALUE!地獄を突破する。FormulaForceUによるShapeSheet強制リカバリ術

Visioの自動化を突き詰めると、必ず「ShapeSheetの泥沼」に足を取られる瞬間が来る。特に、複雑な数式を多用するステンシルや、外部データと連動する図形において、計算エラー(`#VALUE!`)が一度発生すると、通常の `Cell.Formula` への代入さえ拒絶されることがある。

なぜか? Visioの計算エンジンがエラー状態に陥り、再計算のループがスタックしているからだ。GUIで手作業で数式を消して入れ直す? そんなものはエンジニアの仕事ではない。

今回は、Visioの心臓部を一時停止させ、強制的に正常な数式を流し込む「外科手術」の手法を伝授する。

なぜ「通常の代入」では失敗するのか

Visioの `Cell.Formula` は、代入時に即座に再計算を行う。エラーが発生しているセルに対してさらに不整合な値を投げれば、当然、Visioは防御的にその変更を拒むか、クラッシュを引き起こす。

我々が取るべきアプローチは以下の2ステップだ。

1. 再計算の抑制: `Application.DeferRecalc` を使い、Visioの演算サイクルを止める。
2. 強制注入: `FormulaForceU` を使い、エラーチェックをバイパスして数式を上書きする。

この組み合わせこそ、Visio VBAにおいて「死んだ図形を蘇生させる」唯一無二の手段である。

実装:ShapeSheetリカバリ・モジュール

プロダクション環境でそのまま使える、堅牢なリカバリ・ルーチンを以下に示す。エラーハンドリングを怠れば、Visio全体がフリーズするリスクがあるため、`Try-Catch` 構造を徹底せよ。

‘ @brief エラー状態のShapeSheetセルを強制的に修復するプロシージャ
‘ @param shp 対象のShapeオブジェクト
‘ @param cellName 修復対象のセル名 (例: “Width”, “User.MyFormula”)
‘ @param formula 注入する数式 (U言語形式)
Public Sub ForceRecoverCell(ByRef shp As Visio.Shape, ByVal cellName As String, ByVal formula As String)
Dim app As Visio.Application
Set app = shp.Application

‘ 1. 計算の抑制開始(パフォーマンス向上とエラーの連鎖防止)
‘ DeferRecalcをTrueにすると、Trueに設定した回数分だけ、
‘ 後述のDeferRecalc = Falseを呼ぶ必要がある。
Dim recalcState As Integer
recalcState = app.DeferRecalc
app.DeferRecalc = True

On Error GoTo Cleanup

‘ 2. セルの存在確認
If shp.CellExistsU(cellName, 0) Then
‘ 3. FormulaForceUによる強制上書き
‘ 通常のFormula代入ではなく、計算エラーを無視して直接書き込む
shp.CellsU(cellName).FormulaForceU = formula
Debug.Print “Success: ” & shp.Name & “.” & cellName & ” was recovered.”
Else
Err.Raise vbObjectError + 1, “ForceRecoverCell”, “Cell not found: ” & cellName
End If

Cleanup:
‘ 4. 必ず計算を復旧させる
‘ ここを忘れるとVisioが再計算を放棄し、図形が動かなくなる
app.DeferRecalc = recalcState

If Err.Number <> 0 Then
Debug.Print “Error in ForceRecoverCell: ” & Err.Description
End If
End Sub

アーキテクトの知見:運用上の注意点

このコードを実務に組み込む際、以下の3点だけは必ず厳守してほしい。

1. 「戻し忘れ」は即死を意味する

`DeferRecalc = True` を呼び出した後は、いかなる理由があっても `DeferRecalc = False`(あるいは元の状態への復帰)を保証しなければならない。`On Error GoTo` を活用し、例外発生時であっても確実に再計算を再開させる設計が、安定したツール作りの大前提だ。

2. 外部データとの連携時の注意

データベースやExcelから値を流し込む際、データ側に不正な文字が含まれていると、再び `#VALUE!` が発生する。`FormulaForceU` はあくまで「数式の強制書き込み」であり、数式の中身が論理的に正しいことまで保証してはくれない。

  • 対策: `FormulaForceU` を投げる前に、文字列のサニタイズ(クォーテーションの処理や単位の整合性確認)を必ず行うこと。

3. パフォーマンスの重み

`DeferRecalc` は強力だが、大規模な図面で広範囲に適用すると、復帰時の再計算で数秒から数十秒のフリーズが発生する。可能な限り対象を絞り、一括処理は避けるのが賢明だ。

結論:ツールは「壊れない」のではなく「自己修復する」べき

完璧なコードを書くことも重要だが、エンジニアとして真に問われるのは「壊れたときにどう復旧させるか」という設計思想だ。

今回紹介した `FormulaForceU` と `DeferRecalc` の組み合わせは、Visioのブラックボックス的な挙動に対する最も強力なカウンターである。このテクニックをあなたの自動化ライブラリの「切り札」として持っておいてほしい。

Visioというプラットフォームを支配する鍵は、いつだって低レベルなオブジェクトの振る舞いを知り尽くした者だけが手にすることができるのだから。

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