Visio VBAマスターへの道:外部データ取り込み時のテキスト整形を自動化する!〜改行、タブ、異体字よ、さらば〜
Visioで図を描いている皆さん、こんにちは!業務自動化エンジニアの〇〇です。
日々の業務でVisioを駆使されていることと思います。特に、ExcelやCSVからデータを流し込んで図形にテキストを設定する際、予期せぬ改行コードや、表示が崩れる原因となる「あの文字」に悩まされた経験はありませんか?
「せっかくきれいに整えたのに、データを取り込んだらぐちゃぐちゃに…」
「この制御文字、どうやって消せばいいんだろう?」
そんなお悩みを、Visio VBAを使って一気に解決しちゃいましょう!
この記事では、Visio VBAの基本的なオブジェクトモデルから、実用的なテキスト整形テクニックまで、図解も交えながら丁寧に解説していきます。マクロの記録から一歩踏み出し、Visio VBAの真髄に触れたいあなたを、私が優しく、そして力強く導きますよ!
—
1. Visio VBAの「心臓部」を知る:Application, Document, Page, Shapeオブジェクト
VBAを使いこなす上で、まずはVisioの構造を理解することが不可欠です。
VisioのVBAでは、これらの階層構造をオブジェクトとして扱います。それぞれのオブジェクトがどのような役割を持っているのか、一緒に見ていきましょう。
1.1. Application オブジェクト:Visioそのものを指す「親玉」
`Application`オブジェクトは、起動しているVisioアプリケーション全体を表します。
VBAコードは、基本的にこの`Application`オブジェクトから始まります。
- 役割: Visioの起動・終了、開いているドキュメントの管理、グローバルな設定など。
- イメージ: あなたが目の前で操作しているVisioソフトそのもの。
‘ 現在起動しているVisioアプリケーションを取得
Dim visApp As Visio.Application
Set visApp = Visio.Application
‘ もしくは、ActiveDocumentプロパティから間接的に取得することも多い
‘ Dim visDoc As Visio.Document
‘ Set visDoc = Visio.ActiveDocument
1.2. Document オブジェクト:開いている「ファイル」そのもの
`Document`オブジェクトは、現在開いているVisioのファイル(`.vsd`や`.vsdx`など)一つ一つを表します。
通常、複数のVisioファイルを開いている場合、`Application`オブジェクトの`Documents`コレクションから目的の`Document`オブジェクトを取得します。
- 役割: ページ、図形、スタイル、マスターシェイプなどの管理。
- イメージ: あなたがVisioで開いている「図面ファイル」。
‘ 現在アクティブなドキュメントを取得
Dim visDoc As Visio.Document
Set visDoc = Visio.ActiveDocument
‘ 特定のファイルを開く場合 (ファイルパスは適宜変更してください)
‘ Dim visDocNew As Visio.Document
‘ Set visDocNew = visApp.Documents.Open(“C:\Path\To\Your\Drawing.vsdx”)
1.3. Page オブジェクト:図面の「一枚」にフォーカス
`Page`オブジェクトは、`Document`オブジェクト内の個々の「ページ」を表します。
図面には複数のページが存在することがよくありますね。
- 役割: ページ上の図形(Shape)の管理、ページのサイズや向きの設定など。
- イメージ: 図面ファイルの中の、特定の「ページ」。
‘ 現在アクティブなページを取得
Dim visPage As Visio.Page
Set visPage = visDoc.ActivePage
‘ 特定のページを取得する場合 (インデックスは0から始まります)
‘ Dim visPageByName As Visio.Page
‘ Set visPageByName = visDoc.Pages(“Page-1”) ‘ ページ名で指定
‘ Set visPageByName = visDoc.Pages(1) ‘ インデックスで指定 (2ページ目)
1.4. Shape オブジェクト:図形の「実体」
そして、いよいよ本題の`Shape`オブジェクトです。
これは、ページ上に配置されている個々の図形(四角、円、テキストボックス、コネクタなど)そのものを指します。
- 役割: 図形の形状、位置、色、そして「テキスト」の操作。
- イメージ: 図形一つ一つ。これが私たちの操作対象になります。
‘ ページ上の全ての図形を取得する例
Dim visShape As Visio.Shape
For Each visShape In visPage.Shapes
‘ ここで各図形に対して処理を行う
Debug.Print visShape.Name ‘ 図形名を表示
Next visShape
‘ 特定の図形を取得する場合 (NameIDまたはNameプロパティで指定)
‘ Dim visShapeByName As Visio.Shape
‘ Set visShapeByName = visPage.Shapes(“Rectangle 1”) ‘ 図形名で指定
‘ Set visShapeByName = visPage.Shapes.Item(1) ‘インデックスで指定 (最初の図形)
—
2. 図形テキストの「魂」:Shape.Textプロパティを理解する
`Shape`オブジェクトが持つ`Text`プロパティは、図形に表示されるテキストそのものです。
ここが、今回のテキスト整形テクニックの「要」となります。
‘ 図形のテキストを取得する
Dim currentText As String
currentText = visShape.Text
‘ 図形のテキストを設定する
visShape.Text = “新しいテキスト”
この`Text`プロパティに、外部から取り込んだデータがそのまま格納されます。
しかし、そのデータには、私たちが望まない「お邪魔虫」が含まれていることがあるのです。
2.1. テキスト整形における「敵」たち:制御文字と異体字
外部データ、特にCSVやExcelからインポートしたテキストデータには、以下のような「厄介者」が含まれていることがあります。
- 改行コード:
- `vbCrLf` (Carriage Return + Line Feed):Windows環境でよく使われる改行コード。
- `vbLf` (Line Feed):Unix/Linux環境で使われる改行コード。
- Visioのテキストボックス内で、これらのコードは意図しない行分割を引き起こします。
- タブコード:
- `vbTab`:水平タブ文字。これもテキストの見た目を崩す原因になります。
- Unicode制御文字:
- 見えない文字で、テキストの書式や配置に影響を与えることがあります。
- 例: `U+200B` (Zero-width space)、`U+FEFF` (Zero-width no-break space) など。
- 異体字:
- 同じ意味でも、複数の異なる文字コードで表現される漢字(例: 「渡」と「渡」)。
- これらが混在すると、フォントによっては表示が崩れたり、検索性が低下したりすることがあります。
2.2. 目的:これらの「敵」を排除し、見た目を損なわない標準テキストに!
私たちの目標は、これらの不要な文字を削除したり、代替したりして、Visio上で美しく表示される、統一されたテキスト形式にすることです。
—
3. 実践!Shape.Textのサニタイズと正規化VBAコード
いよいよ、具体的なVBAコードを見ていきましょう。
ここでは、CSVやExcelから取り込んだテキストを、`Shape.Text`プロパティに設定する「前」に整形する関数を作成します。
3.1. テキスト整形用VBA関数の作成
以下の関数は、与えられたテキスト文字列を整形します。
‘
‘ 関数名: SanitizeAndNormalizeText
‘ 概要: 図形テキストの不要な制御文字(改行、タブ)や一部のUnicode制御文字を
‘ 除去し、表示を崩す可能性のある異体字を正規化(ここでは単純置換)する。
‘ 引数: inputText (String) – 整形前のテキスト
‘ 戻り値: String – 整形後のテキスト
‘
Function SanitizeAndNormalizeText(ByVal inputText As String) As String
Dim cleanedText As String
cleanedText = inputText
‘ — 1. 改行コードの除去 —
‘ Windows標準の改行コード (CRLF) を削除
cleanedText = Replace(cleanedText, vbCrLf, “”)
‘ Unix/Linux標準の改行コード (LF) を削除
cleanedText = Replace(cleanedText, vbLf, “”)
‘ — 2. タブコードの除去 —
cleanedText = Replace(cleanedText, vbTab, “”)
‘ — 3. 特定のUnicode制御文字の除去 —
‘ 例: Zero-width space (U+200B) を削除
cleanedText = Replace(cleanedText, ChrW(&H200B), “”)
‘ 例: Zero-width no-break space (U+FEFF) を削除
cleanedText = Replace(cleanedText, ChrW(&HFEFF), “”)
‘ 必要に応じて、他のUnicode制御文字も追加で除去してください。
‘ 例: 非表示の区切り線など (U+2060)
‘ cleanedText = Replace(cleanedText, ChrW(&H2060), “”)
‘ — 4. 異体字の正規化(簡易版:特定文字の置換) —
‘ 注意: 異体字の完全な正規化は非常に複雑です。
‘ ここでは、よく問題になる文字の例をいくつか示します。
‘ 本番環境では、より包括的なリストや、外部ライブラリの利用を検討してください。
cleanedText = Replace(cleanedText, “﨎”, “恵”) ‘ 例: 恵の異体字
cleanedText = Replace(cleanedText, “﨏”, “豊”) ‘ 例: 豊の異体字
‘ 他にも、必要に応じて置換処理を追加します。
‘ 例: 渡 (U+6E21) と 渡 (U+FA1B) の場合など。
‘ ただし、単純な置換では意図しない文字に置き換わる可能性もあるため、
‘ 慎重にテストが必要です。
‘ — 5. 前後の空白文字の除去 —
cleanedText = Trim(cleanedText)
‘ 整形後のテキストを返す
SanitizeAndNormalizeText = cleanedText
End Function
3.2. コードの解説:一歩ずつ、丁寧に
この関数は、`Replace`関数と`Trim`関数を組み合わせて、テキストを段階的に整形しています。
- `Replace(文字列, 検索文字列, 置換文字列)`: 指定した文字列の中から、検索文字列をすべて見つけ出し、置換文字列に置き換えます。
- `vbCrLf`, `vbLf`, `vbTab` は、VBAであらかじめ定義されている定数で、それぞれ改行コードやタブコードを表します。
- `ChrW(&HXXXX)` は、Unicodeコードポイント(16進数)を指定して、その文字を取得するための関数です。`&H`は16進数であることを示します。
- `Trim(文字列)`: 文字列の先頭と末尾にある空白文字(スペース、タブ、改行など)を削除します。
【ここがポイント!】異体字の扱いについて
異体字の正規化は、実は非常に奥が深いテーマです。
上記のコードでは、あくまで「よく問題になる例」を単純な文字列置換で対応する簡易的な方法を示しています。
「渡」という漢字一つをとっても、複数の異体字が存在し、それらをすべて網羅して、かつ文脈を考慮して正しい文字に置き換えるのは、高度な自然言語処理技術が必要になります。
もし、異体字の問題が頻繁に発生し、かつ正確な正規化が必要な場合は、以下の方法を検討してください。
1. データソース側の整備: 可能であれば、CSVやExcelの元データ段階で、異体字が混在しないように統一する。
2. 専用ライブラリの利用: .NET Frameworkなどを利用できる環境であれば、文字コード正規化のためのライブラリが存在します。VBAからCOM経由などで呼び出すことも技術的には可能ですが、難易度は上がります。
3. Visioのフォント設定: 図形に設定するフォントによっては、一部の異体字も綺麗に表示される場合があります。フォントの選定も重要です。
まずは、改行コード、タブコード、一般的なUnicode制御文字の除去から始めて、問題の切り分けをすることをおすすめします。
—
4. VBAコードを実際に動かしてみよう!
作成した`SanitizeAndNormalizeText`関数を、図形テキストの操作に組み込んでみましょう。
4.1. サンプルシナリオ:アクティブページ上の全図形テキストを整形
ここでは、現在開いているVisioドキュメントのアクティブページにある、すべての図形のテキストを整形するVBAマクロを作成します。
Sub CleanAllShapeTextsOnActivePage()
Dim visApp As Visio.Application
Dim visDoc As Visio.Document
Dim visPage As Visio.Page
Dim visShape As Visio.Shape
Dim originalText As String
Dim cleanedText As String
‘ — 初期設定 —
‘ Visioアプリケーションオブジェクトを取得
On Error Resume Next ‘ エラー発生時に処理を続行
Set visApp = Visio.Application
If visApp Is Nothing Then
MsgBox “Visioアプリケーションが見つかりません。”, vbCritical
Exit Sub
End If
On Error GoTo 0 ‘ エラーハンドリングを元に戻す
‘ アクティブなドキュメントを取得
Set visDoc = visApp.ActiveDocument
If visDoc Is Nothing Then
MsgBox “アクティブなドキュメントがありません。”, vbCritical
Exit Sub
End If
‘ アクティブなページを取得
Set visPage = visDoc.ActivePage
If visPage Is Nothing Then
MsgBox “アクティブなページがありません。”, vbCritical
Exit Sub
End If
‘ — 図形テキストの処理ループ —
‘ ページ上のすべての図形をループ処理
For Each visShape In visPage.Shapes
‘ 図形にテキストが含まれているか確認
If visShape.TextExists Then ‘ .Textプロパティはテキストがない場合エラーになるため、Existsでチェック
‘ 元のテキストを取得
originalText = visShape.Text
‘ 作成した関数でテキストを整形
cleanedText = SanitizeAndNormalizeText(originalText)
‘ 整形後のテキストが元のテキストと異なる場合のみ更新
If cleanedText <> originalText Then
visShape.Text = cleanedText
Debug.Print “図形 ‘” & visShape.Name & “‘ のテキストを整形しました。 (変更前: ‘” & originalText & “‘, 変更後: ‘” & cleanedText & “‘)”
End If
End If
Next visShape
MsgBox “アクティブページ上の全図形テキストの整形が完了しました。”, vbInformation
End Sub
4.2. マクロの実行方法
1. Visioを開き、整形したい図面ファイルを表示します。
2. `Alt` + `F11` キーを押してVBAエディタを開きます。
3. 左側のプロジェクトエクスプローラーで、対象のドキュメント(例: `ThisDocument`)をダブルクリックします。
4. 表示されたコードウィンドウに、上記の`SanitizeAndNormalizeText`関数と`CleanAllShapeTextsOnActivePage`サブプロシージャをコピー&ペーストします。
5. VBAエディタのメニューから `実行` > `Sub/ユーザーフォームの実行` を選択するか、コードウィンドウ内で `CleanAllShapeTextsOnActivePage` プロシージャ内にカーソルを置いて `F5` キーを押して実行します。
4.3. 陥りやすいエラーとその対策
- `visShape.Text` プロパティへの直接アクセス: テキストが存在しない図形に対して`.Text`プロパティにアクセスすると、エラーが発生します。
- 対策: コード例のように、`visShape.TextExists` プロパティでテキストの存在を確認してからアクセスしましょう。
- `Nothing` オブジェクトへのアクセス: `visDoc` や `visPage` が `Nothing` のまま処理を進めようとするとエラーになります。
- 対策: コード例のように、オブジェクトが正しく設定されているか確認する処理を入れましょう。`On Error Resume Next` と `On Error GoTo 0` を使って、一時的にエラー発生時の挙動を制御することも有効です。
- 異体字の誤った置換: 前述の通り、異体字の単純置換は意図しない結果を招く可能性があります。
- 対策: 置換対象の文字と置換後の文字を慎重にリストアップし、テストを十分に行いましょう。可能であれば、データソース側での対応が最も安全です。
—
5. さらに応用:特定条件の図形のみを対象にする
すべての図形ではなく、特定の条件(例:図形名に特定の文字列が含まれる、図形に特定のプロパティが付与されているなど)を満たす図形のみを対象にしたい場合もあるでしょう。
5.1. 図形名によるフィルタリング
Sub CleanSpecificShapeTexts()
‘ … (visApp, visDoc, visPage の取得は上記と同様) …
Dim targetShapeNamePart As String
targetShapeNamePart = “データ” ‘ 例: 図形名に「データ」が含まれるものを対象
For Each visShape In visPage.Shapes
If visShape.TextExists Then
‘ 図形名に “データ” が含まれているかチェック
If InStr(1, visShape.Name, targetShapeNamePart, vbTextCompare) > 0 Then
Dim originalText As String
Dim cleanedText As String
originalText = visShape.Text
cleanedText = SanitizeAndNormalizeText(originalText)
If cleanedText <> originalText Then
visShape.Text = cleanedText
Debug.Print “図形 ‘” & visShape.Name & “‘ のテキストを整形しました。”
End If
End If
End If
Next visShape
MsgBox “条件に合致する図形テキストの整形が完了しました。”, vbInformation
End Sub
- `InStr(開始位置, 文字列1, 文字列2, 比較方法)`: 文字列1の中に文字列2が含まれているか検索します。`vbTextCompare`を指定すると大文字・小文字を区別せずに比較します。
5.2. 図形のカスタムプロパティによるフィルタリング
図形にカスタムプロパティ(ShapeSheetのUser-defined Cells)を設定しておき、その値でフィルタリングすることも強力な方法です。
‘ ShapeSheetに User.NeedsCleaning = 1 のようなカスタムプロパティが設定されている図形を対象とする例
Sub CleanShapeTextsWithCustomProperty()
‘ … (visApp, visDoc, visPage の取得は上記と同様) …
Dim targetPropertyName As String
targetPropertyName = “NeedsCleaning” ‘ 対象とするカスタムプロパティ名
Dim targetPropertyValue As String
targetPropertyValue = “1” ‘ 対象とするカスタムプロパティの値
For Each visShape In visPage.Shapes
If visShape.TextExists Then
Dim propValue As String
On Error Resume Next ‘ プロパティが存在しない場合のエラー回避
propValue = visShape.CellsU(“User.” & targetPropertyName).ResultStr(visNone)
On Error GoTo 0
If propValue = targetPropertyValue Then
Dim originalText As String
Dim cleanedText As String
originalText = visShape.Text
cleanedText = SanitizeAndNormalizeText(originalText)
If cleanedText <> originalText Then
visShape.Text = cleanedText
Debug.Print “図形 ‘” & visShape.Name & “‘ (プロパティ: ” & targetPropertyName & “=” & targetPropertyValue & “) のテキストを整形しました。”
End If
End If
End If
Next visShape
MsgBox “カスタムプロパティで指定された図形テキストの整形が完了しました。”, vbInformation
End Sub
- `visShape.CellsU(“User.プロパティ名”)`: ShapeSheetのユーザー定義セル(カスタムプロパティ)にアクセスします。`U`はUniversal(言語非依存)を意味します。
- `.ResultStr(visNone)`: セルの値を文字列として取得します。`visNone`は単位なしを意味します。
—
まとめ:Visio VBAで「きれいなテキスト」を手に入れる!
いかがでしたでしょうか?
今回は、Visio VBAの基本的なオブジェクトモデルから、外部データ取り込み時に発生しやすいテキストの「汚れ」をクレンジングする方法を解説しました。
- `Application` > `Document` > `Page` > `Shape` という階層構造を理解する。
- `Shape.Text` プロパティが図形テキストの操作の鍵である。
- `Replace` 関数と `Trim` 関数を駆使して、改行コード、タブコード、Unicode制御文字を除去する。
- 異体字の扱いは慎重に行い、必要に応じてデータソース側での対応や、より高度な技術を検討する。
- `TextExists` や `InStr`、ShapeSheetのカスタムプロパティなどを活用して、対象図形を柔軟に絞り込む。
これらの知識とテクニックをマスターすれば、外部データをVisio図形に流し込む作業が格段にスムーズになり、図面の品質も向上するはずです。
「ここをクリアすれば、Visio VBAの基本はバッチリですよ」と自信を持って言えるレベルに達したのではないでしょうか?
ぜひ、あなたのVisio業務にこのテクニックを取り入れて、作業効率を劇的に改善してくださいね!
もし、さらに「こんなことも自動化できる?」「このエラーはどうすれば?」といった疑問があれば、ぜひコメントで教えてください。皆さんのVisio VBAマスターへの道を、これからも応援していきます!
