Ilogic Rule opens IDWs referenced from parts lists

Ilogic Rule opens IDWs referenced from parts lists

Mac_W
Contributor Contributor
938 Views
4 Replies
Message 1 of 5

Ilogic Rule opens IDWs referenced from parts lists

Mac_W
Contributor
Contributor

Hello Autodesk Community! This is my first post here, I have been lurking the forums for a few weeks now trying to learn how to automate opening all the IDWs relevant to the production of a product. I want to thank the members of this community for their contributions, I've learned and pasted a lot from here.

 

Using Inventor Pro 2022 and Vault Basic 2022, this external Ilogic Rule sometimes successfully runs on a top level assembly IDW. For each row in the parts list, the rule opens the ipt or iam referenced and calls OpenVaultIDW which gets and opens the active document's corresponding IDW from the vault; OpenVaultIDW then closes the ipt or iam.  If the referenced parts list row is an assembly then after OpenVaultIDW ends, the main sub in this rule calls itself recursively. This code works on some assemblies and does not on others. I am pretty new to VBnet and Ilogic, and am struggling to figure out what is wrong with this code; Any help or advice would be greatly appreciated. 

 

This is the parts list for my example: "Test Assy.idw" both items are sub-assemblies containing multiple parts

 

 

 

 

 

 

ITEM    DESCRIPTION            QTY      PART NUMBER
1       ARM, SUB, FOAM, RH      1       E10804
2       ARM, SUB, FOAM, LH      1       E10818

 

 

 

 

 

 

 

I get this error after E10804.idw is opened

 

 

 

 

 

 

Error in rule: OpenAll, in document: Test Assy.idw

(Error Message) 
Error in rule: OpenAll, in document: Test Assy.idw

Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))


(More Info)
System.Runtime.InteropServices.COMException (0x80004005): Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))
   at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
   at Inventor.DrawingBOMRow.get_BOMRow()
   at ThisRule.Main()
   at ThisRule.DupeCheck()
   at ThisRule.Main()
   at Autodesk.iLogic.Exec.AppDomExec.ExecRuleInAssembly(Assembly assem)
   at iLogic.RuleEvalContainer.ExecRuleEval(String execRule)

 

 

 

 

 

 

 

This is the rule:

 

 

 

 

 

 

Sub Main()

	'Source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-parts-list-amp-opening-drawings/td-p/5976549

	Dim oDrawDoc As Document = ThisApplication.ActiveDocument
	Dim oSheet As Sheet = oDrawDoc.ActiveSheet
	Dim oPartList As PartsList

	oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)

	Dim drawBomRow As DrawingBOMRow
	Dim refDoc As Document

	For Each oPartListRow In oPartList.PartsListRows 'goes down the parts list if there is one
	
	
		If oPartListRow.Visible = "True" Then
			Try
				drawBomRow = oPartListRow.ReferencedRows.Item(1)
				refDoc = drawBomRow.BOMRow.ComponentDefinitions.Item(1).Document
				FilePath = refDoc.FullFileName()
				ThisApplication.Documents.Open(FilePath, True) 'Open next Iam/Ipt on parts list for reference
				Dim oDrawDoc2 As Document = ThisApplication.ActiveDocument 'set opened Iam/Ipt as active
	
			Catch
				drawBomRow = oPartListRow.ReferencedRows.Item(1)
				refDoc = drawBomRow.BOMRow.ComponentDefinitions.Item(1).Document
				FilePath = refDoc.FullFileName()
				FilePath = Left(FilePath,Len(FilePath)-3) & "idw"	
				MsgBox(FilePath, "File Not Found")
			End Try
		End If

		DupeCheck()
		
	Next
End Sub

