脱・マクロ職人:外部DB連動型「型番駆動ファミリーチューブ」構築の設計思想
「マクロを作りました。これで作業は一瞬で終わります」
もし君が、クライアントや上司にそう報告しようとしているのなら、今すぐその言葉を飲み込むべきだ。それは「自動化」ではない。ただの「不安定な自動記録」に過ぎない。
真のエンタープライズ・オートメーションとは、「データが変化しても、システムが自律的に整合性を保ち、エラーを自己検知し、完遂する」ことを指す。
今回扱うテーマは、SQL ServerやExcelといった外部データベース(Single Source of Truth: 信頼できる唯一の情報源)から製品仕様を吸い上げ、SolidWorksのコンフィギュレーションを切り替え、それに対応する図面を生成・配置・PDF化・自動仕分けまで行う、いわゆる「型番駆動型ファミリーチューブ」の構築だ。
この記事では、単なるコードの書き方ではなく、プロフェッショナルが実践する「破綻しない設計」と「APIの極限制御」について伝授する。
1. アーキテクチャ設計:関心の分離(Separation of Concerns)
初心者は、一つのプロシージャの中に「DB接続」「SolidWorks操作」「ファイル保存」をすべて書き込む。これは設計として最悪だ。DBの仕様が変わっただけで、SolidWorksの操作ロジックまで壊れることになる。
堅牢なシステムを構築するには、以下の3つのレイヤーに分離せよ。
1. Data Access Layer (DAL): 外部DB(SQL/Excel)から、設計パラメータ(型番、寸法、構成要素)を「純粋なデータ」として取得する。
2. Business Logic Layer (BLL): 取得したデータに基づき、「どのモデルの、どのコンフィギュレーションを、どのテンプレートで展開すべきか」という意思決定を行う。
3. Automation/Driver Layer (AL): SolidWorks APIを叩き、実際にモデルを動かし、図面を生成する。
この分離により、テストが容易になり、保守性が劇的に向上する。
2. 実装の急所:SolidWorks APIを掌握する
図面自動生成において、多くの開発者が陥る罠が3つある。
① コンフィギュレーションの同期不全
モデルのコンフィギュレーションを切り替えた後、図面ビューがその変更を正しく認識していないケースだ。図面ビューの `ReferencedConfiguration` プロパティを明示的に制御しなければ、図面は「古い構成」を表示し続ける。
② ビュー配置の座標計算
「なんとなく」でビューを置くのではない。テンプレート図面のシートフォーマットに基づき、基準点(Origin)からの相対座標を計算して配置せよ。
③ リビルドのコスト管理
`ForceRebuild3` は強力だが、重い。ループ内で不必要に呼び出すと、処理時間は指数関数的に増大する。必要なタイミング、必要なオブジェクトに対してのみ実行するのがプロの作法だ。
3. プロダクション・コード・テンプレート
以下に、実務レベルでそのまま構造として利用できる、堅牢なVBAコードの設計例を示す。ここでは簡略化のため、DB接続部は概念的な関数としているが、構造はそのまま利用できる。
Option Explicit
' ==============================================================================
' プロジェクト: Model-Driven Drawing Automation
' 役割: 型番駆動による図面一括生成エンジン
' 著者: Chief Architect
' ==============================================================================
' 定数定義:マジックナンバーを排除し、保守性を高める
Private Const DRAWING_TEMPLATE_PATH As String = "C:\Standard\Templates\Drawing_A3_ISO.drwdot"
Private Const OUTPUT_ROOT_DIR As String = "C:\Output\Project_Alpha\"
' 列挙型:状態管理を明確にする
Enum ProcessStatus
Status_Success = 0
Status_Error_DB = 1
Status_Error_SW_Model = 2
Status_Error_SW_Drawing = 3
Status_Error_IO = 4
End Enum
''' <summary>
''' メインコントローラー:全体のオーケストレーションを担当
''' </summary>
Public Sub ExecuteBatchProcess()
Dim swApp As SldWorks.SldWorks
Set swApp = Application.SldWorks
Dim targetList As Collection
Set targetList = FetchTargetConfigurationsFromDB() ' DAL層の呼び出し
Dim item As Variant
Dim currentStatus As ProcessStatus
Debug.Print "--- Batch Process Started: " & Now & " ---"
' ループ内でのエラーハンドリング:一つの失敗で全体を止めない
For Each item In targetList
' itemはDictionary形式を想定 (Key: PartPath, Value: ConfigName)
currentStatus = ProcessSingleUnit(swApp, item)
If currentStatus <> Status_Success Then
Debug.Print "FAILED: " & item("PartName") & " | Error Code: " & currentStatus
' ここでエラーログをDBやファイルに書き出す設計にせよ
Else
Debug.Print "SUCCESS: " & item("PartName")
End If
Next item
Debug.Print "--- Batch Process Completed ---"
End Sub
''' <summary>
''' 単一ユニットの処理:BLL層のロジック
''' </summary>
Private Function ProcessSingleUnit(swApp As SldWorks.SldWorks, data As Object) As ProcessStatus
On Error GoTo ErrorHandler
Dim modelPath As String: modelPath = data("Path")
Dim configName As String: configName = data("Config")
Dim partName As String: partName = data("PartName")
' 1. モデルのロードとコンフィギュレーション切り替え
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.OpenDoc6(modelPath, swDocPART, swOpenDocOptions_Silent, "", 0, 0)
If swModel Is Nothing Then GoTo Err_Model
' コンフィギュレーションの切り替え
Dim swConfMgr As SldWorks.ConfigurationManager
Set swConfMgr = swModel.ConfigurationManager
Dim swConf As SldWorks.Configuration
Set swConf = swConfMgr.ActiveConfiguration
' 重要:コンフィギュレーションの強制切り替え
Dim res As Boolean
res = swModel.ShowConfiguration2(configName)
If Not res Then GoTo Err_Model
swModel.ForceRebuild3 True
' 2. 図面の生成
Dim swDrawing As SldWorks.DrawingDoc
Set swDrawing = swApp.NewDocument(DRAWING_TEMPLATE_PATH, 0, 0, 0)
If swDrawing Is Nothing Then GoTo Err_Drawing
' 3. ビューの配置(プロのテクニック:座標指定)
' ここでは例として、正面図を(0.1, 0.1)に配置
Dim swView As SldWorks.View
Set swView = swDrawing.CreateDrawViewFromModelView3(modelPath, "*Front", 0.1, 0.1, 0)
If Not swView Is Nothing Then
' 重要:図面ビューが参照するコンフィギュレーションを明示的に指定
swView.ReferencedConfiguration = configName
swDrawing.ForceRebuild3 True
Else
GoTo Err_Drawing
End If
' 4. PDF出力とファイル仕分け
Dim saveDir As String: saveDir = OUTPUT_ROOT_DIR & partName & "\"
Call EnsureDirectoryExists(saveDir)
Dim pdfPath As String: pdfPath = saveDir & partName & "_" & configName & ".pdf"
Dim swExportData As SldWorks.ExportPdfData
Set swExportData = swDrawing.CreateExportPdfData
' PDF保存実行
Dim swDrawExt As SldWorks.ModelDocExtension
Set swDrawExt = swDrawing.Extension
Dim boolStatus As Boolean
boolStatus = swDrawExt.SaveAs(pdfPath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, swExportData, 0, 0)
If Not boolStatus Then GoTo Err_IO
' クリーンアップ
swApp.CloseDoc swDrawing.GetTitle
swApp.CloseDoc swModel.GetTitle
ProcessSingleUnit = Status_Success
Exit Function
Err_Model:
ProcessSingleUnit = Status_Error_SW_Model
Exit Function
Err_Drawing:
ProcessSingleUnit = Status_Error_SW_Drawing
Exit Function
Err_IO:
ProcessSingleUnit = Status_Error_IO
Exit Function
ErrorHandler:
Debug.Print "Unexpected Error: " & Err.Description
ProcessSingleUnit = Status_Error_IO
End Function
' --- 以下、ユーティリティ関数(DAL/IO層) ---
Private Function FetchTargetConfigurationsFromDB() As Collection
' 本来はここを ADODB.Connection を用いて SQL Server へ接続する
' ここではデモ用に静的なコレクションを返す
Dim col As New Collection
Dim dict As Object
' Mock Data 1
Set dict = CreateObject("Scripting.Dictionary")
dict.Add "Path", "C:\Models\BasePart.SLDPRT"
dict.Add "Config", "Small_Size"
dict.Add "PartName", "BasePart_S"
col.Add dict
' Mock Data 2
Set dict = CreateObject("Scripting.Dictionary")
dict.Add "Path", "C:\Models\BasePart.SLDPRT"
dict.Add "Config", "Large_Size"
dict.Add "PartName", "BasePart_L"
col.Add dict
Set FetchTargetConfigurationsFromDB = col
End Function
Private Sub EnsureDirectoryExists(ByVal folderPath As String)
' フォルダが存在しなければ作成する(WinAPIまたはFileSystemObjectを使用)
If Dir(folderPath, vbDirectory) = "" Then
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
' 再帰的に作成する場合は、さらに高度なロジックが必要
' ここでは簡易的に作成
MsgBox "Directory Creation Logic Required: " & folderPath
End If
End Sub
4. エンタープライズ運用における「鉄則」
このコードをベースに、実務へ投入する際は以下の3点を必ず検討せよ。
1. ログの永続化
`Debug.Print` は開発用だ。本番環境では、処理結果(成功・失敗、エラー内容、実行時間)を必ずCSVまたはSQL Serverのログテーブルに書き出せ。これがないと、夜間に回した自動化が失敗した際、原因究明に丸一日を費やすことになる。
2. ネットワーク・レイテンシへの配慮
DBやモデルファイルがネットワークドライブ上にある場合、`OpenDoc6` の速度は劇的に低下する。大量のファイルを処理する場合、一度ローカルの高速なSSDに同期(キャッシュ)してから処理を開始する設計にせよ。
3. 「例外」の定義
「モデルファイルはあるが、指定したコンフィギュレーションが存在しない」
「図面テンプレートが移動している」
「ネットワークが一時的に切断された」
これらは「バグ」ではなく「想定される例外」だ。例外が発生した際に、システムを「停止」させるのか、「スキップして次へ進む」のか。このポリシーを設計段階で決定しておくこと。
結論
自動化エンジニアの価値は、コードの行数ではなく、「そのシステムがいかに堅牢で、いかにビジネスの変更に強いか」で決まる。
単なるマクロの書き手で終わるな。データとモデルのライフサイクルを制御する、アーキテクトであれ。
