How to update the parameters that stores value from key schedule?

How to update the parameters that stores value from key schedule?

V__K
Contributor Contributor
743 Views
7 Replies
Message 1 of 8

How to update the parameters that stores value from key schedule?

V__K
Contributor
Contributor

In the rvt file I've created one key schedule for generic models category i.e. "_Key Schedule_Lining Selection" where the parameter name for the schedule is "Lining Schedule".

V__K_1-1736264997720.png

 


Now, I can manually update the parameter for any generic model from the dropdown that has the values listed from the key names of the key schedule, as shown below.

V__K_2-1736265155651.png

 

I'm having issues to update this dropdown value, programmatically as the storage type for this parameter "Lining Selection" is ElementID. Now I'm not sure how to get the ElementID for the values I listed in the key schedule because that's what I need eventually to set value for this parameter.

V__K_4-1736265418902.png

 

Can anyone help? I'm not getting how to retrieve the required ElementID values here as it's not directly any element which I can access. Any help is appreciated.




0 Likes
744 Views
7 Replies
Replies (7)
Message 2 of 8

jeremy_tammik
Alumni
Alumni

I may be missing the point, but to me it seems that your answer contains all the information required. Using RevitLookup, you can determine the element id values of the available key schedule options. On the Parameter object, you can set those element id values using the Parameter.Set method overload taking an ElementId argument:

  

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 8

V__K
Contributor
Contributor

Yes, That's correct @jeremy_tammik. Thanks for the response.

I'm trying to understand how things are implemented at API end. I can see the ElementID if I use Revit Lookup. But If I want to know the ElementID for the key schedule entries using the API only, how can I do that?

I mean there should be some work around to get the ElementID corresponding to the text values using the RevitAPI only. I want to understand that workflow.

0 Likes
Message 4 of 8

jeremy_tammik
Alumni
Alumni

Yes, there is a workflow. RevitLookup uses that workflow. I don't know the details, but basically the user interface steps to see the value in RevitLookup match exactly the API calls required and executed to display it. If you want to play with and explore the API interactively, maybe something like the RevitPythonShell or pyRevit command line would help. Then you can navigate and explore just like in RevitLookup, but by executing each API call yourself instead of just clicking buttons and other widgets in the RevitLookup UI.

   

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 5 of 8

GaryOrrMBI
Collaborator
Collaborator

What you have going on in that Key Schedule shouldn't even be possible.

A Key Schedule has a key that a user would select (from a list of all of the entries that you add to the Key Schedule), then it has other fields that will be filled in according to the values that you enter into the schedule on that Key Row. You then create rows that consist of the keys that the user will select from and values for each of the fields that you have added to the schedule.

You seem to have somehow created a Key Schedule in which you select a key and it tries to set the value of itself based upon your selection...

 

The Key itself should always be a text field. You can then have another field(s) that references another parameter that you want to set based upon a user selecting that key.

 

Take a look at the attached file for a reference. When you select the "Lining Selection" Key, it will then set the NOTES?DETAILS parameter to a predefined field and it will set a new "Test Window Type" field that I have added. Since that new field is a Type selector it will be an Element ID field. It will display to the user as the Family Type name that is tied to that Element ID.

 

To add rows programmatically you should now be able to dig into the available types of that Category and assign the Element ID of the desired type, which will then be displayed as the type name to the user.

 

See what happens and how it works with my modified sample. Hopefully it will get you headed in the right direction.

-G

Gary J. Orr
GaryOrrMBI (MBI Companies 2014-Current)
aka (past user names):
Gary_J_Orr (GOMO Stuff 2008-2014);
OrrG (Forum Studio 2005-2008);
Gary J. Orr (LHB Inc 2002-2005);
Orr, Gary J. (Gossen Livingston 1997-2002)
0 Likes
Message 6 of 8

Jannis_Lescher
Participant
Participant

@jeremy_tammik 


I don´t see the "full solution" here. Setting the ElementId would be easy, but I cannot figure out a way to get the ElementIds of row in a schedule.  Do you know any way to get that one, or does anyone else?  Seems to be an easy task, but TableData does not store the ElementIds for the rows, or at least I´m not able to find them.

TableData tableData = schluesselListenSchedule.GetTableData();

TableSectionData sectionData = tableData.GetSectionData(SectionType.Body);

int rows = sectionData.NumberOfRows;
int cols = sectionData.NumberOfColumns;

for (int row = 0; row < rows; row++)
{
    string rowData = "";
    for (int col = 0; col < cols; col++)
    {
        string cellText = sectionData.GetCellText(row, col);
        var elemId = sectionData.GetCellParamId(row, col);  
        rowData += cellText + " | ";
    }
    TaskDialog.Show("Row Data", rowData);
}

 

0 Likes
Message 7 of 8

jeremy_tammik
Alumni
Alumni

I asked Gemini for you, and the answer it provides looks pretty sensible to me. I retrieves the value from the key schedule key column and then uses a filtered element collector to retrieve the corresponding element with a parameter containing that value. Does that sound like a viable approach? Here is my question and its answer:

  

  

Alright, let's tackle the intricate problem of updating parameters within a Key Schedule and, crucially, retrieving the ElementIds associated with each row. This is a common challenge for Revit API developers seeking to automate and manage data within key schedules.