'we need to check if drawing is already open and if it is not then open it
'if already open then we call CopyTab()
Sub DupeCheck()

	'source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-check-if-drawing-file-is-open/td-p/10243425

	Dim oDoc As Document = ThisApplication.ActiveDocument

	ThisName = System.IO.Path.GetFileNameWithoutExtension(oDoc.FullFileName)
	For Each Doc In ThisApplication.Documents 'check if there is an open IDW with matching doc name
		Dim oDC As Document = Doc
		If oDC.DocumentType = DocumentTypeEnum.kDrawingDocumentObject And System.IO.Path.GetFileNameWithoutExtension(oDC.FullFileName) = ThisName
			oDC.Activate
			Call CopyTab() 'copy IDW window to new window
			oDoc.Close(True) 'close the reference doc
			Exit Sub
		End If
	Next

	If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then 'If active doc=Iam, do recursion
		iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\OpenVaultIDW") 'opens matching IDW and closes refDoc
		Call Main()
	Else
		iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\OpenVaultIDW") 'opens matching IDW and closes refDoc
	End If
 
End Sub

'copy IDW window to new window
Sub CopyTab()

	'source: https://help.autodesk.com/view/INVNTOR/2023/ENU/?guid=GUID-DB8C7D03-9B57-403B-885F-2F2180CBD45A
	
    Dim oDoc2 As Document = ThisApplication.ActiveDocument
    
    Dim oView1 As View
    oView1 = oDoc2.Views(1)
    
    Dim oViewTab1 As ViewTab
    oViewTab1 = oView1.ViewTab
        
    Dim oView2 As View
    oView2 = oDoc2.Views.Add
    
End Sub

 

 

 

 

 

 

 

0 Likes
Accepted solutions (1)
939 Views
4 Replies
Replies (4)
Message 2 of 5

WCrihfield
Mentor
Mentor

Hi @Mac_W.  That is a tough one to diagnose.  The error message indicates that it is encountering a problem at a location within your code where you are trying to access the regular BOMRow object from a DrawingBOMRow object, through its property (DrawingBOMRow.BOMRow).  I can see 2 places like that in your code.  Both are on the second line within the Try side, and the Catch side of your inner most Try..Catch block of code, within your Sub Main block of code.  I am not sure why it would be encountering a problem at that specific step.  I assume that would indicate that the row exists on the drawing side, but not on the assembly side, but I am not sure.  According to this API Sample code (which is in VBA, not iLogic), you may need to check the DrawingBOMRow.Custom property at that stage, if that is a possibility.  If that property returns True, that would indicate that the DrawingBOMRow is a custom one, in which case, there would not be a BOMRow object on the assembly side for it.

 

Another thing that you may need to deal with is ModelStates.  If any of the files involved have more than just the one default ModelState included, that would mean that the file on disk will contain multiple Document references within.  And when that is the case, you have to make sure you are dealing with the right Document within that file.  I noticed that you are using the Documents.Open method within your code, but you are only supplying the FullFileName to it.  It will become more important from now on to use the FullDocumentName in those types of places.  The FullDocumentName starts with the FullFileName, but then sometimes it has more information after that to indicate which specific iPartMember or ModelState Member within that file you want to target/reference.

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 5

Mac_W
Contributor
Contributor

@WCrihfield Thanks for helping diagnose the cause of the error and providing excellent reference documentation! I also appreciate your suggestions and have changed my use of FullFileName to FullDocumentName, I haven't tested this on any Iparts or Iassemblies yet but we do have a small percentage of products that utilize them and it would be great if they were compatible. 

 

After reading your post and the links your provided I did some more digging into the differences between the drawings and Boms that this rule works on vs doesn't. I think the error happens when a drawing's parts list uses "BOM View: Legacy Structured" If I right click on the parts list and click "Convert" then when I run the rule again, it executes without issue. I'm now trying to figure out how to Convert the parts list automatically in the rule but I am struggling to figure out how I would do that. Bellow is a picture referencing how you could manually convert the parts list.

 

manual solution.png

 

 

