Family Parameter Value

Pramod asked an interesting

question
on
obtaining the values of family parameters in a family document which led me to explore this topic and discover a little more complexity than I was originally expecting:

Question: We are using the API of Revit Architecture 2010.
We want to get all Parameters and their values from the Family document.
We are referring to the AutoParameter example from the Revit SDK.
With the help of this example, we are able to get parameters of Family, but didn’t get any property or method for getting Value of those parameters.
So please give any code example for getting values of the Family Parameters.

Answer: I dug around a bit to provide an answer for you, and was surprised at the result.
I had not previously noticed the additional level of indirection required to access a family parameter value.

Before we start working on reading family parameter values, let me mention that the addParameters method in the

Revit Family API labs

provides a sample demonstrating how to create family parameters and set their values.

The family has two main aspects, the geometry and the parameter data. Some of the parameters can be used to drive the geometry, so the two areas are interlinked. The data is stored in parameters, and the family contains a set of predefined types which already have predefined values for certain parameters. The family parameter has a pointer to its definition which specifies the name and data type, just like a project parameter. However, it does not have a parameter value, because the values are specific to the family types. Instead, each family type has its own value for each of the family parameters.

One of the main objects in the family document is its family manager, which manages its family types and parameters. A family parameter looks a lot like a normal Revit parameter on a BIM element instance, and has many of the same properties such as the Definition property which defines the parameter name and data type. The big difference between a family and a non-family parameter is that the latter has a value and the former does not.

In a project document, a parameter has a pointer to the parameter definition which defines its name and data type and other properties, and the main data item of the individual parameter is its own personal parameter value. A family parameter has one additional level of complexity and indirection, since the family parameter values are defined individually for each of the family types.

When you retrieve a value for a parameter from a family type, you have to supply the family parameter instance to specify which parameter value to retrieve.

I created a new Building Coder sample command named CmdFamilyParamValue to demonstrate how to read the values of family parameters.

First of all, it ensures that we are running in a family document:


Application app = commandData.Application;
Document doc = app.ActiveDocument;
if( !doc.IsFamilyDocument )
{
  message =
    "Please run this command in a family document.";
}
else

In order to retrieve a parameter value from a family type, we need to provide a pointer to the family parameter instances that we are interested in, so we start off by creating a dictionary containing all the family parameters and mapping their names to the corresponding object instances:


FamilyManager mgr = doc.FamilyManager;
 
int n = mgr.Parameters.Size;
 
Debug.Print(
  "nFamily {0} has {1} parameter{2}.",
  doc.Title, n, Util.PluralSuffix( n ) );
 
Dictionary<string, FamilyParameter> fps
  = new Dictionary<string, FamilyParameter>( n );
 
foreach( FamilyParameter fp in mgr.Parameters )
{
  string name = fp.Definition.Name;
  fps.Add( name, fp );
}
List<string> keys = new List<string>( fps.Keys );
keys.Sort();

I create a sorted list of the parameter names, so that the final result will be sorted and thus more readable.

Before we move on to the iteration over the family types and determining the family parameter values for each, here is a helper method to retrieve and format the family parameter value as a string.
I noticed that a string-valued parameter value can only be retrieved using AsString, and AsValueString returns an empty string for it, so I implemented a switch statement and an optimal specialised access and display for each storage type:


static string FamilyParamValueString(
  FamilyType t,
  FamilyParameter fp,
  Document doc )
{
  string value = t.AsValueString( fp );
  switch( fp.StorageType )
  {
    case StorageType.Double:
      value = Util.RealString(
        ( double ) t.AsDouble( fp ) )
        + " (double)";
      break;
 
    case StorageType.ElementId:
      ElementId id = t.AsElementId( fp );
      Element e = doc.get_Element( ref id );
      value = id.Value.ToString() + " ("
        + Util.ElementDescription( e ) + ")";
      break;
 
    case StorageType.Integer:
      value = t.AsInteger( fp ).ToString()
        + " (int)";
      break;
 
    case StorageType.String:
      value = "'" + t.AsString( fp )
        + "' (string)";
      break;
  }
  return value;
}

