【入門編】【上級者向け】VSDXの内部XMLを直接操作し、ページ設定を数千ページ単位で一括置換する高速化手法 – Visio VBA解析バイブル

スポンサーリンク
スポンサーリンク

【極限の知見】Visio VBAの壁を越えろ:VSDX内部XML直接操作による「数千ページ一括置換」の魔法

こんにちは。これまで数々の自動化プロジェクトを成功させてきた、あなたの「少し先を行く先輩」です。

Visio VBAを学び始め、`Shapes` や `Pages` といったオブジェクトを自在に操れるようになると、「自分はもうVisioマスターだ!」という自信が湧いてきますよね。マクロの記録から一歩踏み出し、自分でコードを書き始めたあなたは、エンジニアとして非常に素晴らしいステップを踏んでいます。

しかし、実務の現場では、時として「Visioの限界」という巨大な壁にぶつかることがあります。

例えば、「5,000ページある図面の全ページのサイズを一括で変更してほしい」という依頼。
これを、いつものように `For Each Page In Visio.Pages` でループを回して処理しようとしていませんか?

もしそうなら、少し立ち止まってください。そのコードは、完了までに数時間、あるいはVisioが応答なし(フリーズ)になってしまうかもしれません。

今日は、そんな「通常のやり方」では太刀打ちできない領域を、一瞬で制圧するための「禁断の、しかし極めて合理的な手法」を伝授します。

1. なぜ、いつものVBAでは遅いのか?(オブジェクトモデルの重み)

まず、なぜ `Page.PageSheet.Cells…` という書き方が遅いのか、その本質を知っておきましょう。

VisioのVBAでオブジェクトを操作するとき、私たちは「生きたVisio」に話しかけています。

1. VBAが「ページの設定を変えて」と命令を出す。
2. Visioのエンジンがその命令を受け取る。
3. メモリ上のオブジェクト構造を更新する。
4. 図面の再計算(レイアウト計算)を実行する。
5. 画面の描画準備を行う。

この「2〜5」のプロセスが、1ページごとに発生します。ページが数千枚あれば、このオーバーヘッド(余計な負荷)が積み重なり、膨大な時間を消費してしまうのです。

これをエンジニア用語で「オブジェクトモデルのオーバーヘッド」と呼びます。

2. VSDXの正体:それは「XMLの詰め合わせパック」である

ここで、魔法の種明かしをしましょう。
あなたが普段使っている `.vsdx` という拡張子のファイル。実はこれ、「複数のXMLファイルがZIP形式で圧縮されたもの」に過ぎません。

ファイルの拡張子を `.zip` に書き換えて解凍してみてください。中には `pages` というフォルダがあり、その中に `Page1.xml`, `Page2.xml` … といったファイルが並んでいるはずです。

ここが重要なポイントです。
「Visioを起動して、ページを一つずつ開いて操作する」のではなく、「ファイルをZIPとして解凍し、中のテキスト(XML)を力技で書き換え、再びZIPに固める」。

これなら、Visioの重い計算エンジンを介さずに、文字の置換だけで数千ページを数秒で処理できます。これが、プロフェッショナルが現場で使う「XML直接操作」の正体です。

3. 実践:XMLを直接操作するプロフェッショナル・ワークフロー

では、具体的な戦略を立てましょう。VBA単体でZIP解凍を行うのは少し手間がかかるため、ここでは「解凍済みのXMLファイルを、XML DOMを使用して高速に書き換えるロジック」に焦点を当てて解説します。

開発のロードマップ

1. 解凍: `.vsdx` を ZIP解凍ツール(またはVBAからShell経由)で展開する。
2. 走査: `pages/*.xml` をすべて取得する。
3. 加工: XMLを解析し、特定のセル(例:`PageWidth`)の値を書き換える。
4. 再圧縮: 書き換えたファイル群を再び ZIP形式で固め、拡張子を `.vsdx` に戻す。

【コード例】XMLのページ設定を書き換える核心部分

以下のコードは、展開された `PageX.xml` の中にある特定のセルの値を書き換える、非常に高度なロジックの雛形です。

