[rvtApi]__How to apprehend Revit API

[rvtApi]__How to apprehend Revit API

·

7 min read

In this article, I will not go deep dive into the basics of programming such a data Types, variables, keywords, logical and arithmetical operators, conditions (if/else), loops (for/while), numbers, characters and arrays, input and output operations. I will detail directly the C# programming specifications in Revit. So I want to shed light on methods, constructors, properties, etc.

Methods

In object-oriented programming like C#, a method/function is defined to carry out our coding tasks. By definition, a method refers to a function that is encased within a class. The goal of using methods is to encapsulate a set of code within it and reuse it elsewhere.

To understand how methods work, we can for instance write these programming lines to show a message :

Console.WriteLine("Hello network,");

Console.WriteLine("----------" + Environment.NewLine);

Console.WriteLine("today, we will learn how to interact with Revit API");

If we want to reuse these lines, we should in each time write them so why not use a method and just call it each time. We can define it as fellow :

static void MsgBox( ) 
{

  Console.WriteLine("Hello network,");

  Console.WriteLine("----------" + Environment.NewLine);

  Console.WriteLine("today, we will learn how to interact with Revit API");

}

Each time we want to show the message, we call the method simply by :

MsgBox( );

and that makes us win time. This method is special because it doesn't have neither a return nor arguments. We can have other type of methods like :

static int MsgBoxImproved(string message1, string message2)
{
int length1=message1.Length;

int length2=message2.Length;

return length1+length2;
}

Properties

A property is a class member that can expose a field. This property has always one of these methods or both : a 'getter' if it retrieves a value and a 'setter' if it sets a value.

Here is an example of using the getter and the setter based on Revit API Documentation

1611935833613.png

If we have a wall and we want to access to its width, we can write :

double WallWidth = wall.Width;

If we want to set a value for a layer of the wall, we should first access to the parameter "Thickness" of this precise layer, after that know its type and then set it within a Transaction. I will talk about transactions later. If I suppose I know the parameter and its type that is double, I can write this :

double thickness = 20.0;

parameter.Set(thickness);

Getters & Setters

In the programming world, getters and setters are used to protect your data, particularly when creating classes. For each instance variable, a getter method returns its value while a setter method sets or updates its value. In C#, each property represents a private field with bound Get and/or Set methods and those methods are seen differently by the compiler :

1612026848787.png

If we take a look at Revit API Documentation, we can conclude that the Wall Property called "Width" has just a getter method.

1612027277677.png

Transaction

A transaction is a single unit of work which means either ALL or NONE. If a transaction is successful, all of the data operations are committed. If a transaction encounters errors/exceptions and must be canceled or rolled back, then all of the data modifications/operations need to be removed.

You should always remember that if you want to modify something in Revit, you ought to write your code within a transaction like this :

using( Transaction tx = new Transaction( doc ) )

{ 
tx.Start("transaction1 starts");

//Your Code

tx.Commit();
}

Use Case Revit API : Retrieve data of designed walls

In this paragraph, I will give you a concrete example of using Revit API by C# leveraging SharpDevelop IDE so follow please these steps to start with your first programming code within SharpDevelop :

Create walls in Revit :

I have created, for instance, 5 basic walls type Generic - 200mm and that are constrained from Level 1 to Level 2.

1612028285043.png

Access to SharpDevelop IDE :

In order to accede to SharpDevelop, you need to start a Macro defining your programming language which is C# in our case : When you click on OK, you will get the SharpDevelop Interface that looks like this interface:

image.png

1️⃣ References : these are the Library Assemblies (.dll) that you will use. It is a set of classes that you will reuse in your code. If you need for example to use a method of Excel, you should add the Excel Reference called Microsoft.Office.Interop.Excel. Furthermore, you can see that RevitAPI and RevitAPIUI are referenced so as to use Revit Functionalities.

2️⃣ Calling the references : adding the references isn't enough. In order to use them in your code, you need to call them by "using ... ;" and you can specifiy exactly which class you need from these references.

3️⃣ Name of your solution that you had defined previously and it is called a namespace, which is a container to organize and provide a level of separation of codes.

4️⃣ & 5️⃣ They are two methods of the class called "ThisDocument" and they are automatically created by Revit when you create a new module. Their purpose is to give you a way to automatically run code when Revit starts and just before Revit exits. Module_Startup code is also executed every time you compile the module.

Create a piece of code to retrieve information of walls :

