Help with adding shared parameters to project!

I’m trying to replicate data shape’s node to add shared parameters from a txt file, I have created a code with the help of GPT but I’m stuck on this one error :

Code :

import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference('RevitAPIUI')
from Autodesk.Revit.UI import *

# Get the current Revit document and application
doc = DocumentManager.Instance.CurrentDBDocument
app = doc.Application

# Inputs
parameter_names = IN[0]  # List of parameter names (strings)
parameter_category = IN[1]  # Revit category object (e.g., "Generic Models")
parameter_group = IN[2]  # ParameterGroup as ForgeTypeId or other valid type
is_instance = IN[3]  # Boolean value for instance or type parameter

# Validate parameter_category
if not isinstance(parameter_category, Category):
    OUT = "Invalid parameter category object."
    raise ValueError("Input 2 should be a valid Category object.")

# Convert parameter_group to ForgeTypeId if it's not already
if not isinstance(parameter_group, ForgeTypeId):
    try:
        # Assuming parameter_group is an integer or enum value
        parameter_group = ForgeTypeId(parameter_group)
    except Exception as e:
        OUT = f"Error converting parameter group: {e}"
        raise ValueError("Input 3 should be a valid ForgeTypeId or convertible to ForgeTypeId.")

# Create CategorySet for parameter binding
catset = app.Create.NewCategorySet()
catset.Insert(parameter_category)

# Start a transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# Determine parameter binding type
if is_instance:
    bind = app.Create.NewInstanceBinding(catset)
else:
    bind = app.Create.NewTypeBinding(catset)

# Add parameters to the project
bindmap = doc.ParameterBindings
added_params = 0
failed_params = []
for param_name in parameter_names:
    try:
        # Create a new ExternalDefinitionCreationOptions object
        param_def_options = ExternalDefinitionCreationOptions(param_name, parameter_group)
        
        # Check if parameter already exists
        existing_param = None
        for param in bindmap:
            if param.Name == param_name:
                existing_param = param
                break

        if existing_param:
            OUT = f"Parameter '{param_name}' already exists."
            continue

        # Add the parameter to the document
        if not bindmap.Insert(param_def_options, bind, parameter_group):
            failed_params.append(param_name)
        else:
            added_params += 1
    except Exception as e:
        failed_params.append(f"{param_name}: {e}")

# Commit the transaction
TransactionManager.Instance.TransactionTaskDone()

# Output the results
if failed_params:
    OUT = f"{added_params} shared parameters added. Failed to add: {', '.join(failed_params)}"
else:
    OUT = f'{added_params} shared parameters added to the project.'
`

Why use Python and not a custom node?

I converted my .txt to a .xlsx.

This specific data shape node takes only 4 above inputs and I wanted to replicate the same, this exact script has worked without any issue but now I’m getting this issue. I would like to learn what’s the issue here is. :sweat_smile:

Why not update your Datashapes to the latest build and make sure you have the correct Python dependencies for your Dynamo environment instead of rebuilding someone else’s code? Note that I believe that Datashapes is distributed using an MIT license so you need to maintain that if you’re passing along the code in the graph itself which is added effort you likely want to avoid.


I have the latest version installed and also have DynamoIronPython installed. but this node does not work.


this node returns null, causing the final node to also fail. I have tried getting a ParameterGroup List by my self which outputs “Autodesk.Revit.DB.ForgeTypeId” values, and I believe final node requires some different type of input?? (unless the nodes are absolutely alright and I’m the issue here lol)

Which Revit version are you in?

I get a different warning when using the Python

Revit 2025.1

Parameter groups got phased out for grouptypeids by revit 2025. Looks like that node might be missing that change.

Check out the family/collector nodes in Crumple which show how to work with the new grouptypeids and their names/enum (but in CPython3).

1 Like

Thank you, I have been able to make it almost work, the issue is it only adds first parameter from the list to the project, throws ‘InstanceBinding’ object has no atrribute ‘name’ error for remainings in the list.

Translated by moderator. See below the line for original post.


Why not update Datashapes to the latest version?


Original post below.


Por que não atualizar o Datashapes para a versão mais recente?

I was finally able to do it, Thanks everyone for your insights and help.

import clr
import traceback

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import *
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Get the current Revit document and application
doc = DocumentManager.Instance.CurrentDBDocument
app = doc.Application

# Inputs
parameter_names = IN[0]  # List of parameter names (strings)
parameter_category_input = IN[1]  # Revit category objects or Dynamo wrappers
parameter_group_name = IN[2]  # String or list of strings (e.g., "General", "Dimensions")
is_instance = IN[3]  # Boolean for instance or type parameter

# If parameter_group_name is passed as a list, use the first element
if isinstance(parameter_group_name, list):
    parameter_group_name = parameter_group_name[0]

# Fetch all group IDs and names
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import ParameterUtils, LabelUtils

# Get group type IDs and names
group_ids = ParameterUtils.GetAllBuiltInGroups()
group_names = [LabelUtils.GetLabelForGroup(g) for g in group_ids]

# Function to convert parameter group name to BuiltInParameterGroup
def get_parameter_group_id(group_name):
    if group_name in group_names:
        group_index = group_names.index(group_name)
        return group_ids[group_index]  # Return corresponding group type ID
    return None

# Validate and convert the parameter group name
parameter_group_id = get_parameter_group_id(parameter_group_name)
if not parameter_group_id:
    OUT = f"Invalid parameter group name: {parameter_group_name}. Available groups: {', '.join(group_names)}"
    raise ValueError(OUT)

# Process categories
try:
    categories = [UnwrapElement(cat) for cat in parameter_category_input]
except:
    raise ValueError("Invalid categories provided.")

# Create CategorySet for binding
catset = app.Create.NewCategorySet()
for cat in categories:
    catset.Insert(cat)

# Access the shared parameter file
shared_param_file = app.OpenSharedParameterFile()
if shared_param_file is None:
    raise ValueError("No shared parameter file is loaded. Please load a shared parameter file.")

# Start the transaction
TransactionManager.Instance.EnsureInTransaction(doc)

# Add parameters
added_params = 0
failed_params = []

for param_name in parameter_names:
    try:
        # Refresh the bindmap in each loop iteration
        bindmap = doc.ParameterBindings

        # Check if the parameter already exists in the document
        existing_param = bindmap.ReverseIterator()
        exists = False
        while existing_param.MoveNext():
            if existing_param.Key.Name == param_name:
                exists = True
                break

        if exists:
            print(f"Parameter '{param_name}' already exists, skipping.")
            continue

        # Look for the parameter in the shared parameter file
        param_def = None
        for group in shared_param_file.Groups:
            param_def = group.Definitions.get_Item(param_name)
            if param_def:
                break

        if param_def is None:
            failed_params.append(f"{param_name}: Not found in shared parameter file.")
            continue

        # Re-create the binding for each parameter
        bind = app.Create.NewInstanceBinding(catset) if is_instance else app.Create.NewTypeBinding(catset)

        # Attempt to bind the parameter
        if bindmap.Insert(param_def, bind, parameter_group_id):
            added_params += 1
        else:
            failed_params.append(param_name)
    except Exception as e:
        failed_params.append(f"{param_name}: {str(e)}")

# Commit the transaction
TransactionManager.Instance.TransactionTaskDone()

# Output results
if failed_params:
    OUT = f"{added_params} shared parameters added. Failed to add: {', '.join(failed_params)}"
else:
    OUT = f"{added_params} shared parameters added to the project."
3 Likes