Automating Instance iProperty Creation inside of Inventor Drawing

Automating Instance iProperty Creation inside of Inventor Drawing

jonathan_honeycutt256PK
Contributor Contributor
284 Views
3 Replies
Message 1 of 4

Automating Instance iProperty Creation inside of Inventor Drawing

jonathan_honeycutt256PK
Contributor
Contributor

The end goal is to be able to add/change an instance iProperty of a single component when selected within a drawing view. The current method is to open the assembly in another window, orient the part and verify that the component is the same one in the drawing, then right click instance properties, create a new property.

 

The property I want to create is "VIEW QTY". Right now, the balloons in the drawing show the total qty of the BOM, and I want to only call out a portion of the BOM, because the view (or assembly step) only needs a portion of the total. So in one view, I want to call out 10 nuts, and in another view, 5 nuts, but the total is 15. Creating an instance property, I can reference "VIEW QTY" in the balloon, and change it to whatever number I like. Ideally, the number would correlate to the BOM total qty, but that is beyond my scope for now.

 

Below is the code that Google Gemini helped me create, so when you look at the code and ask "Why did he do that?!", it's because I didn't do it. I'm not smart enough to write my own code, yet.

 

I know the first error is Line 3: Component is undefined. I don't know where to look to find all the objects I can use. I know it's not a valid object because the text is Orange, not Purple. Not sure how to fix this.

 

Sub Main()
    ' Prompt the user to pick a component
    Dim pickedComponent As Component = ThisApplication.ActiveDocument.ComponentDefinition.PickComponent("Select a component:", False)

    ' Check if a component was picked
    If Not pickedComponent Is Nothing Then
        ' Prompt the user for the "VIEW QTY" value
        Dim viewQty As String = InputBox("Enter the VIEW QTY value:", "VIEW QTY")

        ' Set the "VIEW QTY" iProperty instance value of the selected component
        pickedComponent.iProperties.SetInstanceProperty("VIEW QTY", viewQty)

        ' Inform the user that the property has been set
        MsgBox("VIEW QTY property set to: " & viewQty)
    Else
        ' If no component was picked, inform the user
        MsgBox("No component was selected.")
    End If
End Sub

 Any and all help is appreciated. Thanks!

0 Likes
285 Views
3 Replies
Replies (3)
Message 2 of 4

WCrihfield
Mentor
Mentor

Hi @jonathan_honeycutt256PK.  What you are asking for is very complicated to make happen entirely by code.  And the code example you provided has multiple problems that are not easily fixed, and even if fixed would not give you the results you want, because a whole lot more code would be required.

 

I have another idea though, that may work just as well for you, depending on your requirements.  And this may not even require any code to do, either.  Are you familiar with the filter settings of the PartsList in a drawing?  There are several ways we can filter what is included in a PartsList, to customize its quantities, without making the data shown be 'static'.  Manually, I would first refer you to the following official online help documentation:

About Parts Lists (which includes some stuff about its filter settings)

Filter Settings Reference (which goes into those options in more depth)

Those settings/options are also accessible through Inventor's API after the 2024.1 update of Inventor.  The following are some of those links to the Inventor API related objects, properties, methods.

PartsList.FilterSettings (property)

PartsListFilterSettings (object)

PartsListFilterSettings.Enabled (property)

PartsListFilterSettings.Add (method)

PartsListFilterSettings.Item (property)

PartsListFilterItem (object)

PartsListFilterItem.Enabled (property)

PartsListFilterItem.FilterItemType (property)

PartsListFilterItemTypeEnum (Enum)

PartsListFilterItem.Options (property)

When using this filtering system, you can have a view representation of your assembly, in which only the items you want to be included in your view will be visible.  Then, in the drawing, you can set the view to that specific view representation of the assembly, where the visibility of those items is controlled the way you want.  Then, the PartsList on that specific sheet of your drawing can be independent of the PartsLists on other sheets, and can be filtered to that specific assembly view representation, and further filtered to only include the 'visible' items.  That process could potentially result in the quantities you want to show.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 4

