【入門編】【実務中級者向け】図面内の「特定ブロックの属性値」をファイル名に採用して自動リネーム保存するツール開発 – AutoCAD VBA解析バイブル

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

図面を「データ」として支配せよ:属性値を用いた自動リネーム保存の極意

こんにちは。今日もCADの海で、効率化という名の航路を探しているあなたへ。

「マクロの記録」で、なんとか簡単な操作を自動化できた。一歩前へ踏み出した自分を褒めてあげてください。でも、あなたは気づいているはずです。「記録しただけでは、現場の複雑なルールには太刀打ちできない」ということに。

今日、私たちが挑むのは、単なる「記録」ではありません。「図面の中身(データ)を読み取り、その情報に基づいて図面自身を再定義する」という、一歩進んだ自動化の領域です。

具体的には、「図面枠ブロック内の『図番』という属性値を読み取り、その値をファイル名にして自動でSaveAs(名前を付けて保存)する」というツールを構築します。

これをマスターすれば、あなたは「図面を引く人」から「図面管理の仕組みを作る人」へと進化します。さあ、一緒にコードの深淵を覗いてみましょう。

1. 設計思想:オブジェクトの階層構造を理解する

プログラミングを始める前に、AutoCADが「図面をどう見ているか」という地図(アーキテクチャ)を頭に叩き込んでください。ここを曖昧にすると、必ずエラーの迷宮に迷い込みます。

図面の中には、無数のオブジェクトが眠っています。今回のターゲットは「属性値を持つブロック」です。その階層構造は以下のようになっています。

1. ActiveDocument(開いている図面ファイルそのもの)
2. PaperSpace / ModelSpace(図面が描かれている空間)
3. BlockReference(配置されたブロックの「実体」)
4. AttributeReference(ブロックに紐付いた「属性情報」)
5. TextString(属性の中に書き込まれた「実際の文字」)

私たちがやりたいのは、「空間をスキャンし、特定の名前を持つブロックを見つけ、その中の特定のタグを探し出し、文字列を抜き出す」という一連の探索プロセスです。

2. 実装:属性値を抽出して保存するコード

それでは、魂を込めたコードを提示します。このコードは、単に動くだけでなく、実務で発生しうる「予期せぬ事態」を考慮した設計にしています。

Option Explicit

