Schedules aren't updating after replacing a filter value

So I ran into what appears to be the same issue that it appears this person ran into here:

In my script, which I’ll put below, I used python to look for a certain string in a filter value, replace it, and re-apply the filter.
It works, the filter gets changed, but the schedule won’t update unless I manually click the filter button and then close the window. This works whether or not I make any changes to the filters.

It’s odd, I have a number of scripts regarding schedule filters - One that adds filters, one that removes filters, one that replaces a filter value entirely…
All of them work just fine, it wasn’t until this script that I ran into an error.

I tried using RefreshData(), but that didn’t do anything. I’ve tried regenerating the document, which didn’t do anything either. I’ve tried using some of the other scripts mentioned to add, and then remove a filter, but to no avail.

I’m pretty stumped here. Anyone have any ideas? I’d really prefer not to click the filter button and then close the window for all 200 schedules :frowning:

# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import * 

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements & geometry conversion methods
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

#The System namespace at the root of .NET
import System 

# Import RevitAPI - This gives general access to Revit tools.
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import * 

# Import DocumentManager & TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

#Active Revit file
doc = DocumentManager.Instance.CurrentDBDocument 
#UI level interfaces
uiapp = DocumentManager.Instance.CurrentUIApplication
#Current instance of Revit
app = uiapp.Application
#UI level interfaces of the current instance of Revit
uidoc = uiapp.ActiveUIDocument 


# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
column_header = IN[1]
find = IN[2]
replace = IN[3]
#Start Code

sel = uidoc.Selection.GetElementIds()
sel = [doc.GetElement(x) for x in sel]

TransactionManager.Instance.EnsureInTransaction(doc)

for sched in sel:
    sched = sched.Definition
    count = range(sched.GetFilterCount())
    filters = [sched.GetFilter(x) for x in count]
    field_ids = [sched.GetFilter(x).FieldId for x in count]
    field = [sched.GetField(x) for x in field_ids]
    field_names = [x.GetName() for x in field]
    filt_idx = field_names.index(column_header)
    filt = sched.GetFilter(filt_idx)
    filt_val = filt.GetStringValue()
    new = filt_val.replace(find, replace)
    filt.SetValue(replace)
    sched.SetFilter(filt_idx, filt)
  
TransactionManager.Instance.TransactionTaskDone()

#Assign output
OUT = 0

You could try putting transaction nodes at the beginning and end of your graph. It could just be a refresh issue though. In that case, you might try modifying a schedule value, even if you “change” the parameter to the existing value.

No such luck. I used my add filter script, and tacked on the transaction start and end nodes.
It added the filter, but Revit is still presenting the same behavior.

Here’s the Python Node:

# Enable Python support and load DesignScript library
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import * 

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements & geometry conversion methods
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

#The System namespace at the root of .NET
import System 

# Import RevitAPI - This gives general access to Revit tools.
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import * 

# Import DocumentManager & TransactionManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

#Active Revit file
doc = DocumentManager.Instance.CurrentDBDocument 
#UI level interfaces
uiapp = DocumentManager.Instance.CurrentUIApplication
#Current instance of Revit
app = uiapp.Application
#UI level interfaces of the current instance of Revit
uidoc = uiapp.ActiveUIDocument 

# The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
column_header = IN[1]
value = IN[2]
#Start Code

sel = uidoc.Selection.GetElementIds()
sel = [doc.GetElement(x) for x in sel]

TransactionManager.Instance.EnsureInTransaction(doc)

param_elems = FilteredElementCollector(doc).OfClass(ParameterElement).ToElements()
param_elem = next(x for x in param_elems if x.Name == column_header)
p_id = param_elem.Id

s,f = [],[]

for sched in sel:
    sched_d = sched.Definition
    fld_ids = sched_d.GetFieldOrder()
    fields = [sched_d.GetField(x) for x in fld_ids]
    fld_names = [x.ColumnHeading for x in fields]
    if not fld_names.Contains(column_header):
        new_fld = sched_d.AddField(ScheduleFieldType.Instance, p_id)
        new_fld.IsHidden = True
        fld_id = new_fld.FieldId
    else:
        fld_id = fld_ids[fld_names.index(column_header)]
    count = range(sched_d.GetFilterCount())
    filters = [sched_d.GetFilter(x) for x in count]
    flt_fld_ids = [sched_d.GetFilter(x).FieldId for x in count]
    flt_fld = [sched_d.GetField(x) for x in flt_fld_ids]
    flt_fld_names = [x.GetName() for x in flt_fld]
    if flt_fld_names.Contains(column_header):
        f.append(sched.Name+' already contains filter')
    else:
        new_filter = ScheduleFilter(fld_id, ScheduleFilterType.Equal, value)
        sched_d.AddFilter(new_filter)
        s.append('Filter added to '+sched.Name)
  
TransactionManager.Instance.TransactionTaskDone()

#Assign output
OUT = s,f

Edit:
I just tried putting in a ForceCloseTransaction followed by a new EnsureInTransaction at the end of the script, but that didn’t work either.

The schedules automatically updated for me. What version of Revit are you in?

I also noticed that manually creating elements for a schedule that was already being filtered also didn’t update until I “reapplied” the filter from the dialog box. I only had to do this once though. Can you confirm that this is a problem with each run and not a one-time issue with setting filters?

Okay, well, I’m not exactly sure what happened, but I found the issue…

For starters, I found an error in my script.

filt.SetValue(replace)

Should read

filt.SetValue(new)

So I started doing some troubleshooting. And I added some new parameters for some double checking, and output each step.

column_header = IN[1]
find = IN[2]
replace = IN[3]
#Start Code

sel = uidoc.Selection.GetElementIds()
sel = [doc.GetElement(x) for x in sel]

TransactionManager.Instance.EnsureInTransaction(doc)

for sched in sel:
    v_sched = sched
    sched = sched.Definition
    count = range(sched.GetFilterCount())
    filters = [sched.GetFilter(x) for x in count]
    field_ids = [sched.GetFilter(x).FieldId for x in count]
    field = [sched.GetField(x) for x in field_ids]
    field_names = [x.GetName() for x in field]
    filt_idx = field_names.index(column_header)
    filt = sched.GetFilter(filt_idx)
    o_f = filt.GetStringValue()
    filt_val = filt.GetStringValue()
    new = filt_val.replace(find, replace)
    n_filt = filt
    n_filt.SetValue(new)
    sched.SetFilter(filt_idx, n_filt)
  
TransactionManager.Instance.TransactionTaskDone()

#Assign output
OUT = v_sched, sched, filters, field_ids, field, field_names, filt_idx, filt,filt_val,new, o_f, n_filt.GetStringValue()

That’s the main body of the updated code.

What I’m finding, is that when I output “filt.GetStringValue()”, it’s only outputting the first 2 characters of the filter string.
image

So, essentially, Revit thinks the filter value is just PX. This is probably due to me accidentally having SetValue inputting my “replace” parameter instead of my “new” parameter.

What I don’t understand, is why it doesn’t appear that way when you open up the filter window. It shows as a different value. However, this means that when you click “OK” it sets the filter to the value that was in the window, overwriting the old value.

Edit: I went ahead and marked this as the solution, as technically I did find the issue. It’s fixed by just giving it a new value.