Wednesday, May 18, 2022

iLogic: Custom Sort PartsList with Temporary Column

 



Issue: 

You have a parts list that has a challenging sort criteria, due to needing to sort for values that might or might not exist in the same column. 

In the example above we want to sort the description column based on all items with a mark number (MK) value, and then sort those without a mark number alphabetically.



Solution:

Although we can't accomplish this out of the box, here are 3 code examples to do this that use iLogic and some API calls.


--------------------------------------------------------------
V1: Version to handle single parts list on the active sheet
--------------------------------------------------------------
sSortColumnName = "KEYWORDS"

' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument

' Set a reference to the first parts list on the active sheet.
Dim oPartsList As PartsList
Try
	oPartsList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
Catch
	Return 'exit rule
End Try

Dim oADoc As AssemblyDocument
oADoc = oPartsList.ReferencedDocumentDescriptor.ReferencedDocument
Dim oPropSet As PropertySet
oPropSet = oADoc.PropertySets.Item("Inventor Summary Information")

'add temporary column to the parts list
oID = oPropSet.Item(sSortColumnName).PropId
Try
	oPartsList.PartsListColumns.Add _
	(PropertyTypeEnum.kFileProperty, oPropSet.InternalName, oID)
Catch
End Try

' Iterate through the contents of the parts list.
Dim i As Long
For i = 1 To oPartsList.PartsListRows.Count

	'get the Description value
	oCell = oPartsList.PartsListRows.Item(i).Item("DESCRIPTION")

	'split the string at the comma
	'expecting a string like: 
	'		Bracket, MK B-114
	sArray = Split(oCell.Value, ",")
	sType = sArray(0)

	Try
		sMK = sArray(1)
	Catch 'error when no comma in string
		sMK = ""
	End Try


	'get the temp column cell
	oTempColumnCell = oPartsList.PartsListRows.Item(i).Item(sSortColumnName)

	'write to temp column
	If sMK.Contains("MK") Then
		'strip off the MK
		sMK = Replace(sMK, "MK ", "")
		oTempColumnCell.Value = sMK
	Else
		oTempColumnCell.Value = sType
	End If
Next

'sort and renumber
oPartsList.Sort(sSortColumnName)
oPartsList.Renumber
'remove temp column
oPartsList.PartsListColumns(sSortColumnName).remove

--------------------------------------------------------------
V2: Version for multiple sheets
--------------------------------------------------------------
sSortColumnName = "KEYWORDS"

' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument

Dim oCurrentSheet As Sheet
oCurrentSheet = oDrawDoc.ActiveSheet

Dim oSheet As Sheet
For Each oSheet In oDrawDoc.Sheets
	oSheet.Activate

	' Set a reference to the first parts list on the active sheet.
	Dim oPartsList As PartsList
	Try
		oPartsList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
	Catch
		Return 'exit rule
	End Try

	Dim oADoc As AssemblyDocument
	oADoc = oPartsList.ReferencedDocumentDescriptor.ReferencedDocument
	Dim oPropSet As PropertySet
	oPropSet = oADoc.PropertySets.Item("Inventor Summary Information")

	'add temporary column to the parts list
	oID = oPropSet.Item(sSortColumnName).PropId
	Try
		oPartsList.PartsListColumns.Add _
		(PropertyTypeEnum.kFileProperty, oPropSet.InternalName, oID)
	Catch
	End Try

	' Iterate through the contents of the parts list.
	Dim i As Long
	For i = 1 To oPartsList.PartsListRows.Count

		'get the Description value
		oCell = oPartsList.PartsListRows.Item(i).Item("DESCRIPTION")

		'split the string at the comma
		'expecting a string like: 
		'		Bracket, MK B-114
		sArray = Split(oCell.Value, ",")
		sType = sArray(0)

		Try
			sMK = sArray(1)
		Catch 'error when no comma in string
			sMK = ""
		End Try


		'get the temp column cell
		oTempColumnCell = oPartsList.PartsListRows.Item(i).Item(sSortColumnName)

		'write to temp column
		If sMK.Contains("MK") Then
			'strip off the MK
			sMK = Replace(sMK, "MK ", "")
			oTempColumnCell.Value = sMK
		Else
			oTempColumnCell.Value = sType
		End If
	Next

	'sort and renumber
	oPartsList.Sort(sSortColumnName)
	oPartsList.Renumber
	'remove temp column
	oPartsList.PartsListColumns(sSortColumnName).Remove
