<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Select all content on level in Revit API Forum</title>
    <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10577273#M24101</link>
    <description>&lt;P&gt;I'm trying to put together a new script for one of our structural engineers. He wants to be able to quickly see all the elements that are linked to a particular Level of his choosing. I chose to break this into two parts:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Take the first element in his selection and retrieve its Level.&lt;/LI&gt;&lt;LI&gt;Find all elements with that reference Level and update the selection to match.&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Here's my current code:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from Autodesk.Revit.DB import ElementLevelFilter, FilteredElementCollector
from Autodesk.Revit.DB import Document
from rpw import ui

doc = __revit__.ActiveUIDocument.Document

selection = ui.Selection()

if selection:
    
    if str(selection[0].LevelId) != "-1":
    # if selection[0].LevelId is not None: # seems like this should work, but it doesn't, so I had to convert to strings
        print "LevelId found: " + str(selection[0].LevelId)
        level_id = selection[0].LevelId
    else:
        if selection[0].ReferenceLevel:
            print "ReferenceLevel found:" + selection[0].ReferenceLevel.Name + str(selection[0].ReferenceLevel.Id)
            level_id = selection[0].ReferenceLevel.Id
        else:
            print "nothing found..."
            level_id = None
    
    if level_id:
        level_filter = ElementLevelFilter(level_id)
        
        elements_on_level = FilteredElementCollector(doc).WherePasses(level_filter).ToElements()
        
        if elements_on_level:
            #print "Found elements on level."
            
            # for elem in elements_on_level:
                # print elem.Name
            
            selection.clear()
            selection.add(elements_on_level)
            selection.update()
            
        # else:
            # print "Did not find any elements."
            
    # except:
        # print "Something went wrong."
        # pass
        
# else:
    # print "nothing selected"&lt;/LI-CODE&gt;&lt;P&gt;Step 1 was more challenging that I realized because some elements like cable trays store the associated Level in the ReferenceLevel instead of in the LevelId. If you try to retrieve their LevelId, -1 is returned.&lt;/P&gt;&lt;P&gt;Step 2 is where I'm struggling now. I use a FilteredElementCollector to find all matching LevelIds, but similar to step 1, this fails to include the cable trays in the resulting selection because they have a LevelId of -1.&lt;/P&gt;&lt;P&gt;I'm hoping I'm missing something obvious because I haven't spent enough time with API tutorials, but I'd appreciate if someone could point me in the right direction. Thanks!&lt;/P&gt;</description>
    <pubDate>Fri, 27 Aug 2021 02:48:31 GMT</pubDate>
    <dc:creator>PerryLackowski</dc:creator>
    <dc:date>2021-08-27T02:48:31Z</dc:date>
    <item>
      <title>Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10577273#M24101</link>
      <description>&lt;P&gt;I'm trying to put together a new script for one of our structural engineers. He wants to be able to quickly see all the elements that are linked to a particular Level of his choosing. I chose to break this into two parts:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;Take the first element in his selection and retrieve its Level.&lt;/LI&gt;&lt;LI&gt;Find all elements with that reference Level and update the selection to match.&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Here's my current code:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from Autodesk.Revit.DB import ElementLevelFilter, FilteredElementCollector
from Autodesk.Revit.DB import Document
from rpw import ui

doc = __revit__.ActiveUIDocument.Document

selection = ui.Selection()

if selection:
    
    if str(selection[0].LevelId) != "-1":
    # if selection[0].LevelId is not None: # seems like this should work, but it doesn't, so I had to convert to strings
        print "LevelId found: " + str(selection[0].LevelId)
        level_id = selection[0].LevelId
    else:
        if selection[0].ReferenceLevel:
            print "ReferenceLevel found:" + selection[0].ReferenceLevel.Name + str(selection[0].ReferenceLevel.Id)
            level_id = selection[0].ReferenceLevel.Id
        else:
            print "nothing found..."
            level_id = None
    
    if level_id:
        level_filter = ElementLevelFilter(level_id)
        
        elements_on_level = FilteredElementCollector(doc).WherePasses(level_filter).ToElements()
        
        if elements_on_level:
            #print "Found elements on level."
            
            # for elem in elements_on_level:
                # print elem.Name
            
            selection.clear()
            selection.add(elements_on_level)
            selection.update()
            
        # else:
            # print "Did not find any elements."
            
    # except:
        # print "Something went wrong."
        # pass
        
