Shared Parameters - Create and add to Family in Python

Hi,
here is a fix, (tested with Revit 2021, 2022, 2023)


#Inspired by an archilab node, by Konrad Sobon
#Modifications by Alban de Chasteigner 2020
# test fix by Cyril Poupin for Revit 2022+
#twitter : @geniusloci_bim
#geniusloci.bim@gmail.com
#https://github.com/albandechasteigner/GeniusLociForDynamo

import clr
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application
version=int(app.VersionNumber)

import System
from System.Collections.Generic import List
from System import Guid

_paramName = IN[0] if isinstance(IN[0],list) else [IN[0]]
_groupName = IN[1]
parameterTypes = IN[2] if isinstance(IN[2],list) else [IN[2]]
parameterGroups = IN[3] if isinstance(IN[3],list) else [IN[3]]
_instance = IN[4] if isinstance(IN[4],list) else [IN[4]]
_visible = IN[5] if isinstance(IN[5],list) else [IN[5]]
guids = IN[6] if isinstance(IN[6],list) else [IN[6]]
_categories = IN[7] if isinstance(IN[7],list) else [IN[7]]

paramTypes_len = len(parameterTypes) == 1
paramGroups_len = len(parameterGroups) == 1
instance_len = len(_instance) == 1
visible_len = len(_visible) == 1
guid_len = len(guids) == 1

if version < 2022:
	_paramGroup = [System.Enum.Parse(Autodesk.Revit.DB.BuiltInParameterGroup, parameterGroup) if isinstance(parameterGroup, basestring) else parameterGroup for parameterGroup in parameterGroups]
	_paramType = [System.Enum.Parse(Autodesk.Revit.DB.ParameterType, parameterType) if isinstance(parameterType, basestring) else parameterType for parameterType in parameterTypes]
else:
	# parameter Group 
	propGP_infos = clr.GetClrType(GroupTypeId).GetProperties()
	dictGrp_forgeTypeId = {p.Name : p.GetGetMethod().Invoke(None, None) for p in propGP_infos}
	_paramGroup = [dictGrp_forgeTypeId.get(parameterGroup) for parameterGroup in parameterGroups if isinstance(parameterGroup, basestring)]
	# 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)
	#
	invalid_forgeTypeId = ForgeTypeId()
	_paramType=[dict_forgeTypeId.get(parameterType, invalid_forgeTypeId ) for parameterType in parameterTypes if isinstance(parameterType, basestring)]
	
_guid = [Guid(guid) if isinstance(guid, basestring) else guid for guid in guids]

def IsEqualTo_ParameterType(para_def, paraType):
	"""
	check if ParameterType of a defintion is Equal to a other ParameterType (or SpecTypeId)
	"""
	if version < 2022:
		return para_def.ParameterType == paraType
	else:
		return para_def.GetDataType() == paraType

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 and IsEqualTo_ParameterType(iterator.Key, _paramType):
			paramExists = True
			break
		else:
			paramExists = False
	return paramExists

def RemoveParamBinding(_doc, _paramName, _paramType):
	map = doc.ParameterBindings
	iterator = map.ForwardIterator()
	iterator.Reset()
	while iterator.MoveNext():
		if iterator.Key != None and iterator.Key.Name == _paramName and IsEqualTo_ParameterType(iterator.Key, _paramType):
			definition = iterator.Key
			break
	message = None
	if definition != None:
		map.Remove(definition)
		message = "Success"
	return message

def addParam(doc, _paramName, _paramType, _visible, _instance, _guid, _groupName, _paramGroup,_categories):
	message = None
	if ParamBindingExists(doc, _paramName, _paramType):
		if not RemoveParamBinding(doc, _paramName, _paramType) == "Success":
			message = "Param Binding Not Removed Successfully"
		else:
			message = None		
	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()
	builtInCategories=[doc.Settings.Categories.get_Item(System.Enum.ToObject(BuiltInCategory, _category.Id)) for _category in _categories]
	[cats.Insert(builtInCategory) for builtInCategory in builtInCategories]
	if _instance:
		bind=app.Create.NewInstanceBinding(cats)
	else:
		bind=app.Create.NewTypeBinding(cats)
	param = doc.ParameterBindings.Insert(_def, bind, _paramGroup)
	return message
	
TransactionManager.Instance.EnsureInTransaction(doc)
try:
	file = app.OpenSharedParameterFile()
except:
	message = "No Shared Parameter file found."
	pass

for number in xrange(len(_paramName)):
	t = 0 if paramTypes_len else number
	g = 0 if paramGroups_len else number
	i = 0 if instance_len else number
	v = 0 if visible_len else number
	d = 0 if guid_len else number
	message = addParam(doc, _paramName[number], _paramType[t], _visible[v], _instance[i], _guid[d], _groupName, _paramGroup[g],_categories)
		
TransactionManager.Instance.TransactionTaskDone()

if message == None:
	OUT = "Success"
else:
	OUT = message

I could not test all the parameters, so feedbacks are welcome

FYI @Alban_de_Chasteigner :slightly_smiling_face:

6 Likes