Use/Load Rebar Shape using API

Hi All @c.poupin

In order to enable the use of rebar shapes in Architectural Template projects (as opposed to Structural Template projects), I’m using the code snippet below to either use an existing or load the 0-00 rebar shape from a local path (Rebar_path), as shown in the image below:

I tested my code in both Structural and Architectural projects. However, I’m facing two issues shown in the image below:

  • In the Structural Template project, where rebar shapes are loaded by default, I cannot retrieve the shape’s Name property.
  • In the Architectural Template project, the shape fails to load

import clr
import os
import System
from System.Windows.Forms import MessageBox

# Import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument
from Autodesk.Revit.DB import *


Rebar_path = r"C:\ProgramData\Autodesk\RVT 2023\Libraries\French\Structure\Formes d'armature\NF-P-02-016-1993\0-00.rfa"


def get_rebars_shapes():
    
    try:
        # get existing rebar shapes if a new "Structural Template" project is started
        collector = FilteredElementCollector(doc) \
            .OfCategory(BuiltInCategory.OST_RebarShape) \
            .WhereElementIsElementType() \
            .ToElements()
        rebar_shapes = [s.Name for s in collector]
        if rebar_shapes:
            return rebar_shapes

        # If no shapes exist "Architectural Template" project is started, try loading shape "0-00"
        if not os.path.exists(Rebar_path):
            MessageBox.Show("Rebar shape family file not found:\n{}".format(Rebar_path))
            return None

        with Transaction(doc, "Load Rebar Shape 0-00") as t:
            t.Start()
            if not os.path.exists(Rebar_path):
                MessageBox.Show("Failed to load rebar shape family.")
                return None
            doc.Regenerate()
            t.Commit()

        # Collect rebar shapes again after loading
        collector = FilteredElementCollector(doc) \
            .OfCategory(BuiltInCategory.OST_RebarShape) \
            .WhereElementIsElementType() \
            .ToElements()

        rebar_shapes = [s for s in rebar_shapes if s.Name == "0-00"]

        if not rebar_shapes:
            MessageBox.Show("Shape '0-00' not found even after loading.")
            return None

        return rebar_shapes

    except Exception as ex:
        MessageBox.Show("Error occurred:\n{}".format(str(ex)), title="Critical Error")
        return None

shapes = get_rebars_shapes()        
OUT = shapes

Any help would be apreciated

Thanks

Not sure why that property in particular is inaccessible, but you can just get the parameter values instead.

rebar_shapes = [s.LookupParameter("Type Name").AsValueString() for s in collector]
1 Like

I switched to IronPython 2.7 engine and used this updated code, where I can this time get rebar shape Name property if I start a Structural Template project, however I still unable to load the shape I want if I start an Architectural Template project?

import clr
import os
import System
import traceback
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import MessageBox

# Import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument
from Autodesk.Revit.DB import *


Rebar_path = r"C:\ProgramData\Autodesk\RVT 2023\Libraries\French\Structure\Formes d'armature\NF-P-02-016-1993\0-00.rfa"


def get_rebars_shapes():
    try:
        # get existing rebar shapes if a new "Structural Template" project is started
        collector = FilteredElementCollector(doc)\
                .OfCategory(BuiltInCategory.OST_RebarShape)\
                .WhereElementIsElementType().ToElements()
        rebar_shapes = [Element.Name.GetValue(s) for s in collector]
        if rebar_shapes:
            return rebar_shapes

        # If no shapes exist "Architectural Template" project is started, try loading shape "0-00"
        if not os.path.exists(Rebar_path):
            MessageBox.Show("Rebar shape family file not found:\n{}".format(Rebar_path))
            return None

        with Transaction(doc, "Load Rebar Shape 0-00") as t:
            t.Start()
            if not os.path.exists(Rebar_path):
                MessageBox.Show("Failed to load rebar shape family.")
                return None
            doc.Regenerate()
            t.Commit()

        # Collect rebar shapes again after loading
        collector = FilteredElementCollector(doc)\
                .OfCategory(BuiltInCategory.OST_RebarShape)\
                .WhereElementIsElementType().ToElements()

        rebar_shapes = [s for s in rebar_shapes if Element.Name.GetValue(s) == "0-00"]

        if not rebar_shapes:
            MessageBox.Show("Shape '0-00' not found even after loading.")
            return None

        return rebar_shapes

    except Exception as ex:
        print(traceback.format_exc())
        return None

shapes = get_rebars_shapes()        
OUT = shapes

Thanks.

1 Like

I don’t see where you’re actually loading the rebar shape. You check to see if the path exists but that seems to be it.

1 Like

You’re absolutely right!.. thank you for pointing out the mistake I overlooked!
Instead of writing if not doc.LoadFamily(Rebar_path): , I mistakenly repeated if not os.path.exists(Rebar_path): twice.

I’ve corrected the error in the updated code below, and it now works as expected.

import clr
import os
import System
import traceback
clr.AddReference('System.Windows.Forms')
from System.Windows.Forms import MessageBox

# Import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
from Autodesk.Revit.DB.Structure import *
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

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

doc = DocumentManager.Instance.CurrentDBDocument


def get_rebars_shapes():
    try:
        # Get existing rebar shapes
        collector = FilteredElementCollector(doc)\
                .OfCategory(BuiltInCategory.OST_RebarShape)\
                .WhereElementIsElementType().ToElements()
        rebar_shapes = [Element.Name.GetValue(s) for s in collector]
        if rebar_shapes:
            return rebar_shapes

        # If no shapes exist, try loading "0-00"
        if not os.path.exists(Rebar_path):
            MessageBox.Show("Rebar shape family file not found:\n{}".format(Rebar_path))
            return None

        with Transaction(doc, "Load Rebar Shape 0-00") as t:
            t.Start()
            if not doc.LoadFamily(Rebar_path):
                MessageBox.Show("Failed to load rebar shape family.")
                t.Commit()
                return None
            t.Commit()

        doc.Regenerate()

        # Collect rebar shapes again after loading
        collector = FilteredElementCollector(doc)\
                    .OfCategory(BuiltInCategory.OST_RebarShape)\
                    .WhereElementIsElementType().ToElements()

        rebar_shapes = [s for s in collector if Element.Name.GetValue(s) == "0-00"]

        if not rebar_shapes:
            MessageBox.Show("Shape '0-00' not found even after loading.")
            return None

        return rebar_shapes

    except Exception as ex:
        print(traceback.format_exc())
        return None

shapes = get_rebars_shapes()        
OUT = shapes

Thanks.