Next
oCurrentSheet.activate
InventorVb.DocumentUpdate()



--------------------------------------------------------------
V3: Version for multiple parts list on the active sheet
--------------------------------------------------------------
sSortColumnName = "KEYWORDS"

' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument

Dim oPartsList As PartsList = ThisApplication.CommandManager.Pick _
(SelectionFilterEnum.kDrawingPartsListFilter, "Select a Parts List to sort.")

If oPartsList Is Nothing Then Return 'exit rule

Dim oADoc As AssemblyDocument
oADoc = oPartsList.ReferencedDocumentDescriptor.ReferencedDocument
Dim oPropSet As PropertySet
oPropSet = oADoc.PropertySets.Item("Inventor Summary Information")

'add temporary column to the parts list
oID = oPropSet.Item(sSortColumnName).PropId
Try
	oPartsList.PartsListColumns.Add _
	(PropertyTypeEnum.kFileProperty, oPropSet.InternalName, oID)
Catch
End Try

' Iterate through the contents of the parts list.
Dim i As Long
For i = 1 To oPartsList.PartsListRows.Count

	'get the Description value
	oCell = oPartsList.PartsListRows.Item(i).Item("DESCRIPTION")

	'split the string at the comma
	'expecting a string like: 
	'		Bracket, MK B-114
	sArray = Split(oCell.Value, ",")
	sType = sArray(0)

	Try
		sMK = sArray(1)
	Catch 'error when no comma in string
		sMK = ""
	End Try


	'get the temp column cell
	oTempColumnCell = oPartsList.PartsListRows.Item(i).Item(sSortColumnName)

	'write to temp column
	If sMK.Contains("MK") Then
		'strip off the MK
		sMK = Replace(sMK, "MK ", "")
		oTempColumnCell.Value = sMK
	Else
		oTempColumnCell.Value = sType
	End If
Next

'sort and renumber
oPartsList.Sort(sSortColumnName)
oPartsList.Renumber
'remove temp column
oPartsList.PartsListColumns(sSortColumnName).Remove

InventorVb.DocumentUpdate()

Tuesday, March 29, 2022

Inventor API: using UnitsOfMeasure.ConvertUnits

Issue:

You're writing a bit of code that might be used in Inventor documents of varying unit types. For instance maybe this code is sometimes used in inch based parts, other times it's used in millimeter based parts, and sometime centimeter based parts. Or maybe the part has some dimensions entered in inches and some entered in millimeters. In any case you want your code to handle all of this.


Recall that when we work with the API, inventor returns values in its internal units, which is always centimeters. So we often need to have our code apply a conversion factor. 

Because of this you want the code to detect the units and do the conversion automatically.

Note:
If we're working with straight iLogic and no API calls, then the conversion is *often* handled for us internally in the iLogic function.    

*I won't say always*


Solution:
Below is a quick example that you can use to do the units detection and conversion in your code.

Here is the basic function. It uses the document's length units and centimeters to determine the conversion factor, and displays this in a message box to return the conversion factor.


Dim oUOM As UnitsOfMeasure
oUOM = ThisDoc.Document.UnitsOfMeasure
oLenUnits = oUOM.GetStringFromType(UnitsTypeEnum.kDefaultDisplayLengthUnits)
oInvUnits = UnitsTypeEnum.kCentimeterLengthUnits
oInvUnitString = oUOM.GetStringFromType(oInvUnits)
oConversion = oUOM.ConvertUnits(1, oUOM.LengthUnits, oInvUnits)

