AutoCAD VBAを掌握する極限の知見:SupportPathの動的スイッチングによるフォント・ハッチング完全制御
開発プロジェクトのリーダーである私たちが、現場のCADオペレーターから最も頻繁に受ける理不尽な悲鳴は何だと思うか?
「文字化けしています」「ハッチングパターンの読み込みに失敗しました」「図面が壊れています」
これの根本原因の多くは、AutoCADの検索パス(SupportPath)にプロジェクト固有のフォント(.shx)やカスタムパターン(.pat)のフォルダが通っていない、あるいは他の社内標準パスとの競合によって古いバージョンが優先されていることにある。
素人プログラマーは、こう言うだろう。
「ユーザーにオプション画面を開かせて、手動でパスを追加してもらえばいいじゃないですか」と。
言語道断。
プロの自動化エンジニアが、エンドユーザーに手動設定を強いるなどエンジニアリングの敗北だ。環境設定はコードで支配し、マクロの実行開始と同時に裏側で完璧に整え、終了時にはノーベル賞の受賞者のように「使った痕跡すら残さず美しく原状復帰させる」のがプロフェッショナルの仕事である。
今回は、`AcadApplication.Preferences.Files.SupportPath` をプログラムから一時的かつ安全に書き換え、プロジェクト専用の資源を強制認識させる「環境スイッチング術」の極意を伝授しよう。
—
1. なぜ「そのまま書き換え」は地雷なのか?(アーキテクチャの罠)
`SupportPath` は、AutoCADがフォント、メニュー、LISP、ハッチングなどを探しに行くパスのリストであり、セミコロン区切りの巨大な文字列として格納されている。
これを安易に以下のように書き換えると、致命的なバグを生む。
‘ 【悪手】エラーハンドリングなしの直接書き換え
ThisDrawing.Application.Preferences.Files.SupportPath = “C:\MyFonts;” & 既存のパス
このアプローチがなぜ地雷なのか。理由は3つある。
1. 異常終了時の汚染(State Pollution): マクロ実行中に何らかの予期せぬエラー(ゼロ除算やオブジェクト不参照など)でコードが中断した場合、変更されたSupportPathがそのまま永続化され、次回起動時以降のCAD環境を破壊する。
2. パスの重複汚染: 同じマクロを何度もテスト実行すると、`SupportPath` の先頭に何重にも同じフォルダパスが挿入され、文字列長制限(Windowsの制限やAutoCAD内部バッファ)に抵触して設定がクラッシュする。
3. レジストリ/メモリの不整合: AutoCADのPreferencesオブジェクトは、書き込みタイミングによってメモリ上のキャッシュとレジストリの同期がズレることがある。
したがって私たちが実装すべきは、「RAII(Resource Acquisition Is Initialization)」の概念をVBAに持ち込んだ、例外安全なラッパー構造である。
—
2. 堅牢な環境スイッチング設計の要件
プロダクションコードとして耐えうるシステムにするため、以下の要件を満たす設計とする。
- トランザクション的保証: 処理の開始時に現在のパスのスナップショットを保存し、正常終了・異常終了(`On Error`)のいかんを問わず、必ず元のパスに復元する(`Finally` ブロックのイディオム)。
- 重複登録の防止: すでに目的のパスが含まれている場合は二重に追加せず、強制的に最優先(先頭)へ並び替える。
- パスの正規化: 末尾のセミコロンの有無や大文字小文字の揺れを吸収する。
—
3. 【実用プロダクションコード】SupportPath動的スイッチングモジュール
以下のコードを、あなたのAutoCAD VBAプロジェクトの標準モジュール(例: `ModFontSwitcher`)にそのまま貼り付けてほしい。実務で即座に使えるレベルの堅牢性を担保している。
Option Explicit
‘ ==============================================================================
‘ モジュール名: ModFontSwitcher
‘ 概要: プロジェクト固有のサポートパスを一時的に最優先に挿入し、安全に原状復帰させる
‘ ==============================================================================
‘ メイン処理:特殊フォントやパターンを使用するプロシージャをラップして実行
Public Sub ExecuteWithCustomPath(ByVal targetFolderPath As String)
Dim originalSupportPath As String
Dim appPrefs As AcadPreferencesFiles
Dim isPathInjected As Boolean
isPathInjected = False
‘ 1. 前提条件のチェック
If Not CheckFolderExists(targetFolderPath) Then
MsgBox “指定された専用リソースフォルダが存在しません:” & vbCrLf & targetFolderPath, vbCritical, “パスエラー”
Exit Sub
End
On Error GoTo ErrorHandler
‘ 2. アプリケーション設定オブジェクトの取得
Set appPrefs = ThisDrawing.Application.Preferences.Files
originalSupportPath = appPrefs.SupportPath
‘ 3. パスのインジェクション(最優先に追加し、重複を排除)
Dim newPath As String
newPath = InjectPathToTop(originalSupportPath, targetFolderPath)
‘ 設定適用
appPrefs.SupportPath = newPath
isPathInjected = True
Debug.Print “[Info] SupportPathを一時的に書き換えました: ” & targetFolderPath
‘ ————————————————————————–
‘ 4. 【メイン処理の実行】ここに目的のCAD処理を記述する
‘ ————————————————————————–
Call RunCoreBusinessLogic
‘ 5. 正常終了時の復元
appPrefs.SupportPath = originalSupportPath
Debug.Print “[Info] SupportPathを正常に復元しました。”
Exit Sub
ErrorHandler:
‘ 6. 異常終了時の安全な復元(リソースリークの防止)
If isPathInjected Then
On Error Resume Next
appPrefs.SupportPath = originalSupportPath
On Error GoTo 0
End If
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ — コアビジネスロジック(サンプル) —
Private Sub RunCoreBusinessLogic()
‘ ここで特殊なSHXフォントを使用する文字スタイルの作成や、
‘ 専用PATファイルを必要とするハッチング生成処理を行う
Dim txtStyle As AcadTextStyle
Set txtStyle = ThisDrawing.TextStyles.Add(“ProjectSpecialStyle”)
‘ 例: 特殊フォントファイルを指定(フォルダに配置されている前提)
txtStyle.fontFile = “my_original_font.shx”
MsgBox “専用フォントをロードして処理を実行しました。”, vbInformation, “実行完了”
End Sub
‘ — ヘルパー関数: パスを最優先に挿入し、重複を整理する —
Private Function InjectPathToTop(ByVal currentPath As String, ByVal addPath As String) As String
Dim paths() As String
Dim i As Long
Dim cleanedAddPath As String
Dim resultPath As String
cleanedAddPath = TrimPath(addPath)
paths = Split(currentPath, “;”)
‘ 追加パスを先頭にした新しいリストを構築(既存リストからの重複分は除外)
resultPath = cleanedAddPath
For i = LBound(paths) To UBound(paths)
Dim p As String
p = TrimPath(paths(i))
If p <> “” And StrComp(p, cleanedAddPath, vbTextCompare) <> 0 Then
resultPath = resultPath & “;” & p
End If
Next i
InjectPathToTop = resultPath
End Function
‘ — ヘルパー関数: パスの末尾のセミコロンや空白を除去 —
Private Function TrimPath(ByVal p As String) As String
Dim temp As String
temp = Trim$(p)
If Right$(temp, 1) = “;” Then
temp = Left$(temp, Len(temp) – 1)
End If
TrimPath = temp
End Function
‘ — ヘルパー関数: フォルダの存在確認 —
Private Function CheckFolderExists(ByVal folderPath As String) As Boolean
Dim fso As Object
Set fso = CreateObject(“Scripting.FileSystemObject”)
CheckFolderExists = fso.FolderExists(folderPath)
Set fso = Nothing
End Function
—
4. チーフアーキテクトからの実践的アドバイス
1. ネットワークパス(UNC/共有フォルダ)を扱う場合の注意点
もし `targetFolderPath` に社内サーバーの共有パス(例: `\\server\cad_resources\fonts`)を指定する場合、AutoCADがそのパスにアクセスする権限やネットワーク遅延によって、パス適用時に数ミリ秒のフリーズが発生することがある。可能であれば、マクロ実行時にローカルのテンポラリフォルダ(`Environ(“TEMP”)` など)へサーバー上のフォントを一度一括コピーし、そのローカルパスを `SupportPath` に通す方が圧倒的に動作が軽快で堅牢になる。
2. フォントキャッシュのフラッシュについて
パスを通しただけでは、AutoCADのメモリ内に古いフォント情報が残っている場合がある。必要に応じて、メイン処理の直後に `ThisDrawing.Regen All` を実行するか、あるいは `_.REGEN` コマンドを `SendCommand` で叩くことで、確実に新しいフォントレンダリングを強制させることができる。
—
総括
プログラミングの質は、「ハッピーパス(正常系)」を書く能力ではなく、「アンハッピーパス(異常系・環境差異)」をいかに優雅にコントロールするかで決まる。
今回紹介した `SupportPath` の動的スイッチング技術は、単なる小技ではない。AutoCADという巨大なアプリケーションの実行コンテキストをコードの支配下に置き、環境依存のトラブルを根絶するための強力なアーキテクチャである。
あなたの現場から「文字化け」という二文字を、今日この瞬間から永遠に排除せよ。