I've also made some changes to my rule to handle situations where a part or assembly doesn't have an IDW (ex: nuts and bolts) Bellow is my updated code including the OpenVaultIDW rule and an additional rule that helps handle a potential issues of top level drawings finding themselves in the list(infrequent issue and I don't really know why it happens but this seems to fix that)

 

OpenAll

Sub main()
	
	OgFilePath = ThisDoc.FileName(False)

	Og = RuleArguments("Og")
	Dim map As Inventor.NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap()
	map.Add("Og", OgFilePath)
	iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\OpenAllLogic", map)	
	
End Sub

 

OpenAllLogic

'Source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-parts-list-amp-opening-drawings/td-p/5976549
Sub Main()
	Dim oDrawDoc As Document = ThisApplication.ActiveDocument
	Dim oSheet As Sheet = oDrawDoc.ActiveSheet
	Dim oPartList As PartsList
	Dim drawBomRow As DrawingBOMRow
	Dim refDoc As Document
	Dim CatchBool as Boolean = False
	'Try
		oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
		For Each oPartListRow In oPartList.PartsListRows 'goes down the parts list if there is one
			If oPartListRow.Visible = "True" And oPartListRow.Custom = "False" Then	
				drawBomRow = oPartListRow.ReferencedRows.Item(1)
				refDoc = drawBomRow.BOMRow.ComponentDefinitions.Item(1).Document
				FilePath = refDoc.FullDocumentName()
				ThisApplication.Documents.Open(FilePath, True) 'Open next Iam/Ipt on parts list for reference
				Dim oDrawDoc2 As Document = ThisApplication.ActiveDocument 'set opened Iam/Ipt as active
			Else If oPartListRow.Custom = "True" Then
				MsgBox("Parts list is custom")
				Exit Sub
			End If
			DupeCheck()
		Next
	'Catch
		'oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1).Convert <- Fake code I would like to be real
		'CatchBool = True
	'End Try
	If CatchBool = True Then
		Call Main()
	End If
End Sub

'we need to check if drawing is already open and if it is not then open it
'if already open then we call CopyTab()

'source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-check-if-drawing-file-is-open/td-p/10243425
Sub DupeCheck()
	Dim oDoc As Document = ThisApplication.ActiveDocument
	TopLVL = RuleArguments("Og")
	ThisName = System.IO.Path.GetFileNameWithoutExtension(oDoc.FullDocumentName)
	MsgBox(ThisName & " compared to " & TopLVL)
	For Each Doc In ThisApplication.Documents 'check if there is an open IDW with matching doc name
		Dim oDC As Document = Doc
		If oDC.DocumentType = DocumentTypeEnum.kDrawingDocumentObject And System.IO.Path.GetFileNameWithoutExtension(oDC.FullDocumentName) = ThisName And TopLVL <> ThisName
			oDC.Activate
			Call CopyTab() 'copy IDW window to new window
			If oDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then 'if duped doc is an assy we get recursive
				oDoc.Close(True) 'close the reference doc
				Call Main()
			Else 
				oDoc.Close(True) 'close the reference doc
			End If
			Exit Sub
		End If
	Next

	If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then 'If active doc=Iam, do recursion
		iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\OpenVaultIDW") 'opens matching IDW and closes refDoc
		If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kDrawingDocumentObject Then
			MsgBox("call main")
			Call Main()
		Else If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then
			MsgBox("close iam")
			ThisApplication.ActiveDocument.Close(True)
		End If
	Else If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
		iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\OpenVaultIDW") 'opens matching IDW and closes refDoc
		If ThisApplication.ActiveDocument.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
			MsgBox("close ipt")
			ThisApplication.ActiveDocument.Close(True)
		End If
	End If
 
End Sub

'copy IDW window to new window
'source: https://help.autodesk.com/view/INVNTOR/2023/ENU/?guid=GUID-DB8C7D03-9B57-403B-885F-2F2180CBD45A
Sub CopyTab()
	MsgBox("CopyTab Called")
    Dim oDoc2 As Document = ThisApplication.ActiveDocument
    
    Dim oView1 As View
    oView1 = oDoc2.Views(1)
    
    Dim oViewTab1 As ViewTab
    oViewTab1 = oView1.ViewTab
        
    Dim oView2 As View
    oView2 = oDoc2.Views.Add
    
End Sub

 

OpenVaultIDW

AddReference "Autodesk.Connectivity.WebServices.dll"
Imports ACW = Autodesk.Connectivity.WebServices
AddReference "Autodesk.DataManagement.Client.Framework.Vault.dll"
AddReference "Autodesk.DataManagement.Client.Framework.dll"
Imports VDF = Autodesk.DataManagement.Client.Framework
AddReference "Connectivity.Application.VaultBase.dll"
Imports VB = Connectivity.Application.VaultBase


'source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-open-drawing-from-vault-default/m-p/9809554/highlight/true#M117029
Public Class ThisRule


	Sub Main()

		Dim oApp As Inventor.Application = ThisApplication
		'Dim oDoc As Document = ThisDoc.Document
			Dim oDoc As Document = ThisApplication.ActiveDocument
		If TypeOf ThisDoc.Document Is AssemblyDocument Then
			If ThisDoc.Document.SelectSet.Count > 0 Then
				oDoc = ThisDoc.Document.SelectSet(1).Definition.Document
			End If
		End If
	
		Dim docfullfilename As String = oDoc.FullDocumentName
		Dim docfilename As String = RPointToBackSlash(oDoc.FullDocumentName)

		'Retrieve all drawings from the vault
		'Access Vault Connection and exit if necessary
		Dim mVltCon As VDF.Vault.Currency.Connections.Connection = VB.ConnectionManager.Instance.Connection
		If mVltCon Is Nothing Then Exit Sub
		'Access ACW property definition status
		Dim filePropDefs As ACW.PropDef() = mVltCon.WebServiceManager.PropertyService.GetPropertyDefinitionsByEntityClassId("FILE")
		Dim ACWNamePropDef As ACW.PropDef
		For Each def As ACW.PropDef In filePropDefs
    		If def.DispName = "Name" Then
        		ACWNamePropDef = def
				Exit For
    		End If
		Next def  
		'Set search options
		Dim namesucheoptionen As New ACW.SrchCond() With { _
			.PropDefId = ACWNamePropDef.Id, _
			.PropTyp = ACW.PropertySearchType.SingleProperty, _
			.SrchOper = 3, _
			.SrchRule = ACW.SearchRuleType.Must, _
			.SrchTxt = docfilename & ".idw" _
		}

		Dim bookmark As String = String.Empty
		Dim status As ACW.SrchStatus = Nothing
		Dim results As ACW.File() = mVltCon.WebServiceManager.DocumentService.FindFilesBySearchConditions(New ACW.SrchCond() {namesucheoptionen }, Nothing, Nothing, False, True, bookmark, status)

		Dim settings As New VDF.Vault.Settings.AcquireFilesSettings(mVltCon)
		If results Is Nothing Then
			'MessageBox.Show("The document " & docfilename & " is not in the vault.", "Info")
		Else
			For Each res In results
				Dim oFileIteration As VDF.Vault.Currency.Entities.FileIteration = New VDF.Vault.Currency.Entities.FileIteration(mVltCon, res)
				settings.OptionsRelationshipGathering.FileRelationshipSettings.IncludeRelatedDocumentation = True
				settings.OptionsRelationshipGathering.FileRelationshipSettings.VersionGatheringOption = VDF.Vault.Currency.VersionGatheringOption.Latest
				settings.AddFileToAcquire(oFileIteration, VDF.Vault.Settings.AcquireFilesSettings.AcquisitionOption.Download)
			Next
		End If
		Dim aquiresults As VDF.Vault.Results.AcquireFilesResults = mVltCon.FileManager.AcquireFiles(settings)

		'All downloaded idw's in list
		Dim idwList As New ArrayList
		For Each aquiresult As VDF.Vault.Results.FileAcquisitionResult In aquiresults.FileResults
			Dim aquiresultpath As String = aquiresult.LocalPath.FullPath
			If UCase(aquiresultpath).Contains(".IDW") Then
				idwList.Add(aquiresultpath)
			End If
		Next
		'close active ipt/iam
		If idwList.Count > 0 Then
			ThisApplication.ActiveDocument.Close(True)
		Else
			'MsgBox("~no IDW~")
		End If
		'MsgBox(idwList.Count)
		'idw's open
		For Each idw As String In idwList
			If idw.EndsWith(".idw")
				oApp.Documents.Open(idw, True)
				Exit Sub
				'MessageBox.Show("got " & idw)
			End If
		Next

	End Sub

	Function RPointToBackSlash(ByVal strText As String) As String
    	strText = Left(strText, InStrRev(strText, ".") - 1)
    	RPointToBackSlash = Right(strText, Len(strText) - InStrRev(strText, "\"))
	End Function

End Class

 

 Inclusion of all MsgBox is for debugging purposes

0 Likes
Message 4 of 5

A.Acheson
Mentor
Mentor
Accepted solution

Hi @Mac_W 

 

You can find it from the command list API help here. With keyword convert or partslist.

With the partlist preselected run the below command. The trick then is to have the partslist object or browser node preselected which is another mission. 

 

 

 

Dim oControlDefs As ControlDefinitions = ThisApplication.CommandManager.ControlDefinitions
oControlDefs.Item("DrawingPartsListConvertToBOMCtxCmd").Execute

 

 

 

If this solved a problem, please click (accept) as solution.‌‌‌‌
Or if this helped you, please, click (like)‌‌
Regards
Alan
Message 5 of 5

Mac_W
Contributor
Contributor

Thanks @A.Acheson! That list of command names and their descriptions is super useful. I also appreciate the command code you posted and the advice you gave on what I should do before executing it. The rules seem to work on everything I've tested so far, thanks again everyone!

 

This is my updated logic to handle if a parts list needs to be converted:

'Source: https://forums.autodesk.com/t5/inventor-ilogic-and-vb-net-forum/ilogic-parts-list-amp-opening-drawings/td-p/5976549
Sub Main()
	Dim oDrawDoc As Document = ThisApplication.ActiveDocument
	Dim oSheet As Sheet = oDrawDoc.ActiveSheet
	Dim oPartList As PartsList
	Dim drawBomRow As DrawingBOMRow
	Dim refDoc As Document
	Dim CatchBool As Boolean = False
	Try
		oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
		For Each oPartListRow In oPartList.PartsListRows 'goes down the parts list if there is one
			If oPartListRow.Visible = "True" And oPartListRow.Custom = "False" Then	
				drawBomRow = oPartListRow.ReferencedRows.Item(1)
				refDoc = drawBomRow.BOMRow.ComponentDefinitions.Item(1).Document
				FilePath = refDoc.FullDocumentName()
				ThisApplication.Documents.Open(FilePath, True) 'Open next Iam/Ipt on parts list for reference
				Dim oDrawDoc2 As Document = ThisApplication.ActiveDocument 'set opened Iam/Ipt as active
			Else If oPartListRow.Custom = "True" Then
				MsgBox("Parts list is custom")
				Exit Sub
			End If
			DupeCheck()
		Next
	Catch
		iLogicVb.RunExternalRule("C:\Users\xXxXxXx\Desktop\Inventor Macros\ConvertPartsListBom")
		msgbox("Parts List Converted")
		CatchBool = True
	End Try
	If CatchBool = True Then
		Call Main()
	End If
End Sub

 

This new rule selects a parts list and converts it for each parts list on the active sheet:

'source: https://modthemachine.typepad.com/my_weblog/2009/03/running-commands-using-the-api.html
Sub Main()
	
    ' Get the active document, assuming it is a drawing.
    Dim oDrawDoc As DrawingDocument
    oDrawDoc = ThisApplication.ActiveDocument

    ' Get the collection of partslists on the active sheet.
    Dim oPartsLists As Object
    oPartsLists = oDrawDoc.ActiveSheet.PartsLists

    ' Get a reference to the select set and clear it.
    Dim oSelectSet As SelectSet
    oSelectSet = oDrawDoc.SelectSet
    oSelectSet.Clear

    ' for each partslist select it and convert Bom
    Dim PartsList As Object
    For Each PartsList In oPartsLists
        oSelectSet.Select(PartsList)
		Call ConvertBom()
		oSelectSet.Clear
    Next


End Sub

Sub ConvertBom()
	Dim oControlDefs As ControlDefinitions = ThisApplication.CommandManager.ControlDefinitions
	oControlDefs.Item("DrawingPartsListConvertToBOMCtxCmd").Execute
End Sub