【テクニカル・上級編】【初心者向け】図面保存時に「DXF/DWG」を同時出力するファイル名自動命名ルール実装VBA – SolidWorks VBA解析バイブル

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

保存ボタンの先にある設計思想:SolidWorks図面からDXF/DWGを同時出力する堅牢なアーキテクチャ

業務自動化の現場において、「動けばいい」というコードは、後に技術負債という名の時限爆弾となってシステム全体を破壊する。

特に、設計データのライフサイクルに深く関わる「図面出力(DXF/DWG)」の自動化は、単なるファイル変換ではない。それは、CADデータという高度な構造化データを、製造現場や外部ベンダーが扱うレガシーな形式へと「変換・解釈」する、極めて重要なデータ・パイプラインの構築である。

多くのエンジニアは、SolidWorks APIの `SaveAs` メソッドを呼び出すだけの単純なマクロを書く。しかし、それだけでは不十分だ。ファイル名の命名規則の不整合、メモリリークによるCADの不安定化、あるいはファイルアクセス競合による例外処理の欠如。これらが重なったとき、自動化システムは崩壊する。

本稿では、シニアエンジニアが備えておくべき、「堅牢性・メモリ管理・命名規則の抽象化」を兼ね備えた、実戦的な図面同時出力アーキテクチャを解説する。

1. 設計思想:なぜ「単なるSaveAs」では通用しないのか

プロフェッショナルな自動化において、我々が直面する真の課題は、APIの構文ではなく、以下の3点に集約される。

1.1 オブジェクトのライフサイクル管理

SolidWorksのAPIはCOM(Component Object Model)に基づいている。VBAのガベージコレクションは、COMオブジェクトの解放において必ずしも完璧ではない。特に、同一プロセス内で図面を読み込み、異なる形式で連続して書き出す際、`ModelDoc2` や `DrawingDoc` オブジェクトの参照が適切に破棄されないと、メモリ上に「幽霊オブジェクト」が残り続け、最終的にSolidWorksのクラッシュを引き起こす。

1.2 命名規則の「外部化」と「堅牢性」

社内の命名規則(例:`プロジェクト番号_図番_リビジョン.dxf`)は、設計変更によって容易に変わる。コード内に文字列結合をハードコードすることは、保守性を放棄した行為だ。また、ファイル名に使用できない禁則文字のハンドリングも、システム間連携(PLM/ERPへのアップロード)を前提とするならば必須要件となる。

1.3 例外系への耐性

「ファイルが既に開かれている」「書き込み権限がない」「ネットワークドライブが切断された」といったランタイムエラーに対し、ユーザーにダイアログを表示して処理を止めるのは、自動化の敗北である。

2. 実装アーキテクチャ:堅牢なエクスポート・エンジン

以下に、設計思想を具現化したVBAコードを示す。このコードは、単なるスクリプトではなく、エラーハンドリングとメモリ管理を組み込んだ「モジュール」として設計している。

Option Explicit

' ==============================================================================
' Module: DrawingExportEngine
' Description: SolidWorks図面から規定の命名規則に基づきDXF/DWGを同時出力する
' Author: Chief Architect
' ==============================================================================

' SolidWorks API Constants (定義されていない場合のための定義)
Const swSaveAsOptions_Silent As Long = 1
Const swDocDRAWING As Long = 3

