マクロ記録の限界を超えろ:BOMテーブルを自在に操る「セル走査」の極意
こんにちは。設計自動化の世界へようこそ。
SolidWorksで図面を作成していると、必ずと言っていいほど直面する壁があります。それが「部品表(BOM)のカスタマイズ」です。
「標準のBOMでは、重量の単位を社内規定の数値に変換して表示できない…」
「特定の材質の時だけ、備考欄に『要熱処理』と自動入力したい…」
マクロの記録機能を使って「セルを書き換える」操作を記録しようとしても、うまくいかない。あるいは、記録されたコードが「特定のセル番地(A5など)」を直接指定していて、行が増減すると全く使い物にならない。
もしあなたが今、そんな壁にぶつかっているなら、おめでとうございます。あなたは「単なる操作の記録」から「プログラムによるロジックの実装」へとステップアップする境界線に立っています。
今日は、BOMテーブルを「セル番地」ではなく「構造(オブジェクト)」として捉え、中身を自動計算・更新する、実務直結のテクニックを伝授しましょう。ここをクリアすれば、SolidWorks VBAの基本はバッチリですよ。
1. 思考の転換:セル番地ではなく「走査(スキャン)」せよ
マクロ記録から脱却できない人が陥る最大の罠は、「A列の5行目」という固定的な考え方です。図面の設計変更で部品が増えた瞬間、そのコードはゴミになります。
プロのエンジニアはこう考えます。
「BOMテーブルという箱を見つけ、その中の『重量』という見出しがある列を探し、そこから下の行を一行ずつ順番に見ていく」
これをプログラミング用語で「走査(スキャン)」と呼びます。
「何行目か」を知らなくても、「データの終わりまでループする」という書き方をすれば、部品数が10個でも1000個でも、コードは完璧に動作します。
2. 実践コード:BOMの特定カラムを自動更新する
では、具体的なコードを見ていきましょう。
今回のシナリオは、「BOM内の『重量』カラムを探し、その値を1.1倍(安全率を考慮した値など)して書き換える」というものです。
Option Explicit
''' <summary>
''' 図面内のBOMテーブルを走査し、特定の列の値を計算して更新する
''' </summary>
Sub UpdateBOMWeightColumn()
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim swSheet As SldWorks.Sheet
Dim swTableAnn As SldWorks.TableAnnotation
Dim swBomTable As SldWorks.BomTableAnnotation
Dim vTables As Variant
Dim i As Integer, j As Integer
Dim rowCount As Long
Dim colCount As Long
Dim targetCol As Integer
Dim currentValue As Double
Dim newValue As Double
Dim colHeader As String
' --- 1. 初期設定 ---
Set swApp = Application.SldWorks
Set swModel = swApp.ActiveDoc
' 図面ドキュメントが開かれているかチェック
If swModel Is Nothing Or swModel.GetType <> swDocDRAWING Then
MsgBox "図面ファイルを開いてから実行してください。", vbCritical
Exit Sub
End If
Set swDraw = swModel
' --- 2. テーブルの取得 ---
' 図面上のすべての注釈(Annotation)からテーブルを探す
' ※ここでは簡略化のため、図面上の最初のテーブルを取得するロジックにします
' 本来はスキャンして「BOM」かどうかを判定するのがベストです
' 図面内の全てのテーブル注釈を取得
vTables = swDraw.GetFirstTableAnnotation
If IsEmpty(vTables) Then
MsgBox "図面内にテーブルが見つかりません。", vbExclamation
Exit Sub
End If
' 最初のテーブルを対象とする(実務ではループでBOMを特定する)
Set swTableAnn = vTables
' テーブルがBOM(部品表)であることを確認
If swTableAnn.Type = swTableAnnotation_Bom Then
Set swBomTable = swTableAnn
Else
MsgBox "選択されたテーブルはBOMではありません。", vbExclamation
Exit Sub
End If
' --- 3. ターゲット列の特定 ---
' 「重量」という名前のヘッダーを探す
targetCol = -1
colCount = swTableAnn.ColumnCount
rowCount = swTableAnn.RowCount
For j = 0 To colCount - 1
colHeader = swTableAnn.Text(0, j) ' 0行目はヘッダー
If colHeader = "重量" Or colHeader = "Weight" Then
targetCol = j
Exit For
End If
Next j
If targetCol = -1 Then
MsgBox "「重量」カラムが見つかりませんでした。", vbExclamation
Exit Sub
End If
' --- 4. データの走査と計算 ---
' 1行目(ヘッダー)は飛ばして、2行目から最終行までループ
For i = 1 To rowCount - 1
' セルのテキストを取得
Dim cellText As String
cellText = swTableAnn.Text(i, targetCol)
' 数値に変換可能かチェック(空文字や文字列エラー対策)
If IsNumeric(cellText) Then
currentValue = CDbl(cellText)
' --- ここに独自の計算ロジックを記述 ---
' 例:重量に1.1倍の係数をかける
newValue = currentValue * 1.1
' 書き戻し(小数点第3位まで表示するように整形)
swTableAnn.Text(i, targetCol) = Format(newValue, "0.000")
End If
Next i
' 画面を更新して結果を表示
swModel.GraphicsRedraw
MsgBox "BOMの更新が完了しました!", vbInformation
End Sub
3. コードの「魂」を解剖する:エンジニアの視点
このコードには、単なる記録にはない「堅牢さ」を持たせるための工夫が詰まっています。
① オブジェクトの階層を辿る
`swDraw.GetFirstTableAnnotation` を使って、図面の中に存在する「テーブル」というオブジェクトにアクセスしています。SolidWorks APIにおいて、テーブルは `TableAnnotation` というクラスで制御されます。これが全ての操作の入り口です。
② ヘッダー検索による「動的な列特定」
ここが最も重要なポイントです。
`For j = 0 To colCount – 1` のループを使って、1行目の各セルをチェックしています。これにより、「重量」列がA列にあろうがC列にあろうが、プログラムが自動で見つけ出します。 これが「マクロの記録」との決定的な違いです。
③ エラー回避の「防波堤」
実務のデータは常に綺麗とは限りません。
- `If swModel.GetType <> swDocDRAWING`: 図面じゃない時に実行してエラーで落ちるのを防ぐ。
- `If IsNumeric(cellText)`: セルに「欠品」などの文字が入っていた場合に、計算エラーでプログラムが停止するのを防ぐ。
これらを書くか書かないかで、あなたの作ったツールの「信頼性」が劇的に変わります。
4. 陥りやすいエラーと、プロの回避策
エラー1:インデックスの「0」と「1」の混同
SolidWorks APIの多く(テーブルの行・列など)は 0から数え始めます。
- 1行目 $\rightarrow$ `index 0`
- 1列目 $\rightarrow$ `index 0`
一方、VBAの一般的な配列や、人間が考える数え方と混同すると、「1行ずれて計算される」という恐ろしいバグを生みます。常に「APIリファレンスが0始まりか1始まりか」を確認する癖をつけましょう。
エラー2:計算後の「表示形式」問題
`swTableAnn.Text(i, targetCol) = newValue` とだけ書くと、数値が `1.23456789` のように長くなり、図面が見づらくなります。
必ず `Format(newValue, “0.00”)` のように、「人間が見て心地よい形式」に整えてからセルに戻すのが、プロの仕事です。
最後に:一歩先へ進むあなたへ
今回のコードは、あくまで「BOMの値を書き換える」というシンプルなものでした。
しかし、ここから先は無限の可能性があります。
- 「備考欄に、材質が『アルミ』なら『防錆処理』と追記する」
- 「部品の構成に基づき、特定のサブアセンブリの重量だけを倍増させる」
これらはすべて、今回学んだ「走査(ループ)」と「条件分岐(If)」の組み合わせで実現できます。
「マクロの記録」は、いわば「辞書を写す」作業です。
しかし、今回学んだ「オブジェクト操作」は、「自分の言葉で文章を書く」作業です。
言葉(ロジック)を身につければ、SolidWorksはあなたの強力な武器になります。一歩ずつ、楽しみながらコードを書いていきましょう。応援していますよ!
