レガシーVisioの深淵:Data1/2/3から現代的シェイプデータへの「静かなる移行」戦略
Visioの歴史は、そのまま「混沌としたメタデータの蓄積」の歴史である。
かつて、Visio 2000から2003時代に構築された図面を触る機会があるなら、諸君は間違いなく遭遇するはずだ。`Shape.Data1`、`Data2`、`Data3`という、極めてプリミティブで、型安全性が皆無の「文字列の墓場」に。
これらは、現代の「シェイプデータ(旧:カスタムプロパティ)」という、構造化され、型定義が可能なデータセットとは対極にある。本稿では、このレガシーの呪縛を解き、現代的なデータ管理へと安全に移行するための、アーキテクトとしての「解体新書」を提示する。
—
1. なぜ「Data1-3」は危険な遺物なのか
`Data1`等は、Visioの初期実装において「とりあえず情報を詰め込む」ために用意されたフィールドだ。しかし、これらには以下の致命的な欠陥がある。
- スキーマの不在: 文字列として保存されるため、数値や日付のバリデーションが不可能。
- 可読性の欠如: UI上では「その他」タブに隠蔽されやすく、属性管理には不向き。
- 拡張性の破綻: 4つ以上の属性が必要になった瞬間、コードはスパゲッティ化する。
我々の目的は、これらを`Prop.FieldName`という構造化されたシェイプデータセットへと、既存の図面レイアウトを一切破壊することなく移行することにある。
—
2. 実装の鉄則:オブジェクトのライフサイクル管理
VBAでVisioを操作する際、最も多いミスは「オブジェクトの解放忘れ」によるメモリリークだ。特に数万個のシェイプを走査する際、`Set obj = Nothing`を怠れば、Visioは確実にスローダウンし、最終的にスタックオーバーフローやアクセス違反を引き起こす。
以下のコードは、効率と安定性を両立させた移行ロジックのコアである。
レガシー移行エンジン:Data1-3 to Custom Properties
Option Explicit
‘ 伝説的な安定性を実現する移行プロシージャ
Public Sub MigrateLegacyDataToCustomProps(ByVal targetPage As Visio.Page)
Dim shp As Visio.Shape
Dim propName As String
‘ ページ内のすべてのシェイプを走査
For Each shp In targetPage.Shapes
‘ グループ化されている場合、再帰的に処理するのが賢明だが、
‘ 今回はフラットな構造を想定した極限の最適化を行う
‘ Data1が空でない場合のみ移行プロセスを開始
If Len(shp.Data1) > 0 Then
‘ 1. シェイプデータセクションが存在しない場合は追加
If Not shp.SectionExists(Visio.VisSectionIndices.visSectionProp, Visio.VisExistsFlags.visExistsAnywhere) Then
shp.AddSection Visio.VisSectionIndices.visSectionProp
End If
‘ 2. データの移管とクリーンアップ
Call MapLegacyData(shp, “Legacy_Data1”, shp.Data1)
‘ 3. レガシーデータの消去(重要:これをしないと二重管理の罠に陥る)
shp.Data1 = “”
End If
‘ 毎ループごとにオブジェクトを明示的に解放することは、
‘ 特に大量のシェイプを扱う際のメモリ汚染を防ぐ防波堤となる
Set shp = Nothing
Next shp
End Sub
Private Sub MapLegacyData(ByRef shp As Visio.Shape, ByVal propLabel As String, ByVal val As String)
‘ シェイプデータ行の追加ロジック
Dim rowIdx As Integer
rowIdx = shp.AddNamedRow(Visio.VisSectionIndices.visSectionProp, propLabel, Visio.VisRowIndices.visRowProp)
‘ 値の書き込み
shp.CellsSRC(Visio.VisSectionIndices.visSectionProp, rowIdx, Visio.VisCellIndices.visPropValue).FormulaU = Chr(34) & val & Chr(34)
shp.CellsSRC(Visio.VisSectionIndices.visSectionProp, rowIdx, Visio.VisCellIndices.visPropLabel).FormulaU = Chr(34) & propLabel & Chr(34)
End Sub
—
3. シニアエンジニアのための極限チューニング
A. Windows APIによる描画抑制
何千ものシェイプを更新する際、Visioは1つ1つ描画を更新しようとして激しくパフォーマンスを落とす。`Application.ScreenUpdating = False` も有効だが、より深いレイヤーで制御したい場合は、`Application.BeginUndoScope` を使用し、処理全体を単一のトランザクションとして囲むべきだ。これにより、Undoスタックの肥大化を防ぎ、かつ処理速度が飛躍的に向上する。
B. エラーハンドリングの流儀
レガシー図面は往々にして「保護されたシェイプ」や「ロックされたレイヤー」を含む。
On Error Resume Next
‘ 処理…
If Err.Number <> 0 Then
Debug.Print “Shape ID: ” & shp.ID & ” failed. Reason: ” & Err.Description
Err.Clear
End If
On Error GoTo 0
この程度のハンドリングは必須である。レガシー保守において「止まらないこと」こそが正義である。
—
結論:技術的負債は「消す」のではなく「昇華」させる
`Data1-3`という遺物は、かつてのエンジニアが必死に情報を残そうとした軌跡だ。それを単に削除するのではなく、現代的なスキーマへと昇華させること。それが、我々レガシーシステムを継承するアーキテクトの矜持である。
この記事を読んだ諸君、明日からその「負債」を「資産」へと書き換える作業を始めよ。Visioのオブジェクトモデルを完全に掌握した者にのみ、レガシーの呪縛を解く権利があるのだから。
