If you are not familiar with using RuleArguments, NameValueMap, or passing data between iLogic rules, it can be a little intimidating and maybe a little hard to understand at first, so I created a contribution post about this topic to help others out. Basically a NameValueMap is a single variable that can hold one or multiple name/value pairs of data. It is widely used for storing things like context information, settings, or options, so they can be sent or provided to another block of code or iLogic Rule all at once. Then the RuleArguments object is a tool used to retrieve those NameValueMap objects within the other block of code or iLogic rule.
The idea I had was to use these two tools to send either the referenced PartDocument object itself, or the FullFileName, or FullDocumentName of the referenced PartDocument, to the external rule so that the external rule knows very specifically which document it is supposed to be targeting (working with). Since I wasn't 100% sure if I could send the PartDocument object itself, I decided to switch to using the part's FullDocumentName instead, just to be sure. I don't know if you looked into the one link I included in my earlier post about document references or not, but there are many iLogic specific lines of code that are supposed to make doing some things much easier, but many of those tools are designed to always target whichever document is either currently 'active' or 'local'. But sometimes you need to target a document that is neither 'active' nor 'local', and in those cases, you need to specify the exact document you intend for the code to be targeting, to avoid errors and unintended stuff happening. This is one of those cases, because the Part document the external rule is supposed to be targeting is not the 'local' document, and it isn't going to be the 'active' document either. So we need to specify exactly which document the rule is supposed to be targeting, one way or another.
Here is the slightly revised assembly level rule, for running your external rule. I am now using the other line I mentioned for running the rule 'with arguments'. Just before that line, I create a variable (oArgs) as a NameValueMap, then create a new empty NameValueMap as its value. Then I add one Name/Value pair to it, with the Name being "TargetDoc", and the Value being the FullDocumentName of the referenced part document. Then I supply the variable (oArgs) as the third input variable in the line that runs the external rule. This will send that data to the specified external rule that it will run.
If ThisApplication.ActiveDocumentType <> DocumentTypeEnum.kAssemblyDocumentObject Then
MsgBox("An Assembly Document must be active for this rule (" & iLogicVb.RuleName & ") to work. Exiting.",vbOKOnly+vbCritical, "WRONG DOCUMENT TYPE")
Exit Sub
End If
Dim oADoc As AssemblyDocument = ThisApplication.ActiveDocument
For Each oRefDoc As Document In oADoc.AllReferencedDocuments
If oRefDoc.DocumentType = DocumentTypeEnum.kPartDocumentObject Then
Dim oPDoc As PartDocument = oRefDoc
Dim oArgs As NameValueMap = ThisApplication.TransientObjects.CreateNameValueMap
oArgs.Add("TargetDoc", oPDoc.FullDocumentName)
iLogicVb.Automation.RunExternalRuleWithArguments(oPDoc, "External Rule Name", oArgs)
End If
Next
That extra code at the beginning of the external rule is designed to retrieve the data being sent to it. Since I changed the plan from sending/receiving a PartDocument object to sending/receiving the part's FullDocumentName (String/text), I now have to slightly change that code at the beginning of the external rule to expect and handle that different data. I set-it up so that if it doesn't find this data being sent to it, it will then revert back to using 'ThisDoc.Document' to define which document to target (that way it can still be used directly on an open part document, like it was originally if needed).
So at the top of the external rule, change this code:
Dim oTargetDoc As PartDocument
If RuleArguments.Exists("TargetDoc") Then
oTargetDoc = RuleArguments.Value("TargetDoc")
Else
If TypeOf ThisDoc.Document Is PartDocument Then
oTargetDoc = ThisDoc.Document
End If
End If
to this code:
Dim oTargetDoc As PartDocument
Dim oFullDocumentName As String
If RuleArguments.Exists("TargetDoc") Then
oFullDocumentName = RuleArguments.Value("TargetDoc")
oTargetDoc = ThisApplication.Documents.ItemByName(oFullDocumentName)
Else
If TypeOf ThisDoc.Document Is PartDocument Then
oTargetDoc = ThisDoc.Document
End If
End If
Wesley Crihfield

(Not an Autodesk Employee)