I have been able to remove the formula reference from a family within a project file using python/API script but cannot seem to be able to change the value afterwords. The formula is gone but the value is the same. And the changes are saved to the families within the project.
The script works from the project and can iterate over multiple families/familytypes/instances but still working on it to fix the value setting and to make it iterate more intuitively. For now, if you have the time, could you test it and see if it works for you? Code is below:
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
# class for overwriting loaded families in the project
class FamOpt1(IFamilyLoadOptions):
def __init__(self): pass
def OnFamilyFound(self,familyInUse, overwriteParameterValues): return True
def OnSharedFamilyFound(self,familyInUse, source, overwriteParameterValues): return True
def changeParam(f1,name,result):
famdoc = doc.EditFamily(f1)
try:
trans1.EnsureInTransaction(famdoc)
famMan = famdoc.FamilyManager
par_name = [a for a in famMan.Parameters if a.Definition.Name==name][0]
temp = []
temp.append(par_name.Formula)
famMan.SetFormula(par_name,None)
#famMan.Set(par_name,val)
temp.append(par_name.Formula)
temp.append(par_name.IsDeterminedByFormula)
#pars = [a.AsString() for a in par_name.AssociatedParameters]
#temp.append(pars)
trans1.ForceCloseTransaction()
famdoc.LoadFamily(doc, FamOpt1())
result.append(temp)
except Exception, e:
result.append([False,e])
trans1.ForceCloseTransaction()
famdoc.Close(False)
def unwrapping(ele):
if type(ele).__name__ == "Family":
f1 = UnwrapElement(ele)
elif type(ele).__name__ == "FamilyType":
f1 = UnwrapElement(ele.Family)
else:
f1 = UnwrapElement(ele.Type.Family)
return f1
Note that this is only the function definition to call within Python (changeParam()) so that you can set it up how you want with your own for loops. One example would be:
trans1 = TransactionManager.Instance
trans1.ForceCloseTransaction() #just to make sure everything is closed down
result = []
if hasattr(IN[0], "__iter__") == True and hasattr(IN[1][0], "__iter__") == True:
for i,j in zip(IN[0],IN[1]):
f1 = unwrapping(i)
for y in j:
changeParam(f1,y,result)
elif hasattr(IN[1], "__iter__") == True and hasattr(IN[1], "__iter__") == True:
for i,j in zip(IN[0],IN[1]):
f1 = unwrapping(i)
changeParam(f1,j,result)
elif hasattr(IN[1], "__iter__") == False and hasattr(IN[1], "__iter__") == True:
f1 = unwrapping(IN[0])
for j in IN[1]:
changeParam(f1,j,result)
elif hasattr(IN[1], "__iter__") == False and hasattr(IN[1], "__iter__") == False:
f1 = unwrapping(IN[0])
changeParam(f1,IN[1],result)
The first 3 lines are required before running. This set of if/elif statements allow you to determine how you want to iterate through lists. In this case, it can handle:
- a list of elements and nested list, where each element has a list of parameters to change
- a list of elements and single list of parameters, in this case each element is matched in order to a single parameter
- a single element and a list of parameters to change on it
- a single element and a single parameter to change
The if statements are up to you to change if you want a certain outcome. OUT = result, where result has a list for each element containing: formula that was used before the script, formula after (should be null), and IsDeterminedByFormula (a boolean).
Edit: I guess you could just use a SetParameterValueByName node afterwards and it would change the value in the family doc as well.