In Bill of material i have custom PartQty column and is beside QTY column. I need all informations from QTY column to PartQty column to copy. Possible with iLogic? I'm selecting now manualy copy and paste but it would be nice to have automatic. Could you guys help with please.
Thank you
Solved! Go to Solution.
If you know PartNumber then you may easily get quantity via iLogic function:
quantity = ThisBOM.CalculateQuantity("Model Data", partNumber)
But if your BOM contains overridden quantities then you need to use Inventor API BOMRow.TotalQuantity property for every BOMRow in the BOMView.
(See details here: http://forums.autodesk.com/t5/Inventor-Customization/Exportar-Static-Quantity-da-BOM-para-o-Excel/m-...)
AssemblyDocument ->ComponentDefinition ->BOM->BOMViews->BOMView->BOMRows->BOMRow->TotalQuantity is giving the quantities of the components in the assembly from BOM table.
The following VBA sample illustrates this technique.
Sub GetQuantities() ' a reference to the assembly document. ' This assumes an assembly document is active. Dim oAssyDoc As AssemblyDocument Set oAssyDoc = ThisApplication.ActiveDocument Dim oAssyDef As AssemblyComponentDefinition Set oAssyDef = oAssyDoc.ComponentDefinition ' Get the Representations Manager object. Dim repMgr As RepresentationsManager Set repMgr = oAssyDef.RepresentationsManager ' activate LOD Master - necessary to get BOM object !!! Dim oMasterLOD As LevelOfDetailRepresentation Set oMasterLOD = repMgr.LevelOfDetailRepresentations.Item(1) oMasterLOD.Activate 'set a reference to the BOM Dim oBOM As BOM Set oBOM = oAssyDef.BOM ' Make sure that the "Parts Only" view is enabled. oBOM.PartsOnlyViewEnabled = True Call oBOM.SetPartNumberMergeSettings(True) 'set a reference to the "Parts Only" BOMView Dim oBOMView As BOMView Set oBOMView = oBOM.BOMViews.Item("Parts Only") Dim oBOMRow As BOMRow For Each oBOMRow In oBOMView.BOMRows 'Set a reference to the primary ComponentDefinition of the row Dim oCompDef As ComponentDefinition Set oCompDef = oBOMRow.ComponentDefinitions.Item(1) Dim oPartNumProperty As Property Dim oDescripProperty As Property Dim Qty As String If TypeOf oCompDef Is VirtualComponentDefinition Then 'Get the Virtual Component property that contains the "Part Number" Set oPartNumProperty = oCompDef.PropertySets _ .Item("Design Tracking Properties").Item("Part Number") 'Get the Virtual Component property that contains the "Description" Set oDescripProperty = oCompDef.PropertySets _ .Item("Design Tracking Properties").Item("Description") Qty = oBOMRow.TotalQuantity Debug.Print oBOMRow.ItemNumber; " "; oPartNumProperty.value; " Qty="; _ Qty; " "; oDescripProperty.value Else 'Get the file property that contains the "Part Number" 'The file property is obtained from the parent 'document of the associated ComponentDefinition. Set oPartNumProperty = oCompDef.Document.PropertySets _ .Item("Design Tracking Properties").Item("Part Number") 'Get the file property that contains the "Description" Set oDescripProperty = oCompDef.Document.PropertySets _ .Item("Design Tracking Properties").Item("Description") Qty = oBOMRow.TotalQuantity Debug.Print oBOMRow.ItemNumber; " "; oPartNumProperty.value; " Qty="; _ Qty; " "; oDescripProperty.value End If Next Beep End Sub
iLogic function iProperties.Value("ComponentName", "Custom", "PropertyName") allows you to save any value in the desired custom iProperty:
iProperties.Value("ComponentName", "Custom", "PartQty") = TotalQuantity
or
iProperties.Value("Custom", "PartQty") = TotalQuantity
Does this help?
Sorry this no working for me. 😞
As you can see from this picture i just want to have same Qty in PartQty column. So far i'm using copy paste and i'm cool but easier and faster way would be great.
Thank you
Current Inventor API does not expose the BOM.Columns. So there is no simple way to copy content of one column to another. But you can do it indirectly copying your data to the appropriate custom iProperties that are exposed in the BOM columns.
So for every BOMRow you should
oDoc = oBOMRow.ComponentDefinitions.Item(1).Document
Finally you should update your assembly to refresh its BOM.
Cheers,
MisterZs,
I think this is what Vladimir was trying to show you. Put this into an ilogic rule and run it. The key thing is the part number must be the same as the file name of the part. Hope that helps.
doc = ThisDoc.Document
Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition
Dim oBOM As BOM = oAssyDef.BOM
oBOM.PartsOnlyViewEnabled = True
Dim oBOMView As BOMView = oBOM.BOMViews.Item("Parts Only")
Dim oBOMRow As BOMRow
For Each oBOMRow In oBOMView.BOMRows
'Set a reference to the primary ComponentDefinition of the row
Dim oCompDef As ComponentDefinition
oCompDef = oBOMRow.ComponentDefinitions.Item(1)
Dim oPartNumProperty As String
Dim Qty As String
If TypeOf oCompDef Is VirtualComponentDefinition Then
'Get the Virtual Component property that contains the "Part Number"
oPartNumProperty = oCompDef.PropertySets.Item("Design Tracking Properties").Item("Part Number").Value
Qty = oBOMRow.TotalQuantity
Else
'Get the file property that contains the "Part Number"
'The file property is obtained from the parent
'document of the associated ComponentDefinition.
oPartNumProperty = oCompDef.Document.PropertySets.Item("Design Tracking Properties").Item("Part Number").Value
Qty = oBOMRow.TotalQuantity
End If
oPartNumProperty &= ".ipt"
iProperties.Value(oPartNumProperty, "Custom", "PartQty") = Qty
Next
Hi,
apreciate to All for efort to resolve this problem. I just get this msg. and i run rule. It has error in rule .
Member not found. It doesn't say which member but just not working. I did copy paste into word and then into iLogic.
But hope we are closer.
Thank you
I simplified it and made it not dependant on the part number and file name matching. See how this works. If you are getting the "Not member error", sometimes I notice that Inventor is still holding onto a variable. So just close and restart Inventor and that should correct it. If it doesn't then there's something wrong with the code.
Hope this helps.
doc = ThisDoc.Document
Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition
Dim oBOM As BOM = oAssyDef.BOM
oBOM.PartsOnlyViewEnabled = True
Dim oBOMView As BOMView = oBOM.BOMViews.Item("Parts Only")
Dim oBOMRow As BOMRow
For Each oBOMRow In oBOMView.BOMRows
'Set a reference to the primary ComponentDefinition of the row
Dim oCompDef As ComponentDefinition
oCompDef = oBOMRow.ComponentDefinitions.Item(1)
Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
Dim CompFileNameOnly As String
Dim index As Integer = CompFullDocumentName.lastindexof("\")
CompFileNameOnly = CompFullDocumentName.substring(index+1)
'MessageBox.Show(CompFileNameOnly)
Dim Qty As String
Qty = oBOMRow.TotalQuantity
iProperties.Value(CompFileNameOnly, "Custom", "PartQty") = Qty
Next
This is working. Please remember that the "Item("Parts Only")" must be translated if you have language pack in Inventor. (Took me some time to figur it out).
What about other components that ipt? what about iam? How can I count them (not inseparable)? Any ideas? Similar code in the Structure BOM?
This is an issue I'm tyring to solve for over two years. This topic is very close to my case.
This code will not work. It will count only the assemblies in the first level. And its ok to have custom property (QTY for the moment). I'm not useing Vault so I dont have to check out all files. My rule is launched in the top assembly, searching in every related file the QTY, writing down in customQTY (I will need it in other rules), searching for the drawing and then inserting QTY in the title block. But how to count the assemblies that are used in a few subassemblies?
Let say that I have assembly with two conveyors, A & B. In the main assembly I have 2xA+1xB.
How to count how many H.iam do I need? Each of conveyors contains hangers H.iam (A has 2 hangers but its 2 times in the main assembly so its 2x2 and B has 4 hangers so 4x1) H(QTY)=2x2+4x1=8 H_L.iam is very similar to H.aim, contains the same parts but it's mirrored part do it is welded in a different way. Also has a different QTY because B.iam has 3x H_L.iam. On the end H_L(QTY)=7.
Of course this is an example, in real life this gets more complicated.
I hope you understand my poor language and my big problem. And the screenshot in Polish.
Well here's my first crack at this. Not sure I accounted for everything but see how this works. Hope this helps.
Sub Main
doc = ThisDoc.Document
Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition
Dim oBOM As BOM = oAssyDef.BOM
oBOM.PartsOnlyViewEnabled = True
Dim oBOMViewPO As BOMView = oBOM.BOMViews.Item("Parts Only")
Dim oBOMRowPO As BOMRow
For Each oBOMRowPO In oBOMViewPO.BOMRows
'Set a reference to the primary ComponentDefinition of the row
Dim oCompDef As ComponentDefinition
oCompDef = oBOMRowPO.ComponentDefinitions.Item(1)
Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
Dim CompFileNameOnly As String
Dim index As Integer = CompFullDocumentName.lastindexof("\")
CompFileNameOnly = CompFullDocumentName.substring(index+1)
'MessageBox.Show(CompFileNameOnly)
Dim Qty As String
Qty = oBOMRowPO.TotalQuantity
iProperties.Value(CompFileNameOnly, "Custom", "PartQty") = Qty
Next
If oBOM.StructuredViewEnabled Then
If oBOM.StructuredViewFirstLevelOnly Then
oBOM.StructuredViewFirstLevelOnly = False
End If
Else
oBOM.StructuredViewEnabled = True
oBOM.StructuredViewFirstLevelOnly = False
End If
Dim oBOMViewStruc As BOMView = oBOM.BOMViews.Item("Structured")
Dim oBOMRowStruc As BOMRow
Dim arrSubAssemblyList As New ArrayList
Call QueryBOMRowProperties(oBOMViewStruc.BOMRows, arrSubAssemblyList, 1)
End Sub
Private Sub QueryBOMRowProperties(oBOMRows As BOMRowsEnumerator, arrSubAssembly As ArrayList, oParentQty As Integer)
Dim i As Long
For i = 1 To oBOMRows.count
Dim oBOMRowStruc As BOMRow = oBOMRows.item(i)
Dim oCompDef As ComponentDefinition = oBOMRowStruc.ComponentDefinitions.item(1)
Dim oQty As Integer
If TypeOf oCompDef Is AssemblyComponentDefinition And oCompDef.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
Dim CompFileNameOnly As String
Dim index As Integer = CompFullDocumentName.lastindexof("\")
CompFileNameOnly = CompFullDocumentName.substring(index+1)
'MessageBox.Show(CompFileNameOnly)
oQty = oBOMRowStruc.ItemQuantity * oParentQty
Dim additionalQty As Integer
If arrSubAssembly.Count <> 0 Then
Dim counter As Integer
For Each CompData As String In arrSubAssembly
Dim commaindex As Integer = CompData.indexof(",")
Dim CompName As String = CompData.substring(0,commaindex)
If CompName = CompFileNameOnly Then
additionalQty = CompData.substring(commaindex+1)
Else
counter += 1
End If
Next
If additionalQty = 0 Then
arrSubAssembly.add(CompFileNameOnly & "," & oQty)
Else
arrSubAssembly(counter) = CompFileNameOnly & "," & oQty + additionalQty
End If
Else
arrSubAssembly.add(CompFileNameOnly & "," & oQty)
End If
iProperties.Value(CompFileNameOnly, "Custom", "PartQty") = oQty + additionalQty
'Recursively iterate child rows if present.
If Not oBOMRowStruc.ChildRows Is Nothing Then
Call QueryBOMRowProperties(oBOMRowStruc.ChildRows, arrSubAssembly, oQty)
End If
End If
Next
End Sub
Wow. Big thanks, Dan. It almost worked.
first in the stucture settings I can choose "separator" in your code its comma in my stanrardt it is dot. But the code will fail if someone will choose <none>.
Second thing is more complicated: the code is multipling all levels wchich is good but sometimes I have two machines with the same basic part and the code is writing down only the QTY of last machine.
Please look at the attachment and see if you have the same result (H(QTY)=4 and it should be 8). The tests are run in INV 2013 SP2, WIN7 64bit.
Once again thanks for the efford. I did not know how to get in the BOM structure, I made some tests with exported BOM in excel file, it was mess.
The original code, I was getting 8 for H. I wonder if it's the language is the issue. BTW, I am using Inventor 2014 SP1. But I did notice an index issue and corrected it below. I also changed the separator that my code is using from a comma to a colon. This separator is not the same as the "separator" for the BOM. It should be unrelated. What I am doing is reading each line in the structured BOM and if it's a subassembly then get the name and qty and put it into an array. I am appending the name with a colon and the qty (ex. A.iam:1, B.iam:2, etc). As I am going through each subassembly, I am comparing it to the array that i am building. I ran the following code ont the assembly you gave me and it seems to be working on my end. Try this and let me know how it works.
Sub Main
doc = ThisDoc.Document
Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition
Dim oBOM As BOM = oAssyDef.BOM
oBOM.PartsOnlyViewEnabled = True
Dim oBOMViewPO As BOMView = oBOM.BOMViews.Item("Parts Only")
Dim oBOMRowPO As BOMRow
For Each oBOMRowPO In oBOMViewPO.BOMRows
'Set a reference to the primary ComponentDefinition of the row
Dim oCompDef As ComponentDefinition
oCompDef = oBOMRowPO.ComponentDefinitions.Item(1)
Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
Dim CompFileNameOnly As String
Dim index As Integer = CompFullDocumentName.lastindexof("\")
CompFileNameOnly = CompFullDocumentName.substring(index+1)
'MessageBox.Show(CompFileNameOnly)
Dim Qty As String
Qty = oBOMRowPO.TotalQuantity
iProperties.Value(CompFileNameOnly, "Custom", "cQty") = Qty
Next
If oBOM.StructuredViewEnabled Then
If oBOM.StructuredViewFirstLevelOnly Then
oBOM.StructuredViewFirstLevelOnly = False
End If
Else
oBOM.StructuredViewEnabled = True
oBOM.StructuredViewFirstLevelOnly = False
End If
Dim oBOMViewStruc As BOMView = oBOM.BOMViews.Item("Structured")
Dim oBOMRowStruc As BOMRow
Dim arrSubAssemblyList As New ArrayList
Call QueryBOMRowProperties(oBOMViewStruc.BOMRows, arrSubAssemblyList, 1)
End Sub
Private Sub QueryBOMRowProperties(oBOMRows As BOMRowsEnumerator, arrSubAssembly As ArrayList, oParentQty As Integer)
Dim i As Long
For i = 1 To oBOMRows.count
Dim oBOMRowStruc As BOMRow = oBOMRows.item(i)
Dim oCompDef As ComponentDefinition = oBOMRowStruc.ComponentDefinitions.item(1)
Dim oQty As Integer
If TypeOf oCompDef Is AssemblyComponentDefinition And oCompDef.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then
Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName
Dim CompFileNameOnly As String
Dim index As Integer = CompFullDocumentName.lastindexof("\")
CompFileNameOnly = CompFullDocumentName.substring(index+1)
'MessageBox.Show(CompFileNameOnly)
oQty = oBOMRowStruc.ItemQuantity * oParentQty
Dim additionalQty As Integer
If arrSubAssembly.Count <> 0 Then
Dim counter As Integer = 0
For Each CompData As String In arrSubAssembly
Dim commaindex As Integer = CompData.indexof(":")
Dim CompName As String = CompData.substring(0,commaindex)
If CompName = CompFileNameOnly Then
additionalQty = CompData.substring(commaindex+1)
Else
counter += 1
End If
Next
If additionalQty = 0 Then
arrSubAssembly.add(CompFileNameOnly & ":" & oQty)
Else
arrSubAssembly(counter) = CompFileNameOnly & ":" & oQty + additionalQty
End If
Else
arrSubAssembly.add(CompFileNameOnly & ":" & oQty)
End If
iProperties.Value(CompFileNameOnly, "Custom", "cQty") = oQty + additionalQty
'Recursively iterate child rows if present.
If Not oBOMRowStruc.ChildRows Is Nothing Then
Call QueryBOMRowProperties(oBOMRowStruc.ChildRows, arrSubAssembly, oQty)
End If
End If
Next
End Sub
YEAH!
in the earlier version I also had some problem with index, maybe I messed up something trying to run the code (thats why I had the 4 as a result). Now it works like a charm.
I've added the language handeling
Dim PartsOnly As String Dim Structured As String Select Case ThisApplication.LanguageName Case "Polski" PartsOnly = "Tylko części" Structured = "Strukturalny" Case "English" PartsOnly = "Parts Only" Structured = "Structured" End Select
edit:
I made a test with a file with 1247 related files (274 iam) and after 3min of working I had "index problem".
translated from polish: "Index was out of range. Value has to be non-negative and smaller than a size of a collection. Name of a parameter: index".
In the main assembly 2/3 was done correctly but somwhere in the third part something went wrong and the cQTY remain empty. Although in that part which contains cQTY<>0 I had my answer and it's correct.
I tried to find in which part the errors occurs. So I've added Progress bar to see where the code fails but I handle only the first part, PartsOnly. I'll be graitfull if you coult use this code in further aproaches:
Sub Main doc = ThisDoc.Document Dim oAssyDef As AssemblyComponentDefinition = doc.ComponentDefinition Dim oBOM As BOM = oAssyDef.BOM Dim PartsOnly As String Dim Structured As String Select Case ThisApplication.LanguageName Case "Polski" PartsOnly = "Tylko części" Structured = "Strukturalny" Case "English" PartsOnly = "Parts Only" Structured = "Structured" End Select Dim oPart As PartDocument Dim CollPartList As New Collection CollPartList = New Collection Call GetCollPartList(CollPartList, doc) 'all elements .count Dim i As Long: i = 1 Dim oProgressBar As Inventor.ProgressBar oBOM.PartsOnlyViewEnabled = True Dim oBOMViewPO As BOMView = oBOM.BOMViews.Item(PartsOnly) Dim oBOMRowPO As BOMRow oProgressBar = ThisApplication.CreateProgressBar(False, CollPartList.Count, "Counting quantity in " & iProperties.Value("Project", "Part Number")) oProgressBar.Message = "The begining" For Each oBOMRowPO In oBOMViewPO.BOMRows 'Set a reference to the primary ComponentDefinition of the row Dim oCompDef As ComponentDefinition oCompDef = oBOMRowPO.ComponentDefinitions.Item(1) Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName Dim CompFileNameOnly As String Dim index As Integer = CompFullDocumentName.lastindexof("\") CompFileNameOnly = CompFullDocumentName.substring(index+1) oProgressBar.Message = "Counting .ipt files " & i & "/ " & CollPartList.Count & ": " & CompFileNameOnly oProgressBar.UpdateProgress 'MessageBox.Show(CompFileNameOnly) Dim Qty As String Qty = oBOMRowPO.TotalQuantity iProperties.Value(CompFileNameOnly, "Custom", "cQty") = Qty '& "PO" i+=1 Next oProgressBar.Message = "Counting .iam files "&"CLASSIFIED"&" / " & CollPartList.Count & ": " oProgressBar.UpdateProgress If oBOM.StructuredViewEnabled Then If oBOM.StructuredViewFirstLevelOnly Then oBOM.StructuredViewFirstLevelOnly = False End If Else oBOM.StructuredViewEnabled = True oBOM.StructuredViewFirstLevelOnly = False End If Dim oBOMViewStruc As BOMView = oBOM.BOMViews.Item(Structured) Dim oBOMRowStruc As BOMRow Dim arrSubAssemblyList As New ArrayList Call QueryBOMRowProperties(oBOMViewStruc.BOMRows, arrSubAssemblyList, 1) oProgressBar.Close End Sub Sub QueryBOMRowProperties(oBOMRows As BOMRowsEnumerator, arrSubAssembly As ArrayList, oParentQty As Integer) Dim i As Long For i = 1 To oBOMRows.count Dim oBOMRowStruc As BOMRow = oBOMRows.item(i) Dim oCompDef As ComponentDefinition = oBOMRowStruc.ComponentDefinitions.item(1) Dim oQty As Integer If TypeOf oCompDef Is AssemblyComponentDefinition And oCompDef.BOMStructure = BOMStructureEnum.kNormalBOMStructure Then Dim CompFullDocumentName As String = oCompDef.Document.FullDocumentName Dim CompFileNameOnly As String Dim index As Integer = CompFullDocumentName.lastindexof("\") CompFileNameOnly = CompFullDocumentName.substring(index+1) 'MessageBox.Show(CompFileNameOnly) oQty = oBOMRowStruc.ItemQuantity * oParentQty Dim additionalQty As Integer If arrSubAssembly.Count <> 0 Then Dim counter As Integer = 0 For Each CompData As String In arrSubAssembly Dim commaindex As Integer = CompData.indexof(":") Dim CompName As String = CompData.substring(0,commaindex) If CompName = CompFileNameOnly Then additionalQty = CompData.substring(commaindex+1) Else counter += 1 End If Next If additionalQty = 0 Then arrSubAssembly.add(CompFileNameOnly & ":" & oQty) Else arrSubAssembly(counter) = CompFileNameOnly & ":" & oQty + additionalQty End If Else arrSubAssembly.add(CompFileNameOnly & ":" & oQty) End If iProperties.Value(CompFileNameOnly, "Custom", "cQty") = oQty + additionalQty 'oProgressBar.Message = "Counting " & i & "/ " & CollPartList.Count & ": " & CompFileNameOnly 'oProgressBar.UpdateProgress 'i+=1 'Recursively iterate child rows if present. If Not oBOMRowStruc.ChildRows Is Nothing Then Call QueryBOMRowProperties(oBOMRowStruc.ChildRows, arrSubAssembly, oQty) End If End If Next End Sub Private Sub GetCollPartList(ByRef CollPartList As Collection, oDoc As Document) 'PROGRESS BAR============================================== On Error Resume Next Dim el As Document If oDoc.DocumentType = kAssemblyDocumentObject Then For Each el In oDoc.ReferencedFiles If el.DocumentType = kAssemblyDocumentObject Then GetCollPartList (CollPartList, el) End If If el.DocumentType = kPartDocumentObject Then CollPartList.Add (el, el.FullFileName) End If Next el Else CollPartList.Add (el, el.FullFileName) End If 'END PROGRESS BAR=-============================================ End Sub
I just run into problem. Rule is witting very well, but my problem is with Vaoult. We have some library parts in Vaoul and as Library parts can't be edited rule is making iproperties and we can't save or check file in vault. Is it there solution for this problem
Thank you
Now that Vault has come into play, you will have to write an condition statement to check if the file is located in a library path, checked out or if the file attribute is read only. This will have to occur before you write the value into PartQty.
Can't find what you're looking for? Ask the community or share your knowledge.