# else:
    # print "nothing selected"&lt;/LI-CODE&gt;&lt;P&gt;Step 1 was more challenging that I realized because some elements like cable trays store the associated Level in the ReferenceLevel instead of in the LevelId. If you try to retrieve their LevelId, -1 is returned.&lt;/P&gt;&lt;P&gt;Step 2 is where I'm struggling now. I use a FilteredElementCollector to find all matching LevelIds, but similar to step 1, this fails to include the cable trays in the resulting selection because they have a LevelId of -1.&lt;/P&gt;&lt;P&gt;I'm hoping I'm missing something obvious because I haven't spent enough time with API tutorials, but I'd appreciate if someone could point me in the right direction. Thanks!&lt;/P&gt;</description>
      <pubDate>Fri, 27 Aug 2021 02:48:31 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10577273#M24101</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-08-27T02:48:31Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10577744#M24102</link>
      <description>&lt;P&gt;Your explanation makes perfect sense, and also points towards the solution.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Just as you noticed in retrieving the level from the selected element, different elements store their level in different ways. Unfortunately, some do not store any level information directly at all. Those could be retrieved by determining their Z elevation and comparing that with the various level's Z coordinates.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Many elements provide a valid LevelId property, and you have used that property to retrieve the level from the selected element.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The cable trays apparently do not, and you have to use the&amp;nbsp;ReferenceLevel property instead.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I assume that the&amp;nbsp;ElementLevelFilter is also based on the&amp;nbsp;LevelId property. Therefore, it will not retrieve the cable trays. For those, you can implement a second, separate, filtered element collector that first filters for cable trays, e.g., using their category or some other quick filter property. In a post-processing step, you could check that the value of their&amp;nbsp;ReferenceLevel property matches the desired value.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;These two separate filtered element collectors can be combined into one using a Boolean operation.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I used this technique to put together such combinations of filters to retrieve structural elements, MEP elements and their connectors:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;A href="http://thebuildingcoder.typepad.com/blog/2010/06/retrieve-mep-elements-and-connectors.html" target="_blank"&gt;http://thebuildingcoder.typepad.com/blog/2010/06/retrieve-mep-elements-and-connectors.html&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can check out The Building Coder topic group on filtering for elements to see many more examples:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.9" target="_blank"&gt;https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.9&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 27 Aug 2021 07:46:37 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10577744#M24102</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-08-27T07:46:37Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10578672#M24103</link>
      <description>&lt;P&gt;Thanks Jeremy!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'm still reading through the pages on your site - those are helpful links!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I didn't realize there was so much diversity in the way Revit handles the different type categories behind the scenes until I downloaded your Revit Lookup snoop tool yesterday. For example, I see that Duct and Cable Tray are broken out into separate Duct and CableTray Objects, and they both use Reference Levels. But Duct Fittings and Cable Tray Fittings are saved under the same FamilyInstance Object and they both use LevelIds. Is there a guide/roadmap for how different type categories map to different database objects? It sounds like I need to find out how each and every type category handles levels behind the scenes, then set up different filters to separate them ...which could be very time consuming.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Also, (and perhaps this would be a better question to ask on the pyRevit forums,) is there a better way to check for a null value on the LevelId parameter? I feel like converting the result to a string is not the right solution here.&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 27 Aug 2021 13:33:40 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10578672#M24103</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-08-27T13:33:40Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10578984#M24104</link>
      <description>&lt;P&gt;I'm beginning to wrap my head around the complexity of this problem. From the items I have snooped so far, here are my results:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;&lt;U&gt;Light Fixtures&lt;/U&gt; use &lt;STRONG&gt;Level&lt;/STRONG&gt; (LevelId behind the scenes), unless they are face based, then they use &lt;STRONG&gt;Schedule Level&lt;/STRONG&gt; (not in snoop tool, and LevelId is null).&lt;/LI&gt;&lt;LI&gt;&lt;U&gt;Cable Tray&lt;/U&gt; and &lt;U&gt;Duct&lt;/U&gt; use &lt;STRONG&gt;Reference Level&lt;/STRONG&gt; (Does appear in snoop tool, LevelId is null).&amp;nbsp;&lt;/LI&gt;&lt;LI&gt;&lt;U&gt;Model Groups&lt;/U&gt; use &lt;STRONG&gt;Reference Level&lt;/STRONG&gt; (LevelId behind the scenes)&lt;/LI&gt;&lt;LI&gt;&lt;U&gt;Structural Columns&lt;/U&gt; use &lt;STRONG&gt;Base Level&lt;/STRONG&gt; (LevelId behind the scenes)&lt;/LI&gt;&lt;LI&gt;&lt;U&gt;Structural Foundations&lt;/U&gt; use &lt;STRONG&gt;Level&lt;/STRONG&gt; (LevelId behind the scenes)&lt;/LI&gt;&lt;LI&gt;&lt;U&gt;Structural Framing&lt;/U&gt; has a &lt;STRONG&gt;Reference Level&lt;/STRONG&gt; (not in snoop tool, and LevelId is null).&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Clearly there's not a lot of consistency behind the scenes. I figured I'd take a look at the parameters next, and maybe filter based on those. Using the RevitAPI doc for &lt;A href="https://www.revitapidocs.com/2020.1/fb011c91-be7e-f737-28c7-3f1e1917a0e0.htm" target="_blank" rel="noopener"&gt;BuiltInParameter Enumeration&lt;/A&gt;, I'm seeing a lot of potential parameters that could house the level:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Reference Level&lt;/STRONG&gt; corresponds to&amp;nbsp;&lt;SPAN&gt;MULTISTORY_STAIRS_REF_LEVEL, FABRICATION_LEVEL_PARAM,&amp;nbsp;TRUSS_ELEMENT_REFERENCE_LEVEL_PARAM,&amp;nbsp;GROUP_LEVEL,&amp;nbsp;SPACE_REFERENCE_LEVEL_PARAM,&amp;nbsp;RBS_START_LEVEL_PARAM,&amp;nbsp;FACEROOF_LEVEL_PARAM,&amp;nbsp;STRUCTURAL_REFERENCE_LEVEL_ELEVATION,&amp;nbsp;ROOF_CONSTRAINT_LEVEL_PARAM,&amp;nbsp;INSTANCE_REFERENCE_LEVEL_PARAM&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Base Level&lt;/STRONG&gt; corresponds to&amp;nbsp;&lt;SPAN&gt;DPART_BASE_LEVEL_BY_ORIGINAL,&amp;nbsp;DPART_BASE_LEVEL,&amp;nbsp;STAIRS_BASE_LEVEL,&amp;nbsp;STAIRS_RAILING_BASE_LEVEL_PARAM,&amp;nbsp;IMPORT_BASE_LEVEL,&amp;nbsp;STAIRS_BASE_LEVEL_PARAM,&amp;nbsp;VIEW_UNDERLAY_BOTTOM_ID,&amp;nbsp;SCHEDULE_BASE_LEVEL_PARAM,&amp;nbsp;ROOF_BASE_LEVEL_PARAM,&amp;nbsp;FAMILY_BASE_LEVEL_PARAM&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Schedule Level&lt;/STRONG&gt;&amp;nbsp;corresponds to&amp;nbsp;&lt;SPAN&gt;INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Level&lt;/STRONG&gt;&lt;STRONG&gt;&amp;nbsp;&lt;/STRONG&gt;corresponds to&amp;nbsp;&lt;SPAN&gt;PATH_OF_TRAVEL_LEVEL_NAME,&amp;nbsp;SYSTEM_ZONE_LEVEL_ID,&amp;nbsp;ZONE_LEVEL_ID,&amp;nbsp;WALL_SWEEP_LEVEL_PARAM,&amp;nbsp;ROOM_LEVEL_ID,&amp;nbsp;SLOPE_ARROW_LEVEL_END,&amp;nbsp;CURVE_LEVEL,&amp;nbsp;VIEW_GRAPH_SCHED_BOTTOM_LEVEL,&amp;nbsp;SCHEDULE_LEVEL_PARAM, LEVEL_PARAM,&amp;nbsp;STRUCTURAL_REFERENCE_LEVEL_ELEVATION,&amp;nbsp;STRUCTURAL_ATTACHMENT_START_LEVEL_REFERENCE,&amp;nbsp;FAMILY_LEVEL_PARAM&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Associated Level&amp;nbsp;&lt;/STRONG&gt;corresponds to&amp;nbsp;&lt;SPAN&gt;PLAN_VIEW_LEVEL&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;Admittedly, a lot of these built-in parameters sound like they correspond to families that I'm not looking for, but there are certainly quite a few contenders that may contain the information I need. How would I filter for these? I'm thinking I can create a list of all the parameters, then check for the parameters on each element and if I find a non-null parameter I can compare it to my selected level. But this would be a&amp;nbsp;&lt;EM&gt;very&lt;/EM&gt; slow filter. And how would I get a list of all the elements in the first place?&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 27 Aug 2021 15:04:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10578984#M24104</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-08-27T15:04:14Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10579254#M24105</link>
      <description>&lt;P&gt;Ok so I think I figured out the first part with this new method. Basically it just searches for every parameter in the list, and if it finds one that doesn't equal -1, it will return it as the Element Id of the corresponding level. Next I need to find a way to run this on every element in the project so I can compare the element ids. This feels like the slowest, most brute-force way to accomplish this, so I'm open to alternatives.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from Autodesk.Revit.DB import ElementLevelFilter, FilteredElementCollector
