- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
replace object reference in sheet
Hello,
I have a code which you run within an assembly that makes a copy of the assembly(saveAs) and puts it into a predefined drawing sheet setup. The assembly and parts are all correctly referencing the new(copied) instances, since my code also copies parts.
however it doesn't replace the object reference for my individual part drawings, which means if i generate more than one drawing, they will start interacting with each other since the drawing references the same part file (the original ones)
Imports System.Windows.Forms
Imports Inventor
Sub Main
Dim partpath As String = ThisDrawing.ModelDocument.ComponentDefinition.Parameters.Item("Location").Value
Dim pLoc = parameter("PartLocation") = partpath & "\3D\"
sheet1
sheet2
End Sub
Sub sheet1
Dim doc = ThisDoc.Document
ActiveSheet = ThisDrawing.Sheet("Sheet1:1")
End Sub
Dim oFD As FileDescriptor
Sub sheet2
Dim doc = ThisDoc.Document
ActiveSheet = ThisDrawing.Sheet("sheet1:2")
Dim viewModelDoc As String = pLoc & "Cloth.ipt"
oFD = doc.ReferencedDocumentDescriptors(1).ReferencedDocument
doc.ReplaceReference(viewModelDoc)
doc.Update()
End Sub
I have written this code within the drawing file(.dwg) which i thought would replace the reference, but i can't seem to get it to work.
my thought process was to make a sub for each specific sheet, then as the first action it will open up that sheet to get the active sheet model, replace the reference and then go to the next sheet sub.
the folder \3D\ is an automatically generated folder from the initial assembly, which has both part files and assembly files within. every time a new version of the original assembly is generated, it will create this folder at the selected director. it will also create one called \2D\, however this is for the .dwg and PDF file.
the path could look like this
c:\[PATH to selected folder]\(new folder created with drawing number name)\2D and 3D lies here\
This is the error i'm getting when running the code, the problem lies around Line 27/28, but i can't seem to figure out what im doing wrong.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi @op_thorsager. There is so much here that seems wrong or questionable, I don't even know where to start. In the first part of your code you are attempting to access two different Parameters, one named "Location", and one named "PartLocation". You appear to be getting the initial 'path' information from the one named "Location", but then the next line of code is confusing me. Are you attempting to set the value of 'pLoc' from the parameter named "PartLocation" or are you trying to set the value of the parameter named "PartLocation"? You should not have two equals signs (=) in the same line of code. What is your intent with that line of code? Should the 'pLoc' variable be getting its value from the parameter named "Location" or from the parameter named "PartLocation"? Do you need to set the value of the parameter named "PartLocation" to the same value as the 'pLoc' variable?
Your 'pLoc' variable is not 'shared', like your 'oFD' variable is, therefore, when you are trying to use it within your 'sheet2' Sub routine, it is not only undefined, it also does not have a value yet (as far as that sub routine knows).
In your 'sheet2' sub routine, you are trying to set your 'oFD' variable's value to a Document type object (ReferencedDocument), instead of a FileDescriptor, therefore it is throwing an error. Then on the very next line of code, you are trying to use your 'doc' variable, instead of the 'oFD' variable with the 'ReplaceReference' method, which is only available to the FileDescriptor Type object, so that too would throw an error.
If the active drawing document has more than one referenced model document, then you may need to loop through each DrawingView on each sheet of the drawing, to replace the referenced model of each view, instead of trying to replace just the first file reference of the entire drawing. Otherwise you may need to loop through each referenced document in the drawing documents referenced documents collection, instead of just its first one (if more than one).
I also attempted to correct the line of code stetting the active sheet of the drawing, but I am not sure what your intent was in having an entire sub routine just for activating a specific sheet of the drawing.
Below is a version of your code which I attempted to correct, with my limited understanding of your intents, and before getting the above questions answered yet.
Imports System.Windows.Forms
Imports Inventor
Sub Main
oDDoc = ThisDoc.Document
Dim oModelDoc As Document = ThisDoc.ModelDocument
Dim oCD As ComponentDefinition = oModelDoc.ComponentDefinition
Dim oParams As Inventor.Parameters = oCD.Parameters
'??? which parameter is it supposed to be getting the correct path from ???
'??? is this also supposed to be setting the value of one of these parameters ???
Dim partpath As String = oParams.Item("Location").Value
pLoc = partpath & "\3D\"
oParams.Item("PartLocation").Value = pLoc
sheet1
sheet2
End Sub
'shared variables - available in every routine
Dim oDDoc As DrawingDocument
Dim pLoc As String
Dim oFD As FileDescriptor
Sub sheet1
oDDoc.Sheets.Item("Sheet1:1").Activate
End Sub
Sub sheet2
oDDoc.Sheets.Item("sheet1:2").Activate
Dim viewModelDoc As String = pLoc & "Cloth.ipt"
oFD = oDDoc.ReferencedDocumentDescriptors.Item(1).ReferencedFileDescriptor
oFD.ReplaceReference(viewModelDoc)
oDDoc.Update()
End Sub
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
just a quick explaination - i know the code posted was nowhere near functional, but more of a general visualization of what i was trying to achieve. the parameter named "partLocation" is the location in which the copy of the parts i want to get.
quick process timeline of my tool:
1) open assembly
2) adjust model as needed
3) export to a selected folder, in which a folder named after the drawing number will be made.
4) in here there are two folders created called "2D" and "3D".
5) The folder named 3D is where a copy of the original assembly and used parts will be made.
the component parameter named "Location" is a text parameter which updates to the root folder of the selected path in the assembly (step 3)
What the partlocation parameter is used for is basically to get the specific "3D" folder, instead of the root folder, so that iLogic knows where to look for the reference replacement
i cleaned up a bit and this is is how it's achieved:
Dim partpath As String = ThisDrawing.ModelDocument.ComponentDefinition.Parameters.Item("Location").Value PartLocation = partpath & "\3D\"
i'll be trying out the code you posted, if anything i'll atleast have the correct setup to get the new model references.
as for the double (=) i realized that aswell shortly after posting this thread, and changed it up, same goes for the shared variables.
i dont know if what i wrote made a little more sense
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Yes. That perfectly cleared up the parameters related questions. Since this code appears to be for an 'internal' iLogic rule, and it appears to be stored within the part's DrawingDocument, I assume then that there would only be one model reference in that whole drawing...just that one part, right? If so, then there would not be any need to activate any specific sheet(s), and no need for more than the one 'Main' routine. Assuming that the "PartLocation" parameter is 'local' (within the DrawingDocument), in which case it would usually turn blue.
Sub Main
Dim oDDoc As DrawingDocument = ThisDoc.Document
Dim partpath As String = ThisDoc.ModelDocument.ComponentDefinition.Parameters.Item("Location").Value
PartLocation = partpath & "\3D\"
Dim viewModelDoc As String = PartLocation & "Cloth.ipt"
Dim oFD As FileDescriptor = oDDoc.ReferencedDocumentDescriptors.Item(1).ReferencedFileDescriptor
oFD.ReplaceReference(viewModelDoc)
oDDoc.Update()
End Sub
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Within the drawing document There are multiple sheets, on every sheet There Will be One part present, except for the first sheet in which the assembly lies. The reference to the assembly is updated when doing the export from assembly, however the individual parts dont update. This is where i thought i’s make the sub routines like sheet1 and sheet2.
then when have the code loop through all the sheets, get the initial model from view, then replace the reference with the part copy which is saved in \3D\
end sub and go to next sheet and repeat
alll rules are internal, since we dont utilize vault(yet) so it became a bit tedious to do revisions of the rules as external
but to get back to the question:
drawing has multiple references, but only One model is present in sheet2
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
OK. I understand the situation better now. Things get fairly complicated when there is more than one 'model' being referenced in one drawing file, because a lot of the iLogic snippets were designed around there being just one. I have another idea though that might help with that scenario. What about getting DrawingDocument.ReferencedDocuments collection to a variable (not DrawingDocument.AllReferencedDocuments, because that would go too deep). Then simply loop through those referenced documents, instead of looping every sheet &/or every view, then extracting referenced document from the views. It just seems a bit more efficient that way, and no need to keep track if you have worked with that model before or not, because each would be unique.
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I don't think i understand exactly what you want to do here,
dim oDoc as DrawingDocument
oDoc.ReferencedDocuments
This is what i've put in, but now i'm pointing at all referenced documents.
how do i loop through them and replace them with the correct part reference?
as mentioned, the assembly does not need to replace its reference, since it's already referring to the newly created assembly file(same goes for the parts within it) however the assembly parts placed individually (1 for each sheet) does not have the updated reference, so these are the ones we need to update reference on
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
No need to loop through all the sheets and views.
You only have to exchange the References in the ReferencedFileDescriptors.
This sample exchanges Item(1) by C:\Temp\Part01new.ipt
Set oDrawDoc = ThisApplication.ActiveDocument
If oDrawDoc.DocumentType <> kDrawingDocumentObject Then
MsgBox "no IDW available"
Exit Sub
End If
Dim oFile As File
Set oFile = oDrawDoc.File
Dim oFD As FileDescriptor
Set oFD = oFile.ReferencedFileDescriptors.Item(1)
Call oFD.ReplaceReference("C:\Temp\Part01new.ipt")
During copy of your IAM you have to create a list with the old and the new FullFileName of your IPTs.
Loop through all ReferencedFileDescriptors: For i = 1 to oFile.ReferencedFileDescriptors.Count
With your list you can replace each ReferencedFileDescriptors.Item(i) with the corresponding new FullFileName.
All Sheets with all views will be updated.
Regards
Roland
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Hi @op_thorsager. There are likely several ways to get to the same end result, and whichever way makes the most logical sense to you will probably be just fine. Whichever way you do it, it seems like you would need to have that list of old file names, paired with new file names though, as @raith-mb mentioned, so you know which file references to replace with which other file references. You could likely use something like a NameValueMap or Dictionary(Of String, String) type variable for storing/using those name pairs, if necessary. And if the main assembly's file reference is pointing to the new one, just don't attempt to replace it. You would need a checking system in there to avoid that type of situation. If file reference equals old file, then replace, else do not replace. It looks like that code he posted was formatted for VBA though, so you would have to eliminate the 'Set' keywords, and include the () symbols around the MsgBox contents, and you do not need the 'Call' keyword, but it will not hurt anything.
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
@WCrihfield @raith-mb so just to get this right.
I count the items in the rule which exports the assembly and opens the drawing, then replace the references using Rolan's code?
this is an example of my export/copy code. this is run from the initial assembly(where you start)
Imports System.Windows.Forms
Sub Main
Export
CopyParts
CopyDrawing
CopyXLS
End Sub
Sub CopyXLS
Dim xspec As String = Parameter("Filename")
Dim PartRes As String
GoExcel.Open(xspec, "Tool")
PartRes = PathO & Parameter("FileNaming") & ".xlsx"
GoExcel.Save()
System.IO.File.Copy(xspec, PartRes)
End Sub
Sub CopyParts
Dim OccCrossbar As ComponentOccurrence = Component.InventorComponent("Crossbar")
Dim OccVeneer As ComponentOccurrence = Component.InventorComponent("Veneer")
Dim OccCloth As ComponentOccurrence = Component.InventorComponent("Cloth")
Dim OccExCross As ComponentOccurrence = Component.InventorComponent("ExCross")
Dim OccInsBattCut As ComponentOccurrence = Component.InventorComponent("InsulationBatt_cut")
Dim OccInsBattFull As ComponentOccurrence = Component.InventorComponent("insulationBatt_full")
Dim OccCpanel As ComponentOccurrence
If cutout_sqr = True Then
OccCpanel = Component.InventorComponent("CutoutPanel")
Else If cutout_sqr = False Then
End If
Dim CrossbarFFN As String = OccCrossbar.Definition.Document.fullfilename
Dim VeneerFFN As String = OccVeneer.Definition.Document.fullfilename
Dim ClothFFN As String = OccCloth.Definition.Document.fullfilename
Dim ExCrossFFN As String = OccExCross.Definition.Document.fullfilename
Dim InsBattFullFFN As String = OccInsBattFull.Definition.Document.fullfilename
Dim InsBattCutFFN As String = OccInsBattCut.Definition.Document.fullfilename
Dim CpanelFFN As String
If cutout_sqr = True Then
CpanelFFN = OccCpanel.Definition.Document.fullfilename
Else If cutout_sqr = False Then
End If
CpFile(CrossbarFFN, Path3D & System.IO.Path.GetFileName(CrossbarFFN))
CpFile(VeneerFFN, Path3D & System.IO.Path.GetFileName(VeneerFFN))
CpFile(ClothFFN, Path3D & System.IO.Path.GetFileName(ClothFFN))
CpFile(ExCrossFFN, Path3D & System.IO.Path.GetFileName(ExCrossFFN))
CpFile(InsBattFullFFN, Path3D & System.IO.Path.GetFileName(InsBattFullFFN))
CpFile(InsBattCutFFN, Path3D & System.IO.Path.GetFileName(InsBattCutFFN))
If cutout_sqr = True Then
CpFile(CpanelFFN, Path3D & System.IO.Path.GetFileName(CpanelFFN))
Else If cutout_sqr = False Then
End If
TopDoc.SaveAs(NewAsmFileFFN, False)
Component.Replace("Crossbar", Path3D & System.IO.Path.GetFileName(CrossbarFFN), True)
Component.Replace("Veneer", Path3D & System.IO.Path.GetFileName(VeneerFFN), True)
Component.Replace("Cloth", Path3D & System.IO.Path.GetFileName(ClothFFN), True)
Component.Replace("ExCross", Path3D & System.IO.Path.GetFileName(ExCrossFFN), True)
Component.Replace("insulationBatt_full", Path3D & System.IO.Path.GetFileName(InsBattFullFFN), True)
Component.Replace("InsulationBatt_cut", Path3D & System.IO.Path.GetFileName(InsBattCutFFN), True)
Component.Replace("InsulationBatt_cut", Path3D & System.IO.Path.GetFileName(InsBattCutFFN), True)
If cutout_sqr = True Then
Component.Replace("CutoutPanel", Path3D & System.IO.Path.GetFileName(CpanelFFN), True)
Else If cutout_sqr = False Then
End If
End Sub
Sub CopyDrawing
Dim OrgDrwFFN As String = Replace(OrgAsmFileFFN, ".iam", ".dwg")
Dim NewDrwFFN As String = Path2D & parameter("FileNaming") & ".dwg"
Dim OrgDrwDoc As DrawingDocument = ThisApplication.Documents.Open(OrgDrwFFN)
OrgDrwDoc.Close(True)
If System.IO.File.Exists(OrgDrwFFN) Then
CpFile(OrgDrwFFN,NewDrwFFN )
Else
MessageBox.Show("No existing dwg was found")
Exit Sub
End If
Dim NewDrwDoc As DrawingDocument = ThisApplication.Documents.Open(NewDrwFFN)
Dim oFileDesc As FileDescriptor = NewDrwDoc.ReferencedFileDescriptors(1).DocumentDescriptor.ReferencedFileDescriptor
oFileDesc.ReplaceReference(NewAsmFileFFN)
NewDrwDoc.Update()
End Sub
Dim Path3D As String
Dim Path2D As String
Dim PathO As String
Dim TopDoc As Document
Dim OrgAsmFileFFN As String
Dim NewAsmFileFFN As String
Sub Export
Parameter.UpdateAfterChange = True
Dim filePath As String
Dim subFolderName As String
TopDoc = ThisDoc.Document
OrgAsmFileFFN = TopDoc.FullFileName
' Prompt the user to select the file location
subFolderName = parameter("FileNaming")
Dim FolderBrowserDialog1 As New FolderBrowserDialog
If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
filePath = FolderBrowserDialog1.SelectedPath
' Create the subfolder
Path3D = filePath & "\" & subFolderName & "\3D\"
Path2D = filePath & "\" & subFolderName & "\2D\"
PathO = filePath & "\" & subFolderName & "\"
If Not IO.Directory.Exists(filePath & "\" & subFolderName) Then
IO.Directory.CreateDirectory(Path3D)
IO.Directory.CreateDirectory(Path2D)
End If
End If
parameter("Location") = filePath & "\" & subFolderName
iProperties.Value("Custom", "Location") = parameter("Location")
NewAsmFileFFN = Path3D & subFolderName & ".iam"
End Sub
Sub CpFile(Source As String, Target As String)
'debug("Will copy " & Source & " to " & Target)
System.IO.File.Copy(Source, Target)
'debug(Source & " copied to " & Target)
Dim fInfo As New System.IO.FileInfo(Target)
fInfo.IsReadOnly = False
End Sub
This code only works if the original drawing file/template is located in the same folder as the original assembly(see image)
the code closes down the original assembly without saving to prevent the user from accidentally breaking the initial build. then opens up a DWG with all the sheets and so on, and a new assembly which is located within \3D\ together with the parts.
once the new drawing file is opened, the references will look like this (in this case i selected \temp\303030-2480\ as folder name and save path)
however since there are multiple sheets within this drawing document, where only a single part is present, then there will be more than just one model reference within the drawing document.
The idea is to have an event trigger which launches a rule that will replace the parts still referencing the original part files with the part files saved in the same folder as the assembly, however i will have to get the code working before setting up the trigger, just to prevent messing things up in the initial build.
If we take "cloth.ipt" for example, will this be oFile.ReferencedFileDescriptors.item(2) or how does this work exactly?
im still very new to this, and have been trying to learn the ins-n-outs of iLogic for the past month, and since i don't have anyone to teach me this, i will have to learn by trial and error/looking through forumposts/watching webinars on youtube ![]()
p.s.: @raith-mb when you say "during the copy of your IAM", are you talking about doing the count within the code i posted a bit further up in this reply?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
Wow. That is a rather long, and complex code for someone who is just getting started with iLogic, so I am impressed that it is working this well for you so far. After seeing the whole (or most of) the code you are working with, I can see how attempting to implement our suggestions into it can seem more complicated than I had in mind. Now I am thinking that I would suggest making a few different changes in a few different places. I can see now that you do not yet have a 'list' of old & new full file names, as we were suggesting, so I am thinking about ways to create one within your existing code to help with replacing the drawing file references.
Between your Sub named "CopyDrawing" and the next Sub named "Export", you are declaring several variables. Those variables will be 'shared' because they are being declared between any other routines, and not within any other routine. When done that way, all other routines will recognize them, and be able to use them.
In that same area, I'm thinking we could create something like a NameValueMap or a Dictionary(Of String, String) type variable. Those types of variables can store a list of entries, but unlike a normal/simple list or array, the entries in these each have two parts. In a NameValueMap, you an unlimited number of entries, each pair having a 'Name' and a 'Value'. Similarly in a Dictionary(Of String, String), you have an unlimited number of entries, each having a 'Key', and a 'Value'. Using one of these, we could record the 'old' full file name as the 'Name' or 'Key', then the 'new' full file name as the 'Value' in each entry, at some point earlier in your code, like in your Sub named "CopyParts". Then down within your Sub named "CopyDrawing", we could use that collection variable when we loop through each file reference of the drawing. Instead of just getting 'Item(1)' of the drawing's ReferencedFileDescriptors, we would loop through each FileDescriptor In FileDescriptorsEnumerator (what you get from File.ReferencedFileDescriptors). Then within that loop (For Each Object In Collection...do something...Next), we would check if the FileDescriptor's FullFileName matches any of the 'old' ones in our list, and if to, use its ReplaceReference method to replace the 'old' one with the 'new' one. Does that make sense to you? I know, it is a lot to take in, because this is a big, complex task you are taking on.
Wesley Crihfield
(Not an Autodesk Employee)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I am just getting off work in a few mins, so will have to read about the use of NameValueMap, the posted rule is shortened by about 180 lines, but these were mostly just subroutines doing the same thing as the CopyParts sub, but with a few different components(mostly to skip the supressed components if any), this tool is the only thing i've been working on the past month, and currently sitting at about 750lines split into multiple rules, which luckily all works as intended, so i don't have to mess around in them. The only one i just cant get to work is the model reference updater, i found a few ones on different forums, but they all use a file dialog, but since i already have the path where the new components are, then i feel like its a waste of time to have the user run through each component via a file dialog haha
Thanks alot for the help so far, but i don't have more time today to try and wrap this up (fixed hours employed), so i'll get back to you tomorrow ![]()
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I was thinking a bit about the issue, and since the initial parts are the actual part files on the sheet, which doesn't have the updated assembly reference.
this means it will be hard for the API to know which component i'm pointing at.
my thought was that i could have a rule called "replace" within each part file.
then have the assembly write to a parameter within the part file, which states the location of the "3D" folder.
once the parameter is set, then have the assembly do a runrule within the part, which then does all the copying/ replacing. I don't know if this would work though. I already have all the parts copied to the "3D" folder, its just a matter of getting the reference within the actual drawing(.dwg) to update the reference to the part files which are already copied.
idk if this would work, but thought i'd ask real quick, since it gets a bit complicated for me when it reaches this level
Another way could also look like this:
Have only the sheet showing the assembly file, the rest of the sheets will be deleted.
then just have a rule which looks at the path for the newly created individual parts, create a sheet and place the part in the sheet, loop through all the parts in the assembly save location, and for each part it will create a sheet where it adds the necessary views, this way i won't even be needing to update the other model references