Revit + Python

Revit API – Filteredelementcollector

R

One of the Revit API commands that seems to show up the most in Python scripts is the FilteredElementCollector Class.  This is the basic command that will allow you to collect objects of various types within a Revit model to then filter to the set of objects or individual object with which you want to interact.  Initially, I found this command to be somewhat confusing because there are a number of modifiers for it that can be applied to collect the correct set of elements.  I’m going to break down how you use the FilteredElementCollector along with some of the more commonly used Methods that can be used to modify the collector.

FilteredElementCollector Constructors: There are three types of constructors for a FilteredElementCollector.  Each one requires a document to be used as one of the arguments. Most times you’ll be using your current document (Revit model), which, in pyRevit, is usually set as:
doc = revit.ActiveUIDocument.Document

  • FilteredElementCollector(Document): This collector only needs to have a Revit document fed into it: FilteredElementCollector(doc). It will apply its collection to every object within the model.

  • FilteredElementCollector(Document, ElementId): This collector is looking for a document and the ElementId of a specific view within the model FilteredElementCollector(doc, View.Id).  Collecting elements using this constructor will only apply to elements that are visible within the specific view that’s been applied.

  • FilteredElementCollector(Document, ICollection ElementId): A collector constructed in this way still needs the document, but it also takes an ICollection of ElementIds.  It will only apply to elements that are part of that ICollection, regardless of where they live in the model.
    • ICollections will be covered in another post – they are their own somewhat tricky animal.  It took me quite a while to get my head around them, as they are more of a hold-over from other programming languages that have been applied to Python.  For now, think of them as a single entity made up of a bunch of elementIds (kind of like Python’s version of a group).

FilteredElementCollector Methods:  There are a number of methods available to use with FilteredElementCollector, but I’ve only needed a handful of them for day-to-day use.  Keep in mind that more than one of these can (and most likely will) be used when you implement the FilteredElementCollector.

  • OfCategory():  Using this method will restrict the FilteredElementCollector to only collect objects of a specific category.  It needs to have a BuiltInCategory as an argument, so the use of it would look like this: FilteredElementCollector(doc).OfCategory (BuiltInCategory.OST_Walls).  This collector, for example, would grab all of the wall objects within the model.
    • BuiltInCategory Enumeration can be found here.  It’s a large list of Categories, and the best way to find what you need is to do a ‘Find’ (Ctrl-F) on the page and search for a term. 

  • OfClass():  The OfClass method is used to filter down to just elements of a specific Revit class.  These could be ViewDrafting, or Wall, or SlabEdge – almost any of the classes in the Revit API are fair game.  An example might be: FilteredElementCollector(doc). OfClass(Family) would collect all families within the model.

  • ToElementIds():  This method will usually come at the end of the collector and will return the list of ElementIds that have been selected.  For example, to get all of the ElementIds of all wall elements in the model would look like this: FilteredElementCollector(doc). OfCategory(BuiltInCategory.OST_Walls).ToElementIds().  Notice that there are no arguments in the last set of parenthesis – they can remain empty, but don’t forget them! I’ve made that mistake more than once, and it’s sometimes hard to figure out that that simple omission is what’s causing your error.

  • ToElements():  While similar to ToElementIds(), ToElements() returns the actual elements themselves – not the Ids of those elements.  For example: FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls). ToElements() will return all of the actual wall objects within the model.

  • WhereElementIsElementType():  This collector will only collect types, not individual elements.  For example, if there are 3 instances of a particular wall type, this will grab only the type – not the 3 instances.  From there, you can decide whether you want the Element or ElementId of the objects you collect. For example: FilteredElementCollector(doc). OfCategory(BuiltInCategory.OST_Walls).WhereElementIsElementType(). ToElementIds() will grab all of the wall types in use in the model and return the ElementIds of those types.

  • WhereElementIsNotElementType():  This collector is used when you only want to collect the actual instances of an object, and not the type.  A general collection without specifying whether it should or should not collect a Type will return both individual instance AND all of the types in use.  By specifying a collection using WhereElementIsNotElementType, you ensure that you only get the actual model geometry. An example of this is: FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls). WhereElementIsNotElementType().ToElements().  This will return all of the wall elements in the model, but will not include the types as well – just the individual walls.

  • WherePasses():  This collector requires an argument that is a custom ElementFilter.  I’ll get into those in a future post. For now, know that this is another method that will probably be useful at some point.

FilteredElementCollector Properties:  Unlike a number of the Classes within the Revit API, the Properties within FilteredElementCollector almost never come in to play.  In fact, the only one is ‘IsValidObject’. Essentially, this Property can be ignored – it will almost never be used.


Generally some sort of variable will be used with the collector to create a group of objects that can then be manipulated within Python.  Here are a few examples of how that can be used.

window_type_ids = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Windows). WhereElementIsElementType().ToElementIds() This code will collect all of the Window Types that are used in the model and return a list of the ElementIds of each of those types.

schedules = FilteredElementCollector(doc).OfClass(ViewSchedule). WhereElementIsNotElementType().ToElements() This code will collect all of the schedules within the model and return a list of each of the schedule objects.

wall_tags = FilteredElementCollector(doc).OfCategory (BuiltInCategory.OST_WallTags).WhereElementIsNotElementType().ToElements() This code will collect all of the wall tags within the model and return a list of each of the schedule objects.

As you can see, the FilteredElementCollector is a powerful way to quickly grab a group of Revit elements to then manipulate as necessary.  In future posts I’ll go through some coding on what you can actually do with these elements once you’ve collected them, but this is a good start in understanding this important API command.

About the author

Andrew Urban

With almost 15 years as a registered architect, and nearly as much experience using Revit, I have recently taught myself Python and have begun to create productivity increasing addons for Revit. I'm am always interested in learning new and innovative ways to use Revit and all other tools of our profession.

By Andrew Urban
Revit + Python

Andrew Urban

With almost 15 years as a registered architect, and nearly as much experience using Revit, I have recently taught myself Python and have begun to create productivity increasing addons for Revit. I'm am always interested in learning new and innovative ways to use Revit and all other tools of our profession.