from Autodesk.Revit.DB import Document, BuiltInParameter
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument

#Ask user to pick an object which has the desired reference level
def get_first_element_or_selection():
    from rpw import ui
    selection = ui.Selection()
    
    if selection:
        return selection[0]
    else:
        from Autodesk.Revit.UI.Selection import ObjectType
        return doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select an element.").ElementId)

selected_element = get_first_element_or_selection()
print "Element selected: " + selected_element.Name

BIPs = [
    BuiltInParameter.MULTISTORY_STAIRS_REF_LEVEL,
    #BuiltInParameter.FABRICATION_LEVEL_PARAM,
    BuiltInParameter.TRUSS_ELEMENT_REFERENCE_LEVEL_PARAM,
    #BuiltInParameter.GROUP_LEVEL,
    #BuiltInParameter.SPACE_REFERENCE_LEVEL_PARAM,
    #BuiltInParameter.RBS_START_LEVEL_PARAM,
    BuiltInParameter.FACEROOF_LEVEL_PARAM,
    BuiltInParameter.STRUCTURAL_REFERENCE_LEVEL_ELEVATION,
    BuiltInParameter.ROOF_CONSTRAINT_LEVEL_PARAM,
    BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM,
    BuiltInParameter.DPART_BASE_LEVEL_BY_ORIGINAL,
    BuiltInParameter.DPART_BASE_LEVEL,
    BuiltInParameter.STAIRS_BASE_LEVEL,
    BuiltInParameter.STAIRS_RAILING_BASE_LEVEL_PARAM,
    BuiltInParameter.IMPORT_BASE_LEVEL,
    BuiltInParameter.STAIRS_BASE_LEVEL_PARAM,
    BuiltInParameter.VIEW_UNDERLAY_BOTTOM_ID,
    BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM,
    BuiltInParameter.ROOF_BASE_LEVEL_PARAM,
    BuiltInParameter.FAMILY_BASE_LEVEL_PARAM,
    BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM,
    BuiltInParameter.PATH_OF_TRAVEL_LEVEL_NAME,
    BuiltInParameter.SYSTEM_ZONE_LEVEL_ID,
    #BuiltInParameter.ZONE_LEVEL_ID,
    BuiltInParameter.WALL_SWEEP_LEVEL_PARAM,
    BuiltInParameter.ROOM_LEVEL_ID,
    BuiltInParameter.SLOPE_ARROW_LEVEL_END,
    BuiltInParameter.CURVE_LEVEL,
    BuiltInParameter.VIEW_GRAPH_SCHED_BOTTOM_LEVEL,
    BuiltInParameter.SCHEDULE_LEVEL_PARAM,
    BuiltInParameter.LEVEL_PARAM,
    BuiltInParameter.STRUCTURAL_REFERENCE_LEVEL_ELEVATION,
    BuiltInParameter.FAMILY_LEVEL_PARAM,
    BuiltInParameter.PLAN_VIEW_LEVEL
]

