When learning the Revit API it can be a little confusing, and understanding what does what and how to get what you want out of Revit can be a tedious and time consuming.

One of the first and most important things to learn in the Revit API is the FilteredElementCollector, this allows you to get Elements from the Revit Model and is very powerful when coupled with Filters.

How does it work?

Simply, the FilteredElementCollector looks through your Revit DB Document and find Elements that pass the Filters specified then returns a list of these Elements for you to use later on.

Say we wanted to find all the Level Elements in the project, this can be easily done by using the following code in a Python Node in Dynamo…

import clr
 
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
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 *
 
#collect all Levels in the project...
lvls = FilteredElementCollector(doc).OfClass(Level).WhereElementIsNotElementType().ToElements()
 
OUT = lvls

Where we construct a new FilteredElementCollector passing the Revit document in…

lvls = FilteredElementCollector(doc)

Then specify what Class of Element we are looking for, in this instance it is Levels…

.OfClass(Level)

Then Filtering out the ElementTypes, so only returning the Instances of the Elements…

.WhereElementIsNotElementType()

And finally, we cast these to Elements (Casting is another way of saying converting)…

.ToElements()

This will return all the Instances of Levels in the Project which you can use for whatever you need them for.

Filters

Filters are what make the FilteredElementCollector so useful, you can apply filters easily to find the Elements you are looking for. Here is another example where we want to find all the Elements at a specific Level….

#ElementLevelFilter Example...
#Allows collector to collect Elements that are hosted at a specific Level... import clr
 
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
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 *

#collect all Levels in the project (same as example earlier)...
lvls = FilteredElementCollector(doc).OfClass(Level).WhereElementIsNotElementType().ToElements()

#choose a level and get the Level.Id (I have just chosen one at index [1] for this example, you can use your own logic to find the Level you need or bring one in as a variable)...
lvlId = lvls[1].Id

#Create ElementLevelFilter... 
filter = ElementLevelFilter(lvlId)

#Collect all the Elements that pass the ElementLevelFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()
 
OUT = elems

You can see in this example that we have created taken the code from earlier by finding all the Levels in the project, then selected one by it’s index (as the FilteredElementCollector returns a List of Elements). We then used this selected levels ID as the argument for the ElementLevelFilter() method as it takes an ElementId…

#Create ElementLevelFilter... 
filter = ElementLevelFilter(lvlId)

We are then passing this Filter into the FilteredElementCollector and where the Elements passes the Filter the are returned by the Collector…

elems = FilteredElementCollector(doc).WherePasses(filter)

We are then using the WhereElementIsNotElementType() method to return only the Instances of the Elements and then casting to Elements.

Have a look at the Revit API Docs for more about Filters as they come in a few Flavours:-

  • ElementLogicalFilter
    • You can use these filter to combine other filters using And/Or logic.
  • ElementQuickFilter
    • Low memory filters that act fast as they don’t dig too deep into the Element Properties and don’t expand rejected Elements into memory
  • ElementSlowFilter
    • Slow because they Element has to be expanded into memory first.

There are quite a few Filters to choose from the Slow and Quick Filter Categories, you can also Join these together using the Logical filters to create much larger filters.

I want More!!!

Here are some more Examples of using different Filters in combination with the FilteredElementCollector.

Boiler Plate Code

Copy the following Boiler Plate code into a new Python Node. This should have all the References and Import you need for the Examples to work…

 import clr
 
 clr.AddReference("RevitServices")
 import RevitServices
 from RevitServices.Persistence import DocumentManager
 from RevitServices.Transactions import TransactionManager
 doc =  DocumentManager.Instance.CurrentDBDocument
 app = DocumentManager.Instance.CurrentUIApplication.Application
 
 clr.AddReference("RevitNodes")
 import Revit
 clr.ImportExtensions(Revit.Elements)
 clr.ImportExtensions(Revit.GeometryConversion)
 
 clr.AddReference("RevitAPI")
 from Autodesk.Revit.DB import *
 
 clr.AddReference("RevitAPIUI")
 from Autodesk.Revit.UI import *
 
 import System
 from System.Collections.Generic import *

Basic

Get all Element that are of the FamilyInstance class…

 #Get Elements by Element Class...
 elems = FilteredElementCollector(doc).OfClass(FamilyInstance).WhereElementIsNotElementType().ToElements()

Get all the Element that are of a BuiltInCategory…

 #Get Elements by Built-In Category...
 elems = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()

Get all the Elements that are of a BuiltInCategory in the ActiveView Only…

 #Get Elements by Built-In Category in Active View only...
 elems = FilteredElementCollector(doc, doc.ActiveView.Id).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()

Get all the Elements that are of Class, BuiltInCategory and in the ActiveView Only…

 #Get Elements of the FamilyInstance Class and by Built-In Category of StructuralFraming in Active View only...
 elems = FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(FamilyInstance).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType().ToElements()

Intermediate

ElementMulticlassFilter Example…

Allows collector to collect Elements of Mulitple Classes

#ElementMulticlassFilter Example...
#Allows collector to collect Elements of Mulitple Classes...
 
#Build a new empty Type List...
typeList = List[System.Type]()

#Add some Element Types to TypeList...
typeList.Add(Floor)
typeList.Add(Wall)

#Create a new ElementMulticlassFilter (takes a list of ElementTypes)...
emcf = ElementMulticlassFilter(typeList)

#Collect all element that pass the ElementMulticlassFilter...
elems = FilteredElementCollector(doc).WherePasses(emcf).WhereElementIsNotElementType().ToElements()

ElementIsCurveDriven Example…

Allows collector to collect Elements which are Curve Driven (e.g. beams, raking columns e.t.c.)…

#ElementIsCurveDriven Example...
#Allows collector to collect Elements which are Curve Driven (e.g. beams, raking columns e.t.c.)...
 
#Create an ElementIsCurveDrivenFilter...
filter = ElementIsCurveDrivenFilter()

#Collect all elements that pass the ElementIsCurveDrivenFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()

ElementStructuralTypeFilter Example…

Allows collector to collect Elements of a StructuralType…

#ElementStructuralTypeFilter Example...
#Allows collector to collect Elements of a StructuralType...
 
#Create a filter to get all Elements of the StructuralType of Footing...
filter = ElementStructuralTypeFilter(Structure.StructuralType.Footing)

#Collect all elements that pass the ElementStructuralTypeFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()

ElementStructuralTypeFilter Example (Inverted Filter)…

Similar to the above, this allows collector to collect Elements NOT of a StructuralType by using the Inverted Overload for the filter, note how the ElementStructuralTypeFilter has an additional argument of True, this will Invert the filter and most filters have this ability…

#Inverted ElementStructuralTypeFilter Example...
#Allows collector to collect Elements NOT of a StructuralType...
 
#Create a filter to get all Elements but Elements of the StructuralType of Footing...
filter = ElementStructuralTypeFilter(Structure.StructuralType.Footing, True)

#Collect all elements that pass the ElementStructuralTypeFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()

CurveElementFilter Example…

Allows collector to collect Elements of a CurveElementType…

#CurveElementFilter Example...
#Allows collector to collect Elements of a CurveElementType...
 
#Create a filter that filters by CurveElementType ModelCurve...
filter = CurveElementFilter(CurveElementType.ModelCurve)

#Collect all elements that pass the ElementStructuralTypeFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()

ElementParameterFilter Example…

Allows collector to collect Elements with Parameter Values that pass filter rules…

 #ElementParameterFilter Example...
 #Allows collector to collect Elements with Parameter Values that pass filter rules...
 #We will get all floors greater than 250mm thick...
 
#use the BuiltInParameter for floor thickness as the subject for the ParameterValueProvider...
pvp = ParameterValueProvider(ElementId(BuiltInParameter.FLOOR_ATTR_DEFAULT_THICKNESS_PARAM))

#create a numeric greater filter...
fng = FilterNumericGreater()

#the value we want to test if our parameter value is greater than (NOTE: Vaues are in Feet so if you are using metric make sure to convert)...
ruleValue = 250.00*0.00328084

#Create the rule with the above rules...
fRule = FilterDoubleRule(pvp, fng, ruleValue, 0.000001)

#create the ElementParameterFilter with the new rule...
filter = ElementParameterFilter(fRule)

#Collect all the Elements that pass the ElementParameterFilter...
elems = FilteredElementCollector(doc).OfClass(Floor).WherePasses(filter).WhereElementIsNotElementType().ToElements()

SelectableInViewFilter Example…

Allows collector to collect Elements that are selectable in View…

#SelectableInViewFilter Example...
#Allows collector to collect Elements that are selectable in View...
 
#Create the SelectableInViewFilter (Requires you to Import the RevitAPIUI.dll)...
filter = Selection.SelectableInViewFilter(doc,doc.ActiveView.Id)

#Collect all the Elements that pass the SelectableInViewFilter...
elems = FilteredElementCollector(doc).WherePasses(filter).WhereElementIsNotElementType().ToElements()

 

Advanced (T.B.C.)

Still to come, I’m just lazy 🙂