【入門編】【上級プロ向け】図面内「部品表(BOM)」の構造解析:マルチレベルBOMの階層データをVBAで完全抽出してExcelへ出力 – SolidWorks VBA解析バイブル

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

【上級プロ向け】図面内「部品表(BOM)」の構造解析:マルチレベルBOMの階層データをVBAで完全抽出してExcelへ出力

「マクロの記録」を使って、なんとか自動化の第一歩を踏み出した。そんなあなたへ。
おめでとうございます。あなたは今、エンジニアリング自動化という果てしない旅の入り口に立っています。

しかし、実務の現場で求められるのは「記録された操作の再生」ではありません。
「アセンブリの構造が変わっても、瞬時に、正確に、階層構造を維持したままExcelへデータを出力する」といった、データの構造(ロジック)を理解した高度な自動化です。

今日は、SolidWorks VBAにおける最難関の一つであり、かつ最も価値の高いテーマの一つである「マルチレベルBOM(部品表)の階層抽出」について、その設計思想から実装コードまで、余すことなく伝授しましょう。

1. なぜ「マクロの記録」ではBOM抽出ができないのか?

多くの初心者が陥る罠があります。それは、「図面上のBOMテーブルを読み取ろうとする」ことです。

図面上のBOMテーブルは、あくまで「ある特定の視点」で表示された結果に過ぎません。

  • 構成部品の階層が隠されている場合がある
  • フィルタリングによって一部のデータが欠落している場合がある
  • そもそもBOMテーブルが配置されていない図面もある

プロフェッショナルな自動化エンジニアが目指すべきは、図面(Drawing)を操作することではなく、アセンブリ(Assembly)のデータ構造そのもの(Component Tree)を直接走査(Traverse)することです。

アセンブリのツリー構造を「再帰的(Recursive)」に辿ることで、図面の表示状態に左右されない、完璧なインベントリリストを作成できるのです。

2. 核心となるアルゴリズム:再帰処理(Recursion)

マルチレベルBOMを抽出するための鍵は、「再帰処理」というプログラミング技法です。

想像してみてください。大きな箱(アセンブリ)の中に、中くらいの箱(サブアセンブリ)があり、その中に小さな箱(部品)が入っている構造を。
1. 箱を開ける。
2. 中身が「部品」なら、リストに書き込む。
3. 中身が「別の箱」なら、その箱に対して再び「1」の手順(自分自身を呼び出す)を実行する。

この「自分自身を呼び出す」仕組みが再帰です。これを使えば、階層が3層でも100層でも、同じロジックで無限に深く探索できます。

3. 実装コード:階層構造を維持したExcel出力

それでは、魂を込めて書いたコードを見ていきましょう。このコードは、現在開いているアセンブリを解析し、階層(インデント)を維持したままExcelへ書き出します。

' ==============================================================================
' プロジェクト名: Multi-Level BOM Extractor
' 概要: アセンブリの階層構造を再帰的に解析し、Excelへインデント付きで出力する
' 著者: Legendary Chief Architect
' ==============================================================================

Option Explicit

' Excel操作用の変数(グローバル管理)
Dim xlApp As Object
Dim xlWB As Object
Dim xlSheet As Object
Dim currentRow As Long

Sub Main()
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swAssy As SldWorks.AssemblyDoc
    Dim swConf As SldWorks.Configuration
    Dim swRootComp As SldWorks.Component2
    
    On Error GoTo ErrorHandler

    ' 1. SolidWorksへの接続確認
    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    
    If swModel Is Nothing Then
        MsgBox "SolidWorksでアセンブリファイルを開いてください。", vbCritical
        Exit Sub
    End If
    
    If swModel.GetType <> swDocASSEMBLY Then
        MsgBox "アセンブリファイルを開いてください。", vbCritical
        Exit Sub
    End If

    ' 2. Excelの初期化
    SetExcel
    
    ' ヘッダーの作成
    xlSheet.Cells(1, 1).Value = "階層"
    xlSheet.Cells(1, 2).Value = "部品番号 (Part Number)"
    xlSheet.Cells(1, 3).Value = "部品名 (Description)"
    xlSheet.Cells(1, 4).Value = "数量 (Quantity)"
    xlSheet.Range("A1:D1").Font.Bold = True
    
    currentRow = 2
    
    ' 3. アセンブリ構造の解析開始
    Set swAssy = swModel
    Set swConf = swModel.GetConfigurationByName(swModel.ConfigurationManager.ActiveConfiguration.Name)
    Set swRootComp = swConf.GetRootComponent3(True)
    
    ' 再帰処理の開始(ルートコンポーネントから)
    ' 引数: コンポーネント, 現在の階層レベル
    TraverseComponent swRootComp, 0
    
    ' 4. 後処理
    xlSheet.Columns("A:D").AutoFit
    MsgBox "BOMの抽出が完了しました。", vbInformation
    
    Exit Sub

ErrorHandler:
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

