Getting Categories of View Filter Elements in Dynamo

Hi,

I am trying to get all view filters applied to all views which contains “SFMM” in their rules, however I am stuck because I was unable to get the categories these filters were applied to, and for this I cannot create the new filters with matching categories.

Additionally, only method I could find was to create new, if there is a way to modify rules of existing filters that would work even better.

I would attach the script but I get an error saying new users cannot upload files.

hello,

can you repeat your intent with clearer words and attach some screenshots to understand the issue.

1 Like

In the apidocs you can find that there’s a ‘get’ as a ‘set’ method for the viewfilters:
image

Therefor, the following Python script can give you the categories the filter is applied on:

#Code written by Rick.vandeLagemaat
import clr
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument

# Input from Dynamo (can be a single ParameterFilterElement or a list of ParameterFilterElements)
input_elements = IN[0]

# If the input is not a list, make it a list
if not isinstance(input_elements, list):
    input_elements = [UnwrapElement(input_elements)]
else:
    input_elements = [UnwrapElement(element) for element in input_elements]

# Initialize an empty list for the output
all_category_names = []

# Process each ParameterFilterElement in the list
for parameter_filter_element in input_elements:
    # Use the GetCategories method to retrieve the categories
    categories_ids = parameter_filter_element.GetCategories()

    # Initialize an empty list for the category names of this filter
    category_names = []

    # Retrieve the category names from the ElementId list
    for cat_id in categories_ids:
        category = Category.GetCategory(doc, cat_id)
        if category is not None:
            category_names.append(category.Name)
    
    # Add the category names for this filter to the output list
    all_category_names.append(category_names)

# If the original input was not a list, return the first sublist as output
if len(all_category_names) == 1:
    OUT = all_category_names[0]
else:
    OUT = all_category_names

It’s also possible to Set parameters, using the following script:

#Code written by Rick.vandeLagemaat
import clr
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument

# Input from Dynamo
input_elements = IN[0]  # List of ParameterFilterElement objects or a single ParameterFilterElement
new_categories = IN[1]  # New category or list of categories to set

# If the input is not a list, make it a list
if not isinstance(input_elements, list):
    input_elements = [UnwrapElement(input_elements)]
else:
    input_elements = [UnwrapElement(element) for element in input_elements]

# If the new categories input is not a list, make it a list
if not isinstance(new_categories, list):
    new_categories = [UnwrapElement(new_categories)]
else:
    new_categories = [UnwrapElement(category) for category in new_categories]

# Start a transaction to modify the document
t = Transaction(doc, "Set Filter Categories")
t.Start()

# Process each ParameterFilterElement in the list
for parameter_filter_element in input_elements:
    # Get the current categories
    categories_ids = parameter_filter_element.GetCategories()
    
    # Create a new list of ElementIds including the existing and new categories
    new_categories_ids = List[ElementId](categories_ids)
    
    # Add each new category to the list of category ElementIds
    for category in new_categories:
        if category.Id not in new_categories_ids:
            new_categories_ids.Add(category.Id)
    
    # Set the new list of categories
    parameter_filter_element.SetCategories(new_categories_ids)

# Commit the transaction to save changes
t.Commit()

# Output the modified ParameterFilterElement(s) to Dynamo
OUT = input_elements

Both scripts work with singular elements and lists as inputs.

Be aware that the filter could reset it’s rules depending on the categories you add to the filter… This can also happen when you manually edit a filter.

(all of this is done in Revit 2023, the scripts are based on IronPython2 (NOT CPython3). Different versions may require different code)

In addition, you can also remove Categories from a View Filter by the following code:

#Code written by Rick.vandeLagemaat
import clr
clr.AddReference('System')
from System.Collections.Generic import List
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

# Get the current document
doc = DocumentManager.Instance.CurrentDBDocument

# Input from Dynamo
input_elements = IN[0]  # List of ParameterFilterElement objects or a single ParameterFilterElement
remove_categories = IN[1]  # Category or list of categories to remove

# If the input is not a list, make it a list
if not isinstance(input_elements, list):
    input_elements = [UnwrapElement(input_elements)]
else:
    input_elements = [UnwrapElement(element) for element in input_elements]

# If the remove categories input is not a list, make it a list
if not isinstance(remove_categories, list):
    remove_categories = [UnwrapElement(remove_categories)]
else:
    remove_categories = [UnwrapElement(category) for category in remove_categories]

# Begin transaction
t = None
try:
    t = Transaction(doc, "Remove Filter Categories")
    t.Start()

    # Process each ParameterFilterElement in the list
    for parameter_filter_element in input_elements:
        # Get the current categories
        categories_ids = parameter_filter_element.GetCategories()
        
        # Create a new list of ElementIds, excluding the categories to be removed
        new_categories_ids = List[ElementId]()
        
        remove_category_ids = [cat.Id for cat in remove_categories]
        
        for cat_id in categories_ids:
            if cat_id not in remove_category_ids:
                new_categories_ids.Add(cat_id)
        
        # Set the new list of categories
        parameter_filter_element.SetCategories(new_categories_ids)

    # Commit the transaction to save changes
    t.Commit()

except Exception as e:
    if t is not None and t.HasStarted() and not t.HasEnded():
        t.RollBack()
    raise e

# Output the modified ParameterFilterElement(s) to Dynamo
OUT = input_elements

First Pythonscript in the screenshot shows the currently applied Categories. The second one deletes them and the last one shows the applied Categories at the end of the transaction.

Thank you very much for the help, I have been trying to actually replace a specific string for all filters in the model that I am working, I am trying the SetRules() and GetRules() methods but get an error saying they do not exist as attributes of “ParameterFilterElement” object.

It is a bit messy but I am attaching the script as well.



FilterFromView_modified_19082024.dyn (126.5 KB)

Maybe a different approach?

Add a rule with the correct ‘string’ and remove the old one?

image

Thanks for the suggestion, could you please specify from which package and what version the nodes in the screenshot are?

Orchid 2.16. You need to get it from GitHub.

I tried the nodes from the package but tried another approach as well but I cannot figure out why the method fails

I can’t help you with the Python :snake:

For that you we need the Python gurus on
this forum :see_no_evil:.