jonathan_honeycutt256PK
Contributor
Contributor
I think I've done what you're asking, but I used Model States. FYI, I'm using 2023. Model states work, but there's the issue of a part that is being shown, but not referenced.

Say there's an assembly step, with 6 nuts. I create a model state with just those 6 nuts, and that works out great. But then in the next step, I create another model state with 6 MORE nuts. The original 6 nuts SHOULD still be visible, but not counted when showing the quantities in the balloon. This is just how we do it at this company.

And how we typically make drawings is make a 3D model in inventor, create profile views in an idw, then copy those views and paste into dwg and manually add balloons and edit them in AutoCAD. I'm trying to convince us to move away from AutoCAD, and things like this need to be as seamless as possible. Maybe there's a better way, or maybe we just need to change our standards to keep up with the times.

Thanks for your input. Sorry I didn't see your reply earlier. I didn't get an email notifying me. I'll keep looking into the solution you proposed and see if I can make it work.
0 Likes
Message 4 of 4

jnowel
Advocate
Advocate

I am not familiar yet with the instance iProperty.

But can you give this a try?
It requires a SketchedSymbol named "VIEW QTY" where it contains a PromptedEntry "<VIEW QTY>".
This SketchedSymbol attaches to the part edge you want to know the quantity in view (so instead of a Balloon, you use the SketchedSymbol instead).

You can just run the rule every time for a batch update per sheet.

Btw I've used @matt.greyY3FB5 function (IsPointInView) and modified subroutine (TraverseOccurrences) as a way to check  and count the parts in view.

Sub Main()
	
	' Get the active document (assuming it's a drawing)
	Dim oDrawingDoc As Document
	oDrawingDoc = ThisApplication.ActiveDocument
	
	'Ensure the active document is a drawing document
	If Not TypeOf oDrawingDoc Is DrawingDocument Then
		MessageBox.Show("This rule must be run on a drawing document.")
		Exit Sub
	End If

	For Each oSketchSymbol As SketchedSymbol In oDrawingDoc.ActiveSheet.SketchedSymbols
		
		If oSketchSymbol.Name = "VIEW QTY" Then
			
			Dim oGeometryIntent As GeometryIntent
			oGeometryIntent = oSketchSymbol.Leader.AllLeafNodes(1).AttachedEntity
			
			Dim oCurve As DrawingCurve
			oCurve = oGeometryIntent.Geometry
						
			For Each oTextBox In oSketchSymbol.Definition.Sketch.TextBoxes
				If oTextBox.Text.ToUpper = "<VIEW QTY>" Then
					oSketchSymbol.SetPromptResultText(oTextBox, CStr(Get_ViewQTY(oCurve)))
					oPartDict.clear
					Exit For
				End If
			Next

		End If
	Next
	
End Sub

