こんにちは!今日もAutoCADの自動化開発、お疲れ様です。
図面の一括変換や自動保存ツールを作っていて、「夜間に100枚の図面をバッチ処理させておいたのに、途中の1枚でファイル形式エラーが出て全停止していた……」なんて悔しい経験はありませんか?
`AcadDocument.SaveAs` メソッドは非常に簡単そうに見えて、実はAutoCAD VBAの中でもトップクラスに落とし穴が多い危険な領域なのです。特に、取引先からの指定で「AutoCAD R14形式」や「2013形式」といった古いバージョン(レガシーフォーマット)へ変換保存する際、適切な列挙型(`acSaveAsType`)を指定しないと、実行時エラーや図面データの破損を引き起こします。
今回は、AutoCADのオブジェクトモデルの根本を理解し、「どんな形式を指定されてもエラーを未然に防ぎ、動的に安全なバージョンで保存する堅牢なロジック」を一緒に構築していきましょう。
ここをマスターすれば、あなたの書くVBAコードの信頼性は劇的に向上しますよ!
—
1. なぜ SaveAs は失敗するのか?(エラーのカラクリ)
まずは、エラーが発生するメカニズムを視覚的に整理してみましょう。
多くの初学者の方がハマる原因は、「実行しているAutoCAD自身のバージョン」と「保存しようとしているDWGフォーマット」の間の互換性ルールをVBAコード側で無視してしまうことにあります。
[AcadDocument] ──> (SaveAs 実行)
│
┌──────────────┴──────────────┐
▼ ▼
【NG】直接SaveAsを実行 【OK】本記事の動的判定ロジック
・存在しない形式を指定 ・ホストAutoCADの限界バージョン判定
・上位バージョンへ逆保存 ・acSaveAsType を動的に最適化
・ReadOnly属性でクラッシュ │
│ ▼
▼ [エラーゼロで安定保存!]
(夜間バッチが全停止…)
主なエラー原因
1. ホストAutoCADがサポートしていない未来のバージョンを指定した(例: AutoCAD 2015で2018形式保存を試みる)
2. `acSaveAsType` の定数指定とファイル拡張子の不整合(例: DXFの定数なのに `.dwg` で保存)
3. `AcadDocument.SaveAs` 実行後のドキュメントコンテキストの移動(後述しますが、ここも超重要です)
これらをコード側でスマートに吸収してあげるのが、プロのエンジニアの仕事です。
—
2. 実務でそのまま使える!「動的SafeSaveAs」フルコード
それでは、実務の現場にそのまま持ち込める完全なVBAコードをお渡しします。
このコードは、指定された目標バージョン(例: “2013”, “R14” など)を解析し、実行中のAutoCAD環境で保存可能な最適な `acSaveAsType` を自動算出します。
標準モジュール(`Module1` など)に以下のコードをコピペしてご活用ください。
Option Explicit
‘ ==============================================================================
‘ 機能:エラーを未然に防ぎ、指定バージョンのDWG/DXFで安全に保存するメイン処理
‘ ==============================================================================
Public Sub ExecuteSafeSaveAs()
Dim doc As AcadDocument
Set doc = ThisDrawing ‘ 現在のアクティブ図面を取得
‘ 保存先のフルパスを指定(※環境に合わせて変更してください)
Dim targetFilePath As String
targetFilePath = “C:\Temp\Converted_Drawing.dwg”
‘ 保存したい希望のDWGバージョン(例: “2013”, “2018”, “R14” 等)
Dim targetVersionStr As String
targetVersionStr = “2013”
‘ 安全なSaveAs処理の呼び出し
If SaveDocumentSafely(doc, targetFilePath, targetVersionStr) Then
MsgBox “安全に保存が完了しました!” & vbCrLf & targetFilePath, vbInformation, “成功”
Else
MsgBox “保存処理に失敗しました。ログを確認してください。”, vbCritical, “エラー”
End If
End Sub
‘ ==============================================================================
‘ 機能:バージョン判定とエラーハンドリングを内包した安全な保存関数
‘ 引数:
‘ targetDoc : 対象の AcadDocument オブジェクト
‘ filePath : 保存先フルパス
‘ verString : 希望バージョン文字列 (“R14”, “2000”, “2004”, “2007”, “2010”, “2013”, “2018”)
‘ 戻り値:成功時 True
‘ ==============================================================================
Public Function SaveDocumentSafely( _
ByVal targetDoc As AcadDocument, _
ByVal filePath As String, _
ByVal verString As String) As Boolean
On Error GoTo ErrorHandler
SaveDocumentSafely = False
‘ 1. 引数チェック(ドキュメントが開いているか)
If targetDoc Is Nothing Then
Debug.Print “[Error] 対象のドキュメントが存在しません。”
Exit Function
End If
‘ 2. 適切な acSaveAsType の動的決定
Dim saveType As acSaveAsType
saveType = ResolveSaveAsType(verString)
‘ 3. AutoCADホスト自体のバージョンチェック(未来バージョンへの保存防止)
‘ Application.Version 例: “24.3s (LMSa)” -> 先頭のメジャーバージョンを数値化
Dim hostMajorVer As Long
hostMajorVer = Val(Split(targetDoc.Application.Version, “.”)(0))
‘ 例: AutoCAD 2018 (Internal Ver 22) 未満なのに ac2018_dwg を指定した場合はカレント形式にフォールバック
If saveType = ac2018_dwg And hostMajorVer < 22 Then
Debug.Print "[Warning] ホストAutoCADが2018形式に対応していません。標準形式に変更します。"
saveType = acNative
End If
' 4. 保存先フォルダの存在確認
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Dim folderPath As String
folderPath = fso.GetParentFolderName(filePath)
If Not fso.FolderExists(folderPath) Then
Debug.Print "[Error] 保存先フォルダが存在しません: " & folderPath
Exit Function
End If
' 5. SaveAs の実行
' ※ SaveAs(FileName, SaveAsType)
targetDoc.SaveAs filePath, saveType
' 処理成功
SaveDocumentSafely = True
Exit Function
ErrorHandler:
' 予期せぬエラー(ファイル読み取り専用、ディスクフルなど)を補獲
Debug.Print "[Fatal Error] SaveAs失敗: " & Err.Number & " - " & Err.Description
SaveDocumentSafely = False
End Function
' ==============================================================================
' 機能:文字列から正しい acSaveAsType 定数を返すヘルパー関数
' ==============================================================================
Private Function ResolveSaveAsType(ByVal verStr As String) As acSaveAsType
Select Case UpperCaseTrim(verStr)
Case "R14", "14"
ResolveSaveAsType = acR14_dwg
Case "2000"
ResolveSaveAsType = ac2000_dwg
Case "2004"
ResolveSaveAsType = ac2004_dwg
Case "2007"
ResolveSaveAsType = ac2007_dwg
Case "2010"
ResolveSaveAsType = ac2010_dwg
Case "2013"
ResolveSaveAsType = ac2013_dwg
Case "2018"
ResolveSaveAsType = ac2018_dwg
Case Else
' 指定なし、または不明な場合は実行環境の最新標準形式(acNative)を使用
ResolveSaveAsType = acNative
End Select
End Function
' 補助関数:文字列の整形
Private Function UpperCaseTrim(ByVal str As String) As String
UpperCaseTrim = UCase(Trim(str))
End Function
---
3. プロの視点!コードの深掘り解説
上記のコードには、一見地味ですが実務でトラブルを起こさないための「防犯装置」がいくつも仕込まれています。先輩エンジニアとして、重要ポイントを3つ解説しますね。
ポイント①:`acSaveAsType` 定数の隠された罠
AutoCAD VBAの `SaveAs` メソッドの第2引数には `acSaveAsType` という列挙型(Enum)を渡します。
これを省略して `targetDoc.SaveAs “C:\test.dwg”` のようにパスだけ渡すと、現在開いているファイルの形式のまま保存しようとします。
もし開いているファイルが「AutoCAD R14形式」で、そこに最新機能の動的ブロックや新注釈オブジェクトが含まれていた場合、保存時にデータが欠落するか、サイレントエラーで保存が失敗します。そのため、明示的に `acSaveAsType`(例: `ac2018_dwg` や `acNative`)を注入するのが鉄則です。
ポイント②:ホストバージョン(`Application.Version`)の事前検証
AutoCADの内部バージョン番号をご存じでしょうか?
- AutoCAD 2013~2017 ── メジャーバージョン 19~21(DWG 2013形式まで対応)
- AutoCAD 2018~2024 ── メジャーバージョン 22~24(DWG 2018形式まで対応)
古いAutoCAD(例: 2016)上で動き始めたVBAマクロが、何も知らずに `ac2018_dwg` を指定して `SaveAs` を呼ぶと、即座にVBAが爆発(実行時エラー)します。
コード内の `hostMajorVer` による判定ロジックは、こうした「未来のDWG形式を指定してしまう事故」を未然に防止しています。
ポイント③:`SaveAs` 実行後の「ドキュメントの切り替わり」
VBAで最もハマりやすい仕様がこれです!
‘ A.dwg を開いた状態で実行
ThisDrawing.SaveAs “C:\B.dwg”
これを実行した瞬間、メモリ上の `ThisDrawing` が参照するファイルは 「A.dwg」ではなく「B.dwg」に切り替わります。
もし「元ファイルを変更せずに別名で保存して、元のファイルの処理を続けたい」というバッチ処理を作る場合は、`SaveAs` ではなく `SaveCopyAs` メソッドを使うのが正解です。ここを混同すると、意図しないファイルの上書き事故が発生します。
—
4. 現場で陥りがちなトラブルチェックリスト
開発中に「あれ? 保存できないぞ?」となったら、以下のチェックリストを確認してみてください。
| チェック項目 | 原因と対策 |
| :— | :— |
| エラー: “eNotHandled” や Automationエラー | 指定した `acSaveAsType` が古い/新しい過ぎて現在の環境で非対応。`acNative` で動作確認を! |
| ファイルが書き換えられない | 保存先ファイルが既に存在し、それが「読み取り専用」になっている。FSOで事前に属性変更が必要。 |
| DXFで保存したのにファイルが開けない | 拡張子を `.dxf` にしているのに、`acSaveAsType` に `ac2018_dwg`(DWG用)を指定しているミス。 |
| パスが長すぎてエラーになる | Windowsのパス制限(260文字)を超えているか、ファイル名に `\ / : ? ” < > \|` が含まれている。 |
—
5. まとめ:堅牢なコードがあなたを救う
今回は `AcadDocument.SaveAs` を安全に使いこなすための、バージョン判定ロジックと実践的なコードを解説しました。
- `acSaveAsType` を明示的に指定する
- ホストAutoCADのバージョンと互換性を事前にコードでチェックする
- コンテキストの移動を意識し、用途に応じて `SaveCopyAs` と使い分ける
この3つの原則を守るだけで、あなたの作成するAutoCAD VBAツールは「エラーで止まらないプロ仕様のツール」へと昇華します。
ここをクリアできれば、AutoCAD VBAのオブジェクトモデルの扱いはバッチリですよ!
自信を持って、次の自動化ステップ(ブロック属性の集計や、図面の自動生成など)へ進んでくださいね。応援しています!
