I am having an issue with the the beginning of a problem I am trying to solve. I will describe the overall goal of what I am trying to achieve, and then go into explaining the problem illustrated in the screenshot below.
The problem that needs solving is that I am trying to get each conduit run in a project (easy enough), then get the list of every segment of conduit and conduit fitting that make up the conduit run. I am then taking those segments and conduit fittings and filling out a custom “To” and “From” parameter on them. The reason this needs to be done this way is because Revit itself does not propagate custom parameters to conduit fittings (probably because it doesn’t know how many fittings (bends) there are on a run, so it doesn’t want to collect them and give them a “To” and “From” param, even though they are shared params that should be propagated through all parts in a conduit run)
Now onto the problem:
In the screenshot below, I am pulling a list of all conduit runs. what I need this list to do is feed each individual conduit run in the list to the elements in connected network node (ECTN for short). the ECTN node only has one input of a single element, this means I have to feed the elements in one at a time to receive a list of conduit segments and fittings in the network.
What I need to know is:
A. How do I separate each conduit run in the list in order to feed them one at a time to the ECTN node. If I can accomplish this then I can change the “To” and “from” params of each part in the run myself.
B. What format does the ECTN node take as an input so that I know how to shape the data coming to it, because right now a single conduit run reads as NULL.
The ECTN node does not work with conduit runs actually. It is designed to work with actual elements, so in this case that would be the conduits or conduit Fittings.
I did a little searching and turns out that the Revit API does not provide a way to collect every conduit and fitting of a conduit run. The only thing I found is the ability to get the conduit run of a conduit. So a workaround would be to:
I have thought about the problem a little more and consulted some of my working mates (the ones I am developing this fix for in order to increase their workflow).
The issue they raised was something along the lines of “Our “To” and “From” params are often incomplete throughout the conduit run so what we really need is for you to take the TO and FROM from the junction box at the end of a run and propogate that information to the entire run.”
That is to say that the junction box at the end of the conduit run are the only thing in the network that are guaranteed to contain the TO and FROM params. So I have shifted my focus to trying to copy the junction box params to the params of the whole conduit run by virtue of them being in the same network of elements.
This gets me closer to the solution I am looking for, however, I do not know how to reliably accomplish it. Below is a screen shot of where I am currently in my solution. There is two problems that I have encountered so far with it:
the currentSelection node is not updating properly with the script set to automatically execute. I would expect it to execute every time something is selected in revit, but it does not.
It appears that everything is working right in the script except the GetParameterValueByName node does not appear to recognize the junction box (the currently selected object in the pic)
If you have any more insight to give, I would be greatly appreciative. Thank you for what you have done already.
The pic I linked above actually does work, it is just the currentSelection node that is messed up. I have to restart the script (as in reload the file) every time I want it to update the selection and retrieve the updated param. I have no idea what is causing this but if you know where I could find functionally identical node to the currentSelection node then I could use that as a replacement. The node is in the Springs package.
if isinstance(IN[0], list):
elements = UnwrapElement(IN[0])
else:
elements = [UnwrapElement(IN[0])]
OUT = [doc.GetElement(x.RunId) for x in elements]
What I am finding is that it does grab the (element?) ConduitRun and its associated ID when selecting a Conduit but not for a Conduit fitting (there it shows as null). Do you know if there is something fundamentally different about extracting that data in the conduits vs fittings?
Below I am trying to identify the RunID on both types of elements and can’t seem to extract the right data. Everything that the magenta arrows are pointing at have the same python code. I copied your code from above to make what I called “Find Conduit Run of Selected”
Hi Matthew,
There actually is a fundamental difference between the two: when you look at the Revit API you will see that a conduit is of the ‘Conduit Class’ and when you view its properties you will see the ‘RunId’ property. https://www.revitapidocs.com/2019/160a9aff-f4c5-55b1-fdf8-6ec696d88053.htm
A conduit fitting on the other hand is of the ‘FamilyInstance Class’ and this class does not have that same ‘RunId’ property. That is why it gives you that error.
If you still want to get the RunId that a fitting is part of then you will have to get conduit that is connected to that fitting and then query that conduit’s RunId. You could do something like this:
Hey guys,
I’ve been following Conduit Run issues for years now and searched everywhere for a solution, did a lot of experimentation and finally got something that worked. Hopefully by sharing my solution it will help others.First of all you will never be able to get Conduits and Conduit Fittings in the same schedule, but you can make Project Parameters in Conduits for Conduit Run related things,such as total run length and total run angle. My first step was to create a Project Shared Parameter for Conduit Run ID in Conduits and Conduit Fittings. I would use Iron Python to get the Revit generated RunID and then write it to the elements for scheduling. Here is part of my Dynamo script that deals with RunID.
Then using the following Python scripts I acquired the RunIDs and the wrote them to the Project Shared Parameters in the elements where they could be scheduled grouped by RunID.
Please excuse my programming, this is just the meat of the matter. I really don’t know Python that well, this was done by brute force research and experimenting. I would never have been able to do any of this without RevitLookup from Jeremy Tammik. I hope this insight can help others.
hello @Russell_Palmer can you please post the rest of your script, seems you started on line 15 or 16 in your pictures there and I cant get your scripts to work please advise! thanks!
Can you screen cap the error message above your python script node? And also, pin the output below the node in the screen cap as well. I would like to see what is happening. I would guess that because RunId is found in different places for conduits and conduit fittings that is why you get the error. You can’t use one script to get RunId from conduits and fittings. As for your script, let’s see what your errors messages are first. I spent a lot of time trying to make “Elements in connected network” work for me and couldn’t get consistent results that’s why I went in a different direction.
import clr
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)
if isinstance(IN[0], list):
elements = UnwrapElement(IN[0])
else:
elements = [UnwrapElement(IN[0])]
ids = list()
for item in elements:
ids.append([doc.GetElement(x.RunId) for x in item])
OUT = ids
It because the item not as sequence in some cases, need to add ternary condition probably something like that: ids.append([doc.GetElement(x.RunId) for x in item] if isinstance(item, list) else doc.GetElement(x.RunId))