Get all families from a category python

Hi everyone,

Is it possible to get all families from a category in a single python node?

I have read the post from Jeremy, however, I don’t know if there are any updates in this regard.

Thanks!

Hi @antoniocanerosan

1 Like

Thanks, @Kulkul for the quick answer.

I was wondering whether it could be possible to get only family names, rather than family type names + family names.

Also, whether everything can be within a single python node, not having to use the “categories” node.

Ideally, I would like to know if it is possible to add an extra “filter section” to the following code in order to filter by category getting family names only;

Blockquote

dataEnteringNode = IN

elementlist =
doc = DocumentManager.Instance.CurrentDBDocument

collector = FilteredElementCollector(doc).OfClass(Family)
elementlist = collector.ToElements()

Blockquote

Thanks

Sure! Just replace last line:

OUT = [f.FamilyName for f in fec]

Don’t forget to mark the post as solved.

You’re Welcome!

1 Like

Thanks @Kulkul

Hi @Kulkul

if any of the inputs is an empty value, what do you do to solve this error?

image

Hi @antoniocanerosan

Could you show me your complete graph with all the previews on.

1 Like

Hi @Kulkul

Sure, although it is not exactly the same scenario as my original question, I did use the same principle that you taught me. (Happy to open a new topic)

I am trying to get the Level name of all the elements in the project:

Blockquote

import clr

clr.AddReference(“RevitServices”)
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

clr.AddReference(“RevitNodes”)
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

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

faminsts = UnwrapElement(IN[0])
elementlist = list()
for item in faminsts:
try:
elementlist.append(item.Document.GetElement(item.LevelId).ToDSType(True))
except:
try:
elementlist.append(item.Level.ToDSType(True))
except:
try:
elementlist.append(item.GenLevel.ToDSType(True))
except:
try:
elementlist.append(item.Document.GetElement(item.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId()).ToDSType(True))
except:
elementlist.append(list())
OUT = [f.Name for f in elementlist]

Blockquote

The last except in your list of try/excepts is adding an empty list in the event an object doesn’t have a level property of the ones you are trying, so those empty lists have no Name property. I would suggest either try/excepting in your iteration loop at the end, and returning None (null) if it fails, or appending the object to a failures list instead and passing them out as an extra output for review instead, so your returned list of successful objects would not be parallel to the initial input in that case.

You might find code easier to write/read using an if/elif/else statement using the hasattr() method instead of try/except, which effectively can confirm if an object has an attribute available to use in relation to it (hence it should succeed if you try to apply that method or property to said object). I’m not sure if it’s more efficient than try/except, but definitely easier to read and add to.

Finally, you could construct the name list for said levels in the main loop as well, and then just store that to a variable passed to the OUT variable at the end instead. Not necessary, but again might make it easier to come back to the code later or expand upon it when you add steps after this one.

1 Like

Hi @GavinCrump,

Thanks for the answer,

With regards to your first pharapgrah, can you please provide me an example with your suggestion:

" I would suggest either try/excepting in your iteration loop at the end, and returning None (null) if it fails"

Thanks

For reference, the code formatted:

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc =  DocumentManager.Instance.CurrentDBDocument

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

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

faminsts = UnwrapElement(IN[0])
elementlist = list()
for item in faminsts:
	try:	
		elementlist.append(item.Document.GetElement(item.LevelId).ToDSType(True))
	except:
		try:
			elementlist.append(item.Level.ToDSType(True))
		except:
			try:
				elementlist.append(item.GenLevel.ToDSType(True))
			except:
				try:
					elementlist.append(item.Document.GetElement(item.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId()).ToDSType(True))
				except:
					elementlist.append(list())
OUT = [f.Name for f in elementlist]

Like this:

import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager

doc =  DocumentManager.Instance.CurrentDBDocument

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

# receive input
faminsts = UnwrapElement(IN[0])

# make list for adding names to
names = []

# for each family, check for parameters and get if found
for f in faminsts:
	if hasattr(f, 'LevelId'):
		lvl = f.Document.GetElement(f.LevelId)
	elif hasattr(f, 'Level'):
		lvl = f.Level
	elif hasattr(f, 'GenLevel'):
		lvl = f.GenLevel
	else:
		try:
			#last resort, so we force it into a try
			p = f.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM)
			lvl = f.Document.GetElement(p.AsElementId())
		except:
			# if it isn't available, we return null/None
			lvl = None
	
	try:
		names.append(lvl.Name)
	except:
		# if you wanted to, you could send out an empty string
		names.append(None)

# send the output onward
OUT = names

3 Likes

Great, thanks @GavinCrump !

1 Like