Back

Introduction to Revit Macros, Part 2

In my previous article, “Introduction to Revit Macros,” which appeared in the November 2014 issue of AUGIWORLD, I outlined the basics of writing macros in Revit. In this follow-up article I will step through a macro that was made specifically for my previous company, an MEP firm. The macro is for use during project setup to create views for each of the MEP disciplines.

The macro, called “CreateMEPViews,” will create several discipline views for each level in the model. I built this macro because I was spending hours setting up large projects in Autodesk® Revit®. The process of duplicating a view, renaming it, and applying a view template for every discipline for every level in the model is very time consuming, especially on large, multi-story projects.

This macro is meant to be run after an architectural model has been linked into your MEP model and copy/monitor has been used to copy the architectural levels into your MEP model. In this article, the macro is listed in its entirety first. Following that I break it down to explain the code.

**Note: You will need to modify the view names and view template names to reflect the ones in your model before running this macro; otherwise it will result in an error.

// Description: Create MEP discipline views for each level in the project

public void CreateMEPViews()

{

UIDocument uidoc = this.ActiveUIDocument;

                Document doc = uidoc.Document;

               

                // get all elements in the model

                FilteredElementCollector collector = new FilteredElementCollector(doc);

                // filter out everything but levels

                ICollection<Element> collection = collector.OfClass(typeof(Level)).ToElements();

               

                // create and start a new transaction                                              

                using(Transaction t = new Transaction(doc, "Create MEP Views"))

                {

                                t.Start();

                               

                                // add a counter to count the number of views created

                                int x = 0;                                   

                               

                                // loop through each level in the model

                                foreach (Element e in collection)

                                {                                                              

                                                try

                                                {

                                                                Level level = e as Level;

                                                               

                                                                // to use the routines for createFloorPlan or createCeilingPlan, supply the

// following...

                                                                //                             lvl = level

                                                                //                             planName = text to use after level name (include a space at

//                                                    beginning)

                                                                //                             viewTempName = the exact view template name to be

//                                                    applied to the view

                                                                //                             uidoc = uidoc (from above)

                                                                //                             doc = doc (from above

                                                               

 

                                                                //BIM Management

                                                                createFloorPlan(level, " - BIM Management", "_b_BIM Management Floor

Plan", uidoc, doc);

                                                                x += 1;

                                                               

                                                                // Lighting RCP

                                                                createCeilingPlan(level, " - LIGHTING", "_e_Lighting RCP", uidoc, doc);

                                                                x += 1;

                                                               

                                                                // Power

                                                                createFloorPlan(level, " - POWER", "_e_Power Floor Plan", uidoc, doc);

                                                                x += 1;

                                                               

                                                                // Special Systems

                                                                createFloorPlan(level, " - SPECIAL SYSTEMS", "_e_Special Systems Floor Plan",

uidoc, doc);

                                                                x += 1;

                                                               

                                                                // Mechanical

                                                                createFloorPlan(level, " - MECHANICAL", "_m_Mechanical Floor Plan", uidoc,

doc);

                                                                x += 1;

                                                               

                                                                // Mechanical RCP

                                                                createCeilingPlan(level, " - MECHANICAL CEILING", "_m_Mechanical RCP",

uidoc, doc);

                                                                x += 1;

                                                               

                                                                // Plumbing

                                                                createFloorPlan(level, " - PLUMBING", "_p_Plumbing Floor Plan", uidoc, doc);

                                                                x += 1;

                                                               

                                                }

                                                catch(Exception ex)

                                                {

                                                               

                                                }

                                }

                               

                                // finalize transaction

                                t.Commit();

                               

                                // show dialog of how many views were created

                                TaskDialog.Show("CreateMEPViews", "Views Created: " + x.ToString());

                }

}

 

// Description: Create a new Floor Plan View and apply View Template

public void createFloorPlan(Level lvl, string planName, string viewTempName, UIDocument uidoc, Document doc)

{

                // Find a floor plan view type 

                IEnumerable<ViewFamilyType> viewFamilyTypes = from elem in new

FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))  

                                let type = elem as ViewFamilyType  

                                where type.ViewFamily == ViewFamily.FloorPlan  

                                select type;

               

                // create a new floor plan

                ViewPlan newViewPlan = ViewPlan.Create(doc, viewFamilyTypes.First().Id, lvl.Id);

                // change the name to the level name (in uppercase) + the name provided (planName)

// when calling the routine

                newViewPlan.Name = lvl.Name.ToUpper() + planName;

                // find the view template provided (viewTempName) when calling the routine

                View viewTemp = (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>()

                                where v.IsTemplate == true && v.Name == viewTempName select v).First();

                // apply the view template to the view

                newViewPlan.ViewTemplateId = viewTemp.Id;

               

                // return to original macro

                return;

}

 

// Description: Create a new Ceiling Plan View and apply View Template

public void createCeilingPlan(Level lvl, string planName, string viewTempName, UIDocument uidoc, Document doc)

