How to collect Schedulablefield by Name

Hello eveyone,

So what I’m trying to achive is the following:
:white_check_mark:Add to each and every schedule that have as a SchedulableFields called “_CES_CTR_Nested Family” this field/parameter
:x:Add a filter based on this parameter with the following condition: “If parameter == True>>> Filter it out”.
(The parameter is a yes / no shared Parameter)
:x:Hide this Field from the schedule

With the nodes I’m getting

“Warning: ScheduleView.AddFilters operation failed.
The field ID is not the ID of a field in this ScheduleDefinition.
Parameter name: filter”
similar to this case here: Add schedule filter node error (ScheduleView.AddFilters) - #5 by tuuletin

but whenever I try to use boolean or integer for boolean (0,1) I get this:

I also tried with Python, foolwing the steps of this link:

import clr

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import*


#allow us to use Dynamo nodes
clr.AddReference('DSCoreNodes')
import DSCore
from DSCore import *

schedule = UnwrapElement(IN[0])

def getFields(schedule):
	definition = schedule.Definition

fieldnames = []
definition = []
for s in schedule:
	definition.append(s.Definition.GetFieldOrder())
	unique_flatten_def = set(List.Flatten (definition,-1))
	
	for id in unique_flatten_def:
		param = s.Definition.GetField(id)
		#fieldnames.append(param.GetName())
		



OUT = unique_flatten_def

But had not luck there as well. Any ideas? :slight_smile:

imagen

Schedule fields.dyn (81.2 KB)

The Field ID is not the same as the Parameter ID. It can vary from schedule to schedule. If you try to apply just the one filter to all views, the Field ID of the ScheduableField in your filter may not match in all views. This means you probably have to create a ScheduleFilter for each View, with each filter using the ScheduableField from its respective Schedule.

2 Likes

Thank you @Nick_Boyts,
Yeah, in fact the Id is different
What I could not undestand so far is why when insert a bool in “ScheduleFilter.ByFielTypeand ¡Value” I get an error synce I assume a Shared parameter with “Yes/No” is a boolean parameter, and not a string or Integer one.

It’s a little confusing. The Parameter itself is a Yes/No parameter that takes a boolean. The ScheduleFilter is asking for the value in the filter to compare against the parameter value. The filter value is a string representing a boolean.

Working with Schedule Filters is a bit of a track game

here an example

test set schedule filter

import clr
import sys
import System

clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument


def findFilter(paraName, scheduleDef):
    filterCount = scheduleDef.GetFilterCount()
    for idx_filter in range(filterCount):
        schedFilter = scheduleDef.GetFilter(idx_filter)
        field_Id = schedFilter.FieldId 
        field = scheduleDef.GetField(field_Id)
        if field.GetName() == paraName:
            return idx_filter, schedFilter, field
    return None, None, None 
    
def createField(paraName, scheduleDef):
    #sub foncion
    def checkField(fieldToAdd):
        fieldIds = scheduleDef.GetFieldOrder()  
        for fieldId in fieldIds:
            field = scheduleDef.GetField(fieldId)
            if field.GetSchedulableField() == fieldToAdd:
                return fieldId, field
        return None, None
    #
    # main function ##
    #
    fieldToAdd = None
    #get GetSchedulableField by Name
    lstAvailbleField = scheduleDef.GetSchedulableFields()
    for schField in lstAvailbleField:
        if schField.GetName(doc) == paraName:
            fieldToAdd = schField
            break
    #check if field is already added and find the corresponding fieldId
    fieldId, field = checkField(fieldToAdd)
    if fieldId is not None:
        return fieldId, field
    else:   
        #if not found add the corresponding field
        scheduleDef.AddField(ScheduleFieldType.Instance, fieldToAdd.ParameterId )
        doc.Regenerate()
        #then return the corresponding fieldId
        return checkField(fieldToAdd)
        
toDoList = lambda x : x if hasattr(x, '__iter__') else [x]

lstView = toDoList(UnwrapElement(IN[0]))
nameParaFilter = IN[1]
valueBool = IN[2]

TransactionManager.Instance.EnsureInTransaction(doc)
for v in lstView:
    if v.ViewType == ViewType.Schedule:
        scheduleDef = v.Definition 
        # get index, schedule filter and field
        idx_filter, schedFilter, field = findFilter(nameParaFilter, scheduleDef)
        if field is not None:
            if valueBool:
                schedFilter.SetValue(1)
            else:
                schedFilter.SetValue(0)
            scheduleDef.SetFilter(idx_filter, schedFilter)
        else:
            fieldId, field = createField(nameParaFilter, scheduleDef)
            if valueBool:
                newSchFilter = ScheduleFilter(fieldId, ScheduleFilterType.Equal, 1)
            else:
                newSchFilter = ScheduleFilter(fieldId, ScheduleFilterType.Equal, 0)     
            scheduleDef.AddFilter(newSchFilter)
        # hide the Field
        field.IsHidden  = True
TransactionManager.Instance.TransactionTaskDone()       
    
OUT = lstView
2 Likes