Shared Parameters

Let's look at SharedParamters in more details. It's easy to work with them when they are already in the project. But what if they are missing and we want to fix that?

Shared Parameters

Let's look at SharedParamters in more details. It's easy to work with them when they are already in the project. But what if they are missing and we want to fix that?

Summary

This lesson might look complicated. But once you have all the code snippets, it will not be complicated to work with SharedParameters.

💡 This post will be a little different from the video and contain even more snippets. If you want to get exactly the same code as in the video - scroll all the way down to get it!

And now, Get Ready and let's learn how to Check and Load Shared Parameters!

Shared Parameters Overview

Let's have an overview of SharedParameters in Revit so we can compare Revit UI functionality with Revit API, so you can follow along the code while seeing familiar Revit Interface.

First of all let's explore Project Parameters button in Manage tab.

You get this menu and it has a list of added parameters and we can even Add, Modify or Remove them.

💡 In Revit API it's called BindingMap and we can get it with doc.ParameterBindings property.

# Get Parameter Bindings Map.
bm = doc.ParameterBindings

# Create a forward iterator 
itor = bm.ForwardIterator()

# Reset to the beginning 
itor.Reset()

# Iterate over the map 
while itor.MoveNext():
    d = itor.Key #type: Definition
    print(d.Name)

👆 Use this syntax to read Definition Names

By using this snippet you will go through and read all project and shared parameters in BindingMap. But be aware that you are getting Definitions.

Each Element has unique Parameters which can hold unique values to this Element, but Definition is what parameters are based on. It hold information what is a Parameter.

💡 Also worth noting that you will get both Instance and Type Parameter's Definitions!

Check if SharedParameters are loaded

Let's start with a code snippet to check what parameters are in the project. And if certain parameters are missing we are going to print them in the console to notify.

There are 2 ways to check them.
One way would be to iterate through BindingMap and see all Parameter Names like I showed you above.

Or we could also use SharedParameterElement Class and get them with FilteredElementCollector. However, this second option will not get any Project Parameters, so it's not as effective if you consider checking Project Parameters too.

👇Here is the snippet to check if parameters are loaded.
We can also make it a reusable function for future checks.

#📃 Get Parameter Bindings Map.
bm = doc.ParameterBindings

#💡 Create a forward iterator 
itor = bm.ForwardIterator()
itor.Reset()

#🔁 Iterate over the map and collect Names
param_names = []
while itor.MoveNext():
    d = itor.Key 
    param_names.append(d.Name)
    
#✅ Check if Parameters are loaded:
req_params = ['EF_Text','EF_Material','ImpossibleParam']
missing_params = [p for p in req_params if p not in param_names]

#👀 Display Missing Parameters
if missing_params:
    print('Missing Parameters:')
    for p_name in missing_params:
        print(p_name)

💡Notice that we create a ForwardIterator and use .MoveNext() to iterate through parameters.

If you try to use a for-loop it will not be able to get Definition with a .Key property.

Create Reusable Function

I think we all can agree that this code snippet is already quite useful!

So let's make it a function that can be placed in our reusable library of snippets to use in any of the scripts we want!

👇 Here is the function:

def check_loaded_params(list_p_names):
    """Check if any parameters from list are missing 
    :param list_p_names: List of Parameter Names
    :return:             List of Missing Parameter Names"""
    # 📃 Get Parameter Bindings Map.
    bm = doc.ParameterBindings

    # 💡 Create a forward iterator 
    itor = bm.ForwardIterator()
    itor.Reset()

    #ITerate over the map
    loaded_parameters = []
    while itor.MoveNext():
        try:
            d = itor.Key
            loaded_parameters.append(d.Name)
        except:
            pass

    # ✅ Check if Parameters are loaded:
    missing_params = [p_name for p_name in list_p_names 
                           if p_name not in loaded_parameters]


    return missing_params

And here is an example of how to use it.

You need a list of parameter names that you want in your project and then this function will return you a list of missing parameters (if any).

This way you can stop execution of your scripts and notify users that they should bring certain shared parameters if necessary 😉!

#☑️ Check Missing Parameters
req_params     = ['EF_Text', 'EF_Material', 'B_Param 1', 'A_Param 3', 'Error']
missing_params = check_loaded_params(req_params)

# 👀 Display Missing Parameters
if missing_params:
    print('Missing Parameters:')
    for p_name in missing_params:
        print(p_name)


