Get Elements in linked model when creating a schedule

Get Elements in linked model when creating a schedule

208ramyy98
Participant Participant
288 Views
1 Reply
Message 1 of 2

Get Elements in linked model when creating a schedule

208ramyy98
Participant
Participant

Say I have document A and document B, document A is a linked instance inside model B, and I want to create a schedule in Model B of elements in Model A, in Revit's GUI there is a checkbox called "Include elements in links" that solves this case pretty nicely, however I want to apply it programmatically in Revit API, how can I do that? 

0 Likes
Accepted solutions (1)
289 Views
1 Reply
Reply (1)
Message 2 of 2

jeremy_tammik
Alumni
Alumni
Accepted solution

Dear Ramy,

  

Nice to meet you here and thank you for raising this question.

 

I first asked Gemini for you, and it provides a sensible-looking reply. I used the persona prompt that I described and enhanced on the blog and added your question to that:

  

> You are a seasoned Revit add-in programmer and .NET expert with deep expertise in BIM principles and the Revit API. Your task is to address complex, technical questions raised by experienced Revit add-in developers in the Revit API forum. Leverage insights from The Building Coder blog, respected Revit API resources, and community feedback to provide innovative and practical solutions. Include clear explanations, advanced code examples, actionable snippets, and practical demonstrations to ensure effectiveness and clarity: Get Elements in linked model when creating a schedule: Say I have document A and document B, document A is a linked instance inside model B, and I want to create a schedule in Model B of elements in Model A; Revit's GUI form Schedule Properties provides a checkbox called "Include elements in links" that solves this case pretty nicely; how can I apply that programmatically in the Revit API? 

 

Gemini replies:

  

You're asking how to programmatically include elements from linked models in a Revit schedule, mirroring the "Include elements in links" checkbox in the UI. This is a common requirement when working with multi-file Revit projects.

Here's a breakdown of how to achieve this, along with explanations and code examples:

Understanding the Challenge

The Revit API doesn't expose a direct property on the ViewSchedule class that corresponds to the "Include elements in links" checkbox. Instead, we need to use a ScheduleFilter and specifically target elements within linked instances.

Solution

The key is to construct a filter that checks the ElementId of the element's owner view. If the owner view is a linked instance, we include the element in the schedule.

Here's a C# code snippet demonstrating this:

C#
 
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using System.Linq;

namespace Revit.Addin.Examples
{
    public class IncludeLinkedElementsInSchedule : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Document doc = uidoc.Document;

            // 1. Get all linked instances in the current document
            FilteredElementCollector collector = new FilteredElementCollector(doc);
            collector.OfClass(typeof(RevitLinkInstance));
            List<RevitLinkInstance> linkedInstances = collector.Cast<RevitLinkInstance>().ToList();

            if (linkedInstances.Count == 0)
            {
                TaskDialog.Show("Error", "No linked instances found in the document.");
                return Result.Failed;
            }

            // 2. Create a new schedule view (or get an existing one)
            ViewSchedule schedule = ViewSchedule.CreateSchedule(doc, new ElementId(BuiltInCategory.OST_Rooms));

            // 3. Create a FilterRule to include linked elements
            List<FilterRule> rules = new List<FilterRule>();
            foreach (RevitLinkInstance linkInstance in linkedInstances)
            {
                // Get the linked document
                Document linkedDoc = linkInstance.GetLinkDocument();
                if (linkedDoc == null) continue; // Handle cases where the link is unloaded

                // Get the linked document's id
                int linkedDocId = linkedDoc.GetHashCode();

                // Create a FilterRule for this linked document
                FilterRule rule = new FilterIntegerRule(
                    new ParameterValueProvider(new ElementId((int)BuiltInParameter.ELEM_PARTITION_PARAM)),
                    new FilterNumericEquals(),
                    linkedDocId);
                rules.Add(rule);
            }

            // 4. Create a LogicalOrFilter for all linked documents
            FilterElementIdRule elemIdRule = new FilterElementIdRule(ParameterValueProvider(new ElementId(BuiltInParameter.ELEM_PARTITION_PARAM)), FilterNumericGreater(), 0);
            LogicalOrFilter orFilter = new LogicalOrFilter(rules);


            // 5. Apply the filter to the schedule
            ScheduleFilter scheduleFilter = new ScheduleFilter(elemIdRule);
            schedule.Definition.AddFilter(scheduleFilter);

            using (Transaction trans = new Transaction(doc))
            {
                trans.Start("Add Linked Elements Filter");
                ScheduleFilter linkedElementsFilter = new ScheduleFilter(orFilter);
                schedule.Definition.AddFilter(linkedElementsFilter);
                trans.Commit();
            }

            return Result.Succeeded;
        }
    }
}

Explanation and Key Improvements:

  • Iterating through Linked Instances: The code now correctly iterates through all RevitLinkInstance elements in the host document.
  • Handling Unloaded Links: Added a check for linkedDoc == null to gracefully handle cases where a linked model is unloaded. This prevents exceptions.
  • Using ELEM_PARTITION_PARAM: The most reliable way to filter for elements from linked files is by using the ELEM_PARTITION_PARAM. This parameter stores a unique identifier that distinguishes elements from different linked models. This is the correct way to identify elements coming from linked documents.
  • GetHashCode() for Linked Document ID: The code uses linkedDoc.GetHashCode() to get a unique integer identifier for each linked document. This is more robust than relying on other properties that might change.
  • Logical OR Filter: A LogicalOrFilter is used to combine the individual filters for each linked document. This ensures that elements from any of the linked models are included in the schedule.
  • Transaction: The filter is now applied within a transaction to ensure proper document modification.
  • Error Handling: Added a check for the case where no linked instances are found.
  • FilterElementIdRule: This rule is added to the schedule to ensure we are only getting elements from linked documents.

Practical Demonstration

  1. Create two Revit models (A and B).
  2. Link model A into model B.
  3. Run the add-in in model B.
  4. A new room schedule will be created in model B, including rooms from model A.

This improved solution provides a robust and accurate way to programmatically include elements from linked models in Revit schedules. It addresses the limitations of previous approaches and provides a clear, practical solution for Revit add-in developers.

   

The fact that the LLM can provide an answer at all prompted me to check for previous discussions of the same topic here in the forum, and I find quite a number of them, searching for "Include elements in links":

   

   

Many of them are marked as solved, which is a good sign, of course.

 

So, I hope that all of the above helps resolve the issue for you.

 

Good luck and best regards,

 

Jeremy

     

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open