Resources
Summary
Introduction
Hi everybody.
Welcome back. You will already learned so much about REIT API and I know that you cannot wait to finally start creating your awesome tools for it. But let me give you one more very important concept.
Before you start hacking reit, I want you to master getting the right elements of REIT API. And this is a must to know skill because getting the right elements is often half the solution.
Meet the Filtered Element Collector Class
So let's learn about filtered element collector class that will allow you to do that. It might look a bit intimidating to see how it's used for the first time and yes it is a long line of code, but I promise you it's one of the easiest classes to use in REIT API. 'Cause it's also one of the most repetitive ones.
For example, this line above me will get you all wall instances in your project, but if you would want to get floors for example, you'd make just one change in the middle. If you'd want to get types instead of instances, sure you would make little change right there, and that's how simple it is to modify this.
Alright, and this point, let's just take one step back and talk a little bit about the theory of filtered element collector and how to use it. I'm gonna open my ebook and I'm gonna use a few pages to explain you how it works and then we're gonna go and code something together.
Filtered Element Collector Anatomy
Alright, here is the ebook that I mentioned and I'm in the ninth chapter: master getting the elements. I'm just gonna scroll through here. You have some explanation how it works, all the metals and stuff, but we're gonna go straight to the second page. Filtered element collector anatomy and here's how it works in general.
When you work with filtered element collector, first of all you need to call filtered element collector and provide a document inside of it. DOC refers to the project that you from where you wanna get the elements. As you know, we can have multiple projects open, therefore you will need to select the right dock. Normally you select the active one anyway.
Also, you can optionally provide a second argument, which is gonna be element ID overview. Then you will be able to get elements only visible in that view and that can be useful for different reasons, but it's not as efficient 'cause it needs to load the view in the background.
Now once you have your collector, you can start using different metals. As I mentioned right here, you have a bunch of different metals and you can look them up in the Revit API documentation. But in general the most common ones are OfClass or OfCategory and they exactly what they sound like. They will allow you to filter elements by the class of REIT api. Like for example, we can provide a class of wall, class of floor, class of instance. We can use OfCategory and then we'll provide built-in category of walls, doors, generic models, windows and so on and so on and so on.
You can also use both of them. Let's say that you want elements that have a class of family instance which is loadable family. And then the category is supposed to be windows. That's also possible to combine them.
Now you filter your elements, but at this stage you can have both instances and types. And this is normally the third step we do. We decide do we want to get instances or types by using WhereElementIs.ElementType, WhereElementIs.NotElementType and it just exactly how it sounds like.
Lastly we can convert it to a list of elements, element IDs, or we can also grab the first element, first element ID and so on. This is kinda extra step but it's good to have it.
There's also a little tutorial rate here which you can check if you have the ebook, and if you don't I highly recommend you to download it. It's gonna be under this video.
Now what I want you to know really well is that filtered element collector is really, really repetitive. Here I just put a few examples. Example here is filtering with OfCategory and can see to get wall types we're gonna write:
FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements()
Then if you wanna get different elements like let's say roofs or rooms, you just change the built-in category. That's it. Maybe you wanna also change if it was like types before, now you wanna get instances, that's okay. It was WhereElementIs.ElementType for types. But for instances we're gonna write WhereElementIs.NotElementType. So these two minor changes right here will change what you get. We used to get wall types, now we get wall row instances. You want the rooms, that's fine, we're gonna just change the category and we don't even need that one. We could write it but it's not necessary because rooms they don't have types in Revit.
And if you wanna get something from a view, you would also just provide here kind of view ID, in my case I just took here the active view id which is fine. And then you would get the doors from visible view only. That's pretty much the whole theory about filtered element collector: create collector, filter by category or by class, filter instances or types, and convert to a list of elements. That's it. It's not that complicated but even though it looks like a very long line of code.
Code Snippet Reference — FEC Basics
Here’s a small snippet demonstrating some basics (not the full script, just enough to guide you):
More Filtered Element Collector Insights
Now there are also examples of how to use OfClass. In this case you provide here class of floor or floor type and so on. And here we have more examples inside there kinda ebook right here you can see all the rooms, all windows, window types, how to get floors, structural columns, generic models, walls, lines, materials and so on, so on and so on. And I try to highlight the main changes. So for example here we change the category again the category and we make it WhereElementIs.NotElementType and so on. Everything is quite explanatory itself.
But also I've written a whole other ebook on filtered element collectors and filters. Filters are a bit more advanced topic but still. And here you're gonna find a lot of examples. Again, here's a little bit anatomy. Then inside of here you'll find a lot of different examples here. Examples here like annotation and text, how to get views and sheets, how python filtering versus rate a P filtering goes and so on, so on, so on. So you can get both of these eBooks and just keep them nearby when you need to work with filtered element collector.
Alright guys, now we're gonna go to rate and actually test it and write a little bit of code together so you can see how it works. Let's put this ebook on the side. It might come useful a bit later right here and already prepared the button. It's right here if I'm gonna go to ra it right here. I created a new button, I just duplicated the previous one, changed the icon. Now I have a new button inside is just a regular template, just some information about the button, the regular imports and a few variables. And we're gonna start coding right here on the site.
So first of all, let's just create this comment: "fake basics". Let's just try to u use some of the filtered element collector basic kind of code. You can see it right here on the right as a reference. And you can see, let's say I want to get all walls, which is gonna be that one. Maybe I want to get all windows, but we're gonna see, but I'm just gonna write, I wanna get all walls.
Small Code Snippet — Category vs Class
And we're gonna compare it in just a moment. Next we wanna decide do we want on the instances or types. And for that we're gonna use this line right here WhereElementIs.NotElementType to elements. Where element is not element type two elements. Now we could write the same here in case of the class. This part is not necessary 'cause walls already have classes wall and wall type separated. But as a beginner it's best to use it anyway. It's just gonna be useful for you to remember that you have to use it. That's fine.
Another tip is if you don't like long lines, I prefer long lines because then I can create it many like this and I'm totally fine with that. But if you wanna kind of separate it, you could put here a slash and then enter. And in Python this is a trick. So you can split one line into multiple, but Python will still treat all these lines as a single line 'cause this pretty much says like okay look at the next line as it's continuing this one. So normally you would write like this, I don't like to do this, I prefer one huge line like this, that's totally fine for me.
Now let's try to modify this. Let's say that instead of walls I wanna get here like maybe floors. So we'll just come here and we'll just change the category to floors right here of category. If you don't to get floor types, that's okay. Floor types. We would keep the same category but we would come here and change where element is not element type two where element is element type, that's it. You can see we always gonna make these minor changes either here or here to get different classes or categories or to get different instances or types.
Now that's all fine. First of all, let's just make a few print statements and we're just gonna print these things right here. There's gonna be a lot of print statements but that's okay. Let's just click on it and you can see at the bottom I have different floor types. So I guess this is the list right here. Then I have a list of all the floors in the project, which is huge. And then a list of all the walls. That's fine.
Now what's the difference between OfCategory or OfClass? And it's not as complicated as you might think. Right here already created. This is uh in place family with a category of walls you can sh which you can see right here. Let's select that one. Let's select just regular wall. This one on the facade is fine. Now I'm gonna go to add-ins right here. Revit lookup and Snoop. Current selection, this is just one of the examples but right here, this is my wall instance, right? And right here it says it has a class of wall and this is in place family instance and it has a class of family instance. It already has different classes. So this one has the same class as all Lubo families. This one has the native wall class. But right here in the category you can see this is category of wall. If I select that one, it stays the same category.
Also good thing to know that let's say I select my type, this is gonna be wall type in wall type. My category says walls. And here in the instance my category, uh, let me just find it here. My category says walls. So you can see that the category and class, they have different meaning. They have different use and it's different things on their own. But some people confuse the category and class.
Also we can have a look internally what's going on. So I'm gonna get my let comment all of this out. So we got right here all walls with category and class and let's make two print statements. So I'm just gonna paste it to save a little bit of time like this. We're gonna write of category of class and then with format we're gonna write the length of this list. Just gonna put it here, the number and this one right here. So this will give you a print statement saying how many different walls you get with each of these metals. And this is great to check in the beginning and you'll notice there is some difference which is a bit confusing to be honest. Of category gets you 1,129 and right here you get like 20, 30 more. That's okay, that's all makes sense.
Let me just try to make sense outta it. We're not gonna print it like this. Instead we're gonna do the following statements. I'm gonna make here a print statement. Let's print uh, of category OS ost walls have these types and I'm gonna kind of iterate through all the items here and try to get unique types inside of it. So for wall in all wall category, wall type equals type of the wall. And now we're gonna make this trick, we're gonna create a list of unique items. I'm gonna check if wall type not in unique, then we're gonna add it there and we can also print it just once. 'cause next time we're gonna get the same type like for example type of vol it's gonna see it's already in the unique and we're not gonna print it, that's fine.
And now let's also do the same thing but for class. So I'm just gonna write the same unique, unique classes equals a list. Then for wall in all wall class and in here we wanna get a category. So it's gonna be a wall category, builtin category. Just keep in mind that this builtin category, this property is available from Revy 2023 or 2022. Otherwise you could use here category name I think. But I'm gonna use this one for the lesson. It's gonna make a little bit more sense. Now AI already suggests if category is not in the unique classes then we're gonna add it there and I'm gonna print it and now let's just go and see what we get inside of Revit. This one is gonna be really useful to you.
I'm gonna click on that one. Now we can see when you get your elements with off category of walls, you're gonna get elements with the type of wall obviously then family instance probably represents this in place. Elements face wall, I'm not exactly sure what it is, I haven't worked with it yet, but you can see there is a new class rate here. So you get three different classes and you could get off class wall off class, family of class, face wall to kind of separate them. But when you use off class wall, you get the category of OST walls totally makes sense. But also you get OSD curtain wall panels. So there because you know in curtain wall panels you can actually insert walls. Let me just find here just to explain what I mean. Now let me just zoom on one of the curtain panels, try to select it. And as you know normally you use your curtain panels but also in here you can kind of scroll up and can select any of the walls. So you're gonna kind of make here for example, brick wall inside of the curtain panels. Therefore you can get different, uh, what is it, different categories inside of your classes.
But don't worry, there is a way to go around it. And I'm gonna show you, you don't have to write this, this is just a kind of to look inside so you understand a little bit more what kinda difference you get. Also, if you get confused you can use this trick to read. I wanna show you a trick and we actually gonna combine two things so you can get your all walls by using: here's filtered element, collector of category OST category of walls where element is not element type two elements. But we can also add here of class wall. So we can combine of class wall and of category wall. This is gonna get rid of all inplace families, it's gonna get rid of different um, curtain panels like you saw and so on. This is kind of the trick. You can also use them together in combination.
Filtering with Python
Now for the first step I actually wanna show you how to filter with python. Let's say you wanna get all walls in the project but you wanna kind of filter them only walls which are maybe have width less than, I dunno, 50 centimeters or let's make more than 50 centimeters. I'm gonna write here value in centimeters gonna be 50. I'm gonna go one step ahead and we also gonna convert it. We work in feet, so we're gonna write unit, uto class convert to internal value centimeters and unit type ID is gonna be centimeters.
Now we can make here I wanna get fake walls and I like to use lead comprehensions and for beginners in beginning it's a little bit harder, but once they make sense it's so much easier and makes your code much more readable. First you write here the Canada loop for wall in all walls. And before that you need to specify in the very beginning what do you do? You can use this wall and you can for example write here I wanna get a list of wall widths, uh, like this. Then you would kind of iterate for all walls and you would add wall width one by one. My case, I just wanna use the wall and I can also add here an e statement. And I'm gonna write if wall width is more than value in feed, let me just break it down. In here we have four wall in all walls. This is your fall loop, right? Four loop. Then here in the beginning is kinda return value return. And here we can make if statements. So if, and this is how list comprehension works, just quickly you could make it like an empty list and four wall in all walls. If weave is more than this, then you would add it. So these four lines is exactly the same result as this one. This one is a bit more efficient because it's a generator, but I'm not gonna go in this depth in Python for beginner. Just know that they give you exactly the same return values. That's fine. This one is shorter so I prefer to use it.
Now we've got the thick walls. Now we wanna prove it. So we would also want to select something you already know these concepts. Select thick walls but it's a good exercise. Now how do we select it? We want to get UI doc selection and then there's set element IDs and we would provide here a list of fake wall IDs. As you remember, it has to be a list of element IDs cannot be python list. So we are gonna make python list of IDs first, gonna be wall ID for wall in all walls. Again, this is the follow-up, this is the return value. This is how comprehension works. And now we need to convert it to list of uh, thick wall IDs. This is gonna be a list of element ID and we're gonna provide this list to convert it. And as you remember this list, it has to be imported a little bit special 'cause it comes from.net library like this. But now we have it.
So we're gonna get our walls, then we're gonna filter it with Python. First of all, we're gonna get all walls, and here we're gonna filter it with list comprehension. I wanna get all walls, four wall in all walls if wall weave is more than the value provided and it has to be in feed. And selection is good because you will visually see what we're getting.
Now I know that I rushed here in the code a little bit. It might be a bit confusing to you, but the goal here is the filtered element collector and all the other things. So focus on that. Now let's just go in the view. We have everything here and I click on it and I'm supposed to only select walls which have bigger than 50 centimeters.
I got too many walls because I think I misspelled something. And this is very common, especially when you kinda rush things can see that in here I used all walls so I'm working with all walls, but I wanna use thick walls only. So I'm gonna change it right here. So this all walls is right here and we get thick walls. Then we put thick walls right here. We get element ID and then we take element IDs and make it list of element IDs in the T net library. Okay, now click on it. Now you can see I select different set of walls. Let's isolate it and now it works. Let's select that wall. Look at the type I can see the width is 61 centimeter. This one is 54. All right.
And that's how you use filtered element collector. It's a very simple class and you'll use it a lot. So make sure that you grab my eBooks where you will find a ton of code examples and explanations how, how it works. And most importantly, you'll get examples without thinking, you just kinda copy paste it and it works. And now I want you to practice a little bit getting different elements with classes of category and see what you get. Just get familiar and don't get afraid of this long line of code.
Wrapping Up and Next Steps
And finally, we're done with the basics of rate API concepts. You've learned so much already and now it's time to put all of it to a test. In the next video we'll create a new cool tool together and I'll try to apply all of this concept that you've just learned in this module. I can wait to see you code your first awesome adding together with me. I wish you happy coding and I'm gonna see you very soon. Goodbye.
Additional Helpful Snippet — Filtering & Selecting
Below is a smaller excerpt that shows how filtering by width and selecting the resulting elements could look (in context of the entire lesson):
Use these snippets as a guide, experiment with different categories or classes, and keep practicing to master the Filtered Element Collector. Happy coding!
HomeWork
…
⌨️ Happy Coding!