def get_level_id(elem):
    for BIP in BIPs:
        param = elem.get_Parameter(BIP)
        if param:
            elem_id = param.AsElementId()
            if str(elem_id) != "-1":
                #print BIP
                #print elem_id
                return elem_id

print get_level_id(selected_element)&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 27 Aug 2021 16:43:03 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10579254#M24105</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-08-27T16:43:03Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10581262#M24106</link>
      <description>&lt;P&gt;Latest version, basically complete!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I discovered that some levels can't be retrieved through the get_Parameter method - they only appear in the .LevelId and .ReferenceLevel methods. But these methods don't exist for every element type, so I wrapped them in some Try/Except statements at the end of the level retrieval function.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I discovered a solution to the -1 issue as well. If you retrieve the Element ID and it's null, it means that level parameter doesn't exist for that object. But if you retrieve an Element ID that equals -1, that means the parameter exists, but was never set. I believe the correct way to check for this is by comparing the Element ID to ElementId.InvalidElementId, like so:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;level_id.Compare(ElementId.InvalidElementId) == 1:&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I also added some options so you can select the starting element before or after launching the script.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Unfortunately, I was forced to make a list of all the categories I want to search through, since I haven't found an easier way to filter down the FilteredElementCollector. I included maybe 30 of the greater than 1000 categories, but it's not an exhaustive list, and there's a possibility I missed a few important ones that I'll discover later. I wish &lt;A href="https://www.revitapidocs.com/2020.1/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm" target="_blank" rel="noopener"&gt;this page&lt;/A&gt; separated the 3D model categories from the rest, but alas.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="python"&gt;"""
Selects all elements that share the same Reference Level as the selected element.

TESTED REVIT API: 2020.2.4

Author: Robert Perry Lackowski

"""