With the helper method in hand, we can iterate over the family types and display their family parameter values.
We use HasValue to determine whether a type has a value for each parameter, retrieve its value, and display the result:


n = mgr.Types.Size;
 
Debug.Print(
  "Family {0} has {1} type{2}{3}",
  doc.Title,
  n,
  Util.PluralSuffix( n ),
  Util.DotOrColon( n ) );
 
foreach( FamilyType t in mgr.Types )
{
  string name = t.Name;
  Debug.Print( "  {0}:", name );
  foreach( string key in keys )
  {
    FamilyParameter fp = fps[key];
    if( t.HasValue( fp ) )
    {
      string value
        = FamilyParamValueString( t, fp, doc );
 
      Debug.Print( "    {0} = {1}", key, value );
    }
  }
}

Here is the result of opening a new family document based on the Metric Column template,
running the Family API lab 4 command to create a simple column family and some types, and then listing the family parameter values using CmdFamilyParamValues:


Family Family1 has 13 parameters.
Family Family1 has 5 types:
:
ColumnFinish = -1 ()
Depth = 1.97 (double)
Td = 0.49 (double)
Tw = 0.49 (double)
Width = 1.97 (double)
1000x300:
ColumnFinish = -1 ()
Depth = 0.98 (double)
Td = 0.25 (double)
Tw = 0.82 (double)
Width = 3.28 (double)
600x900:
ColumnFinish = -1 ()
Depth = 2.95 (double)
Td = 0.74 (double)
Tw = 0.49 (double)
Width = 1.97 (double)
Glass:
ColumnFinish = 574 (Materials )
Depth = 1.97 (double)
Td = 0.49 (double)
Tw = 0.49 (double)
Width = 1.97 (double)
600x600:
ColumnFinish = -1 ()
Depth = 1.97 (double)
Td = 0.49 (double)
Tw = 0.49 (double)
Width = 1.97 (double)

Apparently, it includes one unnamed type as well as the four that our sample created intentionally.

I hope this clarifies the structure and usage of family parameters and possibly provides a useful additional little utility for your tool kit.

Here is
version 1.1.0.53
of the complete Building Coder sample source code and Visual Studio solution including the new command.


Comments

