Modify Existing schedule filter using dynamo

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