Application: Revit API
Category: Family Creation
Difficulty: Advanced
Language: C#
You need to create or modify Revit families programmatically - for example, generating parametric furniture families from a catalog, or batch-updating family parameters across multiple files.
Use the Family Document API to create new families or modify existing ones. Family documents have different capabilities than project documents, requiring specific approaches for geometry creation and parameter management.
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
[Transaction(TransactionMode.Manual)]
public class CreateBoxFamily : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
Application app = uiapp.Application;
try
{
// Create new family document
Document familyDoc = app.NewFamilyDocument(
@"C:\ProgramData\Autodesk\RVT 2024\Family Templates\English\Metric Generic Model.rft");
using (Transaction trans = new Transaction(familyDoc, "Create Box"))
{
trans.Start();
// Create reference planes for parametric control
CreateReferencePlanes(familyDoc);
// Create parameters
CreateParameters(familyDoc);
// Create 3D geometry
CreateBoxGeometry(familyDoc);
trans.Commit();
}
// Save family
string savePath = @"C:\Temp\ParametricBox.rfa";
SaveAsOptions saveOptions = new SaveAsOptions();
saveOptions.OverwriteExistingFile = true;
familyDoc.SaveAs(savePath, saveOptions);
TaskDialog.Show("Success", $"Family created: {savePath}");
return Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
private void CreateReferencePlanes(Document doc)
{
// Get the reference plane creation method
FamilyManager famManager = doc.FamilyManager;
// Create reference planes at specific offsets
// These will control the box dimensions
// Front/Back planes (depth)
Plane frontPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisY, new XYZ(0, 0, 0));
SketchPlane frontSketch = SketchPlane.Create(doc, frontPlane);
Plane backPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisY, new XYZ(0, 1000 / 304.8, 0)); // 1000mm in feet
SketchPlane backSketch = SketchPlane.Create(doc, backPlane);
// Left/Right planes (width)
Plane leftPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisX, new XYZ(0, 0, 0));
SketchPlane leftSketch = SketchPlane.Create(doc, leftPlane);
Plane rightPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisX, new XYZ(500 / 304.8, 0, 0)); // 500mm in feet
SketchPlane rightSketch = SketchPlane.Create(doc, rightPlane);
}
private void CreateParameters(Document doc)
{
FamilyManager famManager = doc.FamilyManager;
// Create Width parameter
FamilyParameter widthParam = famManager.AddParameter(
"Width",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true); // isInstance = true
famManager.Set(widthParam, 500 / 304.8); // 500mm default
// Create Depth parameter
FamilyParameter depthParam = famManager.AddParameter(
"Depth",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true);
famManager.Set(depthParam, 1000 / 304.8); // 1000mm default
// Create Height parameter
FamilyParameter heightParam = famManager.AddParameter(
"Height",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true);
famManager.Set(heightParam, 750 / 304.8); // 750mm default
}
private void CreateBoxGeometry(Document doc)
{
// Create extrusion for box shape
CurveArray profile = new CurveArray();
double width = 500 / 304.8; // Convert mm to feet
double depth = 1000 / 304.8;
// Create rectangular profile
XYZ p1 = new XYZ(0, 0, 0);
XYZ p2 = new XYZ(width, 0, 0);
XYZ p3 = new XYZ(width, depth, 0);
XYZ p4 = new XYZ(0, depth, 0);
profile.Append(Line.CreateBound(p1, p2));
profile.Append(Line.CreateBound(p2, p3));
profile.Append(Line.CreateBound(p3, p4));
profile.Append(Line.CreateBound(p4, p1));
// Create sketch plane
Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero);
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
// Create extrusion
double height = 750 / 304.8;
Extrusion extrusion = doc.FamilyCreate.NewExtrusion(
true, profile, sketchPlane, height);
}
}
[Transaction(TransactionMode.Manual)]
public class BatchModifyFamilies : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
Application app = uiapp.Application;
string folderPath = @"C:\Families\ToModify";
string[] familyFiles = System.IO.Directory.GetFiles(folderPath, "*.rfa");
int successCount = 0;
int errorCount = 0;
foreach (string familyPath in familyFiles)
{
try
{
// Open family document
Document familyDoc = app.OpenDocumentFile(familyPath);
using (Transaction trans = new Transaction(familyDoc, "Modify Parameters"))
{
trans.Start();
FamilyManager famManager = familyDoc.FamilyManager;
// Add or modify "Manufacturer" parameter
FamilyParameter mfgParam = famManager.get_Parameter("Manufacturer");
if (mfgParam == null)
{
// Create parameter if it doesn't exist
mfgParam = famManager.AddParameter(
"Manufacturer",
BuiltInParameterGroup.PG_IDENTITY_DATA,
ParameterType.Text,
false); // Type parameter
}
// Set parameter value
famManager.Set(mfgParam, "ACME Corporation");
// Add "Model Number" parameter
FamilyParameter modelParam = famManager.get_Parameter("Model Number");
if (modelParam == null)
{
modelParam = famManager.AddParameter(
"Model Number",
BuiltInParameterGroup.PG_IDENTITY_DATA,
ParameterType.Text,
true); // Instance parameter
}
trans.Commit();
}
// Save and close
familyDoc.Save();
familyDoc.Close(false);
successCount++;
}
catch (Exception ex)
{
errorCount++;
System.Diagnostics.Debug.WriteLine($"Error processing {familyPath}: {ex.Message}");
}
}
TaskDialog.Show("Batch Modify Complete",
$"Successfully modified: {successCount}\nErrors: {errorCount}");
return Result.Succeeded;
}
}
public void LoadFamilyIntoProject(Document projectDoc, string familyPath)
{
using (Transaction trans = new Transaction(projectDoc, "Load Family"))
{
trans.Start();
Family family;
bool loaded = projectDoc.LoadFamily(familyPath, out family);
if (loaded)
{
// Get family symbols (types)
ISet<ElementId> symbolIds = family.GetFamilySymbolIds();
foreach (ElementId symbolId in symbolIds)
{
FamilySymbol symbol = projectDoc.GetElement(symbolId) as FamilySymbol;
// Activate symbol if not already active
if (!symbol.IsActive)
{
symbol.Activate();
}
// Place instance at origin
Level level = new FilteredElementCollector(projectDoc)
.OfClass(typeof(Level))
.FirstElement() as Level;
FamilyInstance instance = projectDoc.Create.NewFamilyInstance(
XYZ.Zero, symbol, level, StructuralType.NonStructural);
}
}
trans.Commit();
}
}
FamilyCreate instead of Create for geometryFamilyManager to manage parameters and typesMistake: Using wrong creation method
// WRONG - Create is for projects only
doc.Create.NewExtrusion(...);
// CORRECT - FamilyCreate is for families
doc.FamilyCreate.NewExtrusion(...);
Mistake: Not activating family symbols
// WRONG - trying to place inactive symbol
FamilyInstance instance = doc.Create.NewFamilyInstance(point, symbol, level, type);
// CORRECT - activate first
if (!symbol.IsActive)
symbol.Activate();
FamilyInstance instance = doc.Create.NewFamilyInstance(point, symbol, level, type);
Mistake: Forgetting unit conversion
// WRONG - treating feet as millimeters
double width = 1000; // This is 1000 feet!
// CORRECT - convert mm to feet
double width = 1000 / 304.8; // 1000mm in feet
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
[Transaction(TransactionMode.Manual)]
public class CreateBoxFamily : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
Application app = uiapp.Application;
try
{
// Create new family document
Document familyDoc = app.NewFamilyDocument(
@"C:\ProgramData\Autodesk\RVT 2024\Family Templates\English\Metric Generic Model.rft");
using (Transaction trans = new Transaction(familyDoc, "Create Box"))
{
trans.Start();
// Create reference planes for parametric control
CreateReferencePlanes(familyDoc);
// Create parameters
CreateParameters(familyDoc);
// Create 3D geometry
CreateBoxGeometry(familyDoc);
trans.Commit();
}
// Save family
string savePath = @"C:\Temp\ParametricBox.rfa";
SaveAsOptions saveOptions = new SaveAsOptions();
saveOptions.OverwriteExistingFile = true;
familyDoc.SaveAs(savePath, saveOptions);
TaskDialog.Show("Success", $"Family created: {savePath}");
return Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
private void CreateReferencePlanes(Document doc)
{
// Get the reference plane creation method
FamilyManager famManager = doc.FamilyManager;
// Create reference planes at specific offsets
// These will control the box dimensions
// Front/Back planes (depth)
Plane frontPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisY, new XYZ(0, 0, 0));
SketchPlane frontSketch = SketchPlane.Create(doc, frontPlane);
Plane backPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisY, new XYZ(0, 1000 / 304.8, 0)); // 1000mm in feet
SketchPlane backSketch = SketchPlane.Create(doc, backPlane);
// Left/Right planes (width)
Plane leftPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisX, new XYZ(0, 0, 0));
SketchPlane leftSketch = SketchPlane.Create(doc, leftPlane);
Plane rightPlane = Plane.CreateByNormalAndOrigin(
XYZ.BasisX, new XYZ(500 / 304.8, 0, 0)); // 500mm in feet
SketchPlane rightSketch = SketchPlane.Create(doc, rightPlane);
}
private void CreateParameters(Document doc)
{
FamilyManager famManager = doc.FamilyManager;
// Create Width parameter
FamilyParameter widthParam = famManager.AddParameter(
"Width",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true); // isInstance = true
famManager.Set(widthParam, 500 / 304.8); // 500mm default
// Create Depth parameter
FamilyParameter depthParam = famManager.AddParameter(
"Depth",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true);
famManager.Set(depthParam, 1000 / 304.8); // 1000mm default
// Create Height parameter
FamilyParameter heightParam = famManager.AddParameter(
"Height",
BuiltInParameterGroup.PG_GEOMETRY,
ParameterType.Length,
true);
famManager.Set(heightParam, 750 / 304.8); // 750mm default
}
private void CreateBoxGeometry(Document doc)
{
// Create extrusion for box shape
CurveArray profile = new CurveArray();
double width = 500 / 304.8; // Convert mm to feet
double depth = 1000 / 304.8;
// Create rectangular profile
XYZ p1 = new XYZ(0, 0, 0);
XYZ p2 = new XYZ(width, 0, 0);
XYZ p3 = new XYZ(width, depth, 0);
XYZ p4 = new XYZ(0, depth, 0);
profile.Append(Line.CreateBound(p1, p2));
profile.Append(Line.CreateBound(p2, p3));
profile.Append(Line.CreateBound(p3, p4));
profile.Append(Line.CreateBound(p4, p1));
// Create sketch plane
Plane plane = Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero);
SketchPlane sketchPlane = SketchPlane.Create(doc, plane);
// Create extrusion
double height = 750 / 304.8;
Extrusion extrusion = doc.FamilyCreate.NewExtrusion(
true, profile, sketchPlane, height);
}
}