Select only specified levels

Hi All,
I am learning Dynamo.
How can I select only specified levels (not all the levels)?

code for all levels:

Returns the index of the found level given a Level and a list of Levels…

def FindLevelIndex(levels, lev):
ind = None
i = 0
for l in levels:
if l.Id.ToString() == lev.Id.ToString():
ind = i
i = i+1
return ind

Thanks for your help

Would you be able to elaborate? Also, you can paste formatted text like this so it’s easier to read:

def FindLevelIndex(levels, lev):
    ind = None
    i = 0
    for l in levels:
        if l.Id.ToString() == lev.Id.ToString():
            ind = i
            i = i+1
    return ind

Thanks for your reply!
I don’t think I can paste screen snapshots here. But I am trying to split walls in my Revit model by some of the specific levels (for example, I named the Levels as “Temp_Level - 02”, “Temp_Level - 04”).
I don’t want to split walls by all the levels because some of the levels are just not that important for the walls.

wall python Script is:


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 *

import System
from System.Collections.Generic import *

############## Definitions Start ##############

Convert to List if singleton…

def tolist(obj1):
if hasattr(obj1,“iter”): return obj1
else: return [obj1]

Returns the index of the found level given a Level and a list of Levels…

def FindLevelIndex(levels, lev):
ind = None
i = 0
for l in levels:
if l.Id.ToString() == lev.Id.ToString():
ind = i
i = i+1
return ind

Copy the original wall and set it’s levels using the Built-In Parameters for the Base and Top Constraints…

def CopyWallByLevel(wall, b, t):
wallOut = None
try:
# Copy the Original Wall with a transformation vector of 0,0,0…
w = ElementTransformUtils.CopyElement(doc,wall.Id,XYZ(0,0,0))
# Since the CopyElements method returns the ElementId of the new wall we need to get this Element from the Document…
w = doc.GetElement(w[0])
# Update the Base and Top constraints Parameters using the Built-In Parameters.
# Note: I have explicitly chosen the Overload as I was getting flaky behaviour where the wrong overload was being used…
p = w.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT)
p.Set.Overloads.Functions2
p = w.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE)
p.Set.Overloads.Functions2
wallOut = w.ToDSType(True)
# Write out any exceptions…
except Exception, e:
wallOut = e.message
# Return new wall…
return wallOut
############## Definitions End ##############

IN-Variables…

run = tolist(IN[0])[0]
walls = tolist(UnwrapElement(IN[1]))

OUT-Variables…

outList =

Main Script…

Test if user has selected Run as True…

if run:
# Get All Levels in the Document and cast to .net List…
levels = list([l for l in FilteredElementCollector(doc).OfClass(Level).ToElements()])
# Sort Levels by Elevation using a lamda expression…
levels.sort(key=lambda x: x.Elevation, reverse=False)

# Start a new Transaction ready for modifying the Document...
TransactionManager.Instance.EnsureInTransaction(doc)
for w in walls:
    arr = []
    # Check if the Element is a Wall...
    if w.GetType() == Wall:
        # Get Base and Top Constraints as Levels...
        p = w.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT)
        base = doc.GetElement(p.AsElementId())
        p = w.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE)
        top = doc.GetElement(p.AsElementId())
        
        # Test whether walls Base and Top levels are NOT the same, if they are we will skip this wall, if they are not then we will get the Index of the Level in the sorted list of Levels we collected earlier for both the Base and Top of the wall...
        if not base.Id.IntegerValue == top.Id.IntegerValue:
            # Note: we are setting the bounds of the Loop below with the Indices of the found Levels so we will only loop through the Levels in between the Base and Top Levels...            
            i = FindLevelIndex(levels,base)
            j = FindLevelIndex(levels,top)
            
            # Loop through the Levels between the Base and Top Levels copying the original wall for each iteration and stepping up one Level...
            while i < j:
                wCopy = CopyWallByLevel(w,levels[i], levels[i+1])
                arr.append(wCopy)    
                i = i+1
            outList.append(arr)
            # Delete original Wall as this has now been split by Level...
            doc.Delete(w.Id)
# End the Transaction...
TransactionManager.Instance.TransactionTaskDone()
# Return the new Walls...
OUT = outList

Return if user has not set input Run to True…

