【入門編】【実務中級者向け】Excelリストに基づいた図面の一括オープン&特定ブロック置換後の自動保存ツール – AutoCAD VBA解析バイブル

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

マクロ記録の先へ。Excelリストで図面を「一括制御」する、極限の自動化術

こんにちは。現場の自動化を支えるエンジニアの皆さん。
日々、山のような図面データと格闘していることでしょう。

「図面を一つずつ開いて、タイトルブロックの案件名を書き換えて、クライアント指定の古いバージョンで保存して、閉じる……」

もし、あなたがこれを手作業で行っているとしたら、それはエンジニアリングではなく「単純作業」です。そして、その作業には必ず「ヒューマンエラー」が混入します。

今回は、マクロの記録レベルを卒業し、「Excelを司令塔(コントローラー)として、AutoCADを自在に操る」という、実務における最高峰のスキルの一つを伝授します。

この記事を読み終える頃には、あなたは「図面を操作する人」から「図面処理のシステムを構築する人」へと進化しているはずです。

1. 設計思想:なぜ「ExcelからAutoCAD」なのか?

多くの初心者は、AutoCAD内のVBAエディタ(VBAIDE)でコードを書き始めます。しかし、実務の現場では「情報の管理はExcel、図面の加工はAutoCAD」という役割分担が最強の布陣です。

なぜなら、図面リストや属性情報は、Excelの方が圧倒的に扱いやすく、管理しやすいからです。

今回構築するシステムのアーキテクチャ

1. 司令塔 (Excel): ファイルパスのリスト、書き換えたい属性情報、保存形式を保持。
2. 実行部 (Excel VBA): ExcelからAutoCADへ「命令」を送り、オブジェクトを制御。
3. 作業員 (AutoCAD): 命令を受け取り、図面を開き、ブロックを書き換え、保存して閉じる。

ここで重要なのは、「オブジェクトのライフサイクル(生存期間)」を意識することです。図面を大量に開く際、適切に閉じ、メモリを解放しないと、AutoCADはたちまち重くなり、最終的にはクラッシュします。これを防ぐのが、プロの仕事です。

2. 実装コード:図面一括処理のマスターピース

それでは、実際のコードを見ていきましょう。このコードは、Excelの標準モジュールに貼り付けて使用することを想定しています。

事前準備

ExcelのVBAエディタのメニューから、`ツール` -> `参照設定` を開き、以下にチェックを入れてください。

  • AutoCAD [バージョン] Type Library
Option Explicit

''' <summary>
''' Excelリストに基づいた図面の一括置換・保存処理
''' </summary>
Sub BatchProcessDrawings()
    ' --- 1. オブジェクトの宣言 ---
    Dim acadApp As Object ' AutoCAD.Application
    Dim acadDoc As Object ' AutoCAD.Document
    Dim ws As Worksheet
    Dim lastRow As Long
    Dim i As Long
    
    ' Excel側の変数
    Dim filePath As String
    Dim newTitle As String
    Dim savePath As String
    Dim dwgVersion As Long ' 保存形式の定数
    
    ' エラーハンドリング:予期せぬエラーで止まらないようにする
    On Error GoTo ErrorHandler

    ' --- 2. 初期設定 ---
    Set ws = ThisWorkbook.Sheets("Sheet1") ' リストがあるシート名
    lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row ' A列の最終行を取得
    
    ' AutoCADに接続(起動していなければ起動する)
    On Error Resume Next
    Set acadApp = GetObject(, "AutoCAD.Application")
    If acadApp Is Nothing Then
        Set acadApp = CreateObject("AutoCAD.Application")
    End If
    On Error GoTo ErrorHandler
    
    acadApp.Visible = True ' 動作を確認するために可視化
    
    ' --- 3. メインループ(Excelの行数分繰り返す) ---
    For i = 2 To lastRow ' 2行目から開始(1行目はヘッダー)
        
        filePath = ws.Cells(i, 1).Value   ' A列: 元のファイルパス
        newTitle = ws.Cells(i, 2).Value   ' B列: 書き換えたいタイトル名
        savePath = ws.Cells(i, 3).Value   ' C列: 保存先のパス
        ' D列に保存形式の定数(例: 2013形式なら acR2013 = 2013相当の数値)を入れる想定
        ' ここでは簡易的に、D列に指定された定数を使用
        dwgVersion = ws.Cells(i, 4).Value 

        ' ファイルが存在するかチェック
        If Dir(filePath) <> "" Then
            Debug.Print "Processing: " & filePath
            
            ' 図面を開く
            Set acadDoc = acadApp.Documents.Open(filePath)
            
            ' --- 4. ブロック属性の書き換え処理 ---
            ' ここでは「TITLE_BLOCK」という名前のブロックを探して属性を書き換える
            Call UpdateTitleBlockAttribute(acadDoc, "TITLE_BLOCK", "PROJECT_NAME", newTitle)
            
            ' --- 5. 指定バージョンで保存 ---
            ' SaveAsメソッドを使用。引数には保存パスとファイル形式を指定
            ' ※ dwgVersionは AutoCADの定数(例: acR2013 = 2013)
            acadDoc.SaveAs savePath, dwgVersion
            
            ' 図面を閉じる(変更はSaveAsですでに保存されているので、保存せずに閉じる)
            acadDoc.Close False
            
            ' メモリ解放の極意:オブジェクトをNothingにする
            Set acadDoc = Nothing
            
            ws.Cells(i, 5).Value = "Success" ' E列に結果を記録
        Else
            ws.Cells(i, 5).Value = "File Not Found"
        End If
        
    Next i

    MsgBox "すべての処理が完了しました!", vbInformation
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました。行: " & i & vbCrLf & "内容: " & Err.Description, vbCritical
    If Not acadDoc Is Nothing Then acadDoc.Close False
    Set acadDoc = Nothing
End Sub

''' <summary>
''' 指定したブロック内の属性値を書き換えるサブプロシージャ
''' </summary>
Sub UpdateTitleBlockAttribute(doc As Object, blockName As String, tagString As String, newValue As String)
    Dim ent As Object
    Dim attr As Object
    
    ' モデル空間内の全オブジェクトを走査
    ' ※大規模図面の場合は、より効率的な検索手法(Select method等)を検討すること
    For Each ent In doc.ModelSpace
        ' オブジェクトが「ブロック参照」であり、かつ指定した名前か確認
        If ent.ObjectName = "AcDbBlockReference" Then
            If ent.Name = blockName Then
                ' ブロック内の属性をループ
                If ent.HasAttributes Then
                    For Each attr In ent.GetAttributes
                        ' タグ名が一致したら値を書き換える
                        If attr.TagString = tagString Then
                            attr.TextString = newValue
                            Exit For
                        End If
                    Next attr
                End If
            End If
        End If
    Next ent