''' <summary>
''' 図面内の特定ブロックから属性値を抽出し、その値でファイル名を変更して保存する
''' </summary>
Sub AutoRenameAndSave()
    On Error GoTo ErrorHandler

    Dim acadDoc As AcadDocument
    Set acadDoc = ThisDrawing
    
    ' --- 設定値 ---
    Const TARGET_BLOCK_NAME As String = "TITLE_BLOCK" ' 探したいブロックの名前
    Const TARGET_TAG_NAME As String = "DWG_NO"        ' 抽出したい属性のタグ名
    ' --------------

    Dim objEntity As AcadEntity
    Dim objBlock As AcadBlockReference
    Dim varAttributes As Variant
    Dim i As Integer
    Dim extractedValue As String
    Dim newFilePath As String
    Dim currentPath As String
    
    extractedValue = ""

    ' 1. 図面内のオブジェクトを走査(ここではレイアウト空間を対象)
    ' ※ModelSpaceを対象にする場合は acadDoc.ModelSpace に変更してください
    For Each objEntity In acadDoc.PaperSpace
        
        ' オブジェクトがブロック参照かどうかを判定
        If TypeOf objEntity Is AcadBlockReference Then
            Set objBlock = objEntity
            
            ' ブロックの名前が一致するか確認 (EffectiveNameは動的ブロックにも対応)
            If UCase(objBlock.EffectiveName) = UCase(TARGET_BLOCK_NAME) Then
                
                ' 2. 属性値の取得
                ' GetAttributesは属性オブジェクトの配列を返します
                varAttributes = objBlock.GetAttributes
                
                For i = LBound(varAttributes) To UBound(varAttributes)
                    ' タグ名が一致するかチェック
                    If UCase(varAttributes(i).TagString) = UCase(TARGET_TAG_NAME) Then
                        extractedValue = varAttributes(i).TextString
                        Exit For
                    End If
                Next i
                
                If extractedValue <> "" Then Exit For ' 見つかったらループを抜ける
            End If
        End If
    Next objEntity

    ' 3. 抽出結果のチェック
    If extractedValue = "" Then
        MsgBox "指定された属性値が見つかりませんでした。", vbExclamation
        Exit Sub
    End If

    ' 4. ファイル名のクレンジング(重要!)
    ' Windowsのファイル名に使えない文字 (\ / : * ? " < > |) を除去する
    extractedValue = CleanFileName(extractedValue)

    ' 5. 保存パスの生成
    ' 現在のフォルダパスを取得し、新しいファイル名を結合
    currentPath = acadDoc.Path
    If currentPath = "" Then
        MsgBox "図面が一度も保存されていません。先に一度保存してください。", vbCritical
        Exit Sub
    End If
    
    ' フォルダパスの末尾に \ がない場合の処理
    If Right(currentPath, 1) <> "\" Then currentPath = currentPath & "\"
    newFilePath = currentPath & extractedValue & ".dwg"

    ' 6. SaveAsの実行
    ' 注意: SaveAsは現在のドキュメントのパス自体を書き換えます
    acadDoc.SaveAs newFilePath
    
    MsgBox "保存完了: " & vbCrLf & newFilePath, vbInformation

    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました。" & vbCrLf & _
           "番号: " & Err.Number & vbCrLf & _
           "内容: " & Err.Description, vbCritical
End Sub

''' <summary>
''' ファイル名に使用できない禁止文字を置換する関数
''' </summary>
Private Function CleanFileName(ByVal fileName As String) As String
    Dim invalidChars As Variant
    Dim i As Integer
    ' 禁止文字のリスト
    invalidChars = Array("\", "/", ":", "*", "?", """", "<", ">", "|")
    
    For i = LBound(invalidChars) To UBound(invalidChars)
        fileName = Replace(fileName, invalidChars(i), "_")
    Next i
    CleanFileName = fileName
End Function

3. ここがプロの視点:陥りやすい罠と回避術

コードをコピペして動いた、それで満足してはいけません。エンジニアとして、以下の「なぜ?」を理解してください。

① `Name` ではなく `EffectiveName` を使え

ブロックには「動的ブロック(Dynamic Block)」という存在があります。ユーザーが形状を変えた瞬間、そのブロックの `Name` プロパティは `*U…` といった匿名の名前に変わってしまいます。しかし、`EffectiveName` を使えば、元の定義名を正しく取得できます。これは実務における鉄則です。

② ファイル名の「クレンジング」を忘れるな

ここが初級者と中級者の最大の分かれ道です。
図面内の属性値に「図面/A-01」のようにスラッシュが入っていた場合、そのまま `SaveAs` しようとすると、Windowsは「/」をフォルダの区切りと誤認し、「そんなフォルダはありません」とエラーを吐きます。
`CleanFileName` 関数のように、禁止文字をアンダースコア `_` などに置換する処理を挟む。これこそが、「壊れないツール」を作るための作法です。

③ `SaveAs` のライフサイクル

`SaveAs` メソッドを実行すると、AutoCAD内で現在開いている図面の「身分(パス)」が、新しい名前へと切り替わります。もし、元のファイルも残しておきたい場合は、`SaveAs` ではなく、一度別の手段でコピーを作成するか、ロジックを慎重に設計する必要があります。

4. 次のステップへ

このツールはまだ、一つの機能に特化した「部品」に過ぎません。
しかし、この「属性を読み取る」「文字列を加工する」「ファイル操作を行う」という3つのステップを組み合わせることで、以下のような高度な自動化へと拡張できます。

  • 一括リネーム: フォルダ内の全DWGを順次開き、属性値でリネームして保存する。
  • 台帳自動作成: 属性値を読み取り、Excelに図番とファイル名を一覧出力する。

「マクロの記録」という魔法の杖を捨て、コードという名の設計図を手にしたあなた。
AutoCAD VBAの世界は、あなたが想像する以上に広大で、そして制御可能なものです。

ここをクリアすれば、AutoCAD VBAの基本はバッチリですよ。
さあ、次はどんな仕組みを作りますか?

Happy Coding!

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