【テクニカル・上級編】【上級プロ向け】外部データベース(SQL Server / Excel)と連動した図面自動生成・型番駆動型ファミリーチューブ – SolidWorks VBA解析バイブル

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

【極限の自動化】DB駆動型図面生成エンジンの設計思想 — 堅牢なエンタープライズ・アーキテクチャの構築

多くのエンジニアが「SolidWorksの自動化」を、単なる繰り返しの作業をプログラムに置き換える作業だと誤解している。しかし、真のエンタープライズ・レベルの自動化とは、単なるマクロの集合体ではない。それは、外部データという「意志」を、SolidWorksという「肉体」に流し込み、寸分の狂いもなく「成果物」へと変換する、決定論的なパイプラインの構築である。

本稿では、SQL Server等のデータベースから製品仕様を読み取り、コンフィギュレーションを切り替え、図面を自動生成・PDF化して指定のディレクトリへ仕分ける。この一連のプロセスを、メモリリークやプロセス残留を許さず、完全無人で完結させるための「極限の知見」を共有する。

1. 破綻する自動化と、設計思想の欠如

現場でよく見られる失敗例がある。それは、`For` ループの中で SolidWorks のオブジェクトを次々と生成し、ループの終端で `Set obj = Nothing` とだけ書いて満足しているコードだ。

これは、プロフェッショナルのコードではない。SolidWorks のような巨大な COM (Component Object Model) オブジェクトを扱う場合、VBA 上の変数への参照を外しただけでは、背後の COM インターフェースは解放されない。結果として、メモリ使用量は指数関数的に増大し、数件の処理後に SolidWorks は「ゾンビプロセス」と化してフリーズする。

我々が目指すべきは、「データ(DB)」「ロジック(VBA)」「プレゼンテーション(Drawing/PDF)」を完全に分離した、ステートレスな設計である。

2. メモリ管理の真髄:COM オブジェクトの明示的解放

エンタープライズ・エンジニアとして、我々は `Nothing` ではなく `ReleaseComObject` を使いこなさなければならない。

SolidWorks API において、`ModelDoc2`、`DrawingDoc`、`SelectionMgr` といったオブジェクトは、相互に複雑な参照関係を持っている。これらを適切に解体しない限り、メモリ上のヒープ領域は枯渇していく。

メモリ管理の鉄則

1. 階層的な解放: 親オブジェクト(SldWorks)から順に、子オブジェクト(ModelDoc2)、孫オブジェクト(SelectionMgr)へと、深い階層から順に明示的に解放する。
2. スコープの限定: オブジェクトの生存期間を最小限に抑える。可能であれば、関数ごとにオブジェクトを完結させる。
3. エラーハンドリングとの同期: エラー発生時、即座に `Cleanup` ラベルへジャンプし、それまで確保したすべてのオブジェクトを解放するルーチンを通るように設計する。

3. 実装:DB駆動型ファミリーチューブ・エンジン

以下に、SQL Server からのデータ取得、コンフィギュレーションの切り替え、図面生成、PDF出力、そしてファイル移動までを統合した、アーキテクチャの核となるコードを示す。

※このコードは概念を示すための高度な抽象化を行っている。実際の運用には、各環境に合わせた参照設定(ADODB, SolidWorks Type Libraries)が必要である。

' ==============================================================================
' Module: EnterpriseDrawingEngine
' Description: DB駆動型図面自動生成エンジニアリング・コア
' Author: Legendary Chief Architect
' ==============================================================================

Option Explicit

' Windows API の宣言 (ファイル操作の高速化と確実性のために使用)
Private Declare PtrSafe Function MoveFile Lib "kernel32" Alias "MoveFileA" ( _
    ByVal lpExistingFileName As String, _
    ByVal lpNewFileName As String) As Long

' 外部定数
Private Const DB_CONNECTION_STRING As String = "Provider=SQLOLEDB;Data Source=SERVER_NAME;Initial Catalog=PROD_DB;Integrated Security=SSPI;"

Sub Main()
    Dim swApp As SldWorks.SldWorks
    Dim dbConn As Object ' ADODB.Connection
    Dim rs As Object     ' ADODB.Recordset
    Dim sql As String
    
    On Error GoTo ErrorHandler

    ' 1. SolidWorks インスタンスの取得(起動していなければ起動)
    Set swApp = GetSolidWorksApplication()
    If swApp Is Nothing Then Exit Sub

    ' 2. データベース接続
    Set dbConn = CreateObject("ADODB.Connection")
    dbConn.Open DB_CONNECTION_STRING
    
    ' 3. 処理対象データの抽出(例:未出力の図面指示リスト)
    sql = "SELECT PartNumber, ConfigName, TargetFolder FROM DrawingOrders WHERE Status = 'Pending'"
    Set rs = dbConn.Execute(sql)

    ' 4. メインループ:データ駆動型プロセス
    Do While Not rs.EOF
        Debug.Print "Processing: " & rs.Fields("PartNumber").Value
        
        ' 個別の図面生成プロセスを呼び出し(メモリ管理をカプセル化)
        ProcessSingleDrawing swApp, _
                            CStr(rs.Fields("PartNumber").Value), _
                            CStr(rs.Fields("ConfigName").Value), _
                            CStr(rs.Fields("TargetFolder").Value)
        
        ' DBの状態更新(処理済みフラグの書き込み)
        dbConn.Execute "UPDATE DrawingOrders SET Status = 'Completed' WHERE PartNumber = '" & rs.Fields("PartNumber").Value & "'"
        
        rs.MoveNext
    Loop

    MsgBox "All processes completed successfully.", vbInformation