Understanding the Challenge

Key schedules in Revit are fundamentally different from regular schedules. They don't directly list model elements. Instead, they define parameter values that can be assigned to elements through a "key" parameter. This creates a powerful system for managing consistent property sets.

The core issue is that the Revit API doesn't expose a direct "row" object in a key schedule that provides ElementIds. Instead, we must work with the KeySchedule element and its associated TableData and TableCell objects, along with the element parameter that references the key.

Solution Breakdown

  1. Retrieving the Key Schedule:

    • First, we need to obtain the KeySchedule element from the Revit document. This can be done by filtering for schedules or by iterating through the document's elements.
  2. Accessing Table Data:

    • The KeySchedule element has a GetTableData() method that returns a TableData object. This object contains the table's structure, including rows and columns.
  3. Iterating Through Rows:

    • We can iterate through the rows of the TableData using its GetSectionData(SectionType.Body).GetNumberOfRows() and GetCell(row, column) methods.
  4. Identifying the Key Column:

    • We need to find the column that holds the key parameter value. This is typically the first column, but it's best to verify by checking the column's header or the associated parameter.
  5. Retrieving the Key Value:

    • For each row, extract the key value from the identified key column's cell.
  6. Finding Elements with the Key Parameter:

    • Use a FilteredElementCollector to find all elements that have the key parameter.
    • Apply a ParameterFilter to filter for elements where the key parameter's value matches the key value extracted from the schedule row.
  7. Updating Parameter Values:

    • Once you have the ElementIds of the elements matching the key row, you can access their parameters and update them as needed.

Code Example (C#)

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

namespace RevitAddin
{
    public class KeyScheduleUpdater
    {
        public static void UpdateKeyScheduleParameters(Document doc, UIDocument uiDoc, ElementId keyScheduleId, string parameterToUpdate, string newValue)
        {
            KeySchedule keySchedule = doc.GetElement(keyScheduleId) as KeySchedule;
            if (keySchedule == null) return;

            TableData tableData = keySchedule.GetTableData();
            TableSectionData bodyData = tableData.GetSectionData(SectionType.Body);
            int rowCount = bodyData.GetNumberOfRows();

            // Find the key column (usually the first)
            int keyColumnIndex = 0; // Adjust if needed

            // Find the key parameter that is used by the schedule.
            ScheduleDefinition schedDef = keySchedule.Definition;
            ScheduleFieldId schedFieldId = schedDef.GetFieldId(keyColumnIndex);
            ScheduleField schedField = schedDef.GetField(schedFieldId);
            ParameterId keyParameterId = schedField.ParameterId;

            using (Transaction t = new Transaction(doc, "Update Key Schedule Parameters"))
            {
                t.Start();

                for (int rowIndex = 0; rowIndex < rowCount; rowIndex++)
                {
                    TableCell keyCell = bodyData.GetCell(rowIndex, keyColumnIndex);
                    string keyValue = keyCell.GetText();

                    // Find elements with the matching key parameter value
                    FilteredElementCollector collector = new FilteredElementCollector(doc);
                    collector.WherePasses(new ElementParameterFilter(new FilterStringRule(new ParameterValueProvider(keyParameterId), new FilterStringEquals(), keyValue)));

                    foreach (Element element in collector)
                    {
                        Parameter parameter = element.LookupParameter(parameterToUpdate);
                        if (parameter != null && !parameter.IsReadOnly)
                        {
                            parameter.Set(newValue);
                        }
                    }
                }

                t.Commit();
            }
        }
    }
}

Explanation:

  • The code iterates through each row of the key schedule.
  • It retrieves the key value from the first column.
  • It uses a FilteredElementCollector and ElementParameterFilter to find elements with the matching key value.
  • It then updates the specified parameter (parameterToUpdate) on those elements with the newValue.

Important Considerations:

  • Error Handling: Add robust error handling to handle cases where the key schedule, parameter, or elements are not found.
  • Transaction Management: Always perform parameter updates within a transaction to ensure data integrity.
  • Performance: For large models, consider optimizing the FilteredElementCollector to improve performance.
  • Key parameter identification: In cases where the key parameter is not the first column, you must add code to iterate the ScheduleFields, and identify the correct ParameterId.
  • Parameter types: Ensure that the parameter you are updating is of the correct type. If you are updating a number, or an elementId, then you must adjust the parameter.Set() method accordingly.

Retrieving ElementIds

The code example above effectively retrieves the ElementIds of elements associated with each key schedule row. You can store these ElementIds in a List<ElementId> or a Dictionary<string, List<ElementId>> (where the key is the key schedule row's key value) for further processing.

This approach provides a solid foundation for managing and updating key schedule parameters. Remember to adapt the code to your specific needs and always prioritize robust error handling and performance optimization.

    

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 8 of 8

Sean_Page
Collaborator
Collaborator

Just use a FEC and pass the scheduleId as the view and the resulting list of elements are each row of the key schedule.

https://forums.autodesk.com/t5/revit-api-forum/key-schedule-revit-api/m-p/5449134/highlight/true#M81...

Sean Page, AIA, NCARB, LEED AP
Partner, Computational Designer, Architect
0 Likes