In this section, I will try to show you how to retrieve data from walls properties (Instance and Type Parameters) using Revit API.

In the example above, we have 5 walls that we want collect them in a variable(eventually a list) and thanks to code, we will get the number of walls created and for each wall, we will retrieve :

👉 Its rank in the list

👉 Its id

👉 Its type name

👉 Its category

👉 Its base constraint

Therefore, you should add a public method in which you encapsulate your code using properties, getters and message box leveraging loops.

The final code that you should get is :

/*
 * Created by SharpDevelop.
 * User: ELJEMLI Zakariae
 * Date: 30/01/2021
 */
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;

namespace Walls_Data
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("9188C47A-92A9-43C9-96DA-AD1F78BC12B3")]


    public partial class ThisDocument
    {

        private void Module_Startup(object sender, EventArgs e)
        {

        }

        private void Module_Shutdown(object sender, EventArgs e)
        {

        }

        private Document doc;
        public void RetrieveWallsData()
        {
            doc = Application.ActiveUIDocument.Document;
            IList<Element> listOfWalls= new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).WhereElementIsNotElementType().ToElements();

            int taille = listOfWalls.Count;

            for (int j=0;j<taille;j++)
            {
                ElementId Identifiant = listOfWalls[j].Id ; 
                string WallName = listOfWalls[j].Name ;
                Category WallCategory = listOfWalls[j].Category ;
                BuiltInParameter builtPara = BuiltInParameter.WALL_BASE_CONSTRAINT ;
                Parameter para = listOfWalls[j].get_Parameter(builtPara);

                TaskDialog.Show("Retrieve Data","Total Walls Number: " + taille.ToString()+Environment.NewLine+"Wall Rank: " + (j+1).ToString()+Environment.NewLine+"Identifiant: " +Identifiant.ToString() +Environment.NewLine+ "Name: " + WallName +Environment.NewLine+ "Category: " + WallCategory.Name+Environment.NewLine+ "Base Constraint: " + para.AsValueString());
            }

        }

        #region Revit Macros generated code

        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(Module_Startup);
            this.Shutdown += new System.EventHandler(Module_Shutdown);
        }

        #endregion

}
}

What was added comparing to the previous code suggested by the SharpDevelop by default is : 📌Attributes :

[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]

It is a transaction Attribute. It declares the way the transaction should work. It could be either Manual or Automatic. Here, you have set the attribute to Manual.

The value of TransactionMode.Manual for the TransactionAttribute requests that Revit don't create a transaction automatically (besides the one Revit creates for any external command to help roll back any changes performed should the external command fail). This setting also implies that you are responsible for creating, naming, committing or aborting your transactions.

  1. 📌 Document Accessibility :

  2. 📌 A public method called "RetrieveWallsData" where we write our code in order to reuse later in need when we want to run the Macro. 3. 📌 Walls collector : 4. 📌Walls total number :

  3. 📌 For Loop : to select walls one by one and retrieve their data 6. 📌 Wall Id getter : 7. 📌 Wall Name getter :
  4. 📌 Wall Category getter : 9. 📌 Wall Base Constraint Enumeration :

    What is an enumeration ? In the programming world, an enumeration is a set of named integer constants. An enumerated type is declared using the enum keyword An example of declaring an enumeration :

enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

So when you try to retrieve data from an enumeration, you can write :

int SundayRank = (int) Days.Sun;
Console.Writeline("Sunday : {0}", SundayRank);

The return will be : Sunday : 1

So the WALL_BASE_CONSTRAINT is an element of an enumeration in Revit API.

BuiltInParameter builtPara = BuiltInParameter.WALL_BASE_CONSTRAINT ;

Parameter para = listOfWalls[j].get_Parameter(builtPara);

After retrieving all of the walls data, we need to show them to the user and in order to do that, we use the TaskDialog Class that takes as arguments two strings :

TaskDialog.Show("Retrieve Data",
"Total Walls Number:" 
+ taille.ToString()
+Environment.NewLine
+"Wall Rank:"
+ (j+1).ToString()
+Environment.NewLine
+"Identifiant:" 
+Identifiant.ToString() 
+Environment.NewLine
+ "Name:" 
+ WallName 
+Environment.NewLine
+ "Category:" 
+ WallCategory.Name
+Environment.NewLine
+ "Base Constraint:" 
+ para.AsValueString());

Dependetly on the parameters type, we should transform the parameter to a string using some specific methods suggested by the IntelliSense of SharpDevelop.