Search code examples
revit-apirevitpythonshell

Revit API & Dynamo, Creating a Family Parameter from Project Document


I'm trying to create a new family parameter by calling a family's document in a project document and using the FamilyManager method to edit the family. There have been about 10 people asking for this on the Dynamo forums, so I figured I'd give it a shot. Here's my Python script below:

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

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

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
#The inputs to this node will be stored as a list in the IN variables.

familyInput = UnwrapElement(IN[0])

familySymbol = familyInput.Symbol.Family
doc = familySymbol.Document

par_name = IN[1]
par_type = ParameterType.Text
par_grp = BuiltInParameterGroup.PG_DATA


TransactionManager.Instance.EnsureInTransaction(doc)

familyDoc = doc.EditFamily(familySymbol)
OUT = familyDoc.FamilyManager.AddParameter(par_name,par_grp,par_type,False)

TransactionManager.Instance.TransactionTaskDone()

When I run the script, I get this error:

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed. 
Traceback (most recent call last):
  File "<string>", line 26, in <module>
Exception: The document is currently modifiable! Close the transaction before calling EditFamily.

I'm assuming that this error is because I am opening a family document that already exists through the script and then never sending the information back to the project document? Or something similar to that. Any tips on how to get around this?


Solution

  • Building up on our discussion from the forum:

    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 *
    
    par_name = IN[0]
    exec("par_type = ParameterType.%s" % IN[1])
    exec("par_grp = BuiltInParameterGroup.%s" % IN[2])
    inst_or_typ = IN[3]
    families = UnwrapElement(IN[4])
    
    # 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
    
    trans1 = TransactionManager.Instance
    trans1.ForceCloseTransaction() #just to make sure everything is closed down
    # Dynamo's transaction handling is pretty poor for
    # multiple documents, so we'll need to force close
    # every single transaction we open
    result = []
    
    for f1 in families:
        famdoc = doc.EditFamily(f1)
        try: # this might fail if the parameter exists or for some other reason
            trans1.EnsureInTransaction(famdoc)
            famdoc.FamilyManager.AddParameter(par_name, par_grp, par_type, inst_or_typ)
            trans1.ForceCloseTransaction()
            famdoc.LoadFamily(doc, FamOpt1())
            result.append(True)
        except: #you might want to import traceback for a more detailed error report
            result.append(False)
            trans1.ForceCloseTransaction()      
        famdoc.Close(False)
    
    OUT = result
    

    image of the Dynamo graph