' ------------------------------------------------------------------------------
' 関数: TraverseComponent (再帰関数)
' 役割: コンポーネントを階層的に辿り、Excelに書き込む
' ------------------------------------------------------------------------------
Private Sub TraverseComponent(swComp As SldWorks.Component2, level As Integer)
    Dim vChildren As Variant
    Dim i As Long
    Dim swChildComp As SldWorks.Component2
    Dim swModelDoc As SldWorks.ModelDoc2
    Dim partNo As String
    Dim desc As String
    
    ' 子コンポーネントのリストを取得
    vChildren = swComp.GetChildren
    
    ' 子コンポーネントがない場合は終了(末端の部品)
    If IsEmpty(vChildren) Then Exit Sub
    
    For i = 0 To UBound(vChildren)
        Set swChildComp = vChildren(i)
        
        ' 抑制(Suppressed)されているコンポーネントはスキップ
        If swChildComp.GetSuppression <> swComponentSuppressed Then
            
            ' コンポーネントの情報を取得
            Set swModelDoc = swChildComp.GetModelDoc2
            If Not swModelDoc Is Nothing Then
                ' プロパティから情報を取得(カスタムプロパティ名は環境に合わせて変更してください)
                partNo = swChildComp.ReferencedConfiguration ' 簡易的に構成名を代用
                desc = swModelDoc.GetCustomInfoValue("", "Description")
                If desc = "" Then desc = "N/A"
            Else
                partNo = "未ロード"
                desc = "N/A"
            End If
            
            ' Excelへの書き込み
            xlSheet.Cells(currentRow, 1).Value = String(level * 4, " ") & "|-- " ' インデント表現
            xlSheet.Cells(currentRow, 2).Value = partNo
            xlSheet.Cells(currentRow, 3).Value = desc
            ' ※ 数量のカウントは、実際には同一部品の出現回数を集計するロジックが必要
            xlSheet.Cells(currentRow, 4).Value = 1 
            
            currentRow = currentRow + 1
            
            ' 【重要】再帰呼び出し:自分自身を呼び出して、さらに深い階層へ
            TraverseComponent swChildComp, level + 1
        End If
    Next i
End Sub

' ------------------------------------------------------------------------------
' 関数: SetExcel
' 役割: Excelアプリケーションを起動し、ワークブックを準備する
' ------------------------------------------------------------------------------
Private Sub SetExcel()
    On Error Resume Next
    Set xlApp = GetObject(, "Excel.Application")
    If xlApp Is Nothing Then
        Set xlApp = CreateObject("Excel.Application")
    End If
    On Error GoTo 0
    
    xlApp.Visible = True
    Set xlWB = xlApp.Workbooks.Add
    Set xlSheet = xlWB.Sheets(1)
End Sub

4. コードの重要ポイント解説

このコードを理解するために、以下の3点を深く意識してください。

① 再帰呼び出しの設計 (`TraverseComponent`)

`TraverseComponent swChildComp, level + 1` という行が、このプログラムの心臓部です。
ここで自分自身を呼び出す際、`level + 1` を渡しています。これにより、「今、自分がどの深さにいるか」という情報を引き継ぎ、Excel上でのインデント(見た目の階層)を実現しています。

② オブジェクトのライフサイクルとNullチェック

`If swModelDoc Is Nothing Then` という判定を忘れてはいけません。
アセンブリ内の部品が「軽量化モード(Lightweight)」であったり、ロードされていない場合、`GetModelDoc2` は `Nothing` を返します。これを確認せずにプロパティにアクセスすると、即座に実行時エラーでプログラムが停止します。これはプロが最も気をつける「防御的プログラミング」の基本です。

③ Excel COMオートメーション

`CreateObject(“Excel.Application”)` を使用して、SolidWorksからExcelを操っています。
実務では、Excelを裏側で動かして高速化させる手法もありますが、まずは `xlApp.Visible = True` で、処理が進んでいる様子をユーザーに見せることが、使いやすいツールを作るコツです。

5. さらにステップアップするためのアドバイス

ここをクリアすれば、SolidWorks VBAの基本はバッチリですよ。しかし、真のプロフェッショナルを目指すなら、以下の課題に挑戦してみてください。

1. 数量の集計ロジック: 現状のコードは「1個」と出力していますが、アセンブリ内で同じ部品が複数ある場合、それらをカウントして集計するロジックを追加してみましょう。
2. カスタムプロパティの柔軟な取得: `GetCustomInfoValue` を使い、設計者が決めた特定のプロパティ(品番、材質、重量など)を自在に取得できるようにしましょう。
3. エラーハンドリングの強化: ネットワーク上のファイルが読み込めない場合や、Excelが編集モードになっている場合など、想定外の事態に備えた `Try-Catch` 的な処理を磨きましょう。

最後に

自動化の道は、単なる「楽をするための手段」ではありません。
「人間が本来集中すべき、創造的な設計業務に時間を戻すための、尊い投資」です。

一歩ずつ、確実に。コードの背後にある「構造」を理解していけば、あなたは必ず、SolidWorksを自由自在に操るマスターになれます。応援していますよ!

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