Modify Existing schedule filter using dynamo

Hi,

Is there any way to modify existing filter used in Revit schedule ?
I have created small dynamo script. But it is adding new filter instead of updating existing filter.

Thanks.

Easier to remove existing filter and add a replacement.

1 Like

Right, that is the last option.

If you’re set on modifying an existing filter then you’d need to go through the API and make all the changes there.
ScheduleFilter Members (revitapidocs.com)

Hi,

Yes, it’s possible to update an existing schedule filter using Dynamo with a Python script — especially when the filter condition is set to “Equals”.

I’ve used a Python approach where the inputs are:

  • Schedule name
  • New value for the filter condition

This script identifies the matching filter in the schedule and replaces the filter value, rather than adding a new filter. It works well when the condition is set to Equals.

Here is the Python code

Python Script Node

import clr
clr.AddReference(‘RevitAPI’)
clr.AddReference(‘RevitServices’)
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager

Inputs: List of schedule names and list of new filter values

scheduleNames = IN[0] # List of strings (schedule names)
filterValues = IN[1] # List of strings or numbers (new filter values)

Get the Revit document

doc = DocumentManager.Instance.CurrentDBDocument

Initialize output

output =

Validate input lists

if not isinstance(scheduleNames, list) or not isinstance(filterValues, list):
output.append(“Error: Inputs must be lists of schedule names and filter values.”)
elif len(scheduleNames) != len(filterValues):
output.append(“Error: Schedule names and filter values lists must have the same length.”)
else:
# Wrap in a transaction
transaction = Transaction(doc, “UpdateBatchScheduleFilters”)
transaction.Start()

try:
    # Process each schedule and filter value pair
    for idx, (scheduleName, newFilterValue) in enumerate(zip(scheduleNames, filterValues)):
        output.append(f"Processing schedule {idx + 1}/{len(scheduleNames)}: '{scheduleName}'")
        
        # Find the schedule by name
        schedules = FilteredElementCollector(doc).OfClass(ViewSchedule).ToElements()
        targetSchedule = None
        for schedule in schedules:
            if schedule.Name == scheduleName:
                targetSchedule = schedule
                output.append(f"  Debug: Found schedule '{scheduleName}', ID='{schedule.Id.IntegerValue}'")
                break
        
        if targetSchedule is None:
            output.append(f"  Schedule '{scheduleName}' not found.")
            continue
        
        # Get the schedule definition
        scheduleDefinition = targetSchedule.Definition
        
        # Debug: List all fields in the schedule
        output.append("  Debug: Schedule fields:")
        for param in scheduleDefinition.GetFieldOrder():
            field = scheduleDefinition.GetField(param)
            output.append(f"    Field: '{field.GetName()}', FieldId='{field.FieldId.IntegerValue}'")
        
        # Get all filters in the schedule
        filters = scheduleDefinition.GetFilters()
        
        # Debug: List all filters and their field names
        output.append(f"  Debug: Found {len(filters)} filters in schedule.")
        for i in range(len(filters)):
            schedFilter = scheduleDefinition.GetFilter(i)
            field = scheduleDefinition.GetField(schedFilter.FieldId)
            fieldName = field.GetName() if field is not None else "Unknown Field"
            output.append(f"    Filter {i}: Field='{fieldName}', Type='{str(schedFilter.FilterType)}', FieldId='{schedFilter.FieldId.IntegerValue}'")
        
        # Find the filter for BIMSF_Id
        bimSFIdParamId = None
        for param in scheduleDefinition.GetFieldOrder():
            field = scheduleDefinition.GetField(param)
            if field.GetName() == "BIMSF_Id":
                bimSFIdParamId = field.FieldId
                output.append(f"  Debug: Found BIMSF_Id field with FieldId='{bimSFIdParamId.IntegerValue}'")
                break
        
        if bimSFIdParamId is None:
            output.append(f"  Parameter 'BIMSF_Id' not found in schedule '{scheduleName}'.")
            continue
        
        # Look for the filter using BIMSF_Id
        filterFound = False
        for i in range(len(filters)):
            schedFilter = scheduleDefinition.GetFilter(i)
            output.append(f"  Debug: Comparing Filter {i} FieldId='{schedFilter.FieldId.IntegerValue}' with BIMSF_Id FieldId='{bimSFIdParamId.IntegerValue}'")
            if schedFilter.FieldId.IntegerValue == bimSFIdParamId.IntegerValue:
                output.append(f"  Debug: Filter type for 'BIMSF_Id' is '{schedFilter.FilterType}' (Expected: '2' for Equals)")
                if schedFilter.FilterType != 2:  # ScheduleFilterType.Equals = 2
                    output.append(f"  Filter for 'BIMSF_Id' is not an 'Equals' filter in schedule '{scheduleName}'. Current type: {schedFilter.FilterType}.")
                    continue
                # Assume BIMSF_Id is a string (modify to int(newFilterValue) or float(newFilterValue) if different)
                try:
                    value = str(newFilterValue)  # Convert to string
                    schedFilter.SetValue(value)
                    scheduleDefinition.SetFilter(i, schedFilter)
                    filterFound = True
                    output.append(f"  Filter for 'BIMSF_Id' updated to '{newFilterValue}' in schedule '{scheduleName}'.")
                    break
                except ValueError:
                    output.append(f"  Invalid filter value '{newFilterValue}' for 'BIMSF_Id' in schedule '{scheduleName}'.")
                    break
        
        if not filterFound:
            output.append(f"  No filter found for 'BIMSF_Id' in schedule '{scheduleName}'.")
    
    transaction.Commit()

except Exception as e:
    transaction.RollBack()
    output.append(f"Error: {str(e)}")

Output result

OUT = output