else:
OUT = “Please Set Run to True”


The only thing I can not do is filtering the Levels which I need to split the walls.

Thanks for your help!

Try this?

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 *
 
import System
from System.Collections.Generic import *
 
############## Definitions Start ##############
# Convert to List if singleton...
def tolist(obj1):
    if hasattr(obj1,"__iter__"): return obj1
    else: return [obj1]
     
# Returns the index of the found level given a Level and a list of Levels...
def FindLevelIndex(levels, lev):
    ind = None
    i = 0
    for l in levels:
        if l.Id.ToString() == lev.Id.ToString():
            ind = i
        i = i+1
    return ind
 
# Copy the original wall and set it's levels using the Built-In Parameters for the Base and Top Constraints...
def CopyWallByLevel(wall, b, t):
    wallOut = None
    try:
        # Copy the Original Wall with a transformation vector of 0,0,0...
        w = ElementTransformUtils.CopyElement(doc,wall.Id,XYZ(0,0,0))
        # Since the CopyElements method returns the ElementId of the new wall we need to get this Element from the Document...
        w = doc.GetElement(w[0])
        # Update the Base and Top constraints Parameters using the Built-In Parameters.
        # Note: I have explicitly chosen the Overload as I was getting flaky behaviour where the wrong overload was being used...
        p = w.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT)
        p.Set.Overloads.Functions[2](b.Id)
        p = w.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE)
        p.Set.Overloads.Functions[2](t.Id)
        wallOut = w.ToDSType(True)
    # Write out any exceptions...
    except Exception, e:
        wallOut = e.message
    # Return new wall..
    return wallOut    
############## Definitions End ##############
 
# IN-Variables...
run = tolist(IN[0])[0]
walls = tolist(UnwrapElement(IN[1]))
levelsMatch = tolist(UnwrapElement(IN[2]))
levelsUse = list()
 
# OUT-Variables...
outList = []
 
# Main Script...
# Test if user has selected Run as True...
if run:
    # Get All Levels in the Document and cast to .net List...
    levels = list([l for l in FilteredElementCollector(doc).OfClass(Level).ToElements()])
    for lvs in levels:
        for lvsMatch in levelsMatch:
            if lvs.Name == lvsMatch.Name:
                levelsUse.append(lvs)     
    # Start a new Transaction ready for modifying the Document...
    TransactionManager.Instance.EnsureInTransaction(doc)
    for w in walls:
        arr = []
        # Check if the Element is a Wall...
        if w.GetType() == Wall:
            # Get Base and Top Constraints as Levels...
            p = w.get_Parameter(BuiltInParameter.WALL_BASE_CONSTRAINT)
            base = doc.GetElement(p.AsElementId())
            p = w.get_Parameter(BuiltInParameter.WALL_HEIGHT_TYPE)
            top = doc.GetElement(p.AsElementId())
            #if we don't include the original wall base and top in our list we can't recreate the extents of the original wall
            levelsUse.append(base)
            levelsUse.append(top)
            # Sort Levels by Elevation using a lamda expression...
            levelsUse.sort(key=lambda x: x.Elevation, reverse=False)
            # Test whether walls Base and Top levels are NOT the same, if they are we will skip this wall, if they are not then we will get the Index of the Level in the sorted list of Levels we collected earlier for both the Base and Top of the wall...
            if not base.Id.IntegerValue == top.Id.IntegerValue:
                # Note: we are setting the bounds of the Loop below with the Indices of the found Levels so we will only loop through the Levels in between the Base and Top Levels...            
                i = FindLevelIndex(levelsUse,base)
                j = FindLevelIndex(levelsUse,top)
                
                # Loop through the Levels between the Base and Top Levels copying the original wall for each iteration and stepping up one Level...
                while i < j:
                    wCopy = CopyWallByLevel(w,levelsUse[i], levelsUse[i+1])
                    arr.append(wCopy)    
                    i = i+1
                outList.append(arr)
                # Delete original Wall as this has now been split by Level...
                doc.Delete(w.Id)
    # End the Transaction...
    TransactionManager.Instance.TransactionTaskDone()
    # Return the new Walls...
    OUT = outList
# Return if user has not set input Run to True...
else:
    OUT = "Please Set Run to True"

Hope that helps,

Mark

1 Like