fitting has Angle family parameter, also have Angle shared parameter, how to read Angle family parameter value and write to Angle shared parameter via coding (Dynamo/Python)?
in fact, i tried traditional way by modifying fitting family, but loading family back to project will screw up all existing fitting which is not desired, even though i only added shared parameter to family and linked to family parameter.
can’t you just…
add new shared parameter to family
add formula to new parameter =existing parameter
reload to project without overriding parameter values
no dynamo or coding required
?
well, maybe project file is not in good health (that’s why 2 Angle parameters existed), reload won’t work well even without overriding parameter values
There’s a node for that… Parameter.IsShared
Building on @Mike.Buttery’s graph: the split works, but the write step is where nodes get stuck, since SetParameterByName grabs whichever “Angle” it finds first, and that may not be the shared one. A Python node can do the same IsShared split and the write in one pass across every fitting:
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
name = IN[0] if IN[0] else "Angle"
fittings = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_PipeFitting).WhereElementIsNotElementType().ToElements()
done, skipped = [], []
TransactionManager.Instance.EnsureInTransaction(doc)
for f in fittings:
params = list(f.GetParameters(name))
src = next((p for p in params if not p.IsShared and p.HasValue), None)
dst = next((p for p in params if p.IsShared and not p.IsReadOnly), None)
if src and dst:
if src.StorageType == StorageType.Double and dst.StorageType == StorageType.Double:
dst.Set(src.AsDouble())
else:
dst.Set(src.AsValueString())
done.append(f)
else:
skipped.append(f)
TransactionManager.Instance.TransactionTaskDone()
OUT = done, skipped
If the shared Angle is an Angle-type parameter, AsDouble copies over as-is, since both are stored in radians internally. Swap in OST_DuctFitting if these are duct fittings. Anything in the skipped list is either missing the shared parameter (check that it’s bound to the category) or has it as a type parameter. Plug a String node with Angle into IN[0] before running.
It doesn’t get ‘stuck’, you just need to use the right parameter nodes
And if you want to update every item a Categories → All Elements of Category is all you need.
Onto the python, many ways to bake the cake, a few thoughts below
# Safe way to set a parameter in Pythonnet3 (3.11)
def set_param_value(builtin, shared):
if builtin.StorageType == shared.StorageType and not shared.IsReadOnly:
match builtin.StorageType:
case StorageType.Integer:
return shared.Set(builtin.AsInteger())
case StorageType.Double:
return shared.Set(builtin.AsDouble())
case StorageType.String:
return shared.Set(builtin.AsString())
case StorageType.ElementId:
return shared.Set(builtin.AsElementId())
return False
# if IN[0] is none, param_name will be "Thickness" in this example
param_name = IN[0] or "Thickness"
# Use a ParameterFilterRuleFactory to only get elements with the shared parameter by name
# My preference is to use Class over category, however some classes like FamilyInstance
# can result in a large collection (so use class and category filters)
bic = BuiltInCategory.OST_Roofs
pfrf = ParameterFilterRuleFactory.CreateSharedParameterApplicableRule(param_name)
epf = ElementParameterFilter(pfrf)
elems = (
FilteredElementCollector(doc)
.OfCategory(bic)
.WherePasses(epf)
.WhereElementIsNotElementType()
)
# You can sort by True/False (True=1, False=0)
params = elem.GetParameters(param_name)
if len(params) == 2:
builtin, shared = sorted(params, key=lambda param: param.IsShared)
param_set.append(set_param_value(builtin, shared))