I’m trying to retrieve the set of parameters associated to a categorie, like the list from a filterrule.
I suspect this is a combination of builtin-parameters and projectparameters assigned to the category.
In the Revit-Api i found the enumaration of builtin-parameters, but i don’t see how i can retrieve only those associated to the category.
For the project parameters the Revit-API provides the ParameterBindings of a document.
below i have some code for this, but it’s not yet perfect (WIP).
Big thanks in advance on any input or info on this issue !
def list_project_parameters_for_category(doc, category_name):
category_set = None
# Find the target category
for cat in doc.Settings.Categories:
if cat.Name == category_name:
category_set = CategorySet()
category_set.Insert(cat)
break
if not category_set:
print("Category '{}' not found.".format(category_name))
return
# List to store project parameter names
project_parameters = []
# Iterate through all parameter bindings
for definitionBindingMapItem in doc.ParameterBindings:
definition = definitionBindingMapItem.Key
binding = definitionBindingMapItem.Value
# Check if the parameter is bound to the target category
if isinstance(binding, InstanceBinding):
if binding.Categories.Contains(category_set.ItemAt(0)):
project_parameters.append(definition.Name)
elif isinstance(binding, TypeBinding):
if binding.Categories.Contains(category_set.ItemAt(0)):
project_parameters.append(definition.Name)
return project_parameters
As far as I understand, the technique proposed by JP is only going to get the user-added shared parameters, but not user-added project parameters or built-in parameters for the chosen category.
True,
but the trick is that one element from a category doesn’t necessarily have the same parameters (built-in and project) as the others.
Let’s say you make a door from a wall-based door family template vs. one created from a generic model and then changed to doors category.
This would result in different built-in parameters.
later this week i will have time to work further on the script and let you know of my progress.
I agree with you. Maybe you would need to loop through all your instances or types for that category, adding their parameters to a set.
There must be a more efficient way, though.
I went back to solving this issue fo finding the correct available parameters.
The correct way of stateing is that i want to find all the possible providers for a category.
Below i generated 3 lists for a category, i took generic models as this is one of the most mixed onces.
List 1: Project parameters
List 2: Buildin parameters on the element level (intersected so only the once that apply to all the elements remain)
List 3: Family parameters (also intersected)
I still don’t get the right list if i would overlap these 3.
On the one hand i’m missing parameters like ‘Omniclass Number’ and ‘Omniclass Title’ or ‘Rebar cover’.
On the other hand i have to many parameters still in my list like ‘Area’, ‘Type Id’, ’ Edited by’,…
Altho the Family parameter list gets close its still not the exact list as in the providers when creating a filter.
the code is just working code and not to clean at all but here you go:
# -*- coding: utf-8 -*-
# imports
# ===================================================
# Autodesk + pyrevit imports
from Autodesk.Revit.DB import *
from pyrevit import revit
# Variables
# ===================================================
doc = revit.doc
uidoc = revit.uidoc
# Functions
# ===================================================
def get_elementtypes_by_category(category):
return FilteredElementCollector(doc).OfCategory(category).WhereElementIsElementType()
def list_project_parameters_for_category(doc, category_name):
target_category = None
# Find the target category
for cat in doc.Settings.Categories:
if cat.Name == category_name:
target_category = cat
break
if target_category is None:
print("Category '{}' not found.".format(category_name))
return []
project_parameters = []
# Correctly iterate through all parameter bindings
iterator = doc.ParameterBindings.ForwardIterator()
while iterator.MoveNext():
definition = iterator.Key # Access the definition
binding = iterator.Current # Access the binding
# Check if the binding's categories contain the target category
if hasattr(binding, 'Categories') and binding.Categories.Contains(target_category):
project_parameters.append(definition.Name)
return project_parameters
# Main
# ===================================================
if __name__ == '__main__':
doortypes = get_elementtypes_by_category(BuiltInCategory.OST_GenericModel)
doors = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericModel).WhereElementIsNotElementType().ToElements()
print('-'*50)
print('PROJECT PARAMETERS')
projectparameters = list_project_parameters_for_category(doc, 'Generic Models')
for param in projectparameters:
print(param)
print('-'*50)
print('BUILD-IN PARAMETERS')
# Initialize a list to hold parameter sets for each door
door_parameters_sets = []
for door in doors:
# Create a set to hold parameters for the current door
current_door_parameters = set()
door_params = door.Parameters
for param in door_params:
# Check if parameter is a BuiltInParameter (Not a direct check for FamilyParameter)
if isinstance(param.Definition, InternalDefinition):
if param.Definition.BuiltInParameter != BuiltInParameter.INVALID:
current_door_parameters.add(param.Definition.Name)
# Add the set of parameters for the current door to the list
door_parameters_sets.append(current_door_parameters)
# Find the intersection of all parameter sets
if door_parameters_sets:
common_parameters = set.intersection(*door_parameters_sets)
for param in sorted(common_parameters):
print("{}".format(param))
else:
print("No common parameters found.")
print('-'*50)
print('FAMILY PARAMETERS')
doors = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_GenericModel).WhereElementIsElementType().ToElements()
door_familyparameters_sets = []
for door in doors:
current_familyparameters = set()
doorfamilyparams = door.Parameters
for param in doorfamilyparams:
if param.Definition.BuiltInParameter != BuiltInParameter.INVALID:
current_familyparameters.add((param.Definition.Name))
door_familyparameters_sets.append(current_familyparameters)
common_familyparameters = set.intersection(*door_familyparameters_sets)
for param in sorted(common_familyparameters):
print("{}".format(param))
print('-'*50)
@ErikFrits in the past i have seen code snippets from you where you are able to retrieve elements with a certain parameter in them. DO you maybe have the solution to this issue, because it seems to be kind of the reverse from that.
Below a short gif with the provider list next to my output lists: