Hello pyRevit friends
I have a pushbutton named
title:
Load Fam/
Type/Para
The filename is “Load_script.py” and the folder is “Load.pushbutton”
If I run the script, which prints a plenty of info I get this window:
Which obviously shows the wrong name in the title.
And even the __commandname__
is returning “hooks.viewnames_doc-created” , weird.
So why are the print results are showing up in the window of another script?
So maybe this hook script gets triggered by the loaded families, or created types?
Is there a way to get the right __commandname__
? I´m writing a user log and it´s confusing if wrong bundle names are logged.
This is the hook code:
from pyrevit import EXEC_PARAMS
import View_Names
doc = EXEC_PARAMS.event_args.Document
app = __revit__
if doc and not doc.IsFamilyDocument:
View_Names.update_view_names(doc,app)
pushbutton:
# -*- coding: utf-8 -*-
# Standard Libraries
import io
import csv
import clr
import sys
import time
from datetime import datetime, timedelta
from os.path import exists
# import ... Library
import Log
# pyRevit Libraries
from pyrevit import script, forms, EXEC_PARAMS
sys.path.append('C:\Program Files (x86)\IronPython 2.7\Lib')
# .NET and System Libraries
import System
from System import Array
from System.Collections.Generic import *
clr.AddReference('ProtoGeometry')
clr.AddReference('PresentationCore')
clr.AddReference('AdWindows')
# Autodesk Libraries
from Autodesk.DesignScript.Geometry import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from Autodesk.Revit.UI import (
TaskDialog, TaskDialogCommonButtons, TaskDialogResult,
TaskDialogCommandLinkId, TaskDialogIcon
)
from Autodesk.Revit.DB import (
DefinitionBindingMapIterator, ViewSheet, FilterStringRule, FilterStringEquals, ParameterValueProvider, ParameterFilterRuleFactory, Transaction, SpecTypeId, BuiltInParameterGroup, Category, IFamilyLoadOptions, Family, FamilySymbol, Viewport, Element,
View, ViewType, ElementId, ElementParameterFilter, FilteredElementCollector,
FilterElementIdRule, BuiltInParameter, BuiltInCategory
)
from Autodesk.Revit.DB.Structure import *
import Autodesk.Windows as adWin
# Revit Document Initialization
uidoc = __revit__.ActiveUIDocument
doc = __revit__.ActiveUIDocument.Document
app = __revit__.Application
version=int(app.VersionNumber)
def Floor_Openings():
family = [x for x in FilteredElementCollector(doc).OfClass(Family).ToElements() if "Deckenöffnung rechteckig".lower() == x.Name.lower()]
return family
def Wall_Openings():
family = [x for x in FilteredElementCollector(doc).OfClass(Family).ToElements() if "Wandöffnung rechteckig".lower() == x.Name.lower()]
if family and isinstance(family, list):
output=family[0]
else:
output = family
return output
# def Doors():
# famTypes = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Doors).OfClass(FamilySymbol).ToElements()
# fams = set(famType.Family.Id for famType in famTypes)
class FamilyOption(IFamilyLoadOptions):
def OnFamilyFound(self,familyInUse,overwriteParameterValues):
overwriteParameterValues = True
return True
def OnSharedFamilyFound(self, sharedFamily, familyInUse, FamilySource, overwriteParameterValues):
overwriteParameterValues = True
return True
def GetSharedParameter(ParameterName):
shared_parameter_file_path = r'X:\3-BU\AT\...\PG11\06 Planungsunterlagen\1_Effizienz-2020\7_Revit\Shared_Parameters\Shared_Parameters_....txt'
if not doc.Application.SharedParametersFilename == shared_parameter_file_path:
doc.Application.SharedParametersFilename = shared_parameter_file_path
file = app.OpenSharedParameterFile()
groups = file.Groups
for group in groups:
for d in group.Definitions:
if d.Name == ParameterName:
defObj = d
defName = d.Name
grpObj = group
grpName = group.Name
return defObj, defName, grpObj, grpName
def AddParameterToFamily(ParameterName, Family):
if Family:
defObj, defName, grpObj, grpName = GetSharedParameter(ParameterName)
definition = defObj
bipgs = BuiltInParameterGroup.INVALID
isInstance = True
famDoc= doc.EditFamily(Family)
params = famDoc.FamilyManager.Parameters
types = famDoc.FamilyManager.Types
# Check if the parameter already exists in the family
existingParameter = None
for param in params:
if param.Definition.Name == ParameterName:
existingParameter = param
break
if existingParameter is not None:
famDoc.Close(False)
return
else:
trans = Transaction(famDoc)
trans.Start("AddSharedParameter (...)")
new = famDoc.FamilyManager.AddParameter(definition,bipgs,isInstance)
trans.Commit()
Results.append("Parameter added to "+ Family.Name +": "+ParameterName )
famDoc.LoadFamily(doc,FamilyOption())
famDoc.Close(False)
def AddParameterToCategory(ParameterName, Category, BIPG):
def ParamBindingExists(_doc, _paramName, _paramType):
map = doc.ParameterBindings
iterator = map.ForwardIterator()
iterator.Reset()
while iterator.MoveNext():
if iterator.Key != None and iterator.Key.Name == _paramName:
paramExists = True
break
else:
paramExists = False
return paramExists
def addParam(doc, _paramName, _paramType, _visible, _instance, _guid, _groupName, _paramGroup,_categories):
group = app.OpenSharedParameterFile().Groups.get_Item(_groupName)
if group == None:
group = file.Groups.Create(_groupName)
if group.Definitions.Contains(group.Definitions.Item[_paramName]):
_def = group.Definitions.Item[_paramName]
else:
opt = ExternalDefinitionCreationOptions(_paramName, _paramType)
opt.Visible = _visible
if _guid != None:
opt.GUID = _guid
_def = group.Definitions.Create(opt)
cats=app.Create.NewCategorySet()
cats.Insert(_category)
if _instance:
bind=app.Create.NewInstanceBinding(cats)
else:
bind=app.Create.NewTypeBinding(cats)
param = doc.ParameterBindings.Insert(_def, bind, _paramGroup)
defObj, defName, grpObj, grpName = GetSharedParameter(ParameterName)
_paramName = defName
_groupName = grpName
parameterType = "Length"
_instance = True
_visible = True
_guid = None
_category = Category
_paramGroup = BIPG
if version < 2022:
_paramType = System.Enum.Parse(Autodesk.Revit.DB.ParameterType, parameterType)
else:
# compute a dictionnary of all SpecTypeId {SpecTypeId Name : SpecTypeId}
dict_forgeTypeId = {}
#
for specTypeId_class in [clr.GetClrType(SpecTypeId), clr.GetClrType(SpecTypeId.Boolean), clr.GetClrType(SpecTypeId.Int), clr.GetClrType(SpecTypeId.String)]:
prop_infos = specTypeId_class.GetProperties()
dict_temp_forgeTypeId = {p.Name : p.GetGetMethod().Invoke(None, None) for p in prop_infos}
dict_forgeTypeId = dict(dict_forgeTypeId, **dict_temp_forgeTypeId)
#
_paramType = dict_forgeTypeId.get(parameterType)
if not ParamBindingExists(doc, _paramName, _paramType):
t = Transaction(doc, "AddParameterToCategory (...)")
t.Start()
try:
file = app.OpenSharedParameterFile()
except:
message = "No Shared Parameter file found."
pass
message = addParam(doc, _paramName, _paramType, _visible, _instance, _guid, _groupName, _paramGroup,_category)
Results.append("Parameter added to Category "+_category.Name+": "+_paramName )
t.Commit()
if _category.Name == "Views":
uncheck_shared_parameters_in_viewtemplates(ParameterName)
Results.append("Unchecked Shared Parameter " + ParameterName + " from all view templates")
def ViewTitles(family_path):
def load_view_title_family_if_not_loaded():
# Check if the family is already loaded
family_name = System.IO.Path.GetFileNameWithoutExtension(family_path)
family_symbols = FilteredElementCollector(doc).OfClass(FamilySymbol).ToElements()
existing_symbols = [symbol for symbol in family_symbols if symbol.Family.Name == family_name]
if not len(existing_symbols) > 0:
# Start a transaction
transaction = Transaction(doc, "Load Family (...)")
transaction.Start()
try:
# Load the family
doc.LoadFamily(family_path)
transaction.Commit()
Results.append("Family loaded: " + family_name + ".rfa")
except Exception as e:
transaction.RollBack()
print "Failed to load the family '{}'.\nError: {}".format(family_name, e)
def existing_viewport_types():
builtInParameter = BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM
rule = ParameterFilterRuleFactory.CreateEqualsRule(ElementId(int(builtInParameter)), "Viewport", False)
filter = ElementParameterFilter(rule)
viewport_types = FilteredElementCollector(doc).WhereElementIsElementType().WherePasses(filter)
names = []
for viewport_type in viewport_types:
name_parameter = viewport_type.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM)
name = name_parameter.AsString()
names.append(name)
return names
def duplicate_viewport_type():
builtInParameter = BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM
rule = ParameterFilterRuleFactory.CreateEqualsRule(ElementId(int(builtInParameter)), "Viewport", False)
filter = ElementParameterFilter(rule)
viewport_types = FilteredElementCollector(doc).WhereElementIsElementType().WherePasses(filter).ToElements()
viewport_type = viewport_types[0]
duplicated_viewport_type = None
duplicated_viewport_types = []
transaction = Transaction(doc, "Duplicate Viewport Type")
transaction.Start()
try:
for type_name in type_names:
name_parameter = viewport_type.get_Parameter(BuiltInParameter.SYMBOL_NAME_PARAM)
name = name_parameter.AsString()
duplicated_viewport_type = viewport_type.Duplicate(type_name)
duplicated_viewport_types.append(duplicated_viewport_type)
Results.append("View Title Type created: " + type_name)
transaction.Commit()
except Exception as e:
transaction.RollBack()
print("Failed to duplicate viewport type.\nError: {}".format(e))
return duplicated_viewport_types
def get_type_by_name(type_names):
"""Function to get Type by Name. by learnrevitapi.com"""
TitleTypes = []
for type_name in type_names:
# CREATE RULE
param_id = ElementId(BuiltInParameter.ALL_MODEL_TYPE_NAME)
f_param = ParameterValueProvider(param_id)
f_evaluator = FilterStringEquals()
if version < 2022:
f_rule = FilterStringRule(f_param, f_evaluator , type_name, True)
else:
f_rule = FilterStringRule(f_param, f_evaluator , type_name)
# Revit 2023 does not need last argument in f_rule!
# CREATE FILTER
filter_type_name = ElementParameterFilter(f_rule)
# GET ELEMENTS
TitleType = FilteredElementCollector(doc).WherePasses(filter_type_name)\
.WhereElementIsElementType().FirstElement()
TitleTypes.append(TitleType)
return TitleTypes
def extension_line():
transaction = Transaction(doc, "Extension Line (...)")
transaction.Start()
for viewport_type in viewport_types:
extension_line_param = viewport_type.get_Parameter(BuiltInParameter.VIEWPORT_ATTR_SHOW_EXTENSION_LINE)
if extension_line_param:
extension_line_param.Set(0)
transaction.Commit()
def set_view_title():
transaction = Transaction(doc, "Set View Title (...)")
transaction.Start()
try:
for viewport_type, title_type in zip(viewport_types, filtered_title_types):
# Set the view title type for the viewport type
viewport_type.get_Parameter(BuiltInParameter.VIEWPORT_ATTR_LABEL_TAG).Set(title_type.Id)
transaction.Commit()
except Exception as e:
transaction.RollBack()
print("Failed to set view title.\nError: {}".format(e))
all_type_names = [
"00_kein Titel",
"01_Schnitt, Detailnummer",
"02_Schnitt, Detailnummer, View Description",
"03_Schnitt, Detailnummer//View Description",
"04_Grundriss, Detailnummer",
"05_Grundriss, Detailnummer, View Description",
"06_Grundriss, Detailnummer//View Description",
"07_Grundriss, Detailnummer, Cut Plane Elevation",
"08_Grundriss, Detailnummer, Cut Plane Elevation, View Description",
"09_Grundriss, Detailnummer, Cut Plane Elevation//View Description",
"10_Detail, Detailnummer",
"11_Detail, Detailnummer, View Description",
"12_Detail, Detailnummer//View Description",
"13_View Description, Detailnummer",
"14_Ansichtsname"]
load_view_title_family_if_not_loaded()
existing_viewport_types = existing_viewport_types()
type_names = []
for type_name in all_type_names:
if type_name not in existing_viewport_types:
type_names.append(type_name)
if type_names:
viewport_types = duplicate_viewport_type()
extension_line()
family_name = "View Title (...)"
TitleTypes = get_type_by_name(type_names)
filtered_title_types = [title_type for title_type in TitleTypes if title_type.FamilyName == family_name]
set_view_title()
def load_family_if_not_loaded(family_path):
# Check if the family is already loaded
family_name = System.IO.Path.GetFileNameWithoutExtension(family_path)
families = FilteredElementCollector(doc).OfClass(Family).ToElements()
existing_families = [fam for fam in families if fam.Name == family_name]
if not existing_families:
# Start a transaction
transaction = Transaction(doc, "Load Family (...)")
transaction.Start()
try:
# Load the family
doc.LoadFamily(family_path)
transaction.Commit()
Results.append("Family loaded: " + family_name + ".rfa")
except Exception as e:
transaction.RollBack()
print("Failed to load the family '{}'.\nError: {}".format(family_name, e))
def load_annotation_family_if_not_loaded(family_path):
# Check if the family is already loaded
family_name = System.IO.Path.GetFileNameWithoutExtension(family_path)
family_symbols = FilteredElementCollector(doc).OfClass(FamilySymbol).ToElements()
existing_symbols = [symbol for symbol in family_symbols if symbol.Family.Name == family_name]
if not len(existing_symbols) > 0:
# Start a transaction
transaction = Transaction(doc, "Load Family (...)")
transaction.Start()
try:
# Load the family
doc.LoadFamily(family_path)
transaction.Commit()
Results.append("Family loaded: " + family_name + ".rfa")
except Exception as e:
transaction.RollBack()
print "Failed to load the family '{}'.\nError: {}".format(family_name, e)
def uncheck_shared_parameters_in_viewtemplates(param_name):
# Collect all views in the document
all_views = FilteredElementCollector(doc).OfClass(View).ToElements()
# Filter out only the view templates using a list comprehension
view_templates = [v for v in all_views if v.IsTemplate]
# Initialize the transaction
t = Transaction(doc, 'Uncheck parameters (...)')
t.Start()
# Iterate over each view template
for template in view_templates:
nonControlledParams = list(template.GetNonControlledTemplateParameterIds())
# Find the shared parameter by name
param = template.LookupParameter(param_name)
# If found, toggle its control
if param:
param_id = param.Id
if param_id not in nonControlledParams:
nonControlledParams.append(param_id)
# Apply changes to the current view template
template.SetNonControlledTemplateParameterIds(List[ElementId](nonControlledParams))
t.Commit()
def Toast():
forms.toaster.send_toast("... families and types loaded successfully to your Revit Model", title="Success", appid="Revit", icon=None, click=None, actions=None)
def user_choice(line1,line2):
taskDialog = TaskDialog("...")
taskDialog.MainInstruction = line1
taskDialog.MainContent = line2
taskDialog.TitleAutoPrefix = False
taskDialog.MainIcon = TaskDialogIcon.TaskDialogIconInformation
taskDialog.CommonButtons = TaskDialogCommonButtons.No | TaskDialogCommonButtons.Yes
#taskDialog.FooterText = "Help"
userinput = taskDialog.Show()
return userinput
def parameter_exists_in_category(doc, bic, param_name):
map = doc.ParameterBindings
iterator = map.ForwardIterator()
while iterator.MoveNext():
if iterator.Key.Name == param_name:
binding = iterator.Current
if binding and binding.Categories.Contains(doc.Settings.Categories.get_Item(bic)):
return True
return False
################################################################################################################################################
userinput = user_choice("Load ... Library","Do you want to load ... Families, Types and Parameters to this project?\nElements that already exist in the project will not be replaced!")
if userinput != TaskDialogResult.Yes:
script.exit()
Results = []
if version == 2022:
ViewTitles(r'...Annotation\View_Title\2022\View Title (...).rfa')
load_family_if_not_loaded(r'...Generic_Model\Opening\2022\Wandöffnung rechteckig.rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Wall Opening (...).rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Floor Opening (...).rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Door Opening (...).rfa')
if version == 2023:
ViewTitles(r'...Annotation\View_Title\2023\View Title (...).rfa')
load_family_if_not_loaded(r'...Generic_Model\Opening\2023\Wandöffnung rechteckig.rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Wall Opening (...).rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Floor Opening (...).rfa')
load_annotation_family_if_not_loaded(r'...Annotation\Tags\2022\Tag Door Opening (...).rfa')
AddParameterToFamily("Top Edge Elevation (...)", Wall_Openings())
AddParameterToCategory("Top Edge Elevation (...)", Category.GetCategory(doc, BuiltInCategory.OST_Doors), BuiltInParameterGroup.INVALID)
AddParameterToCategory("View Description (...)", Category.GetCategory(doc, BuiltInCategory.OST_Views), BuiltInParameterGroup.PG_TITLE)
AddParameterToCategory("Cut Plane Elevation (...)", Category.GetCategory(doc, BuiltInCategory.OST_Views), BuiltInParameterGroup.INVALID)
bics = [BuiltInCategory.OST_Walls, BuiltInCategory.OST_Floors, BuiltInCategory.OST_Ceilings, BuiltInCategory.OST_Columns, BuiltInCategory.OST_GenericModel, BuiltInCategory.OST_Stairs, BuiltInCategory.OST_StructuralColumns, BuiltInCategory.OST_StructuralFoundation]
for bic in bics:
category = Category.GetCategory(doc, bic)
if not parameter_exists_in_category(doc, bic, "Planserie"):
AddParameterToCategory("Sheet Set (...)", category, BuiltInParameterGroup.INVALID)
else:
Results.append("Sheet Set parameter was not loaded to category {0} because the old parameter 'Planserie' exists.".format(category.Name))
if not parameter_exists_in_category(doc, BuiltInCategory.OST_Sheets, "VORPAUSE"):
AddParameterToCategory("Draft (...)", Category.GetCategory(doc, BuiltInCategory.OST_Sheets), BuiltInParameterGroup.INVALID)
else:
Results.append("Draft parameter was not loaded because the old parameter VORPAUSE exists in the project.")
result_string = '\n'.join(Results)
if len(Results) > 1:
Toast()
print result_string
Log.create_log_entry(doc, app)
Appreciate any help