MsgBox("Document Units = " & oLenUnits & vbLf & _
	"Inventor Internal Units = " & oInvUnitString & vbLf & _
	"Conversion factor = " & oConversion, , "Inventor")





And here is a quick example using it to return the value of a selected sketch dimension.
This part is set to inches (Tools tab > Document Setting button > Units tab > Length setting)



Here a sketch dimension/parameter named length is set to 70 mm, even though the part file is using Inches. And because our code is using the API to get the parameter value, we know that it's going to be returned in centimeters. 








Without the conversion factor, the code returns 7, which is the value in Inventor's internal units of centimeters.










So we use the UnitsOfMeasure.ConvertUnits function to handle all of this and return the expected value in the document units. 






With the conversion code, it returns 2.756, which is the value in inches.


Here's the working example:
Dim oUOM As UnitsOfMeasure
oUOM = ThisDoc.Document.UnitsOfMeasure
oConversion = oUOM.ConvertUnits(1, oUOM.LengthUnits, _
				UnitsTypeEnum.kCentimeterLengthUnits)

oMsg = "Select a sketch dimension(Press Esc to continue)"

While True
	Dim oDimension As DimensionConstraint
	oDimension = ThisApplication.CommandManager.Pick(
	SelectionFilterEnum.kSketchDimConstraintFilter, oMsg)
	
	' If nothing gets selected then we're done	
	If IsNothing(oDimension) Then Exit While
	oParam = oDimension.Parameter	
	oParamVal = Round(oParam.Value() / oConversion, 3)
	
	MsgBox(oParamVal,,"Inventor")	
End While

Monday, March 28, 2022

iLogic: Select and Set Sketch Dimension Tolerances

 

Issue:
You want to to quickly select and set standard tolerances for your sketch dimensions.


Solution:
Here is a quick routine written for iLogic using the API to do this. This employs the CommandManager's Pick function to allow you to select individual dimensions and set the tolerance.

Thank you! to Ron Moore, for the question/post idea.


oMsg = "Select sketch dimensions to apply default tolerance (Press Esc to continue)"

While True

        Dim oDimension As DimensionConstraint

        oDimension = ThisApplication.CommandManager.Pick(

        SelectionFilterEnum.kSketchDimConstraintFilter, oMsg) 

        ' If nothing gets selected then we're done   

        If IsNothing(oDimension) Then Exit While 

        oDimension.Parameter.Tolerance.SetToSymmetric(0.05)

End While


Thursday, February 16, 2017

iLogic - Dynamic MultiValue Parameter Lists "Filtered" By Current Selected Value

Issue:
You want to "filter" a list (List B) based on the selection from another list (List A), but the lists are long and writing the If/Then or Select Case statements are repetitive, and difficult to maintain. Is there a better way?

Solution:
You can use ArrayLists and For Each Statements to do this, as shown in this example.

Here an illogic form is used, and when a value is selected from List A, then List B and C are reset to include only values less than or equal to the current selected List A value.



Example file:
Dynamic MultiValue Lists iLogic 2015.ipt ‏68 KB    

SyntaxEditor Code Snippet
Example code:

'reset List B list to default
MultiValue.SetList("List_B", 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16)

'reset List C list to default
MultiValue.SetList("List_C", 2,4,6,8,10,12,14,16)

Dim B_List As New ArrayList
B_List = MultiValue.List("List_B")

Dim C_List As New ArrayList
C_List = MultiValue.List("List_C")

Dim Temp_List As New ArrayList

Temp_List.Clear
For Each oItem in B_List
    If List_A >= oItem Then
        Temp_List.Add(oItem)
    End If
Next

MultiValue.List("List_B") = Temp_List

Temp_List.Clear
For Each oItem in C_List
    If List_A >= oItem Then
        Temp_List.Add(oItem)
    End If
Next

MultiValue.List("List_C") = Temp_List

Friday, February 10, 2017

