I have an iLogic rule that looks at the part number field, looks for "-D-M" within the part number, and separates the BOM based on whether or not the part numbers contained within have the "-D-M" string within them.
"Make" part numbers have it, and "Buy" part numbers don't. The rule then re-numbers the items 1,2,3 for "Make" and 100, 101, 102 for "Buy"
But if I add/remove an item, or make some other changes (I'm not sure exactly what causes it), the numbers revert to what they were, and everything is out of order.
Is there anything I can do to save the item numbers at the assembly level?
Solved! Go to Solution.
Solved by WCrihfield. Go to Solution.
Solved by WCrihfield. Go to Solution.
Hi @claudio.ibarra. In a quick review of your code, the only detail that stands out to me as a possible problem is around Line 30 and Line 35, where you are using a variable in the starter line of those two loops as "bomRow", but then using "BOMRow" variable on the next line within both loops. Spelling and capitalization are both important with code variables. The variable you seem to be using inside of those two loops is exactly the same spelling and capitalization as the Type, which is always bad and causes problems. I do not know if that is the cause of your problems, but should be fixed anyways.
Maybe check something within the BOM dialog. When you click on the 'BOM Settings' button, a small dialog pops-up with two options in it. One of those options is for hiding suppressed components, the other is for renumbering items sequentially. Do you have that second option checked?
Edit: Also, you may want to include a line of code at the end of your Sub Main routine for updating the assembly. That may be needed before the changes will be seen...or something like that.
Wesley Crihfield
(Not an Autodesk Employee)
Thank you for noticing the bomRow vsBOMRow -- I have update that, and (un?)luckily for me, it works the same.
My BOM settings has both things checked --- I unchecked the 2nd box and that looks like it does the trick!!
Am I correct in thinking that checkbox is document-specific? Is there any code I could add to the start of my iLogic script that would un-check the box for me?
Hi @claudio.ibarra. Those 'BOM Settings' settings are saved within that document, not application level settings. And yes, we can access/control them by code also. The main BOM API object, that you get right under the AssemblyComponentDefinition, has properties for those two settings.
BOM.HideSuppressedComponentsInBOM
Both are Read/Write Boolean type properties.
Edit: But those two settings were just added in Inventor 2023, just in case you may be using an earlier version.
Wesley Crihfield
(Not an Autodesk Employee)
I'm using 2023!
If I add the following text to the start of the rule, would that accomplish the goal of ensuring the setting is off whenever the rule is run?
ThisApplication.ActiveDocument.BOM.RenumberItemsSequentially = False
Hi @claudio.ibarra. Actually, you are missing the ComponentDefinition step in that line of code, between the document and the BOM object. But I would suggest replacing your whole Sub Main section of code with something like the following, just to be a bit more thorough. This first makes sure that it is really an assembly, and if not exits the rule. Then gets the BOM to a variable. Then sets that setting. Then makes sure that the 'structured' view is enabled. Then attempts to get that structured BOMView by iterating through the available BOMViews, checking their ViewType property, to make sure we get the correct one. Going by Index number is not stable, because it changes depending on which ones are enabled.
Sub Main()
Dim asm As AssemblyDocument = TryCast(ThisDoc.Document, Inventor.AssemblyDocument)
If asm Is Nothing Then Return 'just in case it gets ran on a part or drawing
Dim oBOM As Inventor.BOM = asm.ComponentDefinition.BOM
oBOM.RenumberItemsSequentially = False
oBOM.StructuredViewEnabled = True
Dim oStructuredBOMView As BOMView = Nothing
For Each oBomView As BOMView In oBOM.BOMViews
If oBOMView.ViewType = BOMViewTypeEnum.kStructuredBOMViewType Then
oStructuredBOMView = oBomView
End If
Next
If oStructuredBOMView Is Nothing Then Return
SortBomView(oStructuredBOMView)
End Sub
Wesley Crihfield
(Not an Autodesk Employee)
I know I'm an internet stranger (I could be a german shepard, you don't know!), but from the bottom of my heart, thank you. That works exactly like how I want it to. Thank you thank you thank you!
One last question because it never hurts to ask -- is it possible to make this rule agnostic to whether it's being run from an assembly or from a drawing that references that assembly? Right now it needs to be run from the modeling environment, but could it be made to run from the drawing directly?
Hi @claudio.ibarra. Yes. That is an odd combination of possible document types that a rule could start from, so the code I injected is maybe a bit longer than it might need to be, but I think this should work OK for you. I copied the whole rule, with the new Sub Main section. Then modified the Sub Main area again. Then modified a couple minor things within the SortBomView Sub routine's code. Mostly just changed your "bomRow" variable to "oBomRow", because the "bomRow" variable kept changing back to "BOMRow" automatically on me, for some odd reason, which is bad. I also got the BOMRows collection to a variable before the start of the loop, because that is more efficient when running (does not have to 'get' the collection again each time).
Sub Main()
Dim oDoc As Inventor.Document = ThisDoc.Document
Dim oBOM As Inventor.BOM = Nothing
If oDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
oBOM = oDoc.ComponentDefinition.BOM
ElseIf oDoc.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
Dim oModelDoc As Inventor.Document = ThisDoc.ModelDocument
If oModelDoc Is Nothing Then Return 'no model referenced in drawing yet
If oModelDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
oBOM = oModelDoc.ComponentDefinition.BOM
Else
Return 'drawing model may have been a part, so no BOM
End If
Else
Return 'main document may have been a part
End If
If oBOM Is Nothing Then Return
oBOM.RenumberItemsSequentially = False
oBOM.StructuredViewEnabled = True
Dim oStructuredBOMView As BOMView = Nothing
For Each oBomView As BOMView In oBOM.BOMViews
If oBomView.ViewType = BOMViewTypeEnum.kStructuredBOMViewType Then
oStructuredBOMView = oBomView
End If
Next
If oStructuredBOMView Is Nothing Then Return
SortBomView(oStructuredBOMView)
End Sub
Private Sub SortBomView(bomView As BOMView)
Dim makeItems As New List(Of BOMRow)
Dim buyItems As New List(Of BOMRow)
'good to get collection to a variable before start of loop (unless adding/removing from collection)
Dim oRows As BOMRowsEnumerator = bomView.BOMRows
For Each oBomRow As BOMRow In oRows
Dim rowDocument As Document = oBomRow.ComponentDefinitions(1).Document
Dim partNumber As String = rowDocument.PropertySets("{32853F0F-3444-11D1-9E93-0060B03C1CA6}")("Part Number").Value.ToString()
If IsMake(partNumber) Then
makeItems.Add(oBomRow)
Else
buyItems.Add(oBomRow)
End If
Next
makeItems = makeItems.OrderBy(Function(item) item.ComponentDefinitions(1).Document.PropertySets("{32853F0F-3444-11D1-9E93-0060B03C1CA6}")("Part Number").Value.ToString()).ToList()
buyItems = buyItems.OrderBy(Function(item) item.ComponentDefinitions(1).Document.PropertySets("{32853F0F-3444-11D1-9E93-0060B03C1CA6}")("Part Number").Value.ToString()).ToList()
Dim makeCounter = 1
Dim buyCounter = 100
For Each oBomRow In makeItems
oBomRow.ItemNumber = makeCounter
makeCounter += 1
Next
For Each oBomRow In buyItems
oBomRow.ItemNumber = buyCounter
buyCounter += 1
Next
End Sub
Private Function IsMake(partNumber As String) As Boolean
If partNumber.Length >= 3 Then
Return partNumber.Substring(3).StartsWith("-D-M")
Else
Return False
End If
End Function
Wesley Crihfield
(Not an Autodesk Employee)
I don't know if these are helpful for understanding the error, but it did give me an error. (I've attached screenshots)
Hi @claudio.ibarra. That error says that the line of code (Line 18) that is attempting to 'Set' the value of the RenumberItemsSequentially property caused the error. We can try to step through a process of elimination to figure this out. We know that the oBOM variable does have a value assigned to it at that point, due to the line of code just above that line, which actually checks if it 'Is Nothing', so that is not the problem. And we know that it is understood as being a BOM object, due to how it was declared, because otherwise it would have thrown a different type of error (for example Type mismatch or can not Cast obj1 Type to obj2 type), plus it correctly understood exactly what that line of code was trying to do. So, the next thought that comes to mind is that maybe either the assembly, or the BOM itself are ReadOnly for some reason.
If the assembly has multiple ModelStates, and maybe the assembly document reference we got earlier in the code is a ModelState 'member' document, instead of the ModelState 'factory' document, that might cause a ReadOnly type status. Because ModelState member documents are generally ReadOnly if accessed directly. To avoid this, we may have to add more code in there to check if the assembly has 2 or more ModelStates, and if so, then we know that we will need to make sure we are working with the ModelState factory document and/or make sure the MemberEditScope of the assembly is set to 'factory scope' or 'all members' so that we can make changes to the member. I know, ModelStates really complicated a lot of stuff, when it comes to controlling things by code.
Wesley Crihfield
(Not an Autodesk Employee)
Can't find what you're looking for? Ask the community or share your knowledge.