The question now is how to add missing parameters to the project?

How to Load SharedParameters ?

First of all let's go through Revit UI and see how do we normally bring Shared Parameters to the project, and I will point your attention to details that we should address in the code.

We will start by going to Manage -> Project Parameters menu.

Right there on the right we have Add, Modify and Remove buttons, and we can find these actions in Revit API:

BindingMap.Insert
BindingMap.Remove

And to Modify, we will have to look inside of InternalDefinition Class, because that's what these Parameters are stored as in this menu.

InternalDefinition - represents a parameter definition in an Autodesk Revit model.

ExternalDefinition - represents a parameter defnition in SharedParameterFIle, outside of Autodesk Revit model.

When we click on Add… we will see this menu.

Probably this menu feels very natural already, and you don't even notice how many steps you need to do to add a Parameter.

So I marked all the parts that we will need to adress with the code and we will go through them one by one in python.

  • 1️⃣ Select SharedParameter from SharedParameterFile

  • 2️⃣ Select Type/Instance

  • 3️⃣ Select Categories

  • 4️⃣ Select Group Parameter Group

  • 5️⃣ Set ValuesVariesBetweenGroups

All these steps will have to be addressed to use BindingMap.Insert method.
So let me break it down for you!

1️⃣ SharedParameterFile

First of all we need to select a Definition to insert. To do that we need to read SharedParameterFile and read through its Groups to find the right Definition.

We will read default file by using Application.OpenSharedParameterFile.

# 📁 Access shared parameter file
app      = __revit__.Application
sp_file  = app.OpenSharedParameterFile()

Also sometimes we don't have any SharedParameterFile associated in the Revit, or we might want to change it, then we can use the following Snippet to provide path to the file before we are going to Read it.

import os
# 📦 Variables
app = __revit__.Application

#📁 Set Shared Parameter File in Revit
shared_param__path = r"N:\...\...\SharedParameters.txt"
if os.path.exists(shared_param_file_path):
    app.SharedParametersFilename = shared_param_file_path

#👀 Read Shared Parameter File
sp_file = app.OpenSharedParameterFile()
How to read SharedParameterFile?

So we opened our SharedParameterFile and now we can go through it and read parameters inside of it.

As you know Parameters are organized in Groups, and to read parameters in Revit API we would need to iterate through Groups and then through parameters.

It's very simple, here is an example:

#📦 Variables
app = __revit__.Application

#🔎 Access shared parameter file
sp_file = app.OpenSharedParameterFile()

#👀 Read ParameterGroups and ParameterDefinitions 
for group in sp_file.Groups:
    print('Group Name: {}'.format(group.Name))
    for p_def in group.Definitions:   
        print('Parameter Name: {}'.format(p_def.Name))

    print('-'*10) #➖ Separator 

💡 Notice that in Revit API parameters will be referred to as Definitions.

Parameters are unique for each elements, because each element can hold unique values in its parameters. But Definitions are what defines parameters!

Find Definitions for Missing Parameters

Now we can rework this snippet to look for missing parameters in our SharedParameterFile like this.

We will collect definitions that we need in missing_def variable.

#☑️ Check Missing Parameters
req_params     = ['EF_Text', 'EF_Material', 'B_Param 1', 'A_Param 3', 'Error']
missing_params = check_loaded_params(req_params)


#🔍 Find Matching Definition to Missing Parameter Names
missing_def = []
if sp_file:
    for group in sp_file.Groups:
        # print('\nGroup Name: {}'.format(group.Name))
        for p_def in group.Definitions:
            if p_def.Name in missing_params:
            # if 'B_' in p_def.Name: # Alternative
                missing_def.append(p_def)

Here you can modify the if statement to any other logic to find your parameters. Maybe you want to get all parameters that have 'B_' in their name…

Read specific Group or Definition in SharedParameterFile.

I prefer to always iterate through all groups and definitions so I can find what I need, but sometimes you might want to look inside of a specific group or for a definition in that group.

Then you can use the following Snippet:

#📦 Variables
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document  #type: Document

group_name = 'Trager'
p_name     = 'Trager Hohe'

# 📁 Access shared parameter file
sp_file        = app.OpenSharedParameterFile()
sp_groups      = sp_file.Groups

#🔎 Read Group and Parameter by Name
selected_group = sp_groups.get_item(group_name)

if selected_group:
    p_def = selected_group.get_item(p_name)
Extra: Ask user to select Parameters

We can also prepare a dictionary, and ask user to select parameters from SharedParameterFile to Add.

It's fairly simple to do, here is the snippet.

#📦 Variables
app = __revit__.Application 

#📁 Access SharedParameterFile
sp_file = app.OpenSharedParameterFile()

#🔁 Sort All Parameters from SharedParameterFile
dict_shared_params = {}
for group in sp_file.Groups:
    for p_def in group.Definitions:   
        combined_name = '[{}]_{}'.format(group.Name, p_def.Name)
        dict_shared_params[combined_name] = p_def
        
#📊 Use pyRevit Forms to choose
from pyrevit import forms
selected_p_names = forms.SelectFromList.show(sorted(dict_shared_params.keys()), 
                                      button_name='Select Parameters',  
                                      multiselect=True)

selected_param_defs = [dict_shared_params[p_name] for p_name in selected_p_names]

#👀 Print Selected Parameters
print(selected_p_names)
print(selected_param_defs)

This snippet will return these elements as ExternalDefinition.
It means that it comes from outside of Revit. Nothing to worry about.

How to add SharedParameter to Project?

Now you know how to select parameters from SharedParameterFile.

Let's continue exploring how to bring it to our Revit project.

As we discussed previously, all project and shared parameters are located inside of BindingMap. It can be access by using Document.ParametersBinding property.

This map has a method called Insert to add new SharedParameters and it has 3 variations.

At the moment we can see that the second method is marked obsolete in Revit 2024, so it will be removed next year. But I will use it because it works well in all previous versions including Revit 2024!

So here is the method we will use: BindingMap.Insert

We can see that it needs 3 arguments.
Let's explore them!

1️⃣ Definition key
2️⃣ Binding item
3️⃣ BuiltInParameterGroup parameterGroup

Let's break them down one by one!

1️⃣ Definition key

First of all we need a Definition. Since it's an abstract class we should use ExternalDefinition instead.

It refers to this section of Parameter Creation Menu 👉

We are getting them by reading DefinitionFile (SharedParameterFile) with Application.OpenSharedParameterFile Method.

👇 I will repeat the code Snippet, so there is no confusion where they come from!

#☑️ Check Missing Parameters
req_params     = ['EF_Text', 'EF_Material', 'B_Param 1', 'A_Param 3', 'Error']
missing_params = check_loaded_params(req_params)


#🔍 Find Matching Definition to Missing Parameter Names
missing_def = []
if sp_file:
    for group in sp_file.Groups:
        # print('\nGroup Name: {}'.format(group.Name))
        for p_def in group.Definitions:
            if p_def.Name in missing_params:
            # if 'B_' in p_def.Name: # Alternative
                missing_def.append(p_def)

💡Notice that we have to iterate through Groups to actually read about Definitions.

2️⃣ Binding item

If you look inside of Binding class you will see that it's also an abstract Class. So it means we can't use it and it is being used by other Revit API classes.

We can go and look in Inheritance Hierarchy to see related Classes.

Then you will see ElementBinding class. But if you look inside, it's also an abstract class so we need to look again in Inheritance.

And this time we can see 2 options:

InstanceBinding
TypeBinding

And you probably already guessed where it's going.

These bindings refer to the Instance/Type option we can see in the menu when we create Parameters. 👉

So let's see how to create these options with Revit API.

InstanceBinding and TypeBinding: Constructors

These classes have identical constructors.
InstanceBinding Constructor (CategorySet)
TypeBinding Constructor (CategorySet)

They both need a single argument with a type of CategorySet.

And it refers to the right part of the menu when we create our parameters. 👉

Category Set

So let's take a step back and explore how do we create a CategorySet for Instance or Type Binding.

It has a simple constructor without any arguments. So it means we create it empty and then we can Insert Categories one by one.

💡Pay attention that it is not a BuiltInCategory Enumeration but a Category Class!

👇 So here are 2 options to get Categories and add them to CategorySet.

#1️⃣ Get All/Specific Categories
# Option A:
all_cats = doc.Settings.Categories
cat_view = all_cats.get_Item(BuiltInCategory.OST_Views) 

# Option B:
cat_view = Category.GetCategory(doc, BuiltInCategory.OST_Views) 


