Renaming a Family in a Project

An interesting question was raised on renaming a family after it has been loaded into a project, which throws some light on the underlying relationship between the family name and the RFA filename.

Before that, we revisit the eternal topic of getting started with the Revit API, and what to do to prepare for it before actually touching Revit at all.

Afterwards, and similarly, we pick up a good suggestion or two on planning and preparing your extensible storage schema for future version handling.

Explaining the similarity between the last two items mentioned above is left as an exercise to the reader   :-)

Before Getting Started

This topic was raised again in the Revit API discussion forum thread on choosing the best API for beginners:

Question: I know AutoLISP and made some tools for AutoCAD, and now I'm starting to take a look at Revit APIs.

My target is to create small tools, not big apps.

What is the recommended API to learn?

I don't want to learn C# or VB.NET, that's maybe a little bit too big.

There is also "Macro with Python" and "Dynamo" – can they be compared (from their features and possibilities), or is there a completely different approach?

Answer: Welcome to the Revit API!

The one and only Revit API is based on .NET.

It makes no difference what language you use to address it: C#, VB, Python or other; they all address the same API, and they are all translated to .NET IL, intermediate language.

That also means that it is easy to translate between these languages, since the IL can be decompiled again to a different language than the one used to generate it.

Dynamo is a separate environment using Python for programming that talks to the Revit API and also adds its own functionality.

The Revit API getting started material lists several other learning resources.

My personal opinion:

Almost all the official Revit SDK samples, Internet sample code and The Building Coder samples are in C#.

By the way: please try to utterly forget AutoLISP and AutoCAD and all its APIs when learning Revit API, because Revit and its API is different.

Please also learn as much as possible about Revit and BIM philosophy before you try to start programming, or nothing will make any sense at all.

Good luck and have fun!

Another conversation on this topic took place via private email:

Question: What C# programming topics would you recommend that someone learn prior to learning the Revit API?

Answer: You just need general .NET programming basics, nothing very high-level or complex.

The more the better, of course.

Actually, any and all programming experience is helpful.

One of the easiest languages to get started with is Python, IMHO.

Some old pointers to related resources:

A good understanding of event-driven programming is very helpful, since the Revit API is entirely event driven.

Response: I've been going through the SoloLearn C# training.

And while it's really good, there's certainly nothing related to Revit at all.

I've really wanted to be able to create customisations for Revit for some time and really want to focus on it to get to a point where I can create, even some rudimentary programs.

Answer: How did you find the Revit API getting started information?

Response: After quite some time, here is the path I’ve taken in pursuit of learning the Revit API:

First, I took a course on the Microsoft Virtual Academy site called C# Fundamentals for Absolute Beginners.

At the moment, I’m almost finished with the second section of Harry Mattison’s Learn to Program the Revit API by Boost Your BIM on Udemy.com.

At the same time, I’m using the SoloLearn app/website to continue reinforcing the basics of C#, and have also started looking at Google’s new 'learn to code' app called Grasshopper.

Any other thoughts?

Answer: Congratulations on the good progress and well targeted approach.

All I can add is: anyone interested in cloud and web-based technologies and/or making a good career and lots of money programming, might want to take a look at freecodecamp.

That has nothing to do with Revit either, however.

Cap

Renaming a Family in a Project

Question: I have a question related to the LoadFamilySymbol method.

Here is the description:

  doc.LoadFamilySymbol( "test.rfa""type1"out symbol1 );
  doc.LoadFamilySymbol( "test.rfa""type2"out symbol2 );

When I load two family symbols together as above, only one single family is created with the two types.

I can modify the family name by using either one of the symbols like this:

  symbol2.Family.Name = "NewName";

Then symbol1.Family.Name will be also updated to "NewName".

But the behaviour changes if I rename the family after the first one has been loaded, for example:

  document.LoadFamilySymbol( "test.rfa""type1"out symbol1 );
  symbol1.Family.Name = "NewName";

After this, the second load will create a new family. Renaming the symbol to the same name then doesn't work:

  document.LoadFamilySymbol( "test.rfa""type2"out symbol2 );

It creates new family, not associated with the first; symbol2.Family.Name remains as the old name.

Answer: Yes, that makes sense to me.

The family name is identical to the RFA filename.

Case 1:

Case 2:

Totally logical.

Response: Thanks Jeremy. So, the family name is always identical with the RFA filename. This should be the answer for the issue. Yes, it makes sense for me.

Is there some way to load other family symbols to the existing family after it has been renamed, instead of creating a new one associated with ‘test’? That’s actually the essential question; I want to load family symbols one by one to save performance, and rename the family sometime after loading the first symbol.

Answer: Yes, I do believe that a very simple workaround can be created based on what we already said:

Now, to load A.S2, it might be sufficient to:

Please try it out, test and confirm.

Response: I can confirm the workaround is working after my verification: Revit will load and name the family by its RFA filename.

Extensible Storage – Versioning Best Practices

Another interesting question was raised in the Revit API discussion forum thread on extensible storage best practices with plug-in development and growth, with helpful answers provided by David Robison, Design Master Electrical RT and Alexander @aignatovich Ignatovich, aka Александр Игнатович:

Question: I'm currently developing a Revit plug-in and need to utilise a schema; for now, I will just need two bool fields.

However, the plug-in will grow over time and eventually will become a ribbon with multiple buttons and various other functionality.

Thus, I assume that at some point I might need more sophisticated extensible storage data.

I already know that once a schema is built, it cannot be extended; what is then the best practice in such situations?

To have separate schemas for each part of my plug-in?

Answer 1: Some people store data in serialized form (such as JSON).

I don't think that it is good practice. Imagine that your app v1.0 requires 2 pieces of data: A and B, and your app v1.2 requires 3 pieces of data: A, B and C. Your v1.2 app reads storage and sees that there is no C. What does this mean? Was it due to old data, or C should not be present? Your next app v.1.3 requires new data format for B → B', may be with old data structure. Again, you have to deal with ambiguous environments; moreover, your app v.1.3 has to deal with 3 data formats: (A, B), (A, B, C) and (A, B', C).

To handle such a situation, you should define and include data version information and build a specific processor for each version:

Since schemas cannot be modified, each specific schema with its unique GUID id works as a version mark. It has strongly typed fields and it is rather comfortable to use. Your task as a software developer is just to organise your code, encapsulate details, and not repeat yourself. Prohibition of scheme modification is a good thing in my opinion.

Answer 2: Not being able to modify schemas does become a problem as your add-in becomes more complicated.

I store everything in map fields, like this:

  builder.AddMapField( 
    "strings"typeofstring ), typeofstring ) );

  builder.AddMapField( 
    "ints"typeofstring ), typeofint ) );

  FieldBuilder field = builder.AddMapField(
    "doubles"typeofstring ), typeofdouble ) );

  field.SetUnitType( UnitType.UT_Custom );

  builder.AddMapField( "bools",
    typeofstring ), typeofbool ) );

These fields allow me to change what I am storing without modifying my schema. The first value I always add is a version to the ints. When I get my entity from an element, if it's not there, I know I need to add it and do any required initialisation. If it is there, I check the version and do whatever upgrades are necessary if it is not the most recent.

Response: It seems like having these four dictionaries (strings, bools, ints, doubles) should be enough to handle every possible data. If you need other types, you can derive them from these four, one way or another.

I really like this idea, it's more generic from Alexander's, yet still it enables version control.

Thanks for sharing, you two!

Jeremy adds: for Revit-specific element relationships, you might also need the ElementId data type.