【実務・中級編】【実務中級者向け】図面を開く際の「フォント置換」ダイアログを自動回避するフォントマップ制御 – AutoCAD VBA解析バイブル

スポンサーリンク

AutoCAD VBAを掌握する極限の知見:フォント置換ダイアログの呪縛を断ち切るフォントマップ自動制御

開発現場のエンジニア諸君、日々のAutoCAD自動化お疲れ様である。
大量のDWGファイルを一括処理するバッチ処理を組んだ際、夜間に走らせたはずのプログラムが、朝に出社してみると「見つからないSHXフォント」の置換ダイアログで完全にフリーズしていた……という悪夢を経験したことはないだろうか?

GUIを持たないバックグラウンド処理において、AutoCADが突然モーダルダイアログを表示してユーザーの入力を待つ状態(ハングアップ状態)になることは、自動化システムにおける最大の罪である。

今回は、この「フォント置換ダイアログ」を根本から無力化し、プログラムの完全な無人化を達成するためのフォントマップ(FMP)動的制御テクニックを授与する。実務で即座に使えるプロダクションコードと共に、その裏側のアーキテクチャを徹底解説しよう。

—

1. なぜ「フォント置換ダイアログ」が発生するのか?

AutoCADは、図面を開く際に指定されたSHXフォントやTrueTypeフォントが見つからない場合、親切心(あるいは余計なお世話)からモーダルダイアログをポップアップさせ、「どの代替フォントを使用するか」をユーザーに問い掛ける。

[警告] 指定されたフォントが見つかりません: “xxx.shx”
代替フォントを選択してください: [ ]

このダイアログはVBAの実行スレッドをブロックし、`Documents.Open` メソッドの処理を完全に停止させる。
`Application.DisplayAlerts = False` といった一般的なVBAのトラップ回避策は、AutoCADのCOMインターフェースにおいては一切機能しない。AutoCADのコアエンジンレベルで制御を握られているからだ。

これを回避する唯一にして最もエレガントなアプローチが、フォントマップファイル(acad.fmp または任意の .fmp ファイル)をプログラムから動的に書き換え、未解決フォントをあらかじめ既知のフォントへルーティング(強制置換)する手法である。

—

2. フォントマップ(FMP)制御のアーキテクチャ

フォントマップファイルは非常にシンプルだ。テキストファイルであり、以下のようなフォーマットで記述されている。

失われたフォント名;置換後のフォント名
shxfont1;standard.shx
oldfont;txt.shx

このファイルを一時的、あるいは動的に書き換えてAutoCADに読み込ませることで、ダイアログを一切出すことなく、安全に図面を開くことが可能になる。

堅牢な設計における3つの鉄則

1. 既存のFMP設定を汚さない:元のFMPファイルを破壊しないよう、処理前後にバックアップ・復元を行う。
2. 一時的なFMPの動的生成:処理対象の図面群に必要なマッピングをインメモリで組み立て、一時ファイルとして吐き出す。
3. エラー時のクリーンアップ(例外保証):万が一VBA側でランタイムエラーが発生しても、確実に元の環境へ復元するトランザクション的な実装にする。

—

3. 【プロダクションコード】フォントマップ自動制御モジュール

以下のコードは、実務の現場でそのまま組み込める堅牢なクラス・標準モジュール群の設計思想を取り入れた実装である。エラーハンドリングとクリーンアップを徹底している点に注目してほしい。

Option Explicit

‘ Windows API: 一時ファイルパス取得用
Private Declare PtrSafe Function GetTempPath Lib “kernel32” Alias “GetTempPathA” (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long

‘ ==============================================================================
‘ メイン処理:フォント置換ダイアログを回避して図面を開く
‘ ==============================================================================
Public Sub OpenDrawingWithoutDialog(ByVal targetDwgPath As String)
Dim originalFmpPath As String
Dim tempFmpPath As String
Dim fso As Object

Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 1. 現在のフォントマップファイルのパスを取得
originalFmpPath = ThisDrawing.Application.Preferences.Files.FontMapFile

‘ 2. 一時的なフォントマップファイルのパスを生成
tempFmpPath = GetTempFolderPath() & “auto_override_” & Format(Now, “yyyymmddhhmmss”) & “.fmp”

On Error GoTo ErrorHandler

‘ 3. ベースとなるFMPの内容を引き継ぐ、または新規作成してマッピングを追加
Call CreateCustomFontMap(originalFmpPath, tempFmpPath, fso)

‘ 4. AutoCADのフォントマップ設定を一時ファイルに切り替え
ThisDrawing.Application.Preferences.Files.FontMapFile = tempFmpPath

‘ 5. 図面を開く(ダイアログはポップアップせず、FMPに従って自動置換される)
Dim targetDoc As Document
Set targetDoc = ThisDrawing.Application.Documents.Open(targetDwgPath)

‘ — ここに図面に対する処理を記述 —
Debug.Sprintf ” Successfully opened: ” & targetDoc.Name

‘ 後処理(必要に応じて保存して閉じるなど)
‘ targetDoc.Close False

ErrorHandler:
‘ 6. 例外の有無に関わらず、必ず元のフォントマップ設定を復元する
ThisDrawing.Application.Preferences.Files.FontMapFile = originalFmpPath

‘ 7. 一時ファイルのクリーンアップ
If fso.FileExists(tempFmpPath) Then
fso.DeleteFile tempFmpPath, True
End If

Set fso = Nothing

If Err.Number <> 0 Then
MsgBox “図面オープン中にエラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End If
End Sub

‘ ==============================================================================
‘ カスタムフォントマップの生成ロジック
‘ ==============================================================================
Private Sub CreateCustomFontMap(ByVal sourceFmp As String, ByVal destFmp As String, ByRef fso As Object)
Dim tsRead As Object
Dim tsWrite As Object
Dim lineContent As String

‘ 書き込み用の一時ファイルを作成
Set tsWrite = fso.CreateTextFile(destFmp, True)

‘ 既存のFMPがあれば、その内容をそのままコピー
If fso.FileExists(sourceFmp) Then
Set tsRead = fso.OpenTextFile(sourceFmp, 1) ‘ ForReading
Do While Not tsRead.AtEndOfStream
lineContent = tsRead.ReadLine
tsWrite.WriteLine lineContent
Loop
tsRead.Close
Set tsRead = Nothing
End If

‘ 【重要】よく遭遇する不明なフォントを強制的に標準フォント(例: roman.shx や txt.shx)にマップ
‘ ワイルドカード的な記述や、組織内で頻出するフォント名を追加していく
tsWrite.WriteLine “;txt.shx” ‘ すべての未定義フォントを txt.shx にフォールバックさせる荒技(必要に応じて調整)

tsWrite.Close
Set tsWrite = Nothing
End Sub

‘ ==============================================================================
‘ Windows一時フォルダのパスを取得するヘルパー
‘ ==============================================================================
Private Function GetTempFolderPath() As String
Dim buffer As String
Dim length As Long

buffer = Space(255)
length = GetTempPath(255, buffer)
GetTempFolderPath = Left(buffer, length)
End Function

—

4. コードの解説と実務におけるインテリジェンス

このコードが「プロの仕事」である所以をいくつかのポイントで解説しよう。

トランザクション・パターン(例外保証)の徹底

VBAには `Try…Catch` 構造がないため、`On Error GoTo` を用いたジャンプ処理が必須となる。ここで最も恐ろしいのは、エラー発生時に `Preferences.Files.FontMapFile` が一時ファイルのまま残ってしまうことだ。
これを防ぐため、`ErrorHandler:` ラベルをエラー時だけでなく正常終了時にも必ず通過するルーティングにしておき、設定の復元と一時ファイルの削除を担保している。

アグレッシブなフォントフォールバック (`;txt.shx`)

コード内の `tsWrite.WriteLine “;txt.shx”` は、いわば「特効薬」である。
フォント名が特定できない、あるいは外部から雑多なCADデータが納品される環境において、すべての未定義フォントを標準の `txt.shx` に強制置換させることで、ダイアログの発生確率を物理的にゼロに収束させている。
もし特定のフォントだけをピンポイントで置換したい場合は、“ の部分を `missing_font_name.shx` に書き換えればよい。

—

5. データベースや外部ファイル連携への発展

実務でこの仕組みをさらにスケールさせる場合、ハードコーディングされたフォントマッピングではなく、外部データベース(SQLite / Access)やCSVファイルから「案件ごとのフォント置換ルール」を動的に読み込む設計へと昇華させるべきだ。

[外部CSV / DB] ──> マッピングルール動的生成 ──> 一時FMP作成 ──> AutoCADオープン

これにより、クライアントAの図面群を開くときはこのマッピング、クライアントBのときは……といったマルチテナントな自動化バッチが完全に破綻なく稼働するようになる。

総括

AutoCAD VBAによる自動化の成否は、「いかに予期せぬGUIの割り込みを排除し、コードを完全な無人(ヘッドレス)状態に保てるか」にかかっている。
今回解説したフォントマップ制御は、単なる小技ではなく、エンタープライズなCADインテグレーションにおいて必須の教養である。

あなたの組む自動化システムから、不要なダイアログボックスが永遠に消え去ることを祈る。
健闘を祈る!

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