Visio VBAの深淵:Charactersオブジェクトで実現する「文字列の外科手術」
Visioで図形内のテキストを扱う際、初心者は決まって`Shape.Text = “ほげほげ”`という乱暴な一括代入に逃げる。だが、実務で求められるのはそんな単純な文字列操作ではない。「特定のキーワードだけ赤字にする」「単位だけフォントを小さくする」といった、部分的な書式設定こそが、図面をプロフェッショナルな情報伝達ツールへと昇華させる鍵だ。
今日は、Visioのオブジェクトモデルにおいて最も繊細で、かつ強力な`Characters`オブジェクトを完全掌握するための極意を伝授する。
—
なぜ「一括代入」ではいけないのか
`Shape.Text`プロパティへの代入は、対象シェイプが保持していた既存の書式情報(文字単位のフォント、色、太字設定など)をすべて破壊する。
もし君が業務効率化ツールを設計しているのなら、「既存の書式を維持しつつ、特定の箇所だけを動的に書き換える」という外科手術のような制御が求められるはずだ。ここで登場するのが`Characters`オブジェクトである。これは、文字列内の特定範囲を「文字のインデックス(開始位置と終了位置)」で切り出し、個別にプロパティを操作するためのインターフェースだ。
—
実践:特定のキーワードを強調するプロダクションコード
単に動くコードを書くのは学生の遊びだ。エンジニアは「堅牢性」を設計する。以下のコードは、指定したシェイプ内の特定の文字列を検索し、その部分だけ色と太さを変える実務的な実装例だ。
‘ @brief シェイプ内の特定文字列を検索し、書式を変更する
‘ @param shp 操作対象のVisio Shapeオブジェクト
‘ @param targetText 検索対象の文字列
‘ @param color RGB値(例: vbRed)
Public Sub FormatSpecificText(ByVal shp As Visio.Shape, ByVal targetText As String, ByVal color As Long)
Dim chrs As Visio.Characters
Dim startPos As Long
Dim endPos As Long
‘ テキストが存在しない場合のガード節
If shp.Characters.Text = “” Then Exit Sub
‘ 検索:InStr関数でインデックスを取得
startPos = InStr(1, shp.Characters.Text, targetText, vbTextCompare)
‘ 見つからなかった場合は終了
If startPos = 0 Then Exit Sub
‘ 文字列の長さを考慮して範囲を定義
endPos = startPos + Len(targetText) – 1
‘ Charactersオブジェクトを取得
Set chrs = shp.Characters
chrs.Begin = startPos – 1 ‘ API仕様:0ベースの開始位置
chrs.End = endPos ‘ API仕様:終了位置(排他的)
‘ 書式設定の適用
With chrs
.CharProps(visCharacterColor) = color
.CharProps(visCharacterStyle) = visBold
End With
‘ 最後にメモリの解放(明示的なSet NothingはVBAでは作法)
Set chrs = Nothing
End Sub
—
アーキテクトの視点:実装上の3つの鉄則
現場でコードを動かす際、以下のポイントを無視すれば必ずバグに遭遇する。
1. インデックスの罠を回避せよ
`Characters.Begin`と`End`の仕様は、直感的ではない。`.Begin`は「文字の直前」を指し、0から始まる。慣れないうちは、デバッグウィンドウで`Debug.Print`を駆使し、ポインタの現在地を常に可視化する習慣をつけろ。
2. データベース連携時の「文字化け」に備えよ
外部DBから取得したテキストをVisioに流し込む際、改行コード(`vbCrLf` vs `vbCr`)の不一致で`Characters`のインデックスがズレることがある。DBからの取得値は必ずVisioが解釈できる形式に正規化(`Replace(text, vbCrLf, vbCr)`など)してから適用せよ。
3. パフォーマンスの重み
大量のシェイプ(数百個以上)に対してこの操作を行うと、Visioの描画エンジンが悲鳴を上げる。
- 処理中は `Application.ScreenUpdating = False` を活用して描画を停止しろ。
- 処理が終わったら必ず `True` に戻すのを忘れるな(これを忘れるとユーザーはフリーズしたと勘違いする)。
—
最後に:効率化の先にあるもの
コードは単に動けばいいというものではない。君が書いたそのスクリプトは、未来のメンテナンス担当者が読み解く「設計図」だ。
`Characters`オブジェクトを使いこなすことは、Visioという巨大なDOM(Document Object Model)と対話することを意味する。このレベルまで理解が深まれば、単なる文字の書き換えだけでなく、データに基づいた自動作図や、複雑な属性値の視覚化など、自動化の幅は劇的に広がる。
さあ、退屈な手作業をコードで駆逐し、よりクリエイティブな課題にリソースを割く準備をしよう。健闘を祈る。
