Convert All Selected Linked Elements to Parts

Why do you want to convert parts in a linked file? As I understand, the advantage of manipulating parts is that you have more control over the way the layers of a component (wall, floor, etc.) are made or join with other parts/components. However, if you have those parts in a linked Revit file, you cannot manipulate them, you can only see them.

Can you explain more in detail why you want this? Perhaps there is a different solution for what you want.

Our workflow on this project is different than most. We’re working in C4R (collaboration for Revit) so have access to all building files. I work for a GC and we’re self performing all concert on the job. We’re still in design but are to a point that we can start breaking out the concrete into pours. We’ve created a file which we’re linking the design model into. I can create parts from the elements in the model which have a direct link to those items in the original model. With a long stretch of wall, for example, I can break those parts into our different pours. Right now, in order to create parts from the elements I have to tab through the link and select each of the elements I want to convert to a part. With Dynamo I can quickly select all elements in the link. What I can’t figure out how to do yet is to then convert that selection into Parts.

Parting out a linked file is, I believe, the original intention of the tool allowing GCs to divide the model for their own purposes study. I’ve also explored the idea for finishes since you can modify the material of the part in the host model. Interesting possibilities… made stronger if I could automate the Parting process.

im glad i came across this topic. We’ve been trying something like this too as a linked file in order to isolate any issues that come from making parts.

The steamnodes package provides nodes that allow you to select certain elements from a link, and another that allows you to create parts from a selected element.

However, we came to a halt when the create parts node did not accept elements from the link. It seemed like the create parts node was meant only for non-link elements. Im not sure if this is still the case, since i last played with this idea quite a while ago.

However, there is a method in the api for specifically creating parts from elements that belong to a link called CreateParts(Document, ICollection(LinkElementId)) that i hope can be used to batch create parts from a link.

Im currently doing some house cleaning for the new revit update, but ill post again after a bit of tinkering.

I did a quick test and it looks like this is working all right:

partsFromLink.dyn (3.1 KB)

import clr

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#Preparing input from dynamo to revit
link = UnwrapElement(IN[0])
category = UnwrapElement(IN[1])
linkDoc = link.GetLinkDocument()

elements = FilteredElementCollector(linkDoc).OfCategoryId(category.Id).WhereElementIsNotElementType()

#Create a genereic list for the elements
eList = List[LinkElementId]()
for e in elements:
	eList.Add(LinkElementId(link.Id,e.Id))

#All actions that makes changes to the Revit database needs to be inside a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

createparts = PartUtils.CreateParts(doc, eList)

TransactionManager.Instance.TransactionTaskDone()

OUT = elements
1 Like

Oh wow look at that!
I was just having some trouble with the linkids

my python is almost non-existent so excuse my ignorance but your script seems to collect and acquire the linkids in one go. I would like to create a node that simply accepts a list of linked elements and create parts for them only.

If you had to filter the walls by type name, for example, how would you do it?
below is my attempt at modifying Julien Benoits(credits to him for the original script) MakePartsNode with your implementation of createparts for linked elements. and I am totally lost. Where are the parts stored? Why did you choose elements as the output?

#python nodes in dynamo 1.0
#proposed by Julien Benoit @jbenoit44 
#http://aecuandme.wordpress.com/
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Import ToDSType(bool) extension method
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
# Import geometry conversion extension methods
clr.ImportExtensions(Revit.GeometryConversion)
# Import DocumentManager and TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
from System.Collections.Generic import *
# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

#feed IN[0] with elements
link = UnwrapElement(IN[1])
elements = []
#Ids = []
#Parts=[]
#IDS = List[LinkElementId]()

for i in IN[0]:
	elements.append(UnwrapElement(i))
	
eList = List[LinkElementId]()
for e in elements:
	eList.Add(LinkElementId(link.Id,e.Id))
	


# Start Transaction tt
TransactionManager.Instance.EnsureInTransaction(doc)

a=PartUtils.CreateParts(doc, eList)
doc.Regenerate()

# End Transaction
TransactionManager.Instance.TransactionTaskDone()

OUT = elements

It was just random for debugging purposes. I believe the CreateParts method returns null. If you need to return the parts, I think you have to use PartUtils.GetAssociatedParts()