' ※ 参照設定に "Microsoft XML, v6.0" を追加してください
Sub UpdatePageXmlDirectly(xmlFilePath As String, newWidth As String)
    Dim xmlDoc As MSXML2.DOMDocument60
    Dim nodeList As MSXML2.IXMLDOMNodeList
    Dim targetNode As MSXML2.IXMLDOMNode
    
    ' 1. XMLドキュメントのロード
    Set xmlDoc = New MSXML2.DOMDocument60
    xmlDoc.async = False
    xmlDoc.validateOnParse = False ' パフォーマンスのためバリデーションはオフ
    
    If Not xmlDoc.Load(xmlFilePath) Then
        Debug.Print "エラー: ファイルの読み込みに失敗しました -> " & xmlFilePath
        Exit Sub
    End If

    ' 2. 特定のセル(例: PageWidth)を探すためのXPathを指定
    ' VisioのXML構造に基づき、Cell要素の ID または Name を指定します
    ' ここでは例として、特定のIDを持つCellノードを検索する想定です
    ' ※実際のIDはVisioの仕様に基づき調査が必要です
    Dim xpath As String
    xpath = "//Cell[@ID='PageWidth']" ' 概念的な例です
    
    Set nodeList = xmlDoc.selectNodes(xpath)
    
    ' 3. 値の書き換え
    If nodeList.Length > 0 Then
        Set targetNode = nodeList.Item(0)
        ' CellのValue属性、またはその下の要素を書き換え
        ' XML構造に合わせて調整してください
        targetNode.Attributes.getNamedItem("Value").Text = newWidth
        Debug.Print "成功: " & xmlFilePath & " を更新しました。"
    Else
        Debug.Print "警告: 指定したセルが見つかりませんでした -> " & xmlFilePath
    End If

    ' 4. ファイルの保存(上書き)
    xmlDoc.Save xmlFilePath
End Sub

' --- 実行用メインルーチン(イメージ) ---
Sub ProcessAllPages()
    Dim folderPath As String
    Dim fileName As String
    
    ' 解凍済みのフォルダパスを指定
    folderPath = "C:\Work\MyVisioUnzipped\"
    fileName = Dir(folderPath & "pages\Page*.xml")
    
    ' 高速化のため、画面更新などを止める(XML操作自体には影響しませんが作法として)
    Do While fileName <> ""
        ' 各ページに対してXML操作を実行
        ' 例:すべてのページの幅を 20cm (214.17 ポイント相当) に変更
        Call UpdatePageXmlDirectly(folderPath & "pages\" & fileName, "214.17")
        
        fileName = Dir() ' 次のファイルへ
    Loop
    
    MsgBox "全ページのXML書き換えが完了しました!あとはZIP圧縮するだけです。"
End Sub

コードの解説と注意点

1. `MSXML2.DOMDocument60`: これはXMLを「構造」として理解するための非常に強力なライブラリです。単なる文字列置換(`Replace`関数)よりも正確で、XMLの構造を壊さずに特定の場所だけを狙い撃ちできます。
2. XPath (`//Cell[@ID=’…’]`): これはXML内の住所を指定する魔法の言葉です。「ドキュメント全体の中から、IDがPageWidthであるCellを探してこい」という命令です。これを使うことで、複雑な階層を瞬時に飛び越えられます。
3. `validateOnParse = False`: 大量処理を行う際は、XMLの文法チェックをスキップすることで、さらにスピードを稼ぐことができます。

4. 陥りやすい罠:ここをクリアすればプロの仲間入り

この手法は強力ですが、扱いを間違えるとファイルが壊れて開けなくなります。以下の3点は必ず守ってください。

① バックアップは「絶対」に取る

XMLを直接書き換える行為は、手術と同じです。失敗すればファイルは死にます。処理を開始する前に、必ずオリジナルの `.vsdx` ファイルをコピーしておきましょう。

② XMLの構造(Schema)を理解する

VisioのXMLは非常に複雑です。`PageWidth` という値が、どのタグの、どの属性(`Value` なのか `Formula` なのか)に入っているのか。これは、一度数ページ分を手動で解凍して、テキストエディタ(VS Codeなど)でじっくり観察することから始まります。

③ 再圧縮時の注意

ZIPに戻す際、ファイル名やフォルダ構造が変わってしまうと、Visioは「これは壊れたファイルだ」と判断します。`pages` フォルダなどはそのままの構造で固める必要があります。

最後に:エンジニアとしての「視点」を磨こう

「マクロの記録」は、Visioが用意してくれた「用意された道」を歩くことです。
「XML直接操作」は、Visioの「裏側にある土台」を直接作り変えることです。

どちらが正しいかではなく、「課題の規模に応じて、最適な手段を選択できること」。これこそが、真に価値のあるエンジニアの姿です。

今回学んだ「オブジェクトモデルの限界を知り、データそのものを操作する」という考え方は、Visioに限らず、Excel、Access、あるいはWeb APIの操作など、あらゆる自動化に応用できる普遍的な知恵です。

一歩ずつ、その深淵へと踏み込んでいきましょう。応援していますよ!

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