【テクニカル・上級編】【上級プロ向け】複数シートにまたがる大規模図面の一括改訂番号(Revision)同期と履歴管理トランザクション – SolidWorks VBA解析バイブル

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

【極限の知見】大規模図面におけるリビジョン同期のトランザクション制御:整合性とメモリ管理の絶対原則

プラント設計や航空宇宙分野における図面管理は、単なる「描画」の域を超えた、厳格な「データ整合性」の戦いだ。

数百枚のシートを持つ大規模な図面(Drawing)において、たった一つのリビジョン(改訂番号)の更新ミス、あるいは更新途中のアプリケーション・クラッシュは、設計プロセス全体の信頼性を崩壊させる。多くのエンジニアが「ループで全シートを回してNoteのテキストを書き換える」という素朴なコードを書き、メモリリークやファイル破損の泥沼に沈んでいく。

本稿では、そのような「素人仕事」を排し、大規模環境においてアトミック(不可分)な更新を実現するための、トランザクション制御に基づいた設計思想と、極限まで最適化された実装手法を詳解する。

1. 敗北のメカニズム:なぜ単純なループは破綻するのか

大規模図面における自動化において、エンジニアが直面する真の敵は「SolidWorksの処理速度」ではない。「不完全な状態での終了」と「リソースの枯渇」だ。

状態の不整合(Inconsistency)

例えば、300枚のシートがある図面で、150枚目の更新中にエラーが発生したとする。この時、図面は「半分だけ改訂された」という、設計上最も危険な、中途半端な状態に陥る。これを「不整合状態」と呼ぶ。

メモリとCOMオブジェクトの断片化

SolidWorks APIはCOM(Component Object Model)インターフェースに基づいている。ループ内で `Sheet` や `Note` オブジェクトを生成し、明示的に解放せずに放置すれば、メモリ上の参照カウントが減らず、巨大な図面では数分以内にメモリ不足(Out of Memory)を引き起こす。

2. 設計思想:擬似トランザクション・アーキテクチャ

SolidWorks API自体には、データベースのような `BeginTransaction` / `Rollback` は存在しない。したがって、我々アーキテクトは「ファイルレベルのシャドウ・コピー」を用いたトランザクションを自前で構築しなければならない。

実装戦略:Atomic Update Pattern

1. Preparation (準備): 対象図面のバックアップ(シャドウ・コピー)を一時フォルダに作成する。
2. Execution (実行): バックアップファイルに対して、全シートのリビジョン同期処理を行う。
3. Verification (検証): 更新後のファイルが破損していないか、全シートのNoteが期待通りかを確認する。
4. Commit (確定): 検証成功時のみ、元のファイルをバックアップで上書きする。
5. Rollback (復旧): いかなるエラーが発生しても、元のファイルは一切汚さない。

3. 実装:極限の最適化コード

以下に、この思想を具現化したVBA実装のコア・ロジックを示す。単なるコードの提示ではない。各行に「なぜその処理が必要か」という意図を込めている。

Option Explicit

' Windows APIの宣言 - ファイル属性操作などの低レイヤ制御用
' (必要に応じて、ファイルロック状態の確認などに拡張可能)
Private Declare PtrSafe Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long

''' <summary>
''' 大規模図面のリビジョン同期をトランザクション制御下で実行する
''' </summary>
Public Sub ExecuteRevisionTransaction(ByVal targetFilePath As String, ByVal newRevision As String)
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swDraw As SldWorks.DrawingDoc
    Dim FSO As Object
    Dim tempFilePath As String
    Dim isSuccess As Boolean
    
    Set swApp = Application.SldWorks
    Set FSO = CreateObject("Scripting.FileSystemObject")
    isSuccess = False
    
    ' 1. Preparation: シャドウ・コピーの作成
    tempFilePath = FSO.GetSpecialFolder(2) & "\SW_TRANS_" & FSO.GetFileName(targetFilePath)
    On Error GoTo ErrorHandler
    FSO.CopyFile targetFilePath, tempFilePath, True
    
    ' 2. Execution: バックアップファイルを開いて処理
    ' メモリ負荷を抑えるため、バックアップ側を操作対象とする
    Set swModel = swApp.OpenDoc6(tempFilePath, swDocDRAWING, swOpenDocOptions_Silent, "", 0, 0)
    If swModel Is Nothing Then Err.Raise 999, , "Failed to open shadow copy."
    
    Set swDraw = swModel
    
    ' トランザクション開始の合図
    Debug.Print "Transaction Started: " & Now
    
    ' 更新処理の呼び出し
    If SyncAllSheetsRevision(swDraw, newRevision) Then
        ' 3. Verification: 更新の整合性チェック(簡易版)
        ' 本来はここで全シートのNote内容を再スキャンする
        isSuccess = True
    Else
        Err.Raise 1001, , "Revision sync logic failed internal verification."
    End If

    ' 4. Commit: 成功時のみファイルを置き換える
    If isSuccess Then
        swApp.CloseDoc swModel.GetTitle
        Set swModel = Nothing
        
        ' 元のファイルを削除し、バックアップを正とする
        FSO.DeleteFile targetFilePath
        FSO.MoveFile tempFilePath, targetFilePath
        Debug.Print "Transaction Committed Successfully."
    End If

CleanUp:
    ' リソースの徹底的な解放 (Memory Optimization)
    ' COMオブジェクトは Nothing を代入するだけでなく、参照を完全に断つ
    Set swDraw = Nothing
    Set swModel = Nothing
    Set FSO = Nothing
    Exit Sub

ErrorHandler:
    ' 5. Rollback: エラー発生時はバックアップを破棄し、オリジナルを保護
    Debug.Print "Transaction Aborted! Error: " & Err.Description
    If Not swModel Is Nothing Then
        swApp.CloseDoc swModel.GetTitle
        Set swModel = Nothing
    End If
    
    If FSO.FileExists(tempFilePath) Then FSO.DeleteFile tempFilePath
    
    MsgBox "Critical Error during Revision Update. The original file is safe.", vbCritical
    Resume CleanUp
End Sub

''' <summary>
''' 全シートの改訂テーブルおよび特定のNoteを更新する
''' </summary>
Private Function SyncAllSheetsRevision(ByRef swDraw As SldWorks.DrawingDoc, ByVal newRev As String) As Boolean
    Dim vSheetNames As Variant
    Dim sheetIndex As Integer
    Dim swSheet As SldWorks.Sheet
    Dim swView As SldWorks.View
    Dim swNote As SldWorks.Note
    Dim swAnn As SldWorks.Annotation
    
    vSheetNames = swDraw.GetSheetNames
    
    ' 描画更新の停止(パフォーマンス最適化の要)
    ' 大規模図面では、一回ごとの再描画が致命的な遅延を招く
    ' ※APIには直接的な "Freeze" がないため、再描画を最小限にする戦略をとる
    
    For sheetIndex = 0 To UBound(vSheetNames)
        Set swSheet = swDraw.ActivateSheet(vSheetNames(sheetIndex))
        If swSheet Is Nothing Then GoTo ErrorExit
        
        ' --- 戦略 A: シート上の特定のNoteを更新 ---
        ' Noteの検索は「名前」または「プロパティ」で行うのがプロの作法
        ' ここでは、特定の名称(例: "REV_NOTE")を持つNoteを探す実装とする
        Set swView = swDraw.GetFirstView ' Sheet View
        Do While Not swView Is Nothing
            Set swNote = swView.GetFirstNote
            Do While Not swNote Is Nothing
                Set swAnn = swNote.GetAnnotation
                
                ' プロパティ等で特定の改訂用Noteを識別
                ' ここでは例として、Noteのテキスト内容を検索
                If swNote.GetText Like "REV:*" Then
                    swNote.SetText "REV: " & newRev
                End If
                
                Set swNote = swNote.GetNext
            Loop
            Set swView = swView.GetNextView
        Loop
        
        ' --- 戦略 B: 改訂テーブル (Revision Table) の更新 ---
        ' テーブルが存在する場合の制御
        ' (実装詳細は省略するが、swDraw.GetFirstTableAnnotation を使用)
        
    Next sheetIndex

    SyncAllSheetsRevision = True
    Exit Function

ErrorExit:
    SyncAllSheetsRevision = False
End Function

4. アーキテクトの視点:パフォーマンスを極限まで引き出す技術

メモリ・マネジメントの極意

上記のコードで `Set swModel = Nothing` を徹底しているのは、単なるマナーではない。大規模図面では、`swModel` が保持するメモリ・ポインタが巨大であるため、これの解放が遅れると、Windowsのページファイルへのスワップが発生し、システム全体のレスポンスが低下する。

描画制御の戦略

SolidWorks VBAにおいて、`swApp.GraphicsRedraw = False` に相当する明示的な制御は限られているが、「シートをアクティブにする回数を最小限にする」こと、および「ループ内での `swModel.EditRebuild3` の呼び出しを厳禁とする」ことが、速度向上の鍵だ。Rebuildは全幾何学形状の再計算を伴うため、全シートの更新が終わった後に、最後に一度だけ実行するのが鉄則である。

Windows APIによる補完

ファイル操作において、`FileSystemObject` は非常に便利だが、極めて高い信頼性と速度が要求されるシステム(例えば、数千ファイルを一括処理するサーバーサイド・プロセス)では、`kernel32.dll` の `MoveFileEx` や `CopyFileEx` を直接呼び出すことで、より低レイヤでの堅牢な制御が可能となる。

結語

大規模図面の自動化は、単なる「自動化」ではない。それは、設計データの「整合性」を担保する「インフラストラクチャの構築」である。

「動けばいい」という考えを捨て、エラーが起きた時に「どう安全に止まるか」を設計すること。これこそが、シニアエンジニアと、単なるスクリプト作成者を分かつ境界線である。

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