🏗️ Revit APIadvancedFamily Creation

Create and Modify Revit Families Programmatically

Learn to create parametric Revit families using the Family Document API with geometry and parameters.

1 views12/14/2025

Create and Modify Revit Families Programmatically

Application: Revit API
Category: Family Creation
Difficulty: Advanced
Language: C#

Problem

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.

Solution

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.

Code Example: Create Simple Parametric Box Family

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);
    }
}

Advanced: Batch Modify Family Parameters

[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;
    }
}

Load Family into Project

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();
    }
}

Key Points

  • Family documents use FamilyCreate instead of Create for geometry
  • Always use family template files (.rft) as starting points
  • Parameters can be Type (shared across all instances) or Instance (unique per instance)
  • Reference planes and dimensions control parametric behavior
  • Use FamilyManager to manage parameters and types
  • Convert units: Revit internally uses feet, so divide mm by 304.8

Common Pitfalls

Mistake: 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

Related Topics

  • Family template selection
  • Nested families
  • Shared parameters
  • Family categories and subcategories
  • Visibility and detail levels
  • Material parameters

Code Example

C#
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);
    }
}