Creation of Revit family instances with Python code in Dynamo is easy to do if you have the right code snippet. So I am sharing it here.
Code snippet shows how to do few useful tasks:
- How to select particular Revit family and type.
- How to create instance of a type.
- How to get particular parameter.
- How to set particular parameter.
- How to rotate family around it’s placement point (around Z axis).
Please have in mind that code will run only once if nothing has been changed in Dynamo. So I usually add one dummy true/false switch (see image) just for testing purposes (true or false is never used in code, it’s just telling (lying to) Dynamo that “something is changed”). This will convince Dynamo to run the code again. Also, have in mind that running the code several times will create new family instance each time (compared to basic Dynamo Revit family creation node).
Dynamo Python uses Revit API internal units (feet) for measurement. So when creating insertion points, make sure they are in feet. Or, create a function for conversion from “your units” to “Revit units”.
For this, I used the following versions:
- Dynamo Core 220.127.116.1110
- Dynamo Revit 18.104.22.16811
- Out-of-the-box Architectural Revit template
Python node looks like this (read comments inside the code for mode details):
# Enable Python support and load DesignScript library import clr import math clr.AddReference('ProtoGeometry') from Autodesk.DesignScript.Geometry import * # Import Revit API clr.AddReference('RevitAPI') from Autodesk.Revit.DB import * # Import Manager Classes clr.AddReference('RevitServices') from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager # The inputs to this node will be stored as a list in the IN variables. dataEnteringNode = IN # Set desired family name and type name: FamilyName = "M_Desk" FamilyType = "1830 x 915mm" doc = DocumentManager.Instance.CurrentDBDocument # Start Transaction TransactionManager.Instance.EnsureInTransaction(doc) collector = FilteredElementCollector(doc) # to have shorter list of candidates, collector can be focused on just one category. # See full list of Revit categories here: https://www.revitapidocs.com/2019/ba1c5b30-242f-5fdc-8ea9-ec3b61e6e722.htm collector.OfCategory(BuiltInCategory.OST_Furniture) # get elements from collector familyTypes = collector.OfClass(FamilySymbol).ToElements() output =  for typ in familyTypes: typeName = typ.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM).AsString() # Check if the family is of the right family and type name: if typ.Family.Name == FamilyName and typeName == FamilyType: if typ.IsActive == False: typ.Activate() doc.Regenerate() # location of the family instance is set here: loc = XYZ(0,0,0) # create family instance: familyInstance = doc.Create.NewFamilyInstance(loc, typ, Structure.StructuralType.NonStructural) # This is how you get particular parameter: param = familyInstance.GetParameters("Phase Created").AsValueString() # This is how you set particular instance parameter: familyInstance.LookupParameter("Comments").Set("This is sample comment") # This is how you set particular type parameter: typ.LookupParameter("Description").Set("This is sample description") angle = 40.0 # 40 degrees. Always add .0 even for round number to make sure Python see it as a float type point1 = XYZ(loc.X, loc.Y, loc.Z) # second point is just above the first point, so add any number to Z point2 = XYZ(loc.X, loc.Y, loc.Z + 100.0) axis = Line.CreateBound(point1, point2) # rotate family instance around axis (line), angle must be converted to radians ElementTransformUtils.RotateElement(doc, familyInstance.Id, axis, math.radians(angle)) # add whatever you want to output list output.append(familyInstance) output.append(param) break # End Transaction: TransactionManager.Instance.TransactionTaskDone() # Transaction ended # from this point onward, family instance had been created, you can do other stuff # Assign your output to the OUT variable. OUT = output
Hope you get good use of it!