from Autodesk.Revit.DB import ElementLevelFilter, FilteredElementCollector
from Autodesk.Revit.DB import Document, BuiltInParameter, BuiltInCategory, ElementFilter, ElementCategoryFilter, LogicalOrFilter, ElementIsElementTypeFilter, ElementId
from Autodesk.Revit.Exceptions import OperationCanceledException
# from pyrevit import DB
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument

from rpw import ui
import sys

#Ask user to pick an object which has the desired reference level
def pick_object():
    from Autodesk.Revit.UI.Selection import ObjectType
    
    try:
        picked_object = uidoc.Selection.PickObject(ObjectType.Element, "Select an element.")
        if picked_object:
            return doc.GetElement(picked_object.ElementId)
        else:
            sys.exit()
    except:
        sys.exit()
    
def get_level_id(elem):
    
    BIPs = [
        BuiltInParameter.CURVE_LEVEL,
        BuiltInParameter.DPART_BASE_LEVEL_BY_ORIGINAL,
        BuiltInParameter.DPART_BASE_LEVEL,
        # BuiltInParameter.FABRICATION_LEVEL_PARAM,
        BuiltInParameter.FACEROOF_LEVEL_PARAM,
        BuiltInParameter.FAMILY_BASE_LEVEL_PARAM,
        BuiltInParameter.FAMILY_LEVEL_PARAM,
        BuiltInParameter.GROUP_LEVEL,
        BuiltInParameter.IMPORT_BASE_LEVEL,
        BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM,
        BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM,
        BuiltInParameter.LEVEL_PARAM,
        BuiltInParameter.MULTISTORY_STAIRS_REF_LEVEL,
        BuiltInParameter.PATH_OF_TRAVEL_LEVEL_NAME,
        BuiltInParameter.PLAN_VIEW_LEVEL,
        # BuiltInParameter.RBS_START_LEVEL_PARAM,
        BuiltInParameter.ROOF_BASE_LEVEL_PARAM,
        BuiltInParameter.ROOF_CONSTRAINT_LEVEL_PARAM,
        BuiltInParameter.ROOM_LEVEL_ID,
        BuiltInParameter.SCHEDULE_BASE_LEVEL_PARAM,
        BuiltInParameter.SCHEDULE_LEVEL_PARAM,
        BuiltInParameter.SLOPE_ARROW_LEVEL_END,
        # BuiltInParameter.SPACE_REFERENCE_LEVEL_PARAM,
        BuiltInParameter.STAIRS_BASE_LEVEL,
        BuiltInParameter.STAIRS_BASE_LEVEL_PARAM,
        BuiltInParameter.STAIRS_RAILING_BASE_LEVEL_PARAM,
        BuiltInParameter.STRUCTURAL_REFERENCE_LEVEL_ELEVATION,
        BuiltInParameter.SYSTEM_ZONE_LEVEL_ID,
        BuiltInParameter.TRUSS_ELEMENT_REFERENCE_LEVEL_PARAM,
        BuiltInParameter.VIEW_GRAPH_SCHED_BOTTOM_LEVEL,
        BuiltInParameter.VIEW_UNDERLAY_BOTTOM_ID,
        BuiltInParameter.WALL_BASE_CONSTRAINT,
        BuiltInParameter.WALL_SWEEP_LEVEL_PARAM
        # BuiltInParameter.ZONE_LEVEL_ID,
    ]
    
    level_id = None
        
    for BIP in BIPs:
        param = elem.get_Parameter(BIP)
        if param:
            # print "A common level parameter has been found:" + str(BIP)
            param_elem_id = param.AsElementId()
            if param_elem_id.Compare(ElementId.InvalidElementId) == 1:
                level_id = param_elem_id
                # print "match found on common level parameter " + str(BIP) + "Level ID: " + str(level_id)
                return level_id
    
    # print "No matching common level parameters found, checking for .LevelId"
    try:
        level_id = elem.LevelId
        if level_id.Compare(ElementId.InvalidElementId) == 1:
            # print "match found on .LevelId. Level ID: " + str(level_id)
            return level_id
    except:
        # print "No LevelId parameter on this element."
        pass

    # print "Still no matches. Try checking for .ReferenceLevel.Id"
    
    try:
        level_id = elem.ReferenceLevel.Id
        if level_id.Compare(ElementId.InvalidElementId) == 1:
            # print "match found on .ReferenceLevel.Id Level ID: " + str(level_id)            
            return level_id
    except:
        # print "No ReferenceLevel parameter on this element."
        pass
    
    # print "No matches found. Returning None..."
    return None

