- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi all, I'm really close to finding a solution to my problem, but the last bits are evading me!
I'm trying to make a rule that loops through a main assembly, checks each occurrence name against a list (on a hit, grab the name to save as and drawing location), recurses if it is an assembly, then saves (into the folder the top-level assembly is saved into) and replaces each component (and drawing/drawing reference) from the bottom up with the new versions until everything named has been replaced with a prefixed version in the assembly folder.
I've gotten it working for parts and assemblies, all drawings save and replace model views properly, but anything involving weldments complicates how things get saved and replaced as they don't follow the rules!
All the components are saved into the folder (i.e. the download folder looks right), but something isn't done in the right order as certain weldments and components within weldments reference the original non-prefixed file instead of the new prefixed replacement after running the rule, and other weldments are fine.
I've included the problem code and how it gets there (something in the SaveComponent() sub). Hopefully someone can make sense of this!
' does not replace:
' sheet metal inside weldment inside assembly: _90_01_01 - _03
' weldment inside weldment: _00 and _01
' weldment: _1400144
Sub Main()
' list of components visited to ensure no double save
Dim visitedDocs As New List(Of String)
' sanity check
Dim oAsmDoc As AssemblyDocument = ThisApplication.ActiveDocument
If oAsmDoc.DocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
MessageBox.Show("You must ony run this rule from an assembly.", "Assembly only!")
Exit Sub
End If
' prefix for saved components and folder to save to
Dim projectName As String = iProperties.Value("Project", "Part Number")
Dim saveFolder As String = ThisDoc.Path
' traverse the assembly
Call SaveAll(oAsmDoc, visitedDocs, saveFolder, projectName)
MessageBox.Show("All components processed and saved!", "You did it!")
End Sub
' recursive sub to take into account normal components then pattern components
Sub SaveAll(oAsmDoc As AssemblyDocument, visitedDocs As List(Of String), saveFolder As String, projectName As String)
If visitedDocs.Contains(LCase(oAsmDoc.FullFileName)) Then Exit Sub
' not a pattern element
For Each oOcc As ComponentOccurrence In oAsmDoc.ComponentDefinition.Occurrences
Try
If Not visitedDocs.Contains(LCase(oOcc.Definition.Document.FullFileName)) Then
Call ProcessOccurrence(oOcc, visitedDocs, saveFolder, projectName)
End If
Catch
End Try
Next
' occurrence of an element in a pattern
For Each oPattern As OccurrencePattern In oAsmDoc.ComponentDefinition.OccurrencePatterns
For Each oElem As OccurrencePatternElement In oPattern.OccurrencePatternElements
For Each oPatOcc As ComponentOccurrence In oElem.Occurrences
Try
If Not visitedDocs.Contains(LCase(oPatOcc.Definition.Document.FullFileName)) Then
Call ProcessOccurrence(oPatOcc, visitedDocs, saveFolder, projectName)
End If
Catch
End Try
Next
Next
Next
' once assembly complete
visitedDocs.Add(LCase(oAsmDoc.FullFileName))
End Sub
' check name of current component
' if match, send to save sub
Sub ProcessOccurrence(oOcc As ComponentOccurrence, visitedDocs As List(Of String), saveFolder As String, projectName As String)
If oOcc.Suppressed Then Exit Sub
Dim oDoc As Document = oOcc.Definition.Document
If oDoc Is Nothing Then Exit Sub
If visitedDocs.Contains(LCase(oDoc.FullFileName)) Then Exit Sub
Dim name As String = LCase(oOcc.Name)
Dim newName As String = ""
Dim drawingTemplate As String = ""
' template for pattern matching
If name = "target name" Then
newName = "save_name"
drawingTemplate = "drawing_path"
End If
' if found, save component
If newName <> "" Then
Call SaveComponent(oDoc, oOcc, saveFolder, projectName, newName, drawingTemplate, visitedDocs)
End If
End Sub
' save component and (hopefully) replace all occs of it with new file
Sub SaveComponent(oDoc As Document, oOcc As ComponentOccurrence, saveFolder As String, projectName As String, newName As String, drawingTemplate As String, visitedDocs As List(Of String))
If visitedDocs.Contains(LCase(oDoc.FullFileName)) Then Exit Sub
visitedDocs.Add(LCase(oDoc.FullFileName))
Dim modelExt As String = ""
Dim newModelPath As String = ""
Dim isWeldment As Boolean = (oDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject AndAlso
oDoc.SubType = "{28EC8354-9024-440F-A8A2-0E0E55D635B0}")
Select Case oDoc.DocumentType
' simple save
Case DocumentTypeEnum.kPartDocumentObject
modelExt = ".ipt"
newModelPath = System.IO.Path.Combine(saveFolder, projectName & newName & modelExt)
If Not System.IO.File.Exists(newModelPath) Then
oDoc.SaveAs(newModelPath, False)
System.Threading.Thread.Sleep(500)
End If
Case DocumentTypeEnum.kAssemblyDocumentObject
modelExt = ".iam"
newModelPath = System.IO.Path.Combine(saveFolder, projectName & newName & modelExt)
If isWeldment Then
If Not System.IO.File.Exists(newModelPath) Then
Try
' copy weldment and let it rest
System.IO.File.Copy(oDoc.FullFileName, newModelPath)
System.Threading.Thread.Sleep(1000)
' make list of who we have visited in the weldment already then iterate through
Dim weldVisited As New List(Of String)
Dim newAsm As AssemblyDocument = ThisApplication.Documents.Open(newModelPath, True)
Try
Call SaveAll(newAsm, weldVisited, saveFolder, projectName)
newAsm.Save()
Finally
newAsm.Close(True)
End Try
Try
' replace old file with new copied file
oOcc.Replace(newModelPath, True)
' update document then give time for update to settle
ThisApplication.ActiveDocument.Update2(True)
System.Threading.Thread.Sleep(1000)
' weldments like to crash all of inventor so try to stabilise
ThisApplication.CommandManager.ControlDefinitions.Item("AppRebuildAllCmd").Execute()
Catch ex As Exception
Logger.Error("Primary replacement failed: " & ex.Message)
' secondary method using document reference (please)
Try
oOcc.Definition.DocumentReference.ReplaceReference(newModelPath)
ThisApplication.ActiveDocument.Update2(True)
System.Threading.Thread.Sleep(500)
Catch ex2 As Exception
Logger.Error("Fallback replacement failed: " & ex2.Message)
End Try
End Try
Catch ex As Exception
Logger.Error("Weldment processing error: " & ex.Message)
End Try
End If
Else
' normal assembly
If Not System.IO.File.Exists(newModelPath) Then
Dim asmDoc As AssemblyDocument = CType(oDoc, AssemblyDocument)
asmDoc.SaveAs(newModelPath, False)
System.Threading.Thread.Sleep(500)
Call SaveAll(asmDoc, visitedDocs, saveFolder, projectName)
End If
End If
End Select
' create drawing
If drawingTemplate <> "" AndAlso System.IO.File.Exists(newModelPath) Then
' give time to let weldment behave itself
If isWeldment Then
System.Threading.Thread.Sleep(1500)
ThisApplication.ActiveDocument.Update()
End If
Try
Dim drawingPath As String = System.IO.Path.Combine(saveFolder, projectName & newName & ".idw")
If Not System.IO.File.Exists(drawingPath) Then
Call SaveDrawing(drawingTemplate, drawingPath, newModelPath)
End If
Catch ex As Exception
Logger.Error("Drawing creation error: " & ex.Message)
End Try
End If
End Sub
Sub SaveDrawing(templatePath As String, outputDrawingPath As String, modelPath As String)
' working - not included
Return drawingPath
End Function
Function SelectDrawing(ByVal name As String) As String
' working - not included
Return drawingPath
End Function
Solved! Go to Solution.