Hybrid Wireframe and Shaded Views in Autodesk Inventor




Issue:
You want to create a view on your drawing that has some parts shaded and some that look wire-framed, so you can show some particular detail of your assembly in your detailed drawing.


In the past you could do it as described in tip #1 at this link, but that seems not to work now.
http://inventortrenches.blogspot.com/2011/06/autodesk-inventor-tips-from-around-web.html

Solution:
Here is another way to do this.

Create one new Positional Representation ( no need to do anything else with it, other than creating it).
  • Create 2 View Representations
  • In View Representation 1, turn off the visibility of the part you want to show wireframe
  • In View Representation 2, turn off the visibility of everything else
  • Create a drawing Base View and set it to use View Representation 2
  • Create an Overlay View, and set it to use the Positional Representation and View Representation 1
  • In the Overlay View dialog box set the style to be not shaded & hidden lines removed
  • And also in the Overlay View dialog box set the Layer dropdown to be 'As Parts'.


  • Here's a link to a quick video I created, but I think the CADLine blog has covered this better at this link:
    https://www.cadlinecommunity.co.uk/hc/en-us/articles/115001863349-Inventor-Partial-Shaded-Drawings

    Thursday, October 23, 2014

    iLogic - Suppress Components in all but the Active Level of Detail

    Issue:
    Your assembly has several Level of Detail Representations set up, which works well. The problem is that when you add a new component to the assembly, you have to go to each Level of Detail and suppress the component in order to prevent it from showing up in those existing Level of Detail Representations.



    Solution:
    Here is an iLogic rule that will suppress any selected components in all of the other LOD's, with the exception of the active LOD.

    This allows you to place the component in the assembly with the LOD you want to add the component to set active, then select the component (or components) and run this iLogic rule to remove the component(s) from the other LODs.

    This iLogic rule also doesn't suppress the selected components in the standard LODs, such as the "Master" LOD, the "All Content Center Suppressed" LOD, etc.

    Note too that it saves the file each time one of the other LODs is modified in order to make the changes "stick", so if you have a large assembly with many LODs it might take a bit for this rule to run.






    Dim oDoc As AssemblyDocument
    oDoc = ThisApplication.ActiveDocument

    ' Find all selected components and add them to an ObjectCollection.
    Dim oSelected As ObjectCollection
    oSelected = ThisApplication.TransientObjects. _
    CreateObjectCollection (oDoc.SelectSet)

    'define LOD rep
    Dim oLODRep As LevelOfDetailRepresentation

    'define rep manager
    Rep_Manager =ThisApplication.ActiveDocument. _
    ComponentDefinition.RepresentationsManager

    'define an arraylist to hold the list of  LOD rep names
    Dim NameList As New ArrayList()

    'look at the LOD reps in the assembly
    For Each oLODRep in Rep_Manager.LevelOfDetailRepresentations
    'add the LOD names to the array list
    NameList.add(oLODRep.Name)
    Next

    Dim myLOD as LevelOfDetailRepresentation
    'get the name of the active LOD
    myLOD = Rep_Manager.ActiveLevelOfDetailRepresentation

    'remove active LOD from list
    NameList.remove(myLOD.name)

    'remove standard LODs from list
    NameList.remove("Master")
    NameList.remove("All Components Suppressed")
    NameList.remove("All Parts Suppressed")
    NameList.remove("All Content Center Suppressed")

    'step through the LOD list
    'and suppress the selected components
    Dim sName as String
    For Each sName in NameList
                    'Activate the LOD
                    Rep_Manager.LevelOfDetailRepresentations(sName).Activate
                    For Each oObject in oSelected
                                    Try
                            'suppress component
                                    Component.IsActive(oObject.Name) = False
                                    Catch ' catch any errors
                                    End Try
                            Next
                ThisDoc.Save
    Next    

    'set the original active LOD back to active
    Rep_Manager.LevelOfDetailRepresentations(Trim(myLOD.Name)).Activate