# print "get selected element, either from current selection or new selection"
selection = ui.Selection()

if selection:
    selected_element = selection[0]
else:
    selected_element = pick_object()

#print "Element selected: " + selected_element.Name

# print "Search selected element for its reference level's element ID"
target_level_id = get_level_id(selected_element)
# print target_level_id

if target_level_id is not None:
    
    #poor attempts at filtering FECs. Not filtered enough - they contain far too many elements.
    #all_elements = FilteredElementCollector(doc).ToElements()
    #all_elements = FilteredElementCollector(doc).WherePasses(LogicalOrFilter(ElementIsElementTypeFilter( False ), ElementIsElementTypeFilter( True ) ) ).ToElements()
    
    #Create a filter. If this script isn't selecting the elements you want, it's possible the category needs to be added to this list.
    BICs = [
        BuiltInCategory.OST_CableTray,
        BuiltInCategory.OST_CableTrayFitting,
        BuiltInCategory.OST_Conduit,
        BuiltInCategory.OST_ConduitFitting,
        BuiltInCategory.OST_DuctCurves,
        BuiltInCategory.OST_DuctFitting,
        BuiltInCategory.OST_DuctTerminal,
        BuiltInCategory.OST_ElectricalEquipment,
        BuiltInCategory.OST_ElectricalFixtures,
        BuiltInCategory.OST_FloorOpening,
        BuiltInCategory.OST_Floors,
        BuiltInCategory.OST_FloorsDefault,
        BuiltInCategory.OST_LightingDevices,
        BuiltInCategory.OST_LightingFixtures,
        BuiltInCategory.OST_MechanicalEquipment,
        BuiltInCategory.OST_PipeCurves,
        BuiltInCategory.OST_PipeFitting,
        BuiltInCategory.OST_PlumbingFixtures,
        BuiltInCategory.OST_RoofOpening,
        BuiltInCategory.OST_Roofs,
        BuiltInCategory.OST_RoofsDefault,
        BuiltInCategory.OST_SpecialityEquipment,
        BuiltInCategory.OST_Sprinklers,
        BuiltInCategory.OST_StructuralStiffener,
        BuiltInCategory.OST_StructuralTruss,
        BuiltInCategory.OST_StructuralColumns,
        BuiltInCategory.OST_StructuralFraming,
        BuiltInCategory.OST_StructuralFramingSystem,
        BuiltInCategory.OST_StructuralFramingOther,
        BuiltInCategory.OST_StructuralFramingOpening,
        BuiltInCategory.OST_StructuralFoundation,
        BuiltInCategory.OST_Walls,
        BuiltInCategory.OST_Wire,
    ]
    
    category_filters = []
    
    for BIC in BICs:
        category_filters.Add(ElementCategoryFilter(BIC))
    
    final_filter = LogicalOrFilter(category_filters)
    
    #Apply filter to create list of elements
    all_elements = FilteredElementCollector(doc).WherePasses(final_filter).WhereElementIsNotElementType().WhereElementIsViewIndependent().ToElements()

    # print "Number of elements that passed collector filters:" + str(len(all_elements))

    selection.clear()

    for elem in all_elements:
        elem_level_id = get_level_id(elem)
        if elem_level_id == target_level_id:
            selection.add(elem)

    selection.update()
    
