【実務・中級編】Application.Versionと言語識別:複数バージョンのVisio環境で破綻しない互換性抜群のコード設計 – Visio VBA解析バイブル

スポンサーリンク

Visio VBAの地雷を回避せよ:複数バージョン混在環境を制する「鉄壁の互換性設計」

Visioの業務自動化において、最もエンジニアを悩ませるのは「環境の不一致」だ。
「自分のPCでは動いたのに、隣の席の古いVisioではエラーで落ちる」。そんな経験はないだろうか?

Visioはバージョンアップのたびに、プロパティの廃止や、微妙なAPIの挙動変化を繰り返してきた。特にVisio 2010から2013、そして2019/2021/Microsoft 365と続く中で、安易な直書きコードは技術的負債以外の何物でもない。

今日は、場当たり的な修正ではなく、「バージョンと環境を正しく検知し、適応する」ための、プロフェッショナルな設計思想を伝授する。

1. なぜ `Application.Version` だけで判断してはいけないのか

多くの開発者は、`If Application.Version = “16.0” Then …` といった条件分岐で済ませようとする。だが、これは罠だ。

  • ビルド番号の壁: 同じ「16.0」でも、アップデートにより使用可能なメソッドが異なる場合がある。
  • 言語IDの罠: 日本語環境と英語環境で、ステンシル名や関数名が異なる(特に `Master` オブジェクトへのアクセス)ケースがある。
  • アーキテクチャの差異: 32bit版と64bit版では、外部DLL呼び出し(API)のスタック構造が異なるため、単純な `Declare` 文はクラッシュの元だ。

真のエンジニアは、「バージョンで分岐する」のではなく、「実行可能な環境を動的にプロファイリングする」設計を行う。

2. 鉄壁の環境検知クラス:`VisioEnvProvider`

各モジュールに条件分岐を散りばめるのは悪手だ。環境情報は、専用のクラスまたはモジュールで一元管理せよ。

以下のコードは、現在のVisio環境を安全に判定し、後続の処理で迷わせないための「環境プロバイダー」のテンプレートだ。

‘ @Module: VisioEnvProvider
Option Explicit

Private m_VersionMajor As Double
Private m_IsLanguageJA As Boolean

‘ コンストラクタ代わりの初期化処理
Public Sub Initialize()
‘ バージョンを数値で取得
m_VersionMajor = CDbl(Application.Version)

‘ 言語設定の確認(日本語環境か否か)
‘ Application.LanguageSettings はOffice共通のAPIとして利用可能
m_IsLanguageJA = (Application.Language = 1041)
End Sub

Public Property Get VersionMajor() As Double
VersionMajor = m_VersionMajor
End Property

Public Property Get IsJapanese() As Boolean
IsJapanese = m_IsLanguageJA
End Property

‘ バージョン依存の分岐を隠蔽するメソッド
Public Function GetStencilName(ByVal baseName As String) As String
‘ 英語環境と日本語環境でのステンシル名の乖離を吸収する
If m_IsLanguageJA Then
GetStencilName = baseName ‘ 必要に応じて “基本図形” などをマッピング
Else
GetStencilName = baseName
End If
End Function

3. 実践:バージョン依存を排除した「安全なアクセス」

例えば、図形を配置する際、古いバージョンでは `Drop` メソッドの挙動が不安定な場合がある。このような場合、メインロジックに `If` を書くのではなく、ラッパー関数で包み込むのが鉄則だ。

‘ 安全にマスターシェイプをドロップするラッパー
Public Sub SafeDrop(targetPage As Visio.Page, masterObj As Visio.Master, x As Double, y As Double)
On Error GoTo ErrorHandler

‘ ここにバージョンごとの挙動差異を吸収するロジックを配置
‘ 例: 特定の古いバージョンだけ座標指定方法を変える等
targetPage.Drop masterObj, x, y

Exit Sub
ErrorHandler:
Debug.Print “Drop処理中にエラー発生: ” & Err.Description
‘ 適切なエラーハンドリングをここに記述
End Sub

4. 保守性を高める3つの鉄則

1. Late Binding (遅延バインディング) を活用せよ:
開発時は `Early Binding`(参照設定あり)でIntelliSenseを効かせつつ、配布時は `Object` 型で定義して `CreateObject` するハイブリッド構成を検討せよ。これにより、参照設定の欠落による起動時エラーを根絶できる。
2. `On Error Resume Next` を「悪」と決めつけるな:
不確実なAPI呼び出しの直前でのみ、`On Error Resume Next` を使い、直後に `If Err.Number <> 0` で判定する。これがVBAにおける唯一の「スマートな回避術」だ。
3. 定数は「環境定義」から読み込め:
ステンシルのパスやマスターシェイプ名は、コードにハードコーディングせず、隠しシートや外部設定ファイル(JSON/XML)から読み込む設計にせよ。これにより、環境依存の修正をコードの再コンパイルなしで実行できる。

最後に:エンジニアとしての誇り

「動けばいい」というコードは、1年後の自分自身を苦しめることになる。
Visioのバージョンは、これからもMicrosoftの戦略によって変化し続けるだろう。その変化を「想定内」として設計に組み込むことこそが、自動化エンジニアとしての腕の見せ所だ。

君たちが書くコードが、環境という名の荒波に揉まれても決して沈まない、堅牢な基盤となることを期待している。

さあ、コードを書き換えろ。そして、自動化の先にある「真の自由」を掴み取れ。

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