I'm working on an AddIn that turns off visibility when some criteria are matched. The issue I am having is that it just stops running after the first subassembly, no errors or warnings....
Any ideas?
For Each occ As ComponentOccurrence In assemblyDef.Occurrences
Try
Dim refDoc As AssemblyDocument
MsgBox("got into assemblies")
refDoc = occ.Definition.Document
MsgBox(occ.Name)
Dim customPropSet = refDoc.PropertySets.Item("Design Tracking Properties")
Dim SAPProp = customPropSet.Item("Stock Number")
Dim SAPVal = SAPProp.Value
'MsgBox(SAPVal)
If SAPVal <> Nothing And IsNumeric(SAPVal) Then
If (oData.ContainsKey(SAPVal) And oDataM.ContainsKey(SAPVal)) Then
If (oData(SAPVal) = oDataM(SAPVal)) Then
occ.Visible = False
Else
occ.Visible = True
estr.Add(CStr(SAPVal) & ": " & oData(SAPVal) & " <> " & oDataM(SAPVal))
End If
End If
End If
Catch Ex As Exception
MsgBox(Ex)
End Try
Solved! Go to Solution.
Solved by ahmed.hagi. Go to Solution.
Hi @ahmed.hagi. First thing I see that does not look right is you use of the keyword "Nothing". When comparing against Nothing you should use 'Is' or 'IsNot', not '=' or '<>'. If the variable were declared as a String, instead of no Type declaration, you could try String.IsNullOrEmpty(SAPVal) or just If SAPVal = "", but if it is a Double, Integer, or other numeric data type, there is no comparison with Nothing, it will just have the value of zero, and Boolean's will always be False by default after creation. Also, you could try checking refDoc.DocumentType property to see if it is an assembly first, before trying to assign it to an AssemblyDocument type variable, then use a smaller Try block of code, for more accurate/useful error handling feedback. I don't know what your oData, oDataM, or estr variables represent, but I assume the first two are Dictionary types, and the third something like a List(Of String), but it's difficult to debug without seeing more. Are you wanting this routine to process down into sub assemblies, or just top level components in your main assembly?
Wesley Crihfield
(Not an Autodesk Employee)
Hi @ahmed.hagi ,
There was a lot in that try/catch, which makes it difficult to troubleshoot because once it hits one error, it quits.
Here is an example that breaks it up a bit.
The exception that I was seeing in my data set was the one that happened when the first part component was encountered and the code attempted to set it as a Assembly Document, so changing that to Document helped.
Note that as it was written it only looked at components ( parts and subassemblies) that occurred in the top level assembly. That is to say it was not looking at subcomponents found in the subassemblies.
This example traverses the entire assembly, looking down into each sub assembly.
I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com
Sub main Dim oDoc As AssemblyDocument oDoc = ThisApplication.ActiveDocument Dim assemblyDef As AssemblyComponentDefinition assemblyDef = oDoc.ComponentDefinition Dim oOccs As ComponentOccurrences = oDoc.ComponentDefinition.Occurrences Call TraverseAssembly(oOccs) End Sub Function TraverseAssembly(oOccs As ComponentOccurrences) oData = "Test2" 'dummy data since original example was incomplete oDataM = "Test2" 'dummy data since original example was incomplete Dim estr As New ArrayList 'dummy data since original example was incomplete Dim oOcc As ComponentOccurrence For Each oOcc In oOccs Dim refDoc As Document refDoc = oOcc.Definition.Document Dim customPropSet = refDoc.PropertySets.Item("Design Tracking Properties") Dim SAPProp = customPropSet.Item("Stock Number") Dim SAPVal = SAPProp.Value 'msgbox(SAPVal) Try If SAPVal <> Nothing And IsNumeric(SAPVal) Then If (oData.ContainsKey(SAPVal) And oDataM.ContainsKey(SAPVal)) Then If (oData(SAPVal) = oDataM(SAPVal)) Then oOcc.Visible = False Else oOcc.Visible = True estr.Add(CStr(SAPVal) & ": " & oData(SAPVal) & " <> " & oDataM(SAPVal)) End If End If End If Catch Ex As Exception 'MsgBox(Ex.Message) End Try sName = Split(oOcc.Name, ":") sName = sName(0) If oOcc.DefinitionDocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then Call TraverseAssembly(refDoc.ComponentDefinition.Occurrences) End If Next End Function
I'm trying to port an external rule I have. Unfortunately iLogic and VB.Net with Visual Studio don't map 1 to 1. The code I have attached works in inventor as an external rule....
Imports System.IO
' initialize empty list for data
Dim estr As New List(Of String)
Dim oFileDlg As Inventor.FileDialog = Nothing
InventorVb.Application.CreateFileDialog(oFileDlg)
oFileDlg.InitialDirectory = "C:\MCAD\Workspace\" 'OLC\"
oFileDlg.Filter = "CSV Files (*.csv)|*.csv"
oFileDlg.DialogTitle = "Select a BOM Sheet"
oFileDlg.CancelError = True
'On Error Resume Next
oFileDlg.ShowOpen()
If Err.Number <> 0 Then
'exit if file not selected
Return
ElseIf oFileDlg.FileName <> "" Then
Dim myCSV As String = oFileDlg.FileName
' initialize dictionary for ebom (oData) and dictionary for BOM (oDataM)
Dim oData As New Dictionary(Of String, String)
Dim oDataM As New Dictionary(Of Integer, Integer)
Using reader As New StreamReader(myCSV)
' Read the header line and discard it
reader.ReadLine()
' Read the rest of the file
While Not reader.EndOfStream
' Read a line of text
Dim Line As String = reader.ReadLine()
' Split the line into fields
Dim fields As String() = Line.Split(","c)
' Add the fields to the dictionary
oData.Add(fields(0), fields(1))
End While
End Using
' Get the active assembly.
Dim oAsmDoc As AssemblyDocument
oAsmDoc = ThisApplication.ActiveDocument
Dim nrOfOccs As Integer = 0
' Get the occurrences that represent this document.
Dim oOccs As ComponentOccurrencesEnumerator
' Print the occurrences to the Immediate window.
Dim oOcc As ComponentOccurrence
For Each kvp As KeyValuePair(Of String, String) In oData
For Each oDocCheck As Document In oAsmDoc.AllReferencedDocuments
Try
If oDocCheck.PropertySets.Item("Design Tracking Properties").Item("Stock Number").Value = kvp.Key Then
nrOfOccs = oAsmDoc.ComponentDefinition.Occurrences.AllReferencedOccurrences(oDocCheck).Count
End If
Catch
End Try
Next
Dim x2 As Integer = kvp.Key
Dim y2 As Integer = nrOfOccs
oDataM.Add(x2, y2)
Next
Dim assemblyDef As AssemblyComponentDefinition = ThisDoc.Document.ComponentDefinition
Try
' Activate a writeable View Rep (master view rep is not writeable)
assemblyDef.RepresentationsManager.DesignViewRepresentations.Item("BOM Check").Activate()
Catch
' Assume error means this View Rep does not exist, so create it
oViewRep = assemblyDef.RepresentationsManager.DesignViewRepresentations.Add("BOM Check")
oViewRep.Activate
End Try
' turn off work features in the model
For Each oDocCheck As Document In oAsmDoc.AllReferencedDocuments
For Each oworkplane In assemblyDef.WorkPlanes
oworkplane.Visible = False
Next
For Each oworkaxis In assemblyDef.WorkAxes
oworkaxis.Visible = False
Next
For Each oworkpoint In assemblyDef.WorkPoints
oworkpoint.Visible = False
Next
Next
' turn off visibility if quantities in dictionaries are equal (part level)
For Each occ In assemblyDef.Occurrences.AllLeafOccurrences
Dim refDoc As PartDocument = occ.Definition.Document
customPropSet = refDoc.PropertySets.Item("Design Tracking Properties")
SAPProp = customPropSet.Item("Stock Number")
SAPVal = SAPProp.Value
If SAPVal <> Nothing And IsNumeric(SAPVal) Then
If (oData.ContainsKey(SAPVal) And oDataM.ContainsKey(SAPVal)) Then
If (oData(SAPVal) = oDataM(SAPVal)) Then
occ.Visible = False
Else
occ.Visible = True
estr.Add(CStr(SAPVal) & ": " & CStr(oData(SAPVal)) & " <> " & CStr(oDataM(SAPVal)))
End If
End If
End If
Next
' turn off visibility if quantities in dictionaries are equal (assembly level)
For Each occ In assemblyDef.Occurrences
Dim oANAME As String = occ.Name
iPropSAP = iProperties.Value(oANAME, "Project", "Stock Number")
If iPropSAP <> Nothing And IsNumeric(iPropSAP) Then
If (oData.ContainsKey(iPropSAP) And oDataM.ContainsKey(iPropSAP)) Then
If (oData(iPropSAP) = oDataM(iPropSAP)) Then
occ.Visible = False
Else
occ.Visible = True
estr.Add(CStr(iPropSAP) & ": " & CStr(oData(iPropSAP)) & " <> " & CStr(oDataM(iPropSAP)))
End If
End If
End If
Next
' try to activate level of detail
Try
If oAsmDoc.PropertySets.Item("Inventor Summary Information").Item("Comments").Value.ToString.Contains("GC Series") Then
assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("All Content Center Suppressed").Activate()
Else
assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("iLogic").Activate()
End If
Catch
MsgBox("Not a GC or Legacy System", , "Bom Check")
End Try
End If
' create list of results, remove duplicates
Dim result As List(Of String) = estr.Distinct().ToList
' concatenate results to variable for msgbox display
For i As Integer = 0 To result.Count - 1
If i = 0 Then
oText = result(i)
Else
oText = oText & vbLf & result(i)
End If
Next
' Create and write to a text file
oWrite = System.IO.File.CreateText(ThisDoc.PathAndFileName(False) & ".txt")
' Write list out to file
oWrite.WriteLine("SAP No: EBOM QTY <> BOM QTY:")
For Each Item As String In result
oWrite.WriteLine(Item)
Next
' close the file
oWrite.Close()
' display data to user
MsgBox("The following Items have inconsistent quantities:" & vbCrLf & "SAP No: EBOM QTY <> BOM QTY:" & vbCrLf & oText, ,"BOM Check")
' open the file
ThisDoc.Launch(ThisDoc.PathAndFileName(False) & ".txt")
I've got a working external iLogic Rule, but the shortcuts in iLogic need re-writing, for example "This" doesn't work.
This line uses an iLogic dependent object 'InventorVb', so it should be changed to get/reference the Inventor.Application object another way.
InventorVb.Application.CreateFileDialog(oFileDlg)
Maybe something like this:
Dim InvApp As Inventor.Application = GetObject(,"Inventor.Application")
InvApp.CreateFileDialog(oFileDlg)
Where that variable to represent the Inventor.Application object is at the top of your code.
Also keep in mind that the iLogic rule editor environment already has references to several resources included for us, so that we do not need to have really long 'header' codes in each of our iLogic rules (such as AddReference & Imports lines). And it also creates the 'ThisRule' Class for us, and creates several variables for us that represent Interface type objects within that class that are ready for us to use, without needing to instantiate them. This is all to make life easier for less experienced coders to get into design automation.
And since 'ThisDoc' is also unique to iLogic, the following line would also not work outside of the influence of an iLogic rule, unless you recreated it:
Dim assemblyDef As AssemblyComponentDefinition = ThisDoc.Document.ComponentDefinition
...it seems to me like you could use this instead:
Dim assemblyDef As AssemblyComponentDefinition = oAsmDoc.ComponentDefinition
The term 'ThisDoc' is another one of those super useful/helpful/dynamic variables created for us in iLogic rules that represents an Interface, and since we do not have access to its source code, the closest API object might be the ThisApplication.ActiveEditDocument.
Same for these two lines:
oWrite = System.IO.File.CreateText(ThisDoc.PathAndFileName(False) & ".txt")
ThisDoc.Launch(ThisDoc.PathAndFileName(False) & ".txt")
...in both cases, you could create a variable to use for the needed full file name, with the ".txt" file extension, like the following:
Dim oAsmTxtFile As String = System.IO.Path.ChangeExtension(oAsmDoc.FullFileName, ".txt")
...then use that variable instead of the 'ThisDoc.PathAndFileName()'. Below is an example:
oWrite = System.IO.File.CreateText(oAsmTxtFile)
Since all that 'ThisDoc.Launch() line does is visibly open the file, there are other ways of doing that with vb.net. Perhaps the simplest would be something like this:
Process.Start(oAsmTxtFile)
Wesley Crihfield
(Not an Autodesk Employee)
What I've got so far is the following. It get's to the Assemblies and only turns off one subassembly.
Had to comment out all the creating and changing level of details/view representations since I can't get that to work.
' initialize empty list for data
Dim estr As New List(Of String)
Dim oPropSet As PropertySet
Dim oProp As Inventor.Property
Dim oDoc As Inventor.Document
Dim StrFilter As String = "CSV files (*.csv)|*.csv" ' "CSV files (*.csv)|*.csv"
Dim filename As String
Dim ofDlg As Windows.Forms.OpenFileDialog = New Windows.Forms.OpenFileDialog()
Dim user As String = Windows.Forms.SystemInformation.UserName
ofDlg.Title = "Open File"
ofDlg.InitialDirectory = "C:\Temp\" ' "\\UK11SF001\DATA\Everyone\Purchasing\New Materials\" '"C:\Documents and Settings\" + user + "\Desktop\"
ofDlg.Filter = StrFilter 'Example: "Inventor files (*.ipt; *.iam; *.idw)|*.ipt;*.iam;*.idw"
ofDlg.FilterIndex = 1
ofDlg.RestoreDirectory = True
ofDlg.ShowDialog()
filename = ofDlg.FileName
If filename.Length = 0 Then
MsgBox("yep")
Return
End If
Dim myCSV As String = ofDlg.FileName
'MsgBox(myCSV)
' initialize dictionary for ebom (oData) and dictionary for BOM (oDataM)
Dim oData As New Dictionary(Of String, String)
Dim oDataM As New Dictionary(Of Integer, Integer)
Using reader As New StreamReader(myCSV)
' Read the header line and discard it
reader.ReadLine()
' Read the rest of the file
While Not reader.EndOfStream
' Read a line of text
Dim Line As String = reader.ReadLine()
' Split the line into fields
Dim fields As String() = Line.Split(","c)
'MsgBox(fields(0))
' Add the fields to the dictionary
oData.Add(fields(0), fields(1))
End While
End Using
' Get the active assembly.
Dim oAsmDoc As AssemblyDocument
oAsmDoc = g_inventorApplication.ActiveDocument
Dim nrOfOccs As Integer = 0
For Each kvp As KeyValuePair(Of String, String) In oData
For Each oDocCheck As Document In oAsmDoc.AllReferencedDocuments
Try
If oDocCheck.PropertySets.Item("Design Tracking Properties").Item("Stock Number").Value = kvp.Key Then
nrOfOccs = oAsmDoc.ComponentDefinition.Occurrences.AllReferencedOccurrences(oDocCheck).Count
End If
Catch
End Try
Next
Dim x2 As Integer = kvp.Key
'MsgBox(x2)
Dim y2 As Integer = nrOfOccs
oDataM.Add(x2, y2)
Next
Dim assemblyDef As AssemblyComponentDefinition = oAsmDoc.ComponentDefinition
'Try
' ' Activate a writeable View Rep (master view rep is not writeable)
' 'assemblyDef.RepresentationsManager.DesignViewRepresentations.Item("BOM Check").Activate()
' ' Activate the new design view representation
' assemblyDef.ComponentDefinition.DesignViewRepresentations.ActiveRepresentation = "BOM Check"
' MsgBox("Tried to activate")
'Catch
' ' Assume error means this View Rep does not exist, so create it
' 'Dim oViewRep = assemblyDef.RepresentationsManager.DesignViewRepresentations.Add("BOM Check")
' 'oViewRep.Activate()
' ' Create a new design view representation
' Dim oNewRep As DesignViewRepresentation = assemblyDef.ComponentDefinition.DesignViewRepresentations.Add("BOM Check")
' ' Activate the new design view representation
' assemblyDef.ComponentDefinition.DesignViewRepresentations.ActiveRepresentation = oNewRep
' MsgBox("Failed to activate tried to create")
'End Try
' turn off work features in the model
For Each oDocCheck As Document In oAsmDoc.AllReferencedDocuments
For Each oworkplane In assemblyDef.WorkPlanes
oworkplane.Visible = False
Next
For Each oworkaxis In assemblyDef.WorkAxes
oworkaxis.Visible = False
Next
For Each oworkpoint In assemblyDef.WorkPoints
oworkpoint.Visible = False
Next
Next
MsgBox("got to after workplanes")
' turn off visibility if quantities in dictionaries are equal (part level)
For Each occ As ComponentOccurrence In assemblyDef.Occurrences.AllLeafOccurrences
If occ.DefinitionDocumentType = DocumentTypeEnum.kPartDocumentObject Then
Dim refDoc As PartDocument = occ.Definition.Document
Dim customPropSet = refDoc.PropertySets.Item("Design Tracking Properties")
Dim SAPProp = customPropSet.Item("Stock Number")
Dim SAPVal = SAPProp.Value
If SAPVal IsNot Nothing And IsNumeric(SAPVal) Then
If (oData.ContainsKey(SAPVal) And oDataM.ContainsKey(SAPVal)) Then
If (oData(SAPVal) = oDataM(SAPVal)) Then
occ.Visible = False
Else
occ.Visible = True
estr.Add(CStr(SAPVal) & ": " & CStr(oData(SAPVal)) & " <> " & CStr(oDataM(SAPVal)))
End If
End If
End If
End If
Next
MsgBox("got to after parts")
' turn off visibility if quantities in dictionaries are equal (assembly level)
For Each occ As ComponentOccurrence In assemblyDef.Occurrences
Try
Dim refDoc As AssemblyDocument
MsgBox("got into assemblies")
If occ.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
refDoc = occ.Definition.Document
MsgBox(occ.Name)
Dim customPropSet = refDoc.PropertySets.Item("Design Tracking Properties")
Dim SAPProp = customPropSet.Item("Stock Number")
Dim SAPVal = SAPProp.Value
'MsgBox(SAPVal)
If SAPVal IsNot Nothing And IsNumeric(SAPVal) Then
If (oData.ContainsKey(SAPVal) And oDataM.ContainsKey(SAPVal)) Then
If (oData(SAPVal) = oDataM(SAPVal)) Then
occ.Visible = False
Else
occ.Visible = True
estr.Add(CStr(SAPVal) & ": " & oData(SAPVal) & " <> " & oDataM(SAPVal))
End If
End If
End If
End If
Catch Ex As Exception
MsgBox(Ex)
End Try
Next
MsgBox("got to after assemblies")
' try to activate level of detail
'Try
' If oAsmDoc.PropertySets.Item("Inventor Summary Information").Item("Comments").Value.ToString.Contains("GC Series") Then
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("All Content Center Suppressed").Activate()
' Else
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("iLogic").Activate()
' End If
'Catch
' MsgBox("Not a GC or Legacy System", , "Bom Check")
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("All Content Center Suppressed").Activate()
'End Try
' create list of results, remove duplicates
Dim result As List(Of String) = estr.Distinct().ToList
Dim oText As String
' concatenate results to variable for msgbox display
For i As Integer = 0 To result.Count - 1
If i = 0 Then
oText = result(i)
Else
oText = oText & vbLf & result(i)
End If
Next
' Create and write to a text file
Dim oWrite = System.IO.File.CreateText(oAsmDoc.PathAndFileName(False) & ".txt")
' Write list out to file
oWrite.WriteLine("SAP No: EBOM QTY <> BOM QTY:")
For Each Item As String In result
oWrite.WriteLine(Item)
Next
' close the file
oWrite.Close()
' display data to user
MsgBox("The following Items have inconsistent quantities:" & vbCrLf & "SAP No: EBOM QTY <> BOM QTY:" & vbCrLf & oText, , "BOM Check")
' open the file
oAsmDoc.Launch(oAsmDoc.PathAndFileName(False) & ".txt")
These two lines will not work:
Dim oWrite = System.IO.File.CreateText(oAsmDoc.PathAndFileName(False) & ".txt")
oAsmDoc.Launch(oAsmDoc.PathAndFileName(False) & ".txt")
Because 'PathAndFileName() is a method of the 'ThisDoc' object, not a method of a regular Inventor.Document. If you want to get the full path and file name of an Inventor document, with a different file extension, you can use the line of code I posted in my previous response, as follows:
Dim oAsmTxtFile As String = System.IO.Path.ChangeExtension(oAsmDoc.FullFileName, ".txt")
This would be on its own line just before you get to those other two lines mentioned. Then just use that 'oAsmTextFile' variable as the 'input' into that 'CreateText()' method, or to specify which file to open after it has been created.
oAsmDoc.Launch will not work either, because 'Launch()' is a method of the 'ThisDoc' object, not a method of the regular Inventor.Document type object, and the ThisDoc type object can not be used outside of iLogic. As I mentioned in my previous response, you can use the Process.Start() method in vb.net to open & show that text file after it has been created, instead of the 'ThisDoc.Launch() method, then supply the oAsmTxtFile variable as its 'input'.
Wesley Crihfield
(Not an Autodesk Employee)
Yeah, i know, I've been converting it as i hit errors. I'm just stuck on the looping through the assemblies. For some reason the parts loop works just fine, even before I added a check for the document type.
Ok, so I've managed to get the turning off visibility to work, i just need to get the creation of a design view representation and changing to a level of details working.
Any ideas on what I'm doing wrong in these 2 sections?
'Try
' ' Activate a writeable View Rep (master view rep is not writeable)
' 'assemblyDef.RepresentationsManager.DesignViewRepresentations.Item("BOM Check").Activate()
' ' Activate the new design view representation
' assemblyDef.ComponentDefinition.DesignViewRepresentations.ActiveRepresentation = "BOM Check"
' MsgBox("Tried to activate")
'Catch
' ' Assume error means this View Rep does not exist, so create it
' 'Dim oViewRep = assemblyDef.RepresentationsManager.DesignViewRepresentations.Add("BOM Check")
' 'oViewRep.Activate()
' ' Create a new design view representation
' Dim oNewRep As DesignViewRepresentation = assemblyDef.ComponentDefinition.DesignViewRepresentations.Add("BOM Check")
' ' Activate the new design view representation
' assemblyDef.ComponentDefinition.DesignViewRepresentations.ActiveRepresentation = oNewRep
' MsgBox("Failed to activate tried to create")
'End Try
' try to activate level of detail
'Try
' If oAsmDoc.PropertySets.Item("Inventor Summary Information").Item("Comments").Value.ToString.Contains("GC Series") Then
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("All Content Center Suppressed").Activate()
' Else
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("iLogic").Activate()
' End If
'Catch
' MsgBox("Not a GC or Legacy System", , "Bom Check")
' assemblyDef.RepresentationsManager.LevelOfDetailRepresentations.Item("All Content Center Suppressed").Activate()
'End Try
Can't find what you're looking for? Ask the community or share your knowledge.