#2️⃣ Create CategorySet and Add Categories
cat_set  = app.Create.NewCategorySet()
cat_set.Insert(cat_view)

1️⃣ First of all we need to get Category

Option - A is good because you get all Categories, and you can get individual as well. It's especially good if you want to create an UI to let user select Categories.

Option - B is alternative on how to get specific Category.

2️⃣ Once you have Categories, we can create an empty CategorySet() and then Insert Categories one by one.

NewInstanceBinding / NewTypeBinding

So we've created a cat_set, now we can use it to create InstanceBinding or TypeBinding, depending on what kind of parameter you want.

#🎯 Create Binding
new_instance_binding = InstanceBinding(cat_set)
new_type_binding     = TypeBinding(cat_set)

#P.S. Sometimes you can see this syntax and it's the same...
new_instance_binding = app.Create.NewInstanceBinding(cat_set)
new_type_binding     = app.Create.NewTypeBinding(cat_set)

💡 NB! Choose only 1 line! I show you more examples!

3️⃣ BuiltInParameterGroup parameterGroup

Last one is simple!

It's an enumeration, so we just need to select one of available options.

And they all refer to Parameter Groups that organize parameters in the project browser or Type Edit menu. 👇

#👉 Select BuiltInParameterGroup
parameter_group = BuiltInParameterGroup.PG_ANALYSIS_RESULTS
doc.ParameterBindings.Insert

Now we have all the puzzle pieces, let's combine it together into a single code.

To make it simple I will iterate through all Parameters in SharedParameterFile and only add parameters that have a prefix 'EF_'.

Binding: InstanceBinding
Categories: Views, Sheets
BuiltInParameterGroup: PG_TEXT

You can modify it to anything you want!

#📦 Variables
app = __revit__.Application 
doc = __revit__.ActiveUIDocument.Document  

#👉 Get Categories
cats = doc.Settings.Categories
cat_sheets = cats.get_Item(BuiltInCategory.OST_Sheets)
cat_views  = cats.get_Item(BuiltInCategory.OST_Views)

#📃 Create Category Set 
cat_set = CategorySet()
cat_set.Insert(cat_sheets)
cat_set.Insert(cat_views)

#📁 Open shared parameter file
sp_file   = app.OpenSharedParameterFile()
sp_groups = sp_file.Groups

# 🔓 Start Transaction
t = Transaction(doc, 'Add Shared Parameters')
t.Start()

# Iterate through ParameterGroups and ParameterDefinitions
for d_group in sp_groups:
    for p_def in d_group.Definitions:
      
        #✅ Add Parameters with prefix 'EF_'    
        if 'EF_' in p_def.Name:
            new_instance_binding = InstanceBinding(cat_set)        
            doc.ParameterBindings.Insert( p_def, 
                              new_instance_binding, 
                             BuiltInParameterGroup.PG_TEXT)
            print('Added Parameter: {}'.format(p_def.Name))


t.Commit()#🔒 Commit Transaction

👀 Now so bad after all!

As I said in the beginning, there will be a lot of new classes, but once you have a working code snippet it's not that complicated. Especially since I showed you all the tricks.

What about VariesByGroup?

We are not done yet!

Lastly, I want to show you how to modify VariesByGroup property of newly added parameters.

It's a bit tricky, but I got you!

There is a method called - SetAllowVaryBetweenGroups, and that's exactly what we need. It's part of InternalDefinition Class.

And to get InternalDefinitions, we will just iterate through doc.ParameterBindings

t = Transaction(doc, 'SetVariesByGroup')
t.Start()

binding_map = doc.ParameterBindings
it          = binding_map.ForwardIterator()
it.Reset()

while it.MoveNext():
    definition = it.Key

    if 'EF' in definition.Name:
        try:
            definition.SetAllowVaryBetweenGroups(doc, True)
            print('SetVaryByGroup: {}'.format(definition.Name))
        except:
            pass
            #import traceback
            #print(traceback.format_exc()) 
            #> Param Doesn't Support VaryByGroup

t.Commit()

💡 Always use Try/Except, because not all parameters can be VaryBetweenGroups!

Add Missing Parameters

So we covered everything I wanted about SharedParameters.

Lastly, let's create something useful!

Often times we will start a script, and we would want to make sure that we have all required SharedParameters inside our project. And we should know enough about SharedParameters by now to make these functions!

