Show level for pipe, duct, and conduits on schedles

Show level for pipe, duct, and conduits on schedles

stever66
Advisor Advisor
3,252 Views
10 Replies
Message 1 of 11

Show level for pipe, duct, and conduits on schedles

stever66
Advisor
Advisor

Not a question, but I wanted to respond to an idea request.  Except I can't attach images there, so I started a new thread.

 

Original comment by  Sujanc;

 

"Pipe, duct, conduit reference level need in schedule

We can't distinguish the pipe, duct & conduit level wise in schedule for a high rise building. It will be very much helpful if we get an option in schedule to segregate the items by their reference level."

https://forums.autodesk.com/t5/revit-ideas/pipe-duct-conduit-reference-level-need-in-schedule/idc-p/...

 

My response:

 

This is actually possible if you feel like trying a macro, and you can add a project parameter.  Here are the steps:

 

1.  Start the macro manager (you may have to check your security settings.)

2.  In the Macro Manager (MM) window, hit the "Create Module" button.

3. Name the module "SetMEPElevations".  (Spelling and keeping capitalization the same is critical - C# is case sensitive, and close doesn't cut it.  You can also change the naming later once you get it working, if you want to.)

4.  Make sure the language is "C#" and select OK.

5.  A code window will open up.  Delete the contents and paste the following in the window:

 

/*
 * Created by SharpDevelop.

 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;

namespace SetMEPElevations
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.DB.Macros.AddInId("1B655761-F700-49B1-9AB4-4036C5BA5C83")]
	public partial class ThisApplication
	{
		private void Module_Startup(object sender, EventArgs e)
		{

		}

		private void Module_Shutdown(object sender, EventArgs e)
		{

		}

		#region Revit Macros generated code
		private void InternalStartup()
		{
			this.Startup += new System.EventHandler(Module_Startup);
			this.Shutdown += new System.EventHandler(Module_Shutdown);
		}
		#endregion
		public void SetMEPElevationsMacro()
		{
					//Get references to revit and the current open file
			UIDocument uidoc = this.ActiveUIDocument;
            Document doc = this.ActiveUIDocument.Document;
            int n = 0;
            
            //get all the conduits
            ElementClassFilter conduitFilter = new ElementClassFilter(typeof(Conduit));
            ElementCategoryFilter conduitCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_Conduit);
            LogicalAndFilter conduitInstancesFilter = new LogicalAndFilter(conduitFilter, conduitCategoryfilter);
			
			//get all the pipes
			ElementClassFilter ductFilter = new ElementClassFilter(typeof(Pipe));
			ElementCategoryFilter pipeCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_PipeCurves);
            LogicalAndFilter pipeInstancesFilter = new LogicalAndFilter(ductFilter, pipeCategoryfilter);
			
			//get all the ducts
			ElementClassFilter pipeFilter = new ElementClassFilter(typeof(Duct));
            ElementCategoryFilter ductCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_DuctCurves);
            LogicalAndFilter ductInstancesFilter = new LogicalAndFilter(pipeFilter, ductCategoryfilter);
 			
			//Combine the three filters
			LogicalOrFilter conduitsandPipesFilter = new LogicalOrFilter (conduitInstancesFilter, pipeInstancesFilter);
			LogicalOrFilter allItemsFilter = new LogicalOrFilter (conduitsandPipesFilter, ductInstancesFilter);
			
			//put the items in a collector
			FilteredElementCollector collector = new FilteredElementCollector(doc);
			ICollection<ElementId> allIds = collector.WherePasses(allItemsFilter).ToElementIds();	
			//TaskDialog.Show("All Items size", allIds.Count.ToString());
			
			//Go through each item in the lists
			Transaction myTransaction = new Transaction(doc);
            myTransaction.Start("Set Conduit Elevations");
            foreach (ElementId id in allIds)
                {
            	
            	
					
            	try
            	{
            		//Get the element from the id
					Element e = doc.GetElement(id);
                    //Get the elements level        
                	String ConduitElevationString = e.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsValueString();
					//Get the Project Parameter for the current element
                	Parameter ConduitElevationParam = e.LookupParameter("MyConduitElevation");
                	//if the elevation is vaild, then set the project parameter to the elements level;
                	if (ConduitElevationString != null)
                	
                	{
                	ConduitElevationParam.Set(ConduitElevationString);
                	}
            	}
            	catch (Exception ex)
            	{
            		//something went wrong with an element - skip that element and continue
            		n=n+1;
            		
            	}
                	
       			}//end foreach
			
               myTransaction.Commit();
               if (n != 0)
               {
               	string mymessage = "There were " + n.ToString () + " elements that could not have their elevation set.";
               	TaskDialog.Show("Revit Macro Message", mymessage);
               }
		}
			
	}//end partial class
}//end namespace

6.  On the "Build Menu" (in the code window) select build solution.  You will get a warning, but you should not get any errors. (Tested on revit 2018-2020)

7.  Go back to the macro manager window, and highlight the "SetMEPElevationsMacro".  The run button should be enabled.  Press run, and you should get a message that X number of elevations could not be set.   Press OK.  Don't worry about the message box - that means the code is working and the hard part is done.

8.  Now we have to make a project parameter.  Again spelling and capitalization is critical.  It has to be called MyConduitElevation to match the code.  (If you want to change the name later, you can, but you have to change the macro code to match.)

8A.  Select project parameters under the manage tab. 

8B.  Select "Add".   Name the parameter as noted above.  Select  "Project Parameter",  "Text"  for the type, and select "Values can vary by group instance".  In the Categories list, select "conduits", "ducts", and "pipes".  (See the example window image I've attached.)

8C.  Select OK.

9.  Now you can add the "MyConduitElevation" parameter to your schedules. If you go to the edit fields, it will appear in the drop down list.

10.  They will all be empty to start, but if you run the macro again, it should fill in all the elevations, and you shouldn't get a message box that says elevations couldn't be set.

 

If you change elevations, or add more items, you will have to re-run the macro.  But that's pretty easy.  On a file with 5000 items, it took about 30 seconds to run the first time, and it only took about 5 seconds to update a few changed elevations. 

 

You will have to add the project parameter to every file you use this in, so you might want to add it in your template.

 

Let me know if this helps out.  

 

3,253 Views
10 Replies
Replies (10)
Message 2 of 11

stever66
Advisor
Advisor

And yes, I'm going to be vain and give myself a solution for this 🙂

 

 

Message 3 of 11

Scott_D_
Collaborator
Collaborator

While this is awesome (and it really is awesome), it's something Revit should be doing OOTB imo.

Message 4 of 11

stever66
Advisor
Advisor

No, I won't argue that this is something that Revit should do on its own, but I'm also not going to hold my breath!

 

Feel free to also vote for the revit idea linked in the first post 🙂

0 Likes
Message 5 of 11

sujanc
Advocate
Advocate

Thank you @stever66 for your reply. It will really help us to segregate the elements as per their level. 

Please select "Accept solution" if the information was helpful (This allows other users with the same issues to find it higher in search results), or reply back if you need more help!
0 Likes
Message 6 of 11

msmall1041
Explorer
Explorer

will this work on conduit fittings

 

0 Likes
Message 7 of 11

hakanern
Collaborator
Collaborator

You can close this problem with dynamo as follows photo,

 

hakanern_0-1608273360680.png

 

0 Likes
Message 8 of 11

Anonymous
Not applicable

Hello @stever66 

while running the Build Solution, it gives me 5 errors.

 

Could you help me on this?

 

Thank youimage.png

0 Likes
Message 9 of 11

sragan
Collaborator
Collaborator

Yes, you need to make an application macro, not a document level macro.  Make sure you have the "Application" tab selected when you hit the "Module" button.  See the attached image.

 

Hope that helps.

 

 

0 Likes
Message 10 of 11

draftingelecnsw1
Explorer
Explorer

This is fantastic! Brilliant work.

0 Likes
Message 11 of 11

sragan
Collaborator
Collaborator

Someone asked if cable trays could be added to this.  Its pretty easy to do.  We just have to create a new class filter, a new category filter, and a new instance filter using the category "OST_CableTray".   We can really name the filters anything we want, but I've tried to keep names similar to the other filters.  Then we have to combine the filters which is starting to get a little cumbersome with 4 different filters since we can only combine 2 at a time.

 

Anyhow, this gives us the code below.  Then the Project parameter just needs to be added to cable trays also.  Following this procedure should let you add any categories that have a "reference level".  The hardest part is trying to figure out which OST category you need.  For some reason, for pipes and ducts is actually OST_DuctCurves and OST_PipeCurves, but for conduits its just OST_Conduit.    Anyhow, when you start to type this you should get a drop down list to choose from, so its usually just a matter of trial and error to get the category you want.

 

 

{
					//Get references to revit and the current open file
			UIDocument uidoc = this.ActiveUIDocument;
            Document doc = this.ActiveUIDocument.Document;
            int n = 0;
            
            //get all the conduits
            ElementClassFilter conduitFilter = new ElementClassFilter(typeof(Conduit));
            ElementCategoryFilter conduitCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_Conduit);
            LogicalAndFilter conduitInstancesFilter = new LogicalAndFilter(conduitFilter, conduitCategoryfilter);
			
			//get all the pipes
			ElementClassFilter ductFilter = new ElementClassFilter(typeof(Pipe));
			ElementCategoryFilter pipeCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_PipeCurves);
            LogicalAndFilter pipeInstancesFilter = new LogicalAndFilter(ductFilter, pipeCategoryfilter);
			
			//get all the ducts
			ElementClassFilter pipeFilter = new ElementClassFilter(typeof(Duct));
            ElementCategoryFilter ductCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_DuctCurves);
            LogicalAndFilter ductInstancesFilter = new LogicalAndFilter(pipeFilter, ductCategoryfilter);
            
            //get all the CABLE TRAYS
			ElementClassFilter cabletrayFilter = new ElementClassFilter(typeof(CableTray));
            ElementCategoryFilter cabletrayCategoryfilter = new ElementCategoryFilter(BuiltInCategory.OST_CableTray);
            LogicalAndFilter cabletrayInstancesFilter = new LogicalAndFilter(cabletrayFilter, cabletrayCategoryfilter);
 			
			//Combine the FOUR filters
			LogicalOrFilter conduitsandPipesFilter = new LogicalOrFilter (conduitInstancesFilter, pipeInstancesFilter);
			LogicalOrFilter conduitspipesductsItemsFilter = new LogicalOrFilter (conduitsandPipesFilter, ductInstancesFilter);
			LogicalOrFilter allItemsFilter = new LogicalOrFilter(conduitspipesductsItemsFilter , cabletrayCategoryfilter );
			
			
			//put the items in a collector
			FilteredElementCollector collector = new FilteredElementCollector(doc);
			ICollection<ElementId> allIds = collector.WherePasses(allItemsFilter).ToElementIds();	
			//TaskDialog.Show("All Items size", allIds.Count.ToString());
			
			//Go through each item in the lists
			Transaction myTransaction = new Transaction(doc);
            myTransaction.Start("Set Conduit Elevations");
            foreach (ElementId id in allIds)
                {
            	
            	
					
            	try
            	{
            		//Get the element from the id
					Element e = doc.GetElement(id);
                    //Get the elements level        
                	String ConduitElevationString = e.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsValueString();
					//Get the Project Parameter for the current element
                	Parameter ConduitElevationParam = e.LookupParameter("MyConduitElevation");
                	//if the elevation is vaild, then set the project parameter to the elements level;
                	if (ConduitElevationString != null)
                	
                	{
                	ConduitElevationParam.Set(ConduitElevationString);
                	}
            	}
            	catch (Exception ex)
            	{
            		//something went wrong with an element - skip that element and continue
            		n=n+1;
            		
            	}
                	
       			}//end foreach
			
               myTransaction.Commit();
               if (n != 0)
               {
               	string mymessage = "There were " + n.ToString () + " elements that could not have their elevation set.";
               	TaskDialog.Show("Revit Macro Message", mymessage);
               }

 

0 Likes