28 responses to “Family Parameter Value”

  1. Hi Jeremy,
    This is exactly what i need. Do you have the code perhaps in VB? I’m a starter and it’s difficult to see it from C#.
    Greets Patrica van Leeuwen

  2. Dear Patricia,
    Wow, great, lucky you, I am glad it is useful. Sorry to say, I do not have the code in VB. I discussed the issue of converting from C# to VB a couple of times, and there should be no issue converting this little class using any of the tools mentioned in the following posts:
    http://thebuildingcoder.typepad.com/blog/2008/10/converting-between-vb-and-c-and-net-decompilation.html
    http://thebuildingcoder.typepad.com/blog/2009/05/vb-samples-and-other-questions.html#2
    http://thebuildingcoder.typepad.com/blog/2009/07/porting-from-c-to-vbnet.html
    Good luck to you and lots of success getting into the Revit API!
    Cheers, Jeremy.

  3. Dan Tartaglia Avatar
    Dan Tartaglia

    Hi Jeremy, I’m new to the API and followed your example. One problem, you didn’t define the variable: ‘Util’ in the example code on the web page and in the example CS. Could you please tell me where and how to define this variable?
    Thanks,
    Dan

  4. Dear Dan,
    Simply download the entire attached version 1.1.0.53 of the source code and Visual Studio solution.
    It contains all the code required, including the Util class.
    Cheers, Jeremy.

  5. Dear Jeremy:
    When I tried to add a shared parameter to a Family Instance, the value is not being set. I have followed the “FireRating” example for the implementation.
    My procedure is as follows:
    1. Create a Family instance
    2. Create a Parameter by accessging the shared parameter file and adding the same under the “others” group.
    3. I set a value to the parameter.
    The problem:
    Some times the binding result in false return.
    Even if I get the parameter by get_parameter() method, the value is not being set.
    //My code is like this
    FamilyInstance FI – is my instance object
    Parameter p = FI.get_parameter(“IFCGUID”);
    … The above returns the correct parameter object
    p.Set(“my value”);
    … Setting the value does not happens
    For you information, IFCGUID parameter is already existing for OST_Rooms category also.
    Does it affect the same parameter name to be set for OST_Furniture also?
    Please help me.

  6. Dear Saro,
    Thank you for the description, but I am afraid I have no idea what the problem might be. I would simply suggest the standard debugging procedure of reducing and simplifying until either the problem disappears or you have reduced it to the absolute minimal case at which point everything suddenly becomes clear.
    Cheers, Jeremy.

  7. Dear Jeremy:
    Thanks for your reply.
    I would like to know one simple thing as below.
    Is it possible to create identical shared parameter name for different Family categories?
    Ex: I have a param named “MyParam”.
    I want to create this param to diffent Family categories such as Furnitues, Floors, Rooms, etc.
    Is this possible?
    Thanks,
    -Saro

  8. Dear Saro,
    First of all, yes. I believe that you can create as many shared parameters with the same name as you like. Obviously, this is a brilliant way to confuse your users. The different identically named parameters are differentiated by their different GUIDs.
    Secondly, when you bind a shared parameter to Revit elements, you are always binding it to a set of categories, i.e. one or more categories. Therefore, instead of creating multiple different shared parameters with the same name, a more efficient and easily manageable approach would be to add al the required categories to the category set you bind the parameter to. Please refer to the discussion
    http://thebuildingcoder.typepad.com/blog/2009/06/model-group-shared-parameter.html
    This post also links back to other topics dealing with shared parameters.
    Cheers, Jeremy.

  9. Dear Jeremy,
    I was wondering if there is a sample somewhere for replacing parameters in multiple families from non-shared to shared parameters in a batch type environment.
    Similar to the Auto Parameter application out of the SDK.
    Thanks,
    Michael

  10. Dear Michael,
    Not that I am aware of, I’m afraid. The existing samples should provide all the information needed to create a utility like that yourself. They are only intended to demonstrate the basic principles, you know, not provide ready-made solutions for every need :-)
    Cheers, Jeremy.

  11. Dear Jeremy,
    I have developed a simular extension and the purpose is to add some shared parameters to a set of families and set the value to some of the paramaters as strings.
    This works but only for one type of the family. Let say I have a table for example with one type for each dimension. If I try to run my extension the parameters are set but the value is only assign to the first type in the family.
    I’m using code simular to this:
    FamilyManager familyManager = doc.FamilyManager;
    foreach (FamilyType type in familyManager.Types)
    {
    foreach (FamilyParameter para in familyManager.Parameters)
    {
    if (para.Definition.Name == “MySpecialNameOfTheParameter”)
    {
    familyManager.Set(para, “Some text…”);
    }
    }
    }
    Do you have any idea how to solve this? It seems that there is no connection between the FamilyType and the FamilyParameter so what I’m actually doing is to set the value of the same parameter the number of times I have Types.
    Thanks in advance,
    Carl

  12. Käre Carl,
    The parameters in a family are structured differently from the ones in a project file, and this needs to be understood first. In a project file, there is a parameter definition which defines the parameter name and data type etc., and a parameter instance which determines it value and other details. In a family file, there is another level of indirection, because one individual parameter can have different values for each type in the family. Therefore, the parameter itself does not hold the parameter value for an individual type, but rather each type holds a value for each parameter of the family.
    When you call FamilyManager.Set, it sets the value only for the currently active type in the family. You need to iterate over all the types contained in the family, set each one in turn to be the current type, and then call FamilyManager.Set for each parameter to set the parameter value for that type.
    This is explained in detail and demonstrated for reading family type parameter values in
    http://thebuildingcoder.typepad.com/blog/2009/11/family-parameter-value.html
    You can also take a look at
    http://thebuildingcoder.typepad.com/blog/2009/11/change-family-parameter-value.html
    Cheers, Jeremy.

  13. Is it possible to create an instance parameter for a FamilyInstance while running in project mode? I noticed that I can reload a family and this functionality will overwrite the existing parameter types (for each FamilyInstance) in my project, I wish to do this at the project level (programmatically).
    The FamilyManager class only seems to run in Family Editor mode. Is there a different way to go about this? Thanks

  14. Dear J,
    You can open and manipulate a family document through the API in the background, while the user interface remains in the project editor. The user will not notice these background operations taking place. Many applications manipulate family documents through the API while the user interface continues displaying the open active project document. So yes, what you ask for is eminently doable.
    Cheers, Jeremy.

  15. Jeremy,
    In this case, is this approach limited only to Type Parameters?
    What about Instance Parameters? Are they stored by the same way (per Type) and can also be accessed through FamilyManager?
    Regards.

  16. Dear Fernando,
    Yes, I would say that the parameters listed above such as Width, Depth, Tw and Td are type parameters, just as you say. I don’t know about instance parameters. I had a look at various other posts dealing with this issue, such as
    http://thebuildingcoder.typepad.com/blog/2009/06/adding-a-shared-parameter-to-an-rfa-file.html
    http://thebuildingcoder.typepad.com/blog/2009/08/the-revit-family-api.html
    http://thebuildingcoder.typepad.com/blog/2009/10/revit-family-creation-api-labs.html
    http://thebuildingcoder.typepad.com/blog/2009/11/family-parameter-value.html
    http://thebuildingcoder.typepad.com/blog/2009/11/change-family-parameter-value.html
    http://thebuildingcoder.typepad.com/blog/2010/02/creating-a-dimension-label.html
    All the calls made to the AddParameter method a made with a false value for the Boolean isInstance argument. I would suggest you try it out and see. I assume that will require a similar exploration as above to understand. If you do document your exploration, please feel free to guest edit a blog post on it :-)
    Cheers, Jeremy.

  17. Jeremy,
    I’m testing your code and I’m facing a problem (or API limitation).
    It is possible to create Families without any types. Even by creating those families the parameter value can still be set but I can’t retrieve them by searching inside FamilyManager.Types collection because it is empty.
    As an alternative I have tried to look into FamilyManager.CurrentType property which is null in this case.
    I have also explored several RevitLookup nodes looking for the parameter values without any success.
    Where are the parameter values being stored on this “Typeless Family” scenario and how to retrieve them through the API?
    Regards.

  18. Ok, I will further investigate this.
    Thank you.

  19. Jeff Z. Avatar
    Jeff Z.

    Jeremy,
    Thank you for all your helpful coding pages… I have a question that involves several steps.
    I’m attempting to create a plugin for a school project in which you can measure the light intensity at a specific point given a certain layout of lights. To simplify this, lets assume there is only a single light. In order to calculate this you need to extract the parameter values for the light initial intensity as well as the distance between the light and the point of measurement. I imagine This can be done two ways, one where you extract the world coordinate points (if possible) of each object and through trigonometry calculate distance. The other would be to extract a distance from a dimension line.
    I’m a beginner at this coding business, and all I’ve been able to work out myself is how to extract type values of the lighting fixture.
    What suggestions can you provide me? Any help is greatly appreciated!
    Best,
    Jeff Z.

  20. Dear Jeff,
    Thank you for your appreciation.
    I would definitely stick with the standard simple geometry and geometrical analysis.
    Extracting coordinate points is possible and easy.
    I would not try to start creating additional Revit elements such as dimensions. That sounds vastly more complicated to me.
    Cheers, Jeremy.

  21. Sebastjan Avatar
    Sebastjan

    Dear Jeremy.
    I have followed this example and doing so I was able to create an addin that allows you to get family parameters from family document in Revit 2013.
    The only thing that does not work is the “second storage case” (case StorageType.ElementId:).
    Is this a Revit version specific problem, while as I mentioned I am creating an addin for Revit 2013?
    The second question I want to ask is: is it possible to get “Materials and Finishes” parameter value because as it can be seen from result of your example this code only allows you to get reference to a specific material “ColumnFinish = 574 (Materials )”.
    Thanks.

  22. Dear Sebastjan,
    This code should work in Revit 2013 as well. The “Materials and Finishes” parameter value type is an element id. It contains the element id of a specific material, whatever was assigned to the selected element. That is basically just an integer. The string representation is generated by the FamilyParamValueString method.
    Cheers, Jeremy.

  23. Jasper Desmet Avatar
    Jasper Desmet

    Hey Jeremy,
    just a question to understand why (I encountered this just now while writing code):
    In the code you use a cast to ensure the return of a double when using the AsDouble()-method:
    ( double ) t.AsDouble( fp );
    This cast is necessary, as the AsDouble()-method returns a ‘double?’.
    What exactly is a ‘double?’; What’s the difference with a normal ‘double’ and why does the AsDouble()-method not return an normal ‘double’?
    I had never encountered a ‘double?’ before, and can’t seem to find an explanation using google. Just interested in how it works. :)
    Greeting,
    Jasper

  24. Dear Jasper,
    Thank you for the pertinent question.
    That probably has only historical reasons. I assume that an earlier version of the code did not call the RealString method, maybe just used a straight call ToString or something like that, and needed some disambiguation.
    As far as I can tell by just looking at it, the cast no longer makes any sense whatsoever and can be removed.
    I think that almost all you can possibly wish to learn about doubles is provided by the Wikipedia article:
    http://en.wikipedia.org/wiki/Double-precision_floating-point_format
    Cheers, Jeremy.

  25. sorry to drop this post here , but here is serious question :
    i need a parameter which can share same values for two categories. Ex: if in a structural member(beam or column or footing) reinforcement is assigned . i need a parameter in structural member which should be shared by the rebars in that structural member.
    please let me know if this can be possible ..!!

  26. Dear Preetesh,
    I cannot really answer this from the Revit side of things, since it is more of a product and user interface question than an API issue.
    If the user interface supports this, which I doubt, then the API does as well.
    From a programming point of view, I can think of numerous way to achieve an effect similar to what you are asking for.
    For example, if Revit forces you to add separate parameters on each el;element, you can use the DMU framework to keep them all synchronised.
    Depending on what you want them for, you may be better off using other techniques instead, e.g. extensible storage, possibly in one single separate container for all members, an external database, etc.
    Sounds like some creative thinking outside the box might come in useful here…
    Cheers, Jeremy.

  27. vyom dixit Avatar
    vyom dixit

    Hi Jeremy,
    Thanks to you for such a nice and helpful post. You have demonstrated the way perfectly, but i have a question about this post. Can we get the selected element family parameters and it’s values in Revit document? Is there any way or approach that you can suggest. It would be more helpful if you can do so.
    Please reply ASAP. I am developing an add-in that fetch all information from a selected RevIT document element and store it in external database.
    Thanks

  28. Dear Vyom Dixit,
    This is amply covered in the getting started material:
    http://thebuildingcoder.typepad.com/blog/about-the-author.html#2
    For instance, both the My First Revit Plug-in and DevTV tutorials demonstrate this.
    Cheers, Jeremy.

Leave a Reply to MichaelCancel reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading