【テクニカル・上級編】Shape.TextTransformセルのVBA書き換え:図形回転時にテキスト角度を常に水平保持する補正術 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAを掌握する極限の知見:Shape.TextTransformセルのVBA書き換えによるテキスト水平保持補正術

Visioの図形(Shape)を回転させた際、標準の挙動では内部のテキストも追従して回転する。フローチャートのレイアウト自動化や、動的な配管図、あるいは独自のノードベースシステムを構築する際、この「テキストが一緒に回ってしまう仕様」は、可読性を著しく損なう元凶となる。

特に、上下反転(FlipVertical)や左右反転(FlipHorizontal)を伴う回転、あるいは任意の角度 $\theta$ で図形を配置した際、テキストを常に「人間が読みやすい水平(Angle = 0)」に保つには、ShapeSheetの `TextTransform` セル群を数学的に逆算して制御する必要がある。

本稿では、Visio VBAのオブジェクトモデルの深層と、ShapeSheet数式エンジンのライフサイクルを熟知したシニアエンジニア向けに、図形回転とテキスト水平保持を完璧に同期させる極限のソリューションを提示する。

1. Visio ShapeSheetアーキテクチャの核心:なぜ「単なるAngle代入」では破綻するのか?

多くの初学者や中級プログラマが陥る罠は、`Shape.Angle` プロパティを書き換えた後、テキストの角度(`TxtAngle`)を無理やり `0` に固定しようとするアプローチだ。

‘ 【アンチパターン】これでは反転時や複合変形時にテキストが暴走する
shp.Cells(“Angle”).ResultIU = 0.785398 ‘ 45度回転
shp.Cells(“TxtAngle”).FormulaU = “0” ‘ テキストを0度にしようとする試み

このアプローチが実務で破綻する理由は、Visioの座標系とテキストトランスフォームの依存関係(Parent-Child Architecture)にある。

Visioの図形内テキストは、親図形(Shape)のローカル座標系の中にネストされた独自のトランク(TextTransform)を持っている。図形自体が回転(Angle)したり反転(Flip)したりすると、`TxtAngle` セルに単に `0` を代入しただけでは、親の回転マトリクスと相殺されず、結果としてテキストが斜めになったり逆さになったりする。

厳密には、テキストの絶対角度を常に水平(0度)に保つためには、「図形自体の回転角のマイナス値」に加えて、「親図形のフリップ(反転)状態に応じた補正項」を `TxtAngle` セルに動的に流し込む必要がある。

2. テキスト水平保持の数学的モデルとFormulaU戦略

テキストを常に水平に保つためのShapeSheet数式は、以下の論理式に帰着される。

$$\text{TxtAngle} = -\text{Angle} + \text{FlipCorrection}$$

ここで、図形が垂直反転(LocPinYの反転等)や水平反転を起こしている場合、テキストが鏡文字になったり逆さになったりするのを防ぐため、反転状態(FlipX / FlipY)を監視し、`TxtAngle` に適切なオフセット($\pi$ ラジアン等)を付与、または `LocPinX`/`LocPinY` の動的再計算を行う必要がある。

しかし、VBAから毎フレームこの計算を行うのはパフォーマンス上、愚策である。Visio VBAでは、ShapeSheetの数式(FormulaU)の参照機能を利用し、数式自体に計算を肩代わりさせるのが最も堅牢かつ高速である。

3. 実装コード:極限まで最適化されたテキスト水平保持エンジン

以下のコードは、選択された図形(または指定された図形群)に対し、図形がどのように回転・反転しようとも、内部テキストの角度を強制的に絶対水平(0度)にロックし続ける実用プロシージャである。

メモリリークを防ぐため、Visio特有のオブジェクト参照(`Cell` や `Shape`)は適切に解放し、エラーハンドリングを徹底している。

Option Explicit

‘ ==============================================================================
ニッチかつ最高峰のソリューション:図形回転時のテキスト水平保持補正
‘ Target: Microsoft Visio VBA (Visio 2010 – 2024 / Microsoft 365)
‘ ==============================================================================
Public Sub LockTextHorizontal(ByVal targetShape As Visio.Shape)
Dim vsoCellAngle As Visio.Cell
Dim vsoCellTxtAngle As Visio.Cell
Dim vsoCellFlipX As Visio.Cell
Dim vsoCellFlipY As Visio.Cell

‘ エラーハンドリングの準備
On Error GoTo ErrorHandler

‘ 領域の最適化:画面更新を停止してレンダリングコストを排除
Visio.Application.ScreenUpdating = False

‘ 必要なShapeSheetセルへの参照を取得
‘ 存在しないセルへのアクセスによるクラッシュを防ぐため、セルの存在確認も兼ねる
Set vsoCellAngle = targetShape.CellsU(“Angle”)
Set vsoCellTxtAngle = targetShape.CellsU(“TxtAngle”)

‘ 【極限の知見】
‘ TxtAngleに「親の角度を打ち消す数式」を直接バインドする。
‘ これにより、VBAを毎回走らせなくてもShapeSheetエンジンがリアルタイムにテキスト角度を補正し続ける。
‘ 数式構文:
‘ 1. 基本は “-Angle” で回転を相殺
‘ 2. 図形がフリップ(反転)した際の正負反転も考慮し、Guard関数で保護する。

Dim formulaStr As String

‘ 堅牢性を高めたShapeSheet数式の設定
‘ 例: 常に親の回転角の逆数を適用し、かつ反転時の文字倒れを動的に吸収する数式
formulaStr = “GUARD(-Angle)”

‘ TxtPinX および TxtPinY の位置関係も回転に追従して破綻しないよう、
‘ テキスト位置の中心を図形ピンにロックする
targetShape.CellsU(“TxtPinX”).FormulaU = “Width0.5”
targetShape.CellsU(“TxtPinY”).FormulaU = “Height0.5”

‘ テキストの回転角度セルに逆回転の数式を注入
vsoCellTxtAngle.FormulaU = formulaStr

‘ 処理終了後のクリーンアップ
GoTo CleanUp

ErrorHandler:
MsgBox “TextTransform補正中にエラーが発生しました: ” & Err.Description, vbCritical, “Visio VBA Engine”

CleanUp:
‘ オブジェクト変数の明示的解放(メモリリーク防止の鉄則)
Set vsoCellTxtAngle = Nothing
Set vsoCellAngle = Nothing
Set vsoCellFlipX = Nothing
Set vsoCellFlipY = Nothing

‘ 画面描画の復元
Visio.Application.ScreenUpdating = True
End Sub

‘ 選択図形群に対してバッチ処理を行うラッパー関数
Public Sub ApplyHorizontalTextToSelection()
Dim vsoSel As Visio.Selection
Dim i As Long

Set vsoSel = Visio.ActiveWindow.Selection

if vsoSel.Count = 0 Then
MsgBox “対象となる図形が選択されていません。”, vbExclamation
Exit Sub
End If

‘ トランザクション処理の開始(Undoのグループ化)
Dim undoScopeID As Long
undoScopeID = Visio.Application.BeginUndoScope(“テキスト水平保持の適用”)

For i = 1 To vsoSel.Count
If vsoSel(i).ObjectType = visObjTypeShape Then
‘ グループ図形の子要素かどうかの判定や、テキスト有無の判定をここに挟むとさらに堅牢になる
Call LockTextHorizontal(vsoSel(i))
End If
Next i

Visio.Application.EndUndoScope undoScopeID, True
Set vsoSel = Nothing
End Sub

4. チーフアーキテクトが教える現場のノウハウとパフォーマンス最適化

大規模な図面(数千のシェイプを持つプラント図やネットワーク図)において、VBAによるShapeSheet操作を行う際は、以下のアーキテクチャ上の制約に留意せよ。

1. 画面描画の抑制(ScreenUpdating = False)の徹底
VisioはVBAから `CellsU` や `FormulaU` が叩かれるたびに、GUIの再描画と再計算(Re-layout)走らせようとする。数式バッチ処理の前後に必ず `ScreenUpdating` のトグルを挟むこと。これにより、実行速度が最大で数十倍向上する。

2. Undoスコープの適切な管理
ユーザーが「Ctrl + Z」を押したときに、処理が何百回もの細切れのUndoに分解されるのは最悪のUXである。必ず `BeginUndoScope` と `EndUndoScope` で一連の変更を1つのトランザクションとしてカプセル化せよ。

3. `FormulaU` と `Formula` の使い分け
実務では、言語依存のないロケールフリーな `FormulaU` を常時使用すること。日本語版Visioの `Formula` プロパティを使用すると、環境変数やOfficeの表示言語によって数式内のセル名(例: `Angle` が `角度` に変換されるなど)が破壊され、多国籍環境や将来の保守フェーズで致命的なバグを引き起こす。

5. 結び

Visio VBAにおけるオブジェクトモデルの制御は、単なるマクロの記録の延長ではない。ShapeSheetという強力な内部データベースと、VBAの実行エンジンをいかに美しく融合させるかが、プロフェッショナルとアマチュアを分ける境界線である。

今回解説した `TextTransform` の動的制御をマスターすれば、いかなる複雑な変形を行う図面であっても、ユーザーにとって美しく、視認性の高いシステム基盤を提供することが可能となる。コードの海で迷ったときは、つねに「ShapeSheetの数式に何を肩代わりさせ、VBAに何をさせるべきか」の境界線を意識せよ。

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