こちらの続きです。
同一UUIDのDraw参照元ファイルを差し替える3 - C#ATIA
まだちょっと不安定な気もしているのですが、手元のデータでは
上手く行っているので公開しておきます。
先日の組合せのファイルを読み込ませ、Partファイルと同一名の
Drawingファイルを作成します。
Option Explicit
Private Const EXP_EXTENSION = "comb"
Private Const SelectionType = "*." & EXP_EXTENSION
Private Const BAT_CATVBS = "ReplaceDrawLinkBat.catvbs"
Private Const BAT_SCRIPT = "ReplaceDrawLink"
Private Const BAT_FUNCTION = "ExecReplaceLink"
Private Const EVACUATION_NAME = "EVAC"
Private Const DELIMTER = "@"
Private Const DELIMTER_COMB = "|"
Private Const DEBUGMODE = False
Sub CATMain()
Dim msg As String
msg = "Drawリンクを修正する為のリストファイル(" & EXP_EXTENSION & ")を選択してください"
Dim lst_path As String
lst_path = CATIA.FileSelectionBox( _
msg, _
SelectionType, _
CatFileSelectionModeOpen)
If lst_path = vbNullString Then Exit Sub
Dim paths As Variant
paths = KCL.ReadFile(lst_path)
msg = UBound(paths) + 1 & "個のバッチ処理を行います。宜しいですか?"
If MsgBox(msg, vbYesNo + vbQuestion) = vbNo Then
Exit Sub
End If
Dim catPathtmp As Variant
catPathtmp = Split(CATIA.SystemService.Environ("CATDLLPath"), ";")
Dim catPath As String
catPath = catPathtmp(0)
Dim environmentPath As Variant
environmentPath = SplitPathName(CATIA.SystemService.Environ("CATEnvName"))
Dim catTmp As Variant
catTmp = CATIA.SystemService.Environ("CATTemp")
Dim macroPath As String
macroPath = catTmp & "\" & BAT_CATVBS
Dim code As String
code = GetCatvbsCode(Join(paths, DELIMTER), macroPath)
KCL.WriteFile macroPath, code
Dim cmd As String
cmd = catPath & "\CNEXT.exe -direnv " & _
environmentPath(0) & " -env " & _
environmentPath(1) & " -batch -macro " & _
Chr(34) & macroPath & Chr(34)
Call CreateObject("Wscript.Shell").exec(cmd)
MsgBox "バッチ処理をスタートしました"
End Sub
Private Function GetCatvbsCode( _
ByVal path As String, _
ByVal me_path As String) As String
Dim apc As Object
Set apc = GetApc()
Dim execPjt As Object
Set execPjt = apc.ExecutingProject
Dim pjtPath As String
pjtPath = execPjt.DisplayName
Dim code As String
code = _
"Set SS = CATIA.SystemService" & vbCrLf & _
"VBAProjectPath = " & Chr(34) & CStr(pjtPath) & Chr(34) & vbCrLf & _
"LibraryType = catScriptLibraryTypeVBAProject" & vbCrLf & _
"ScriptName = " & Chr(34) & BAT_SCRIPT & Chr(34) & vbCrLf & _
"FunctionName = " & Chr(34) & BAT_FUNCTION & Chr(34) & vbCrLf & _
"Dim Params(0)" & vbCrLf & _
"Params(0) = " & Chr(34) & path & Chr(34) & vbCrLf & _
"Call SS.ExecuteScript(VBAProjectPath, LibraryType, ScriptName, FunctionName, Params)" & vbCrLf
If Not DEBUGMODE Then
code = code & _
"CreateObject(" & Chr(34) & "Scripting.FileSystemObject" & Chr(34) & ").DeleteFile(" & _
Chr(34) & me_path & Chr(34) & ")" & vbCrLf
End If
code = code & _
"CreateObject(" & Chr(34) & "WScript.Shell" & Chr(34) & ").Popup " & Chr(34) & "Done" & _
Chr(34) & ", 0 , " & Chr(34) & "ReplaceDrawLink" & Chr(34) & " , 0"
GetCatvbsCode = code
End Function
Private Function SplitPathName(ByVal FullPath) As Variant
Dim path(1) As String
With CreateObject("Scripting.FileSystemObject")
path(0) = .GetParentFolderName(FullPath)
path(1) = .GetBaseName(FullPath)
End With
SplitPathName = path
End Function
Private Function GetApc() As Object
Set GetApc = Nothing
Dim COMObjectName$
#If VBA7 Then
COMObjectName = "MSAPC.Apc.7.1"
#ElseIf VBA6 Then
COMObjectName = "MSAPC.Apc.6.2"
#Else
MsgBox "VBAのバージョンが未対応です"
Exit Function
#End If
Dim apc As Object: Set apc = Nothing
On Error Resume Next
Set apc = CreateObject(COMObjectName)
On Error GoTo 0
If apc Is Nothing Then
MsgBox "MSAPC.Apcが取得できませんでした"
Exit Function
End If
Set GetApc = apc
End Function
Sub ExecReplaceLink(ByVal all_path As String)
Dim paths As Variant
paths = Split(all_path, DELIMTER)
Dim i As Long
Dim path As Variant
For i = 0 To UBound(paths)
path = Split(paths(i), DELIMTER_COMB)
If UBound(path) < 1 Then GoTo continue
If IsExistsFiles(path) Then
Call ReplaceLink(path(0), path(1))
End If
continue:
Next
If Not DEBUGMODE Then
CATIA.Quit
End If
End Sub
Private Sub ReplaceLink( _
ByVal tgtPartPath As String, _
ByVal refDrawPath As String)
Dim evac As String
evac = GetEvacuationPath(refDrawPath)
Dim refPartAry As Variant
refPartAry = KCL.SplitPathName(refDrawPath)
refPartAry(2) = "CATPart"
Dim refPart As String
refPart = refPartAry(0) & "\" & _
refPartAry(1) & "." & _
refPartAry(2)
Dim fso As Object
Set fso = KCL.GetFSO()
If KCL.IsExists(refPart) Then
fso.MoveFile refPart, evac & "\"
refPart = evac & "\" & _
refPartAry(1) & "." & _
refPartAry(2)
Else
refPart = vbNullString
End If
Dim tgtBackup As String
tgtBackup = tgtPartPath & ".backup"
fso.CopyFile tgtPartPath, tgtBackup
Dim tgtPartAry As Variant
tgtPartAry = KCL.SplitPathName(tgtPartPath)
Dim tmpPart As String
tmpPart = refPartAry(1) & "." & _
tgtPartAry(2)
fso.GetFile(tgtPartPath).name = tmpPart
tmpPart = tgtPartAry(0) & "\" & _
tmpPart
Dim tgtDoc As PartDocument
Set tgtDoc = CATIA.Documents.Open(tmpPart)
Dim refDoc As DrawingDocument
Set refDoc = CATIA.Documents.Open(refDrawPath)
Call UpdateUnlockViews(refDoc)
Call SaveAs(tgtDoc, tgtPartPath)
Dim tgtDraw As String
tgtDraw = tgtPartAry(0) & "\" & _
tgtPartAry(1) & ".CATDrawing"
Call SaveAs(refDoc, tgtDraw)
fso.DeleteFile tgtBackup
If Not refPart = vbNullString Then
fso.MoveFile refPart, refPartAry(0) & "\"
End If
fso.DeleteFolder evac
fso.DeleteFile tmpPart
tgtDoc.Close
refDoc.Close
End Sub
Private Sub UpdateUnlockViews( _
ByVal doc As DrawingDocument)
Dim sht As DrawingSheet
Dim v As DrawingView
For Each sht In doc.Sheets
If sht.IsDetail Then GoTo continue_sheet
For Each v In sht.Views
If v.LockStatus Then GoTo continue_view
If Not HasLink(v) Then GoTo continue_view
v.GenerativeBehavior.Update
continue_view:
Next
continue_sheet:
Next
End Sub
Private Function HasLink( _
ByVal view As DrawingView) As Boolean
HasLink = False
On Error Resume Next
Dim behv As DrawingViewGenerativeBehavior
Set behv = view.GenerativeBehavior
Dim v As Document
Set v = behv.Document.Parent
On Error GoTo 0
If v Is Nothing Then Exit Function
HasLink = True
End Function
Private Function GetEvacuationPath( _
ByVal path As String) As String
Dim evac As String
evac = KCL.GetFSO.GetParentFolderName(path) & "\" & _
EVACUATION_NAME
evac = GetNewFolderName(evac)
GetEvacuationPath = evac
KCL.GetFSO.CreateFolder evac
End Function
Private Function GetNewFolderName$(ByVal oldPath$)
Dim newPath As String
newPath = oldPath
If Not KCL.IsExists(newPath) Then
GetNewFolderName = newPath
Exit Function
End If
Dim TempName$, i&: i = 0
Do
i = i + 1
TempName = newPath + "_" + CStr(i)
If Not KCL.IsExists(TempName) Then
GetNewFolderName = TempName
Exit Function
End If
Loop
End Function
Private Function IsExistsFiles( _
ByVal ary As Variant) As Boolean
IsExistsFiles = False
Dim i As Long
For i = 0 To UBound(ary)
If Not KCL.IsExists(ary(i)) Then Exit Function
Next
IsExistsFiles = True
End Function
Private Sub SaveAs( _
ByVal doc As Document, _
ByVal path As String)
CATIA.DisplayFileAlerts = False
doc.SaveAs path
CATIA.DisplayFileAlerts = True
End Sub
最大の特徴は、マクロの実行はバッチモードで起動させたCATIA側に
処理させる点です。その為、作業を行っているCATIAのオペレーションは
マクロの起動までしか奪われません。
イロイロと注意すべき点があるのですが、恐らく世間的には
「今更・・・」なマクロだろうとは思ってます。
先日客先より支給されたDrawファイルは、リンク元の差し替えは
行われていましたが、Updateされていませんでした。
恐らく、リンク元を差し替えるマクロのようなものを持っている
のではないかな? と勝手に思っています。
実は単純にUpdateした際、データの状態によってはダイアログが
出現しマクロが停止してしまう状況に遭遇しました。
Updateしたくなくなる気持ちもわかりますが、上記のマクロでは
対応出来ていると思います。
まだ、ちょっと機能不足なのですが、組合せリストを作る方の
マクロが異常なほど使いにくい・・・。