else:
    
    print "No level associated with element."&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Aug 2021 15:47:26 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10581262#M24106</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-08-28T15:47:26Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10603348#M24107</link>
      <description>&lt;P&gt;Thank you for all your research and sharing the solution in its current state!&amp;nbsp;Edited and preserved for posterity on the blog:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://thebuildingcoder.typepad.com/blog/2021/09/view-sheet-from-view-and-select-all-on-level.html#3" target="_blank"&gt;https://thebuildingcoder.typepad.com/blog/2021/09/view-sheet-from-view-and-select-all-on-level.html#3&lt;/A&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 06 Sep 2021 16:29:51 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10603348#M24107</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-09-06T16:29:51Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10606221#M24108</link>
      <description>&lt;P&gt;Thanks Jeremy, I hope you and others find this helpful!&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;One little improvement, at the suggestion of our structural engineer. There are times he wants to move a level, and doesn't know what's on the level. So in these situations, he'd like to select the level, rather than something on the level. To implement this, I added an additional if statement, as below:&lt;/P&gt;&lt;P&gt;Replace this:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# print "Search selected element for its reference level's element ID"
target_level_id = get_level_id(selected_element)&lt;/LI-CODE&gt;&lt;P&gt;With this:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# print "Check if selected element is a Level and get its ID. If not, search through the parameters for the reference level."
if selected_element.Category.Name.Equals("Levels"):
    target_level_id = selected_element.Id