''' <summary>
''' 図面ファイルを保存し、同時にDXF/DWGを自動生成するメインルーチン
''' </summary>
Public Sub ExportDrawingWithNamingRules()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim swFilePath As String
    Dim baseName As String
    Dim folderPath As String
    Dim extension As String
    Dim targetName As String
    Dim errors As Long
    Dim warnings As Long
    
    On Error GoTo ErrorHandler

    ' 1. オブジェクトの取得
    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    
    ' 図面が開かれているかチェック
    If swModel Is Nothing Then
        MsgBox "図面ファイルが開かれていません。", vbCritical
        Exit Sub
    End If
    
    If swModel.GetType <> swDocDRAWING Then
        MsgBox "アクティブなドキュメントが図面ではありません。", vbCritical
        Exit Sub
    End If

    Set swDraw = swModel.GetDrawings ' DrawingDocへのキャスト
    
    ' 2. パス情報の解析
    swFilePath = swModel.GetPathName
    If swFilePath = "" Then
        MsgBox "ファイルを一度保存してから実行してください。", vbExclamation
        Exit Sub
    End If
    
    ' フォルダパスとベースファイル名の分離
    folderPath = Left(swFilePath, InStrRev(swFilePath, "\"))
    baseName = Mid(swFilePath, InStrRev(swFilePath, "\") + 1)
    baseName = Left(baseName, InStrRev(baseName, ".") - 1)

    ' 3. 命名規則の適用 (ここをロジックとして分離可能)
    ' 例: {OriginalName}_EXPORT
    targetName = GenerateTargetName(baseName)

    ' 4. ネイティブ図面の保存 (既存の保存処理)
    ' Silentオプションにより、ユーザーへの確認ダイアログを抑制
    Dim status As Boolean
    status = swModel.Save3(swSaveAsOptions_Silent, errors, warnings)
    
    If Not status Then
        Err.Raise vbObjectError + 513, "Save3", "ネイティブ図面の保存に失敗しました。"
    End If

    ' 5. DXF/DWGへの同時出力
    ' DXF出力
    Call PerformSaveAs(swModel, folderPath & targetName & ".dxf", errors, warnings)
    
    ' DWG出力
    Call PerformSaveAs(swModel, folderPath & targetName & ".dwg", errors, warnings)

    MsgBox "エクスポート完了: " & targetName, vbInformation

CleanUp:
    ' 6. メモリの明示的解放 (極めて重要)
    ' COMオブジェクトの参照カウントをゼロにする
    Set swDraw = Nothing
    Set swModel = Nothing
    Set swApp = Nothing
    Exit Sub

ErrorHandler:
    MsgBox "致命的なエラーが発生しました。" & vbCrLf & _
           "Error No: " & Err.Number & vbCrLf & _
           "Description: " & Err.Description, vbCritical
    Resume CleanUp
End Sub

''' <summary>
''' 命名規則を制御する関数
''' </summary>
Private Function GenerateTargetName(ByVal originalName As String) As String
    ' ここに社内独自のロジックを実装する
    ' 例: プロジェクトコードの付与、リビジョン管理、禁則文字の置換など
    Dim sanitizedName As String
    sanitizedName = originalName
    
    ' 禁則文字の簡易置換 (実務では正規表現やより広範なリストが必要)
    sanitizedName = Replace(sanitizedName, " ", "_")
    sanitizedName = Replace(sanitizedName, "/", "-")
    
    ' 命名ルールの適用
    GenerateTargetName = sanitizedName & "_AUTO"
End Function

''' <summary>
''' SaveAsを実行する低レベル・ルーチン
''' </summary>
Private Sub PerformSaveAs(ByRef model As SldWorks.ModelDoc2, ByVal fullPath As String, _
                          ByRef errs As Long, ByRef warns As Long)
    Dim success As Boolean
    
    ' SaveAs4/5 を使用することで、より詳細な制御が可能
    ' swSaveAsOptions_Silent により、UIの割り込みを防ぐ
    success = model.SaveAs4(fullPath, 0, swSaveAsOptions_Silent, errs, warns)
    
    If Not success Then
        ' ここでログ出力やリトライロジックを検討する
        Debug.Print "Failed to save: " & fullPath & " | Error: " & errs
    End If
End Sub

3. 技術的深掘り:アーキテクトの視点

3.1 `SaveAs4` と `swSaveAsOptions_Silent` の重要性

図面出力において、最も忌避すべきは「ユーザーへのダイアログ表示」である。自動化プロセス中に「上書きしますか?」というダイアログが出た瞬間、そのプロセスは「自動化」としての性質を失い、人間が介入しなければならない「半自動」へと格下げされる。`swSaveAsOptions_Silent` を指定することで、APIはバックグラウンドで処理を完結させる。

3.2 メモリ管理の極意:`Set obj = Nothing`

VBAは、スコープを抜ければ変数が破棄されると考えてしまいがちだ。しかし、SolidWorksのような巨大なアプリケーションのAPIを叩く場合、COM参照のライフサイクルは開発者が管理しなければならない。
`CleanUp` ラベルによる明示的な `Set Nothing` は、単なる作法ではない。これは、長時間稼働するサーバーサイドの自動化や、大量の図面をバッチ処理する際に、「メモリ使用量が右肩上がりに増えていく現象(メモリリーク)」を防ぐための防波堤である。

3.3 Windows APIへの拡張性

もし、このマクロをさらに進化させ、ファイルがロックされているかどうかを瞬時に判定したいのであれば、VBA標準の `Dir` 関数ではなく、Windows APIの `GetFileAttributes` や、FileSystemObjectを介した高度なファイル制御を検討すべきだ。

4. 結論

優れた自動化エンジニアは、コードを書く前に「失敗のシナリオ」を書く。

今回提示したアーキテクチャは、単にファイルを保存するだけのものではない。命名規則の変更に耐え、メモリ消費を抑え、エラー発生時にもシステムを停止させない、「運用に耐えうるソフトウェア」としての構造を持っている。

図面出力の自動化は、CADエンジニアリングにおける「最後のミッシングリンク」だ。ここを疎かにせず、アーキテクチャレベルで設計すること。それが、真のプロフェッショナルへの道である。

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