👀 What should they do?

  • Check Missing Parameters

  • Ask user to Confirm

  • Load Paramters

  • SetVariesBetweenGroups if possible

  • Report if any parameters weren't found

💡 I will also use pyRevit forms to ask user for confirmation.

#⬇ Imports
from Autodesk.Revit.DB import *
from pyrevit import forms

# 📦 Variables
app = __revit__.Application
uidoc = __revit__.ActiveUIDocument
doc   = __revit__.ActiveUIDocument.Document


# FUNCTIONS
def get_loaded_parameters_as_def():
    """Get Loaded Parameters in the project as Definitions"""
    definitions = []

    binding_map = doc.ParameterBindings
    it = binding_map.ForwardIterator()
    for i in it:
        definition = it.Key
        definitions.append(definition)
    return definitions



def check_missing_params(list_param_names):
    """Function to check Loaded Shared Parameters.
    :param list_param_names: List of Parameter names
    :return:                 List of Missing Parameter Names"""
    #1️⃣ Read Loaded Parameter Names
    loaded_p_definitions = get_loaded_parameters_as_def()
    loaded_param_names   = [d.Name for d in loaded_p_definitions]

    # Check if Parameters Missing
    missing_params = [p_name for p_name in list_param_names if p_name not in loaded_param_names]
    # 👇 It's the same as
    # missing_params = []
    # for p_name in list_param_names:
    #     if p_name not in loaded_param_names:
    #         missing_params.append(p_name)
    return missing_params


def load_params(p_names_to_load,
                bic_cats,
                bind_mode = 'instance',
                p_group   = BuiltInParameterGroup.PG_TITLE):
    #type: (list, list, str, BuiltInParameterGroup) -> None
    """Function to check Loaded Shared Parameters.
    :param p_names_to_load: List of Parameter names
    :param bic_cats:        List of BuiltInCategories for Parametetrs
    :param bind_mode:       Binding Mode: 'instance' / 'type'
    :param p_group:         BuiltInParameterGroup"""

    # 📁 Ensure SharedParameterFile is available
    sp_file = app.OpenSharedParameterFile()
    if not sp_file:
        forms.alert('Could not find SharedParameter File. '
                    '\nPlease Set the File in Revit and Try Again', title=__title__, exitscript=True)

    #🙋‍ Ask for User Confirmation
    if missing_params:
        confirmed = forms.alert("There are {n_missing} missing parameters for the script."
                                "\n{missing_params}"
                                "\n\nWould you like to try loading them from the following SharedParameterFile:"
                                "\n{p_filepath}".format(n_missing      = len(missing_params),
                                                        missing_params = '\n'.join(missing_params),
                                                        p_filepath     = sp_file.Filename),
                                yes=True, no=True)

        if confirmed:
            # Prepare Categories
            all_cats = doc.Settings.Categories
            cats     = [all_cats.get_Item(bic_cat) for bic_cat in bic_cats]

            # Create Category Set
            cat_set = CategorySet()
            for cat in cats:
                cat_set.Insert(cat)

            # Create Binding
            binding = TypeBinding(cat_set) if bind_mode == 'type' \
                      else InstanceBinding(cat_set)

            # Add Parameters (if possible)
            for d_group in sp_file.Groups:
                for p_def in d_group.Definitions:
                    if p_def.Name in p_names_to_load:
                        doc.ParameterBindings.Insert(p_def, binding, p_group)
                        p_names_to_load.remove(p_def.Name)

            # SetAllowVaryBetweenGroups (If Possible
            loaded_p_definitions = get_loaded_parameters_as_def()
            for definition in loaded_p_definitions:
                if definition.Name in p_names_to_load:
                    try:
                        definition.SetAllowVaryBetweenGroups(doc, True)
                    except:
                        pass

            #👀 Reported Not Loaded Parameters
            if p_names_to_load:
                msg = "Couldn't Find following Parameters: \n{}".format('\n'.join(p_names_to_load))
                forms.alert(msg, title=__title__)



# MAIN
required_params = ['B_Bool', 'B_Material', 'C_Unknown']
missing_params  = check_missing_params(required_params)

if missing_params:
    # 🔓 Transaction Start
    t = Transaction(doc, 'Add SharedParameters')
    t.Start()

    bic_cats = [BuiltInCategory.OST_Walls,
            BuiltInCategory.OST_Floors]

    load_params(p_names_to_load = missing_params,
                bic_cats        = bic_cats,
                bind_mode       = 'instance',
                p_group         = BuiltInParameterGroup.PG_TITLE)

    t.Commit()

