I’ve been going in circles with this for far too long.
I am developing a script based on a Dynamo script I developed that automates the visibility of keyplan areas. I am struggling with learning to work with the Revit API and have outpaced my capabilities.
Here’s my pyRevit pushbutton script so far:
# AUTO KEYPLAN AREA tool
# Initial imports
from pyrevit import revit, forms
from Autodesk.Revit.DB import FilteredElementCollector, FamilySymbol, ElementCategoryFilter, BuiltInCategory, Parameter
# New imports for adding a parameter
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# Initialization
uidoc = __revit__.ActiveUIDocument
doc = uidoc.Document
# Fetch all Titleblock families
def get_titleblock_families():
collector = FilteredElementCollector(doc)
titleblock_filter = ElementCategoryFilter(BuiltInCategory.OST_TitleBlocks)
titleblocks = collector.WherePasses(titleblock_filter).WhereElementIsElementType().ToElements()
return titleblocks
# Get Titleblock families from the project
titleblock_families = get_titleblock_families()
# Prepare data for the dropdown menu (family names and family IDs)
family_options = {}
for titleblock in titleblock_families:
family_symbol = titleblock # Since we're dealing with FamilySymbols, not Families directly
family = family_symbol.Family # Access the Family object
family_name = family.Name # Now access the Family name
family_id = family_symbol.Id
family_options[family_name] = family_id
# If there are families to choose from, display the dropdown menu
if family_options:
# Using SelectFromList for dropdown-style selection
selected_family_name = forms.SelectFromList.show(list(family_options.keys()), title="Select Titleblock Family")
if selected_family_name:
selected_family_id = family_options.get(selected_family_name)
selected_family = doc.GetElement(selected_family_id)
# Check if the selected titleblock contains the parameter "KeyplanAreaToggle"
parameter = selected_family.LookupParameter("KeyplanAreaToggle")
if parameter:
print("The selected titleblock contains the 'KeyplanAreaToggle' parameter.")
else:
print("The selected titleblock does not contain the 'KeyplanAreaToggle' parameter.")
else:
forms.alert("No titleblock families found in this project.", exit=True)
# Add the KeyplanAreaToggle parameter
# Define the shared parameter file path
shared_param_file_path = r'P:\STL\TB\pyRevit Shared Parameters\pyRevitSharedParameters_byTB.txt'
# Open the shared parameter file
app = doc.Application
app.SharedParametersFilename = shared_param_file_path
shared_param_file = app.OpenSharedParameterFile()
# Get the shared parameter definition
param_def = None
for group in shared_param_file.Groups:
if group.Name == "Graphics":
for definition in group.Definitions:
if definition.Name == "KeyplanAreaToggle":
param_def = definition
break
# Create a category set and add the family category
category_set = app.Create.NewCategorySet()
category_set.Insert(doc.Settings.Categories.get_Item(BuiltInCategory.OST_TitleBlocks))
# Create an instance binding
instance_binding = app.Create.NewInstanceBinding(category_set)
# Start a transaction
TransactionManager.Instance.EnsureInTransaction(doc)
try:
# Add the shared parameter to the family
if param_def:
doc.FamilyManager.AddParameter(param_def, BuiltInParameterGroup.PG_GRAPHICS, True)
# Commit the transaction
TransactionManager.Instance.TransactionTaskDone()
except Exception as e:
print("An error occurred: {}".format(e))
TransactionManager.Instance.ForceCloseTransaction()
Well - at a quick glance you are mixing Dynamo and pyRevit references. Not the way to go.
Dump RevitServices (Dynamo) and just use the api for your transactions and documents.
Thank you all for your responses. I have researched your recommendations and implemented them to the best of my ability.
My script:
# Initial imports
from pyrevit import revit, forms
from Autodesk.Revit.DB import FilteredElementCollector, FamilySymbol, ElementCategoryFilter,\
BuiltInCategory, Parameter, FamilyManager
# New imports for adding a parameter
import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')
from Autodesk.Revit.DB import *
#from RevitServices.Persistence import DocumentManager
#from RevitServices.Transactions import TransactionManager
# Initialization
uidoc = __revit__.ActiveUIDocument
doc = uidoc.Document
# Fetch all Titleblock families
def get_titleblock_families():
collector = FilteredElementCollector(doc)
titleblock_filter = ElementCategoryFilter(BuiltInCategory.OST_TitleBlocks)
titleblocks = collector.WherePasses(titleblock_filter).WhereElementIsElementType().ToElements()
return titleblocks
# Get Titleblock families from the project
titleblock_families = get_titleblock_families()
# Prepare data for the dropdown menu (family names and family IDs)
family_options = {}
for titleblock in titleblock_families:
family_symbol = titleblock # Since we're dealing with FamilySymbols, not Families directly
family = family_symbol.Family # Access the Family object
family_name = family.Name # Now access the Family name
family_id = family_symbol.Id
family_options[family_name] = family_id
# If there are families to choose from, display the dropdown menu
if family_options:
# Using SelectFromList for dropdown-style selection
selected_family_name = forms.SelectFromList.show(list(family_options.keys()), title="Select Titleblock Family")
if selected_family_name:
selected_family_id = family_options.get(selected_family_name)
selected_family = doc.GetElement(selected_family_id)
# Check if the selected titleblock contains the parameter "KeyplanAreaToggle"
parameter = selected_family.LookupParameter("KeyplanAreaToggle")
if parameter:
print("The selected titleblock contains the 'KeyplanAreaToggle' parameter.")
else:
print("The selected titleblock does not contain the 'KeyplanAreaToggle' parameter.")
else:
forms.alert("No titleblock families found in this project.", exit=True)
# Add the KeyplanAreaToggle parameter
# Define the shared parameter file path
shared_param_file_path = r'P:\STL\TB\pyRevit Shared Parameters\pyRevitSharedParameters_byTB.txt'
# Open the shared parameter file
app = doc.Application
app.SharedParametersFilename = shared_param_file_path
shared_param_file = app.OpenSharedParameterFile()
# Get the shared parameter definition
param_def = None
for group in shared_param_file.Groups:
if group.Name == "Graphics":
for definition in group.Definitions:
if definition.Name == "KeyplanAreaToggle":
param_def = definition
break
# Create a category set and add the family category
category_set = app.Create.NewCategorySet()
category_set.Insert(doc.Settings.Categories.get_Item(BuiltInCategory.OST_TitleBlocks))
# Create an instance binding
instance_binding = app.Create.NewInstanceBinding(category_set)
# Start a transaction
#TransactionManager.Instance.EnsureInTransaction(doc)
"""
try:
# Add the shared parameter to the family
if param_def:
doc.FamilyManager.AddParameter(param_def, BuiltInParameterGroup.PG_GRAPHICS, True)
# Commit the transaction
TransactionManager.Instance.TransactionTaskDone()
except Exception as e:
print("An error occurred: {}".format(e))
TransactionManager.Instance.ForceCloseTransaction()
"""
# Transaction solution suggestion from pyRevit forum.
with revit.Transaction("AKPA_script"):
doc.FamilyManager.AddParameter(param_def, BuiltInParameterGroup.PG_GRAPHICS, True)
generates an error:
"P:\STL\TB\BR+A_Tools\BR+A_Tools.extension\BR+A_Tools.tab\BR+A_Tools.Panel\Sheets.pulldown\AutoKeyplanArea.pushbutton\AKPA_script.py", line 106, in <module>
Exception: Document.FamilyManager can only be used in the Revit Family Editor.
Can I continue here or should I start another topic?