Cleanup:
    ' リソースの厳格な解放
    On Error Resume Next
    If Not rs Is Nothing Then rs.Close: Set rs = Nothing
    If Not dbConn Is Nothing Then dbConn.Close: Set dbConn = Nothing
    Set swApp = Nothing
    Exit Sub

ErrorHandler:
    MsgBox "Critical Error: " & Err.Description, vbCritical
    Resume Cleanup
End Sub

' ------------------------------------------------------------------------------
' Sub: ProcessSingleDrawing
' Description: 単一の製品に対するコンフィギュレーション切替・図面生成・PDF化
' ------------------------------------------------------------------------------
Private Sub ProcessSingleDrawing(ByRef swApp As SldWorks.SldWorks, _
                                ByVal partNo As String, _
                                ByVal configName As String, _
                                ByVal targetFolder As String)
    
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim swPart As SldWorks.PartDoc
    Dim partPath As String
    Dim templatePath As String
    Dim pdfPath As String
    Dim errorFlag As Boolean
    
    On Error GoTo SubError
    
    ' パス構築(実際は管理テーブルから取得すべき)
    partPath = "C:\CAD_Data\Parts\" & partNo & ".SLDPRT"
    templatePath = "C:\CAD_Templates\Standard_A3.drwdot"
    pdfPath = targetFolder & "\" & partNo & ".pdf"

    ' A. 3Dモデルのロードとコンフィギュレーション切替
    Set swModel = swApp.OpenDoc6(partPath, swDocPART, swOpenDocOptions_Silent, "", 0, 0)
    If swModel Is Nothing Then Err.Raise 1001, , "Failed to open part: " & partNo
    
    ' コンフィギュレーションの強制切り替え
    Dim status As Boolean
    status = swModel.ShowConfiguration2(configName)
    If Not status Then Err.Raise 1002, , "Config not found: " & configName

    ' B. 図面テンプレートの新規作成
    Set swDraw = swApp.NewDocument(templatePath, 0, 0, 0)
    If swDraw Is Nothing Then Err.Raise 1003, , "Failed to create drawing"
    
    ' C. ビューの自動配置(モデル参照の確立)
    ' ※ここでは簡略化しているが、実際には座標計算やスケール制御が必要
    Dim swView As SldWorks.View
    Set swView = swDraw.CreateDrawViewFromModelView3(partPath, "*Isometric", 0.1, 0.1, 0)
    
    ' D. PDF出力
    ' SaveAs を使用して PDF 形式でエクスポート
    Dim exportData As Object
    Set exportData = swDraw.Extension.GetExportFileData(swExportData_currentPage, "")
    
    Dim errors As Long, warnings As Long
    Dim result As Boolean
    result = swDraw.Extension.SaveAs(pdfPath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, exportData, errors, warnings)
    
    If Not result Then Err.Raise 1004, , "PDF Export failed"

    ' E. ファイルの移動/整理 (Windows API を使用して高速に処理)
    ' 必要に応じて、生成された図面ファイル自体も移動させる
    
SubError:
    If Err.Number <> 0 Then
        Debug.Print "Error in " & partNo & ": " & Err.Description
        errorFlag = True
    End If

    ' --- 徹底的なオブジェクト解放 ---
    ' 階層を下から順に明示的に解放する
    If Not swView Is Nothing Then Set swView = Nothing
    If Not swDraw Is Nothing Then Set swDraw = Nothing
    If Not swModel Is Nothing Then 
        swApp.CloseDoc swModel.GetTitle
        Set swModel = Nothing
    End If
    
    If errorFlag Then Err.Raise Err.Number, , Err.Description
End Sub

' ------------------------------------------------------------------------------
' Function: GetSolidWorksApplication
' Description: 実行中のSolidWorksインスタンスを確実に捕捉する
' ------------------------------------------------------------------------------
Private Function GetSolidWorksApplication() As SldWorks.SldWorks
    Dim swApp As Object
    On Error Resume Next
    Set swApp = GetObject(, "SldWorks.Application")
    If swApp Is Nothing Then
        Set swApp = CreateObject("SldWorks.Application")
        swApp.Visible = True
    End If
    Set GetSolidWorksApplication = swApp
End Function

4. 実践的な設計の要諦

コンフィギュレーションの整合性

DBから渡される `ConfigName` が、3Dモデル側に存在しない場合、プロセスは即座にクラッシュする。これを防ぐには、`swModel.GetConfigurationNames` を用いて、事前チェックを行うロジックを組み込むべきだ。これは「防衛的プログラミング」の基本である。

Windows API によるファイル操作

VBA 標準の `FileCopy` や `Name` ステートメントは、ネットワークドライブやレガシーなファイルシステムにおいて、エラーハンドリングが不十分な場合がある。`kernel32.dll` の `MoveFile` を呼び出すことで、OS レベルの原子的な操作を保証し、パフォーマンスを極限まで高めることができる。

ロギングとトレーサビリティ

完全無人システムにおいて、最も恐ろしいのは「静かな失敗」である。
エラーが発生した際、単に `MsgBox` を出すのではなく、エラー内容、タイムスタンプ、失敗したPartNumber、および SolidWorks のエラーコードを、DB上のログテーブルに書き戻す仕組みを必ず実装せよ。これにより、システム管理者は翌朝、ログを確認するだけで、どの設計データに不備があったかを即座に特定できる。

結論

図面の自動生成を「単なる作業の自動化」から「エンタープライズ・ソリューション」へと昇華させるには、SolidWorks API の知識だけでは足りない。オブジェクトのライフサイクル、メモリの挙動、OS レベルのファイル操作、そしてデータの整合性。これらすべてのレイヤーに対して、アーキテクトとしての視点を持つことが不可欠である。

これこそが、伝説的なエンジニアが築き上げる、真に堅牢な自動化の世界である。

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