SolidWorks VBAを掌握する極限の知見
【マルチドキュメント管理】Documentsファイルコレクションを巡回した複数図面の一括印刷自動化
開発現場のリーダーである私に、よくこんな相談が持ち込まれる。
「設計変更に伴い、数十枚、あるいは数百枚の図面(`.slddrw`)を急遽再印刷しなければならない。しかし、1枚ずつ開いてプリンターの設定を確認し、印刷ボタンを押す作業だけで何時間も奪われている。なんとかならないか?」
手作業による印刷地獄。これはエンジニアの創造的な時間を奪う最悪の無駄だ。
そして、この課題を安易なVBAのループ処理で解決しようとし、「SolidWorksがフリーズした」「メモリリークでPCがクラッシュした」「バックグラウンドでプロセスがゾンビ化した」という壁にぶつかる者も後を絶たない。
今回は、SolidWorks APIのオブジェクトモデルの挙動、特にメモリ管理とドキュメントのライフサイクルを完全に掌握したプロフェッショナルだけが書ける、「極限まで堅牢で実用的な複数図面一括印刷自動化マクロ」の全貌を伝授する。
—
なぜ素人のVBAコードはSolidWorksを破壊するのか?
多くの初学者は、ネットから拾ってきたコードを継ぎ接ぎし、次のようなアンチパターンを実装してしまう。
1. `SldWorks.OpenDoc6` を乱用し、メモリを解放しない
開いたドキュメントを適切に閉じない(`CloseDoc`の失念)と、RAMは瞬時に枯渇する。SolidWorksは1つのドキュメントを開くだけでも膨大なリソースを消費する怪物なのだ。
2. アクティブドキュメントへの依存
`Set swModel = swApp.ActiveDoc` のようなコードは、ユーザーが途中でマウスクリックや別ウィンドウの操作を行った瞬間に破綻する。
3. エラーハンドリングの欠如
破損した図面や参照切れの図面に当たった際、マクロがダイアログで完全停止し、夜間のバッチ処理や放置プレイが台無しになる。
これらを完全にクリアし、「指定フォルダ内の図面を、メモリリークなしで、バックグラウンドに近い挙動で完全自動印刷し、ログを残す」プロダクションコードを提示しよう。
—
プロダクションコード:一括印刷自動化エンジン
以下のコードは、エラーハンドリング、ファイルシステムオブジェクト(FSO)による堅牢なパス走査、そして何よりも「確実にドキュメントを破棄するメモリ管理」を実装した、そのまま現場で使える実戦仕様である。
Option Explicit
‘ ==============================================================================
‘ 担当者必携:SolidWorks 図面一括高速印刷マクロ (Production Grade)
‘ Logic & Architecture by 首席チーフアーキテクト
‘ ==============================================================================
Public Sub BatchPrintDrawings()
‘ — 1. 定数定義 —
Const TARGET_FOLDER As String = “C:\Projects\TargetDrawings\” ‘ 対象フォルダのパス
Const PRINTER_NAME As String = “” ‘ 空欄の場合はデフォルトプリンター
Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swDraw As SldWorks.DrawingDoc
Dim fso As Object
Dim targetFolderObj As Object
Dim fileObj As Object
Dim lErrors As Long
Dim lWarnings As Long
Dim successCount As Long
Dim errorCount As Long
Dim startTime As Double
startTime = Timer
‘ — 2. SolidWorks アプリケーションの取得 —
Set swApp = Application.SldWorks
If swApp Is Nothing Then
MsgBox “SolidWorksが起動していません。”, vbCritical, “致命的エラー”
Exit Sub
End If
‘ — 3. FileSystemObjectによるフォルダ検証 —
Set fso = CreateObject(“Scripting.FileSystemObject”)
If Not fso.FolderExists(TARGET_FOLDER) Then
MsgBox “指定されたフォルダが存在しません: ” & TARGET_FOLDER, vbCritical, “パスエラー”
Exit Sub
End If
Set targetFolderObj = fso.GetFolder(TARGET_FOLDER)
‘ 処理中の画面描画を停止し、パフォーマンスを爆発的に向上させる
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swInteractiveMode, False
swApp.Visible = True ‘ 完全に隠すと一部の印刷ドライバが死ぬため表示は維持
successCount = 0
errorCount = 0
‘ — 4. ファイルコレクションの巡回 —
For Each fileObj In targetFolderObj.Files
‘ 拡張子が .slddrw のファイルのみをターゲットにする
If LCase(fso.GetExtensionName(fileObj.Name)) = “slddrw” Then
Dim filePath As String
filePath = fileObj.Path
On Error GoTo ErrorHandler
‘ 【重要】Silentモードでドキュメントを開く(ダイアログによる停止を防ぐ)
‘ swOpenDocOptions_Silent = 1
Set swModel = swApp.OpenDoc6(filePath, swDocumentTypes_e.swDocDRAWING, swOpenDocOptions_Silent, “”, lErrors, lWarnings)
If Not swModel Is Nothing Then
Set swDraw = swModel
‘ プリンター設定の適用(必要に応じてここでページ設定を上書き可能)
‘ 例: swDraw.SetPrintPageSize などのAPIをここに挟む
‘ 印刷実行 (全ページ印刷)
‘ 引数: 印刷部数, ページ指定文字列(空欄は全ページ), カラー/モノクロ設定等
Dim printSetting As Object
Set printSetting = swApp.GetPrintSpecification()
If PRINTER_NAME <> “” Then
printSetting.Printer = PRINTER_NAME
End If
printSetting.PrintToFile = False
printSetting.Collate = True
‘ 印刷の実行
Dim printResult As Boolean
printResult = swModel.PrintDoc3(printSetting, 0, 0)
If printResult Then
successCount = successCount + 1
Else
errorCount = errorCount + 1
Debug.Print “[印刷失敗] ” & filePath
End If
‘ 【最重要ライフサイクル管理】開いたドキュメントを即座に完全閉鎖する
‘ メモリリークを防ぐため、SaveWithoutPrompt (変更を保存しない) で閉じる
swApp.CloseDoc swModel.GetTitle
Else
errorCount = errorCount + 1
Debug.Print “[ファイルオープン失敗] ” & filePath & ” (Errorコード: ” & lErrors & “)”
End If
On Error GoTo 0
End If
Next fileObj
CleanUp:
‘ — 5. 終了処理と環境復元 —
swApp.SetUserPreferenceToggle swUserPreferenceToggle_e.swInteractiveMode, True
Dim elapsedTime As Double
elapsedTime = Timer – startTime
MsgBox “一括印刷プロセスが完了しました。” & vbCrLf & _
“成功: ” & successCount & ” 件” & vbCrLf & _
“失敗: ” & errorCount & ” 件” & vbCrLf & _
“処理時間: ” & Format(elapsedTime / 60, “0.0”) & ” 分”, _
vbInformation, “処理完了”
Exit Sub
ErrorHandler:
‘ 予期せぬ例外発生時でもSolidWorksがインタラクティブモードに戻らなくなるのを防ぐ
errorCount = errorCount + 1
Debug.Print “[例外発生] Path: ” & filePath & ” / Error: ” & Err.Description
‘ 念のためドキュメントが残っていれば閉じる試行
On Error Resume Next
If Not swModel Is Nothing Then
swApp.CloseDoc swModel.GetTitle
End If
On Error GoTo 0
Resume Next
End Sub
—
アーキテクトが解説する、このコードの勝負ポイント
1. `swOpenDocOptions_Silent` による無人化の担保
実務の現場において、古い図面を開いた瞬間に現れる「参照が見つかりません」「モデルのコンフィギュレーションが更新されています。保存しますか?」といったダイアログは、自動化の最大の敵だ。
`OpenDoc6` のオプションに `swOpenDocOptions_Silent` を指定することで、これらのポップアップを完全に無視し、デフォルト動作で強制的にロードさせることができる。
2. `swApp.SetUserPreferenceToggle` によるインタラクティブ制御
`swInteractiveMode` を `False` に設定すると、ファイルを開く・閉じる際の画面描画やUIの更新が抑制される。これにより、処理速度が文字通り数倍〜十数倍に跳ね上がり、画面のちらつきによるストレスからも解放される。
3. ゾンビプロセスを生み出さない例外設計 (`ErrorHandler`)
ファイルが破損している、あるいは他のユーザーによって排他制御(ロック)されている場合、APIは容赦なくランタイムエラーを吐く。
このコードでは、`On Error GoTo ErrorHandler` によってループが途中で途切れるのを防ぎ、エラーをイミディエイトウィンドウにダンプした上で、次のファイルへ強制的に処理をコンティニューする設計にしている。さらに、例外時でも必ず開いたモデルを閉じるクリーンアップ機構を備えているため、メモリリークの心配は微塵もない。
—
データベースやPLM連携への拡張性
今回はローカルフォルダの巡回に絞ったが、実務の現場では「SQL ServerやExcel管理台帳(CSV)から本日の対象図面リストを取得し、そのパス配列だけをループさせる」というアプローチへ容易に拡張できる。
FileSystemObjectの部分を、データベースから取得したパスの配列(Array)に置き換えるだけで、「社内ニッチなPLMシステムから直接図面をサイレント一括印刷する特製エンジン」へと昇華する。
結びにかえて
自動化とは、単に手作業を置き換えることではない。
「ヒューマンエラーの完全撲滅」と「エンジニアが本来向き合うべき設計品質へのリソース集中」を成し遂げるための投資である。
このコードをあなたの環境に導入し、毎日の苦痛だった印刷作業をボタン一つで終わらせる快感をぜひ味わってほしい。SolidWorks APIを掌握した者だけが、真の効率化の果実を手にすることができるのだ。
