I’ve created a script behind a pushbutton with Iselection, but it won’t work.
I’m trying to select structural foundations with only Type Parameter “Assembly Code” contains “17.”
Does any body know what I’m doing wrong?
file: select-palen_script.py
# Import Revit and pyRevit modules
from pyrevit import revit, DB, UI
from pyrevit import script
from Autodesk.Revit.UI.Selection import ISelectionFilter, Selection, ObjectType
# Get the current document
doc = revit.doc
uidoc = __revit__.ActiveUIDocument
class StructuralFoundationFilterByCategory(ISelectionFilter):
def AllowElement(self, elem):
# Controleer of het element tot de categorie OST_StructuralFoundation behoort
elem = self.linkedDoc.GetElement(reference.LinkedElementId)
if elem is not None:
if elem.Category.Id == ElementId(BuiltInCategory.OST_StructuralFoundation):
# Haal de parameter voor UNIFORMAT_CODE op
uniformat_code_param = elem.get_Parameter(DB.BuiltInParameter.UNIFORMAT_CODE)
if uniformat_code_param:
param_value = uniformat_code_param.AsString()
# Controleer of de waarde van de parameter "17" bevat
if param_value and "17" in param_value:
return True
return True
return False
# Laat de gebruiker Structural Foundations selecteren met het filter
ref_elems = uidoc.Selection.PickObjects(ObjectType.Element, StructuralFoundationFilterByCategory())
# Haal de geselecteerde elementen op
sel_elems = [doc.GetElement(ref) for ref in ref_elems]
print(sel_elems)
Above is my script but it’s not working. Does anybody know how to make this work?
But I have also a function available. (see below) This works insida a script. Can I use this in de code above?
def CollectPalen(document):
"""
Verzamel alle palen in dit document waarbij parameter 'Assembly Code' de tekst "17" bevat.
Parameters:
doc (Autodesk.Revit.DB.Document): The Revit document from which to select piles.
The document can be either a Document or an ActiveView.
Returns:
List[Autodesk.Revit.DB.Element]: A list of all piles in the model,
filtered by the specified Uniformat code.
"""
# Create a list of selected elements using the Param_filter function
param_id = ElementId(BuiltInParameter.UNIFORMAT_CODE)
pfrf = ParameterFilterRuleFactory.CreateContainsRule(param_id, "17")
epf = ElementParameterFilter(pfrf)
output = FilteredElementCollector(document)\
.OfCategory(BuiltInCategory.OST_StructuralFoundation)\
.WhereElementIsNotElementType()\
.WherePasses(epf)\
.ToElements()
return output
pointer, your uniformat_code param is a type parameter
so you need to collect type element
if you select a type element, it won’t show in the UI except in the filter at the bottom right of the revit UI
so you need to get the dependent elements from the type, and from these dependent elems, the FamilyInstances
# Import Revit and pyRevit modules
from pyrevit import revit, DB
from Autodesk.Revit.DB import (
FilteredElementCollector,
BuiltInCategory,
ParameterFilterRuleFactory,
ElementParameterFilter,
ElementId,
)
from System.Collections.Generic import List
# Get the current document
doc = revit.doc
uidoc = __revit__.ActiveUIDocument
LOOKED_FOR_CODE = "17"
param_id = ElementId(DB.BuiltInParameter.UNIFORMAT_CODE)
pfrf = ParameterFilterRuleFactory.CreateContainsRule(param_id, LOOKED_FOR_CODE)
epf = ElementParameterFilter(pfrf)
matching_elements = (
FilteredElementCollector(doc)
.OfCategory(BuiltInCategory.OST_StructuralFoundation)
.WhereElementIsElementType()
.WherePasses(epf)
.ToElements()
)
dependent_family_instances = []
for elem in matching_elements:
dependent_family_instances.extend(
elem.GetDependentElements(DB.ElementClassFilter(DB.FamilyInstance))
)
if matching_elements:
# Convert to .NET collection for selection
element_ids = List[ElementId](
[
elem
for elem in dependent_family_instances
]
)
uidoc.Selection.SetElementIds(element_ids)
print(
"Selected {} structural foundations type with code containing '{}'".format(
len(matching_elements), LOOKED_FOR_CODE
)
)
print("Dependent family instances selected: {}".format(len(dependent_family_instances)))
else:
print("No matching elements found")
Thanks @Jean-Marc.
Sorry, but with your code I can’t make a user-selection in my model.
May I wasn’t clear enough. I want to make a user-selection in my model to select some filtered elements and not select all filtered elements.
With your code it selects ALL filtered elements in my project. It could also be achieved with my function CollectPalen. (with the correct modules imported) That works too.
And… correct me if I’m wrong, but as fas as I know I can only do a user-selection with Iselection ?
But I don’t know how to write the code to make this work.
Do not worry, I understood you just right and pointed you in the direction to solve it yourself
ISelection and interfaces are not the easiest concept to grasp as a beginner.
Disclaimer ;)
I try to not provide with the solution but with pointers _ my day job is to provide solutions to my clients and taking care of the whole pyrevit ecosystem is not my day job
The solution would be like :
# encoding: utf-8
from pyrevit import revit, DB
from Autodesk.Revit.UI.Selection import ISelectionFilter, ObjectType
LOOKED_FOR_CODE = "17"
doc = revit.doc
uidoc = revit.uidoc
UNIFORMAT_CODE_PARAM = DB.BuiltInParameter.UNIFORMAT_CODE
class StructuralFoundationTypeUniformatFilter(ISelectionFilter):
def AllowElement(self, elem):
# Only allow Structural Foundations
if elem.Category and elem.Category.Id.IntegerValue == int(
DB.BuiltInCategory.OST_StructuralFoundation
):
# Get the element type (FamilySymbol)
elem_type = doc.GetElement(elem.GetTypeId())
if elem_type:
# Try to get the UNIFORMAT_CODE parameter robustly
try:
uniformat_param = elem_type.get_Parameter(UNIFORMAT_CODE_PARAM)
except Exception:
uniformat_param = None
if uniformat_param:
value = uniformat_param.AsString()
if value and LOOKED_FOR_CODE in value:
return True
return False
def AllowReference(self, reference, point):
return False # Only element selection
# Let the user select elements with the filter
try:
refs = uidoc.Selection.PickObjects(
ObjectType.Element,
StructuralFoundationTypeUniformatFilter(),
"Select Structural Foundations with UNIFORMAT_CODE containing '{}'".format(
LOOKED_FOR_CODE
),
)
selected_elems = [doc.GetElement(r.ElementId) for r in refs]
print("Selected elements:", selected_elems)
except Exception as e:
print("Selection cancelled or failed:", e)