Resources
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.
👆 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.
💡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:
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 😉!
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.
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.
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:
💡 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.
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:
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.
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!
💡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:
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️⃣ 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.
💡 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. 👇
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!
👀 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
💡 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.
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!
Extra: Get SharedParameter GUID
If you want to get GUID of your SharedParameters you can use the following Snippet:
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!