End Sub

3. ここがプロの分かれ道:技術的深掘り

コードをコピペするだけで終わらせてはいけません。なぜこのような書き方をしているのか、その「意図」を理解してください。

① オブジェクトの「解放」と「メモリ管理」

コード内で `Set acadDoc = Nothing` を執拗に行っている理由に気づきましたか?
AutoCAD VBAにおいて、`Document` オブジェクトは非常に重いリソースです。ループの中で図面を開きっぱなしにすると、メモリ上に「見えない図面」が蓄積され、PCの動作を著しく低下させます。
「使い終わったら、明示的に手放す」。これが、長時間稼働するバッチ処理を安定させる鉄則です。

② `SaveAs` とバージョンの制御

`acadDoc.SaveAs savePath, dwgVersion` の部分です。
AutoCADには、`acR2013` (AutoCAD 2013形式) や `acR2018` (AutoCAD 2018形式) といった定数があります。これらをExcel側から数値として渡すことで、「最新版で作成した図面を、クライアント指定の2013形式で納品する」といった高度な制御が可能になります。

③ 属性(Attribute)へのアクセス

ブロックを書き換える際、単に「ブロックを消して新しいのを置く」のは、座標やスケールがズレるリスクがあるため、中級者以上は行いません。
今回のように、「既存のブロックを探し、その中の特定の属性(TagString)だけを書き換える」手法が、最も安全で正確なアプローチです。

4. 陥りやすいエラーと対策(トラブルシューティング)

実務でこのツールを走らせると、必ずと言っていいほど壁にぶつかります。

  • 「ファイルが読み取り専用です」エラー
  • 原因: 他のユーザーが図面を開いているか、プレビューウィンドウでファイルを選択している。
  • 対策: `Dir(filePath)` で存在確認をするだけでなく、エラーハンドリングで「開けなかった場合は次の行へスキップする」処理を組み込みましょう。
  • 「ブロックが見つからない」
  • 原因: ブロック名が「大文字・小文字」まで一致していない、あるいは「ダイナミックブロック」を使用している。
  • 対策: ダイナミックブロックの場合、`ent.Name` ではなく `ent.EffectiveName` を参照する必要があります。ここが、AutoCAD APIの奥深いところです。
  • 実行速度が遅すぎる
  • 原因: `For Each ent In doc.ModelSpace` は、図面内の全要素をチェックするため、要素数が多い図面では時間がかかります。
  • 対策: 特定のレイヤーにブロックを配置する運用ルールを作るか、`Select` メソッドを使用して対象を絞り込む工夫が必要です。

最後に:一歩踏み出すあなたへ

ここまで読んでくれたあなたは、単なる「マクロ使い」ではなく、「自動化エンジニア」への道を歩み始めています。

プログラミングは、一度にすべてを理解する必要はありません。まずは今回のような「決まったパターン」を自分の手で動かし、その挙動を観察することから始まります。

「ここをこう変えたら、どうなるだろう?」
その好奇心が、あなたの業務を劇的に変え、周囲から頼られる唯一無二のエンジニアへとあなたを導いてくれるはずです。

応援しています。さあ、コードを書いて、退屈な作業を過去のものにしましょう!

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