Yes, the script would be even easier if you can get the elements from an IN-port. Just replace the filtered element collector with IN[1] or something similar. Here is a modified version of the script:

import clr

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

#Preparing input from dynamo to revit
link = UnwrapElement(IN[0])
elements = UnwrapElement(IN[1])

#Create a genereic list for the elements
eList = List[LinkElementId]()
for e in elements:
	eList.Add(LinkElementId(link.Id,e.Id))

#All actions that makes changes to the Revit database needs to be inside a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

createparts = PartUtils.CreateParts(doc, eList)
doc.Regenerate()
TransactionManager.Instance.TransactionTaskDone()

OUT = []

for id in eList:
	partIDs=PartUtils.GetAssociatedParts(doc, id, 0, 0)
	OUT.append(partIDs)

Check out the free addin! https://partslab.pcl.com/

3 Likes

thanks alot! i have a much better understanding now. :slight_smile:
However I tried to use your script with a filtered list of elements, and I get an error.

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed. 
Traceback (most recent call last):
  File "<string>", line 28, in <module>
AttributeError: 'List[object]' object has no attribute 'Id'

I was looking at the LinkElementID class, and im quite confused if I need to feed the doc or the instance. Actually Im just lost. Is it the way in which the input was generated from the other nodes that is causing the problem?

EDIT: nvm, I did what u did earlier and used select model element to feed the doc and it works perfectly!!! Im about to have some real fun with this and navisworks. thank you.

Tchunoo-What package is Get Documents node from?

Thank you for everyone’s help! I’ve yet to get something to work, but I’m excited as I am catching up on all of the responses!

@Einar_Raknes I downloaded the graph and I’m getting the following error when trying to run:

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 27, in
TypeError: iteration over non-sequence of type Category

I’m not sure where to start?

Its from the archilab_grimshaw package. This topic was something I really enjoyed playing with awhile ago and forgot. Im so glad I came across your post and found answers thanks to @Einar_Raknes .

Odd…I opened an ran on a different model and it worked!

I’ll have to take a closer look as to why the other file failed. Might be because it is hosted on A360?

@Einar_Raknes @Tchunoo_Kahng The error I was getting was due to parts already existing in the model. It looks like this works if no parts exist. I’d be curious to know if this could be modified to do a couple things:

1.) Delete any orphaned parts.
2.) Create parts for any NEW elements. Existing parts would stay.

I can definitely see that becoming an issue if the linked file is updated while working with parts, considering how volatile modified parts are to any changes to the original element . I might have to do some digging, but steamnodes and other packages have nodes related to parts operations that might have some clues as to how to handle coordination of parts from links. finding new elements will be easy if there is a set of fixed elements, ie structural walls only, and compare the new list with list of elements from existing parts. im not sure about deleted elements, as parts that were modified heavily from elements that react to others can simply vanish completely. Very interesting issue! ill try some stuff out and post soon.

@Tchunoo_Rhee_Kahng based on what I’m seeing in the PartUtils Members, it doesn’t look like it’s possible to find orphaned parts. I could be wrong, as I’m just recently started getting myself familiar with the API and learning how to use the help file.

I think this can be done if you filter out the elements that are already parts with something similar to this:

	if PartUtils.AreElementsValidForCreateParts(doc, wallList):
		createParts = PartUtils.CreateParts(doc, wallList)
		doc.Regenerate()

The code is from this post:

This free addin has Part visualization tools that hide/isolate Parts by the original category / family / type. These tools are automatically added to the Revit context ribbon menu just by selecting Parts in the model. Start watching this video @ 3:10 Creating Parts with PartsLab

Even if you continue to use Dynamo to create your Parts, this tool is a must to quickly work with a LOT of parts, without having to create a bunch of filtered views.

@Daron_Denton @Greg.McDowell.Jr This works great on a typical project. I am however having issues on a project with all models loaded to A360 (Collaboration for Revit). When launch the app, it will ‘think’ for hours. I finally have to give up. The models aren’t too large. I think the issue might be communication with the cloud?

Hello David,

Thank you for your comment. Out of courtesy, I don’t want to hijack this thread with PartsLab conversation. Could we pick this up at suggestions @ partslab dot com?