else:
    target_level_id = get_level_id(selected_element)&lt;/LI-CODE&gt;&lt;P&gt;You may be able to help me create a language agnostic version of this, but I was unable to get the syntax working on my own.&lt;/P&gt;</description>
      <pubDate>Tue, 07 Sep 2021 18:29:33 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10606221#M24108</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-09-07T18:29:33Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10607147#M24109</link>
      <description>&lt;P&gt;Thank you for the improvement. It looks pretty language agnostic to me... at least the idea is simple and clear and effective.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Sep 2021 05:01:59 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10607147#M24109</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-09-08T05:01:59Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10607152#M24110</link>
      <description>&lt;P&gt;... added the improvement to the blog post as well.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 08 Sep 2021 05:07:08 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10607152#M24110</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-09-08T05:07:08Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10608402#M24111</link>
      <description>I was referring to spoken languages, rather than programming languages. It&lt;BR /&gt;checks against the english string for lines rather than checking against&lt;BR /&gt;the Revit class for lines.&lt;BR /&gt;</description>
      <pubDate>Wed, 08 Sep 2021 14:57:23 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10608402#M24111</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-09-08T14:57:23Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10610256#M24112</link>
      <description>&lt;P&gt;Oh, of course. Yes, very good idea. The language agnostic identifier is&amp;nbsp;BuiltInCategory.OST_Levels. It is a negative integer value. You compare it with the element's category Id property, e.g., using&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="general"&gt;  elem.Category.Id.IntegerValue.Equals( (int) BuiltInCategory.OST_Levels )&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp; &amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 09 Sep 2021 08:57:27 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10610256#M24112</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2021-09-09T08:57:27Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10611371#M24113</link>
      <description>&lt;P&gt;Awesome, thanks!&lt;/P&gt;</description>
      <pubDate>Thu, 09 Sep 2021 16:06:13 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/10611371#M24113</guid>
      <dc:creator>PerryLackowski</dc:creator>
      <dc:date>2021-09-09T16:06:13Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/12752314#M24114</link>
      <description>&lt;P&gt;I've been trying to run this code and it works when I run it on RPS but when I run on pyRevit with CPython, I get the error.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;DIV class=""&gt;TypeError : No method matches given arguments for get_Parameter: (&amp;lt;class 'int'&amp;gt;)&lt;/DIV&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV class=""&gt;This error is at&amp;nbsp;&lt;DIV class=""&gt;param = element.get_Parameter(BIP)&lt;/DIV&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV class=""&gt;When I print the BIP, the O/P is an integer. What could be the potential reason for this?&amp;nbsp;&lt;/DIV&gt;&lt;DIV class=""&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV class=""&gt;When I use this line -&amp;nbsp;&lt;/DIV&gt;&lt;DIV class=""&gt;&lt;DIV&gt;&lt;SPAN&gt;exec("param = %s" % BIP)&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;The code runs but the O/P is an integer and the code errors at&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN&gt;param&lt;/SPAN&gt;&lt;SPAN&gt;.AsElementId().&amp;nbsp;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;How do I rectify this?&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;&lt;SPAN&gt;However, the code runs when I remove -&amp;nbsp;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN&gt;#!python3.&amp;nbsp;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;DIV&gt;&lt;SPAN&gt;So does that mean get_Parameter doesn't work in CPython since I tried printing get_Parameter with a random BuiltInParameter and it showed the same error?&lt;/SPAN&gt;&lt;/DIV&gt;&lt;/DIV&gt;&lt;/DIV&gt;</description>
      <pubDate>Sat, 04 May 2024 08:49:14 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/12752314#M24114</guid>
      <dc:creator>adarsh_aromabim</dc:creator>
      <dc:date>2024-05-04T08:49:14Z</dc:date>
    </item>
    <item>
      <title>Re: Select all content on level</title>
      <link>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/12752487#M24115</link>
      <description>&lt;P&gt;Nice to hear that it runs. For the Python specific aspects, you will probably be better served in the Dynamo forum, since we really only discuss the pure .NET desktop Revit API here:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="https://forum.dynamobim.com" target="_blank"&gt;https://forum.dynamobim.com&lt;/A&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 04 May 2024 12:17:27 GMT</pubDate>
      <guid>https://forums.autodesk.com/t5/revit-api-forum/select-all-content-on-level/m-p/12752487#M24115</guid>
      <dc:creator>jeremy_tammik</dc:creator>
      <dc:date>2024-05-04T12:17:27Z</dc:date>
    </item>
  </channel>
</rss>

