Most non-geometrical element data in Revit is stored in element parameters, so this is obviously an important topic, and one that we have not explored much yet. We did touch on it when discussing adding a shared parameter to a DWG file, and now we will recapitulate some basics and discuss the built-in parameter checker, which is a useful tool for exploring element parameters.
First some brief basic facts of life on parameters. They are discussed in more detail by the DevTV recording available for online viewing or download and the Revit API introduction labs, especially the sample commands in Labs4.cs.
Every Revit element has parameters attached to it, and the 'official' collection of parameters can be accessed through the Element Parameters property. If you are looking for a specific parameter, you can also use one of the direct access methods to retrieve a parameter from an element:
- Parameter( BuiltInParameter ): given a built-in parameter enumeration id.
- Parameter( Definition ): given a parameter definition.
- Parameter( Guid ): given a GUID for a shared parameter.
- Parameter( String ): given a localised parameter name.
A parameter has a value and a definition associated with it. The definition manages data such as the user visible parameter name and the interpretation of the parameter data. Shared parameters also have a GUID associated with them. All four methods above can be used to retrieve an individual parameter. Using the localised parameter name should be avoided, though, since it will cause the application to be language dependent. The build-in parameter enumeration is a hard-coded list of several hundred different parameters and provides a language independent method to identify most parameters.
Sometimes an element will have other parameters attached to it as well, which are not listed in the 'official' collection returned by the Parameters property. To explore all parameters attached to an element, one can make use of the built-in parameter checker.
This useful tool is included with the labs. It iterates over all the built-in parameter enumeration values and attempts to read a parameter for each one. Each one successfully retrieved is listed with all of its data, including the enumeration value, the localised name, the value, the string representation, and its read-write status. If the value is an element id, the id is evaluated and the type and name of referenced element is listed.
This tool can be used in conjunction with another tool also provided by the labs, the element lister implemented in Lab2_1_Elements, to discover information about elements that are not easy to access otherwise. As an example, let us analyse the data associated with Revit filters in the database, starting with the following question:
How can I access the filters stored in a Revit document?
We can explore this issue in the following manner: First, create an empty Revit model. In that, list all the elements in the document into a text file RevitElementsBeforeFilter.txt. Then, create a filter and list the elements again in RevitElementsAfterFilter.txt. Now we can determine the properties of the filter element that was added:
C:\tmp\ > diff RevitElementsBeforeFilter.txt RevitElementsAfterFilter.txt 2159a2160 > Id=127147; Class=Symbol; Category=?; Name=Filter 1
As you can see, one single element was added to the database, the filter element. Its System.Type is Symbol. It does not have a category associated with it, so we cannot use that to identify it. Its element name is "Filter 1". Next, we can explore its parameters and see whether they might be used to help identify filter elements. Entering the element id in the Revit menu entry Tools > Element Ids > Select by ID, select the filter into the current Revit selection set and list its parameters using the built-in parameter checker:
Symbol 'Filter 1' 127147 Instance Built-in Parameters ELEM_CATEGORY_PARAM_MT Category ElementId read-only -1 ELEM_CATEGORY_PARAM Category ElementId read-only -1 DESIGN_OPTION_ID Design Option ElementId read-only -1 PHASE_DEMOLISHED Phase Demolished ElementId read-write -1 PHASE_CREATED Phase Created ElementId read-write -1 ELEMENT_LOCKED_PARAM Locked Integer read-write 0 ELEM_DELETABLE_IN_FAMILY Deletable Integer read-write 1 UNIFORMAT_DESCRIPTION Assembly Description String read-only UNIFORMAT_CODE Assembly Code String read-write ID_PARAM Id ElementId read-only Symbol 'Filter 1' 127147 EDITED_BY Edited by String read-only ELEM_PARTITION_PARAM Workset Integer read-write 0 ELEM_FAMILY_AND_TYPE_PARAM Family and Type ElementId read-only -1 ELEM_FAMILY_PARAM Family ElementId read-only -1 ELEM_TYPE_PARAM Type ElementId read-only -1 SYMBOL_FAMILY_AND_TYPE_NAMES_PARAM Family and Type String read-only Filters: Filter 1 SYMBOL_FAMILY_NAME_PARAM Family Name String read-only Filters SYMBOL_FAMILY_NAME_PARAM Family Name String read-only Filters SYMBOL_NAME_PARAM Type Name String read-only Filter 1 SYMBOL_NAME_PARAM Type Name String read-only Filter 1 SYMBOL_ID_PARAM Type Id ElementId read-only -1
Please excuse the overly long lines ... you can see them in full by copying them to a text file. This shows all the information accessible through the API for the filter element. This information may be enough to identify the filters in the document. For instance, it might be possible to use combinations of these built-in parameters to construct a Revit API filter to extract all database elements of interest.
Addendum: For an improved version of the built-in parameter checker for Revit 2012, please refer to the BipChecker.
Dear Jeremy,
Following this post and the possibilities you commented us on the training this week, I would like to know how much data a parameter can store. As you know in Autocad the XData has a limit. I really liked your idea to store a xml tree structure on a parameter with our custom data instead of many different parameters.
Thanks a lot for the training the last three days, it has been a fantastic time.
Cheers, RJ.
Posted by: Ramon Jesus Gonzalez-Marquez | January 15, 2009 at 17:26
Dear Ramon,
How nice to hear from you again so soon, and I am very glad you liked the training. I also enjoyed it very much.
The technique of storing large amounts of structured data encoded into XML and then further encoded into a string using base64 encoding has been used successfully for some pretty large data sets. As far as I know, the only limitation is memory size, but of course Revit has never been tested in this context. So please be aware that you are using this technique at your own risk! I am planning to post on this topic quite soon, and will provide a detailed code sample when I do so.
Cheers, Jeremy.
Posted by: Jeremy Tammik | January 15, 2009 at 20:00
Hey Jeremy,
I noticed for certain special parameters I can't access the value.
For example with Lighting Fixtures, there are parameters like Light Loss Factor, Initial Intensity and Initial Color. The value field is a button, which opens a special window.
Do you think it's possible to access the value of these parameters?
Posted by: Nicholas | April 02, 2009 at 11:13
Dear Nicholas,
Thank you for posting your query as a comment instead of just sending a mail, that helps keep things sorted and in place, and ensures that others can share and participate in our conversation.
As far as I know, the only element properties accessible through the Revit API are the ones that are listed through the element viewer mentioned above. These do include some properties that are not present in the element Parameters collection.
Have you tried to list the properties of one of your lighting fixture instances using this tool?
I had a look at one lighting fixture instances in my installation, but I did not see the properties that you mention.
Cheers, Jeremy.
Posted by: Jeremy Tammik | April 02, 2009 at 11:23
Hey Jeremy,
These parameters I mentioned above are available when there is a Light Source Definition in the family and can be found under the Type parameters.
When I use param.Definition.ParameterType.ToString on these parameters, the result is "Invalid". The value of these parameters is "0" and it's an Integer (checked that with Parameters.StorageType.Integer)
Cheers
Posted by: Nicholas | April 02, 2009 at 15:54
Dear Nicolas,
Thank you for the update and clarification. I am exploring this issue and found that it merits an own post, which I plan to submit next week. I hope you can wait until then. I wish you a nice weekend.
Cheers, Jeremy.
Posted by: Jeremy Tammik | April 03, 2009 at 10:16
The discussion of this topic is continued at:
http://thebuildingcoder.typepad.com/blog/2009/04/deeper-parameter-exploration.html
Posted by: Jeremy Tammik | April 06, 2009 at 14:59
Hi Jeremy,
Just a quick question, I was having trouble with your code above, were you executing this all through VSTA and the macro editor built into Revit, or through MS Visual Studio with DLL com links to Revit? And was this the entire code required? Any clarifications would be greatly appreciated!
Thanks,
Brandon
Posted by: Brandon Schumacher | January 29, 2010 at 13:45
Dear Brandon,
I don't know exactly which "code above" you mean. In any case, I almost never executed any VSTA code myself at all, I always use the plug-in style implementation as illustrated by The Building Code samples.
Cheers, Jeremy.
Posted by: Jeremy Tammik | February 02, 2010 at 06:39
Dear Jeremy,
I want to explore the all available parameters in entire revit so that will get clear idea for all parameters.
Thanks
Sandeep
Posted by: Sandeep | December 21, 2010 at 01:33
Dear Sandeep,
I would suggest RevitLookup first of all, and my built-in parameter checker included in the Revit API introduction labs:
http://thebuildingcoder.typepad.com/blog/2010/07/change-element-type.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 21, 2010 at 02:31
Hi Jeremy,
Thank you so much for the link. Form download i got the "BuilInParameter" for particular element.Specially, small code as below explains a lot:
Array bips = Enum.GetValues(typeof(BuiltInParameter));
Parameter p;
foreach (BuiltInParameter a in bips)
{
try
{
p = elem.get_Parameter(a);
}
catch { }
}
Thanks
Sandeep
Posted by: Sandeep | December 22, 2010 at 07:16
Dear Sandeep,
I am glad that it helped and clarified things.
That try-catch statement to retrieve a value for each and every built-in parameter enum value is also used by the RevitLookup 'Built-In Enum Snoop' in the Snoop Parameters dialogue.
Cheers, Jeremy.
Posted by: Jeremy Tammik | December 23, 2010 at 02:51
Hello, Jeremy.
In my project I've found parameter of particular Element that doesn't exists in Element.Parameters collection.
You wrote: "Sometimes an element will have other parameters attached to it as well, which are not listed in the 'official' collection returned by the Parameters property. To explore all parameters attached to an element, one can make use of the built-in parameter checker." And nothing more. Can you explain that means these parameters?
In my case I need to get length of any element if length exists. I wrote next code for it:
http://pastebin.com/GgKFmxdD
At first In BuiltInParameters I find parametes that contains "LENGTH" word. Then I check if this BuiltInParameter exists in element. If it exists return value of this parameter. The problem there are no length parameter in element.Parameters but a can get it via element.get_Parameter.
Of course I can get length of the element enumerate each parameter and check parameter for length but I'm curios about these "strange invisible" parameters.
Best regards, Victor
Posted by: Victor | September 21, 2011 at 23:52
Dear Victor,
Yes, there are lots of parameters attached to elements that do not appear in the 'official' Element.Parameters collection.
You can retrieve them using any of the standard Element.Parameter property overloads. Yes, it is a property, and yes, it still takes an argument, and yes, it does not exist in C#, because it is called get_Parameter there. All a bit strange. The overloads are
Parameter(BuiltInParameter) Retrieves a parameter from the element given a parameter id.
Parameter(Definition) Retrieves a parameter from the element based on its definition.
Parameter(Guid) Retrieves a parameter from the element given a GUID for a shared parameter.
Parameter(String) Retrieves a parameter from the element given its name.
So if the parameter you are looking for is named "Length", you can retrieve it using that name.
I would recommend you not to do so, however, because this makes you code language dependent.
Better is to determine exactly which built-in parameter corresponds to it and use that instead.
Here is a code snippet with a loop that shows how to retrieve all parameters from an element. Actually, it may not retrieve all, but it mostly retrieves more than the official Parameters collection contains:
Array bips = Enum.GetValues(typeof(BuiltInParameter));
Parameter p;
foreach (BuiltInParameter a in bips)
{
try
{
p = elem.get_Parameter(a);
}
catch { }
}
This kind of loop to retrieve a value for each and every built-in parameter enumeration value is also used by the RevitLookup 'Built-In Enum Snoop' in the Snoop Parameters dialogue and my own built-in parameter checker:
http://thebuildingcoder.typepad.com/blog/2008/11/exploring-element-parameters.html
http://thebuildingcoder.typepad.com/blog/2009/02/locked-dimensioning.html
http://thebuildingcoder.typepad.com/blog/2009/04/deeper-parameter-exploration.html
http://thebuildingcoder.typepad.com/blog/2009/09/door-marks.html
http://thebuildingcoder.typepad.com/blog/2009/11/room-occupancy.html
http://thebuildingcoder.typepad.com/blog/2009/11/title-block-of-sheet.html
http://thebuildingcoder.typepad.com/blog/2010/05/pre-post-and-pick-select.html
http://thebuildingcoder.typepad.com/blog/2010/05/determine-sheet-size.html
I hope this explains.
Actually, after direct email contact and lots more discussion with Victor, this thread was promoted to an entirely new blog post of its own, including a completely revamped version of the built-in parameter checker, BipChecker:
http://thebuildingcoder.typepad.com/blog/2011/09/unofficial-parameters-and-bipchecker.html
Cheers, Jeremy.
Posted by: Jeremy Tammik | September 28, 2011 at 09:52