Function Get_ViewQTY(oSelect As Object) As Double

	' Get the active document (assuming it's a drawing)
	Dim oDrawingDoc As Document
	oDrawingDoc = ThisApplication.ActiveDocument
	
	Dim oSheet As Sheet
	oSheet = oDrawingDoc.ActiveSheet
	
	'Dim oSelect As Object
	'Select = ThisApplication.CommandManager.Pick(SelectionFilterEnum.kDrawingCurveSegmentFilter, "Select a component's edge:")
		
	Dim oView As DrawingView
	'oView = oSelect.Parent.Parent  'Segment -> DrawingCurve -> DrawingView
	oView = oSelect.Parent
	
	'Dim oSelectComp As ComponentOccurrence
	'oSelectComp = oSelect.Parent.ModelGeometry.Parent.Parent 'Segment -> DrawingCurve -> Model Geometry -> SurfaceBodyProxy -> ComponentOccurrenceProxy
	
	Try
		oSelectComp = oSelect.ModelGeometry.Parent.ContainingOccurrence 'SurfaceBodyProxy
	Catch
		oSelectComp = oSelect.ModelGeometry.ContainingOccurrence 'Face Proxy
	End Try
	
	Dim oCompDoc As Document
	oCompDoc = oSelectComp.ReferencedDocumentDescriptor.ReferencedDocument

	Dim oReferencedDoc As Document
	oReferencedDoc = oView.ReferencedDocumentDescriptor.ReferencedDocument
	
	' Check if the referenced document is an assembly
	Dim oAssemblyDoc As AssemblyDocument
	If oReferencedDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
		oAssemblyDoc = CType(oReferencedDoc, AssemblyDocument)
		' Traverse all occurrences and place symbols on parts visible in the selected view
		TraverseOccurrences(oAssemblyDoc.ComponentDefinition.Occurrences, oView, oSketchSymDef, oSheet)
	Else
		MessageBox.Show("Referenced document is not an assembly.")
	End If
			
	Dim sList As String = vbLf
	For Each key In oPartDict.Keys
		sList = sList & key.DisplayName & " - QTY: " & oPartDict(key) & vbLf
	Next 

	Dim oViewQty As Double
	oViewQty = oPartDict(oCompDoc)
	
	'Logger.Info("View '" & oView.Name & "' Part: " & oCompDoc.DisplayName)
	'Logger.Info(sList)
	'MessageBox.Show(sList, "View " & oView.Name & " included parts")
	
	Return(oViewQty)
	
	'Update the sheet
	'oSheet.Update()

End Function

Public oPartDict As New Dictionary(Of Document, Double)

' Function to check if a point is within the view's viewport
Function IsPointInView(oPoint As Point2d, oView As DrawingView) As Boolean

	Dim viewWidth As Double = oView.Width
	Dim viewHeight As Double = oView.Height
	Dim viewCenter As Point2d = oView.Center
	
	Dim minX As Double = viewCenter.X - viewWidth / 2
	Dim maxX As Double = viewCenter.X + viewWidth / 2
	Dim minY As Double = viewCenter.Y - viewHeight / 2
	Dim maxY As Double = viewCenter.Y + viewHeight / 2
	
	Return oPoint.X >= minX AndAlso oPoint.X <= maxX AndAlso oPoint.Y >= minY AndAlso oPoint.Y <= maxY
	
End Function

' Recursive function to traverse all occurrences and place symbols on parts visible in the selected view
Sub TraverseOccurrences(oOccurrences As ComponentOccurrences, selectedView As DrawingView, oSketchSymDef As SketchedSymbolDefinition, oSheet As Sheet)

	Dim oOccurrence As ComponentOccurrence
	For Each oOccurrence In oOccurrences
		' Check if the occurrence is a part (not a subassembly)
		If oOccurrence.ReferencedDocumentDescriptor.ReferencedDocument.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
			Dim oPartDoc As PartDocument
			oPartDoc = CType(oOccurrence.ReferencedDocumentDescriptor.ReferencedDocument, PartDocument)
			
			Dim oTestPoint As Point
			Dim oPoint As Point2d
			
			For Each oBody As SurfaceBody In  oOccurrence.SurfaceBodies
				For Each oEdge As Edge In oBody.Edges
					i += 1
					oTestPoint = oEdge.PointOnEdge
					oPoint = selectedView.ModelToSheetSpace(oTestPoint)
					If IsPointInView(oPoint, selectedView) Then
						'Logger.Info(i & "  " & oOccurrence.Name)
						Exit For
					End If
				Next
				
				If IsPointInView(oPoint, selectedView) Then
					If oPartDict.ContainsKey(oPartDoc) Then
						oPartDict.Item(oPartDoc) += 1
					Else
						oPartDict.Add(oPartDoc, 1)
					End If
					Exit For
				End If
			Next
				
		ElseIf oOccurrence.ReferencedDocumentDescriptor.ReferencedDocument.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			' Recursively traverse subassemblies
			'Logger.Info("-------" & oOccurrence.ReferencedDocumentDescriptor.ReferencedDocument.Displayname)
			TraverseOccurrences(oOccurrence.SubOccurrences, selectedView, oSketchSymDef, oSheet)
		End If
	Next
	
End Sub