Code from Video

You might have noticed that code in the video and this blog post is slightly different.

So here is the exact code from the video in case you need it!

# -*- coding: utf-8 -*-
__title__ = "04.04 - Shared Parameters"
__doc__ = """Date    = 29.10.2023
_____________________________________________________________________
Description:
Learn how to work with Shared Parameters.
How to check if they are loaded in the project?
How to load more Shared Parameters?
How to modify existing Shared Parameter?
_____________________________________________________________________
Author: Erik Frits"""

# ╦╔╦╗╔═╗╔═╗╦═╗╔╦╗╔═╗
# ║║║║╠═╝║ ║╠╦╝ ║ ╚═╗
# ╩╩ ╩╩  ╚═╝╩╚═ ╩ ╚═╝ IMPORTS
#==================================================
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI.Selection import ObjectType, Selection

# ╦  ╦╔═╗╦═╗╦╔═╗╔╗ ╦  ╔═╗╔═╗
# ╚╗╔╝╠═╣╠╦╝║╠═╣╠╩╗║  ║╣ ╚═╗
#  ╚╝ ╩ ╩╩╚═╩╩ ╩╚═╝╩═╝╚═╝╚═╝ VARIABLES
#==================================================
uidoc     = __revit__.ActiveUIDocument
doc       = __revit__.ActiveUIDocument.Document
app       = __revit__.Application
selection = uidoc.Selection # type: Selection

# ╔═╗╦ ╦╔╗╔╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
# ╠╣ ║ ║║║║║   ║ ║║ ║║║║╚═╗
# ╚  ╚═╝╝╚╝╚═╝ ╩ ╩╚═╝╝╚╝╚═╝ FUNCTIONS
#==================================================
def check_loaded_params(list_p_names):
    """Check if any parameters from provided list are missing in the project
    :param list_p_names: List of Parameter Names
    :return:             List of Missing Parameter Names"""
    # 📃 Get Parameter Bindings Map.
    bm = doc.ParameterBindings

    # 💡 Create a forward iterator
    itor = bm.ForwardIterator()
    itor.Reset()

    #ITerate over the map
    loaded_parameters = []
    while itor.MoveNext():
        try:
            d = itor.Key
            loaded_parameters.append(d.Name)
        except:
            pass

    # ✅ Check if Parameters are loaded:
    missing_params = [p_name for p_name in list_p_names if p_name not in loaded_parameters]
    # missing_params = []
    # for p_name in req_params:
    #     if p_name not in loaded_parameters:
    #         missing_params.append(p_name)

    return missing_params


# if missing_params:
#     print('Missing Parameters:')
#     for p_name in missing_params:
#         print(p_name)

# #📁 Access Shared Paramtere File
# sp_file = app.OpenSharedParameterFile()
# # app.SharedParametersFilename = r'C:\Users\ef\Desktop\LearnRevitAPI - SharedParameters\04.04 - SharedParameters.txt'
#
# #🔍 Find Matching Definition to Missing Parameter Names
# missing_def = []
# if sp_file:
#     for group in sp_file.Groups:
#         # print('\nGroup Name: {}'.format(group.Name))
#         for p_def in group.Definitions:
#             # if p_def.Name in missing_params:
#             if 'B_' in p_def.Name:
#                 missing_def.append(p_def)
#
#
# # Select Categories
# all_cats   = doc.Settings.Categories
# cat_views  = all_cats.get_Item(BuiltInCategory.OST_Views)
# cat_sheets = all_cats.get_Item(BuiltInCategory.OST_Sheets)
#
# # Create Category Set
# cat_set = CategorySet()
# cat_set.Insert(cat_views)
# cat_set.Insert(cat_sheets)
#
# #🎯 Create Binding
# binding = InstanceBinding(cat_set)
# # binding = TypeBinding(cat_set)
#
# #📦 Select ParameterGroup
# param_group = BuiltInParameterGroup.PG_TEXT
#
# #✅ Add parameters
# t = Transaction(doc, 'AddSharedParameters')
# t.Start()
#
# for p_def in missing_def:
#     if not doc.ParameterBindings.Contains(p_def):
#         doc.ParameterBindings.Insert(p_def, binding, param_group)
#         print('Adding SharedParameter: {}'.format(p_def.Name))
#
# t.Commit()





# t = Transaction(doc, 'SetVariesByGroup')
# t.Start()
#
#
# binding_map = doc.ParameterBindings
# it = binding_map.ForwardIterator()
# it.Reset()
#
# while it.MoveNext():
#     p_def = it.Key
#
#     if 'B_' in p_def.Name:
#         try:
#             p_def.SetAllowVaryBetweenGroups(doc, True)
#             print('SetVaryByGroup for: {}'.format(p_def.Name))
#         except:
#             pass
#
# t.Commit()
from pyrevit import forms

def load_params(p_names_to_load,
                bic_cats,
                bind_mode='instance',
                p_group=BuiltInParameterGroup.PG_TEXT,
                set_vary_by_group=True):
    #type: (list, list, str, BuiltInParameterGroup, bool) -> None
    """Function to check Loaded Shared Parameters.
    :param p_names_to_load: List of Parameter names
    :param bic_cats:        List of BuiltInCategories for Parametetrs
    :param bind_mode:       Binding Mode: 'instance' / 'type'
    :param p_group:         BuiltInParameterGroup
    :param set_vary_by_group: Bool to set parameters as VaryByGroup if possible."""

    # 📁 Ensure SharedParameterFile is available
    sp_file = app.OpenSharedParameterFile()
    if not sp_file:
        forms.alert("Couldn not find SharedParameterFile."
                    "\nPlease Set The file in Revit and Try Again", exitscript=True)

    #👉 Get Parameter Definitions
    p_def_to_load = []
    found_params  = []
    for group in sp_file.Groups:
        for p_def in group.Definitions:
            if p_def.Name in p_names_to_load:
                p_def_to_load.append(p_def)
                found_params.append(p_def.Name)

    not_found_params = [p_name for p_name in p_names_to_load if not p_name in found_params]

    if not_found_params:
        print("Couldn't find following Parameters:\n{}".format('\n'.join(not_found_params)))


    #📦 Prepare Categories
    all_cats = doc.Settings.Categories
    cats = [all_cats.get_Item(bic_cat) for bic_cat in bic_cats]

    #📦 Create CategorySet
    cat_set = CategorySet()
    for cat in cats:
        cat_set.Insert(cat)

    #🎭 Binding
    binding = InstanceBinding(cat_set) if bind_mode=='instance' else TypeBinding(cat_set)

    #✅ Add Parameters
    for p_def in p_def_to_load:
        doc.ParameterBindings.Insert(p_def, binding, p_group)

    #🧬 SetVaryByGroup
    if set_vary_by_group:
        binding_map = doc.ParameterBindings
        it = binding_map.ForwardIterator()
        it.Reset()

        while it.MoveNext():
            p_def = it.Key

            if p_def in p_def_to_load:
                try:    p_def.SetAllowVaryBetweenGroups(doc, True)
                except: pass


# ╔╦╗╔═╗╦╔╗╔
# ║║║╠═╣║║║║
# ╩ ╩╩ ╩╩╝╚╝
#==================================================

req_params     = ['EF_Text', 'EF_Material', 'B_Param 1', 'A_Param 3']
missing_params = check_loaded_params(req_params)

t = Transaction(doc, 'Add SharedParameters')
t.Start()

bic_cats = [BuiltInCategory.OST_Walls, BuiltInCategory.OST_Floors]

load_params(missing_params,
            bic_cats,
            bind_mode='instance',
            p_group=BuiltInParameterGroup.PG_DATA,
            set_vary_by_group=True)
t.Commit()

Extra: Get SharedParameter GUID

If you want to get GUID of your SharedParameters you can use the following Snippet:

element = ... # Get Your Element
look    = element.LookupParameter('HauptmaterialitaetElement')
shared  = look.IsShared
guid    = look.GuidValue

HomeWork

You will have a lot of tools where you need to check if you have required SharedParameters in the project. And now you know how to add them to the project if you need to!

I know I mentioned during the video that here is going to be a homework here.

But I feel like there was a lot of information in this lesson, so It's okay if you skip this homework. But if you really want to practice let me know in the community and I will add it here!

✅ Give it a try!

⌨️ Happy Coding!

Questions:

Can we create Project Parameters?

Can we create Project Parameters?

Discuss the lesson:

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API