Thanks!
“class” should be changed to some other name.
I still would want to know why “OST_Rooms” cannot be used in Python.
Thanks!
“class” should be changed to some other name.
I still would want to know why “OST_Rooms” cannot be used in Python.
You’re right, I’ve changed it to “klass” (this happens when you code on a smartphone inside a forum without testing anything
Two untested options:
categoryString = "OST_StructuralColumns"
categoryId = BuiltInCategory(getattr(BuiltInCategory, categoryString))
Or maybe
from System import Enum
category = Enum.Parse(categoryString)
PythonNet 3 (in pyRevit WIP) should handle .net enums, IIRC
The following works:
import pyrevit
from pyrevit import DB
from Autodesk.Revit.DB import *
doc = pyrevit.revit.doc
categoryString = "OST_StructuralColumns"
bic = getattr(BuiltInCategory, categoryString)
elements = FilteredElementCollector(doc).OfCategory(bic).WhereElementIsNotElementType()
elements = sorted(elements, key=lambda elements:elements.Name)
for element in elements:
print (element.Name + " " + str(element.Id))
print ("end")
If categoryString = “OST_Rooms”, then there is:
TypeError : property cannot be read
referring to elements.Name in:
elements = sorted(elements, key=lambda elements:elements.Name)
If bic = BuiltInCategory(getattr(BuiltInCategory, categoryString)), then this line gives
TypeError : property cannot be read
The following does not work:
import clr
clr.AddReference("System")
from System import Enum
categoryString = "OST_StructuralColumns"
category = Enum.Parse(categoryString)
It gives:
TypeError : No method matches given arguments for Parse: (<class ‘str’>)
Referring to:
category = Enum.Parse(categoryString)
Have not tried PythonNet.
My workaround to handle the special case where OST_Rooms cannot lead to element.Name:
import pyrevit
from pyrevit import revit, DB
from Autodesk.Revit.DB import *
doc = __revit__.ActiveUIDocument.Document # type: ignore
#categoryString = "OST_StructuralColumns"
# or
categoryString = "OST_Rooms"
bic = getattr(BuiltInCategory, categoryString)
elements = FilteredElementCollector(doc).OfCategory(bic).WhereElementIsNotElementType().ToElements()
print ("total : " + str(len(elements)))
for element in elements:
try:
name = element.Name
elements = sorted(elements, key=lambda elements:elements.Name)
except:
name = element.LookupParameter("Name").AsString()
elements = sorted(elements, key=lambda elements:elements.LookupParameter("Name").AsString())
print (str(element.Id) + " " + name)
print ("end")
The sorting should be done first before listing each element.
The corrected codes are:
#from operator import attrgetter ## if attrgetter used
import pyrevit
from pyrevit import revit, DB
from Autodesk.Revit.DB import *
doc = __revit__.ActiveUIDocument.Document # type: ignore
categoryString = "OST_StructuralColumns"
# or
#categoryString = "OST_Rooms"
bic = getattr(BuiltInCategory, categoryString)
elements = FilteredElementCollector(doc).OfCategory(bic).WhereElementIsNotElementType().ToElements()
hasName = True
try:
elements = sorted(elements, key=lambda elements: elements.Name)
# or
#elements = sorted(elements, key=attrgetter('Name'))
except:
elements = sorted(elements, key=lambda elements:elements.LookupParameter("Name").AsString())
hasName = False
print ("total : " + str(len(elements)))
for element in elements:
if hasName:
name = element.Name
else:
name = element.LookupParameter("Name").AsString()
print (str(element.Id) + " " + name)
print ("end")
You can get the name and id of the element, put them into a tuple and sort the list
def get_name(element):
try:
return element.Name
except AttributeError:
return element.LookupParameter("Name").AsString()
# ...
ids_and_names = ((e.Id, get_name(e) for e in elements)
for item in sorted(ids_and_names, key=lambda x: x[1]):
print("{} {}".format(*item)
category.BuiltInCategory is category.Id if using cpython (with #! python3) but is name in string if using ironpython (without #! python3)
#! python3
# List Categories
from Autodesk.Revit.DB import *
doc = __revit__.ActiveUIDocument.Document # type: ignore
result = "CATEGORIES"
for category in doc.Settings.Categories:
result += "\n" + category.Name + " " + str(category.Id) + " " + str(category.BuiltInCategory)
print (result)
print(("End"))
That is respectively:
Building Type Settings -2008120 -2008120
Building Type Settings -2008120 OST_HVAC_Load_Building_Types
How to get name in string when using cpython?