{

                // Find a ceiling plan view type 

                IEnumerable<ViewFamilyType> viewFamilyTypes = from elem in new

FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))  

                                let type = elem as ViewFamilyType  

                                where type.ViewFamily == ViewFamily.CeilingPlan  

                                select type;

               

                // create a new ceiling plan

                ViewPlan newViewPlan = ViewPlan.Create(doc, viewFamilyTypes.First().Id, lvl.Id);

                // change the name to the level name (in uppercase) + the name provided (planName)

// when calling the routine

                newViewPlan.Name = lvl.Name.ToUpper() + planName;

                // find the view template provided (viewTempName) when calling the routine

                View viewTemp = (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>()

                                where v.IsTemplate == true && v.Name == viewTempName select v).First();

                // apply the view template to the view

                newViewPlan.ViewTemplateId = viewTemp.Id;

               

                // return to original macro

                return;

}

 

First, I need to define the Revit UI and Document objects so I can work with the current Revit model.

UIDocument uidoc = this.ActiveUIDocument;

                Document doc = uidoc.Document;

 

This code will collect all the levels in the model so I can create views for each level.

                FilteredElementCollector collector = new FilteredElementCollector(doc);

                ICollection<Element> collection = collector.OfClass(typeof(Level)).ToElements();

 

Next, I need to create a transaction. A transaction is required whenever I am going to make changes to the Revit model. In this case, I am creating views. Then I am going to start the transaction named “t”.                                       

                using(Transaction t = new Transaction(doc, "Create MEP Views"))

                {

                                t.Start();

   

In order to show a dialog at the end of the macro with how many views were created, I use the following code to create a counter named “x”.

                int x = 0;

Now I will start looping through each level. The foreach code in C# will step through each level in my model and run the code within its set of brackets { }. After running the code on the first level it will start at the top again and run the code on the next level in the model. It will do this until it has reached the last level and then it will continue on with the code outside the foreach.

foreach (Element e in collection)

In the first article I explained about the try and catch tools used for error catching within macros. I use this here to catch any errors that might occur when I start the process of creating my views.

Next I need to define that the elements in my collection are actually levels. This bit of code does just that.

Level level = e as Level;

Now I get into the meat of my code, which is creating the different discipline views, naming them appropriately, and finally applying a view template. Because I want to do the same thing over and over with different disciplines, I can reduce the amount of code by creating a routine that can be reused as many times as I want. I have created two separate routines, one for floor plans and one for ceiling plans because they use a bit of different code. I will explain how the floor plan routine works and you can review the ceiling plan routine to see the minor differences.

First, I need to create a routine outside of my main macro code. I then need to name it and list the information it needs from my main macro in order to run the code. I named the routine createFloorPlan. It requires a Level, the name for the new view, the view template name, and the Revit UI and Document objects in which I am currently running the main macro.

public void createFloorPlan(Level lvl, string planName, string viewTempName, UIDocument uidoc, Document doc)

Next, I need to get the type of view that I am going to be creating. In this case, it’s a floor plan. The following code will search through all the view types in the model and find the one that represents a floor plan. Because the line of code is so long, it has been broken into multiple lines for easier reading.

IEnumerable<ViewFamilyType> viewFamilyTypes = from elem in new

FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType))  

                                let type = elem as ViewFamilyType  

                                where type.ViewFamily == ViewFamily.FloorPlan  

                                select type;

Now that I have the view type, I can create the view based on all the supplied information (Document, View Family Type Id, and the Level Id).

ViewPlan newViewPlan = ViewPlan.Create(doc, viewFamilyTypes.First().Id, lvl.Id);

With the view created, I can now name it based on the Level name plus the discipline name I provided. I also use a method to make it UPPERCASE.

newViewPlan.Name = lvl.Name.ToUpper() + planName;

Finally, I search through the model for my view template for which I provided the name and then apply it to the newly created view; and a return statement to get back to my main macro.

View viewTemp = (from v in new FilteredElementCollector(doc).OfClass(typeof(View)).Cast<View>()

                                where v.IsTemplate == true && v.Name == viewTempName select v).First();

                newViewPlan.ViewTemplateId = viewTemp.Id;

With this routine in place, I can now call it from my main macro with the following code. I supply the Level, the discipline name I want added to the view name, the view template name (must be exact and in my current model), and the UI and Document objects for my current model. You’ll see in the full code listing above, I reuse the same code again for each of the disciplines and their appropriate view templates. I also increment the counter (x) by 1 because I have added a new view to the total being created by the macro.

createCeilingPlan(level, " - LIGHTING", "_e_Lighting RCP", uidoc, doc);

                x += 1;

Next, I need to commit the changes to the Revit model and then finally, I show a dialog box with the total number of views created using my counter object (x).

                t.Commit();

TaskDialog.Show("CreateMEPViews", "Views Created: " + x.ToString());

If you want to download the code above in a text file, you can download it from here: http://goo.gl/Y0Xg9Q

Appears in these Categories

Back