Vintage computer from the seventies representing retro technology and innovation

Automating Metadata Cleanup in Revit – A Custom Live Updater

Digital By Feb 13, 2025 No Comments

When working in Revit, copied elements will inherit instance parameter values that should be unique—room numbers, tracking codes, asset IDs, or any other metadata that doesn’t logically carry over.

Problem: Copying elements can introduce data inconsistencies if certain instance parameters retain values they shouldn’t.

Solution: A Revit API Updater that automatically clears specific parameters whenever elements are copied.

This tutorial will walk you through:
How the Updater Works
Setting Up the Revit Ribbon UI (Enable/Disable Feature)
Registering the Updater
Code Implementation
How to Extend the Tool for Your Own Needs

How the Revit Updater Works

The Updater leverages Revit’s Dynamic Model Update (DMU) API, which allows you to react to changes in the model:

  • Detects when elements are copied or added
  • Checks if the copied element contains the specified parameter
  • Automatically clears the parameter value

Why Use This?

  • Prevents copied elements from inheriting unique metadata
  • Reduces errors in schedules and exported data
  • Ensures compliance with data integrity requirements

Step 1: Setting Up the Revit Ribbon UI

To provide better user control, this tool includes a simple Revit Ribbon UI that allows users to toggle the updater on or off.

How the UI Works

Activate button – Enables the updater
Deactivate button – Disables the updater
Placed inside a custom Revit tab: “Updater Tool”

  • Activate button – Enables the updater
  • Deactivate button – Disables the updater
  • Placed inside a custom Revit tab: “Updater Tool”

Code: Creating the Revit UI (ExternalProgram.cs)

Click to expand and see the code
using System;
using System.IO;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Windows.Media.Imaging;

namespace UpdaterTool
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class ExternalProgram : IExternalApplication
    {
        public Result OnStartup(UIControlledApplication application)
        {
            application.CreateRibbonTab("Updater Tool");

            string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            string dllPath = Path.Combine(appData, @"Autodesk\REVIT\Addins\2023\UpdaterTool.dll");
            string appFolderPath = Path.Combine(appData, @"Autodesk\REVIT\Addins\2023");

            RibbonPanel ribbonPanel = application.CreateRibbonPanel("Updater Tool", "Updater");

            RadioButtonGroupData radioButtonGroupData1 = new RadioButtonGroupData("radioButtonGroup1");
            RadioButtonGroup radioButtonGroup1 = ribbonPanel.AddItem(radioButtonGroupData1) as RadioButtonGroup;

            ToggleButtonData toggleButton1 = new ToggleButtonData("toggleButton1", "Deactivate", dllPath, "UpdaterTool.Deactivated");
            toggleButton1.LargeImage = new BitmapImage(new Uri(Path.Combine(appFolderPath, "Stop.png")));

            ToggleButtonData toggleButton2 = new ToggleButtonData("toggleButton2", "Activate", dllPath, "UpdaterTool.Activated");
            toggleButton2.LargeImage = new BitmapImage(new Uri(Path.Combine(appFolderPath, "Check.png")));

            radioButtonGroup1.AddItem(toggleButton1);
            radioButtonGroup1.AddItem(toggleButton2);

            return Result.Succeeded;
        }

        public Result OnShutdown(UIControlledApplication application)
        {
            return Result.Succeeded;
        }
    }
}
Code language: C# (cs)

Step 2: Registering the Updater

To enable the updater, we register it inside a separate command class (InternalProgram.cs).

Code: Activating & Deactivating the Updater

Click to expand and see the code
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;

namespace UpdaterTool
{
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    class Activated : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            AddInId addInId = uiapp.ActiveAddInId;

            UpdaterClass updater = new UpdaterClass(addInId);
            UpdaterId updaterId = updater.GetUpdaterId();

            if (!UpdaterRegistry.IsUpdaterRegistered(updaterId))
            {
                UpdaterRegistry.RegisterUpdater(updater);
                UpdaterRegistry.EnableUpdater(updaterId);
                TaskDialog.Show("Updater", "Updater Activated!");
            }
            else
            {
                TaskDialog.Show("Updater", "Updater is already active.");
            }

            return Result.Succeeded;
        }
    }

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    class Deactivated : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            AddInId addInId = uiapp.ActiveAddInId;

            UpdaterClass updater = new UpdaterClass(addInId);
            UpdaterId updaterId = updater.GetUpdaterId();

            if (UpdaterRegistry.IsUpdaterRegistered(updaterId))
            {
                UpdaterRegistry.RemoveAllTriggers(updaterId);
                UpdaterRegistry.DisableUpdater(updaterId);
                UpdaterRegistry.UnregisterUpdater(updaterId);
                TaskDialog.Show("Updater", "Updater Deactivated!");
            }
            else
            {
                TaskDialog.Show("Updater", "Updater was not active.");
            }

            return Result.Succeeded;
        }
    }
}
Code language: C# (cs)

Step 3: The Updater Logic

The core functionality of this tool is inside UpdaterClass.cs.

  • Listens for new elements being added (including copied elements)
  • If the new element has the target parameter, it clears the value

Listens for new elements being added (including copied elements)
If the new element has the target parameter, it clears the value

Code: UpdaterClass.cs

Click to expand and see the code
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace UpdaterTool
{
    class UpdaterClass : IUpdater
    {
        private static AddInId addInId;
        private static UpdaterId updaterId;

        public UpdaterClass(AddInId addInId)
        {
            UpdaterClass.addInId = addInId;
            updaterId = new UpdaterId(UpdaterClass.addInId, new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
        }

        public void Execute(UpdaterData data)
        {
            Document doc = data.GetDocument();

            using (SubTransaction str = new SubTransaction(doc))
            {
                try
                {
                    str.Start();

                    var addedElementIds = data.GetAddedElementIds();
                    foreach (ElementId id in addedElementIds)
                    {
                        Element element = doc.GetElement(id);
                        if (element == null) continue;

                        Parameter param = element.LookupParameter("YourParameterNameHere");
                        if (param != null && !param.IsReadOnly)
                        {
                            param.Set("");  // Clears the copied parameter
                        }
                    }

                    str.Commit();
                }
                catch
                {
                    str.RollBack();
                }
            }
        }

        public UpdaterId GetUpdaterId() => updaterId;
        public ChangePriority GetChangePriority() => ChangePriority.FreeStandingComponents;
        public string GetUpdaterName() => "Custom Parameter Updater";
        public string GetAdditionalInformation() => "Clears a specific parameter when elements are copied.";
    }
}
Code language: C# (cs)

Summary

✅ Created a Revit Updater that listens for copied elements
✅ Clears specified instance parameters to prevent unintended metadata retention
✅ Included a Revit UI toggle to enable or disable the updater

How Can You Extend This?

  • Modify the parameter name to suit your project needs
  • Expand functionality to reset multiple parameters
  • Add logging to track when elements are modified

No Comments

Leave a comment

Your email address will not be published. Required fields are marked *