Hi
I am trying to create a stair number system to a multistory stair using this method .
I am getting an error ‘StairsRun is not iterable’ I think because I am feeding in multiple levels for the placement levels but I don’t know Python very well. Ideally I want to be able to feed in multiple stair runs and levels. Any suggestions?
import clr
import math
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Architecture import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import Autodesk
out = []
doc = DocumentManager.Instance.CurrentDBDocument
stairnum = []
elements = UnwrapElement(IN[0])
view = UnwrapElement(IN[1])
refs = UnwrapElement(IN[2])
TransactionManager.Instance.EnsureInTransaction(doc)
for item,ref in zip(elements,refs):
stairnum = Autodesk.Revit.DB.NumberSystem.Create(doc, view.Id, LinkElementId(item.Id), "Left", ref.Id)
out.append(stairnum)
TransactionManager.Instance.TransactionTaskDone()
OUT = out
18018_Stair Documentation_Part 10_Number system multistory_1.dyn (9.0 KB)
kennyb6
November 27, 2018, 5:51am
2
You just need to convert the elements variable into a list if it is a single item. There are a lot of examples but basically this:
if not isinstance(elements, list):
elements = [elements]
This is because of your for loop on line 28 has you going through the elements variable like it is a list but you can’t iterate through a single item.
Thanks @kennyb6
Do you mean like this?
import clr
import math
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Architecture import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import Autodesk
out = []
doc = DocumentManager.Instance.CurrentDBDocument
stairnum = []
elements = UnwrapElement(IN[0])
view = UnwrapElement(IN[1])
refs = UnwrapElement(IN[2])
TransactionManager.Instance.EnsureInTransaction(doc)
if not isinstance(elements, list):
elements = [elements]
for item,ref in zip(elements,refs):
stairnum = Autodesk.Revit.DB.NumberSystem.Create(doc, view.Id, LinkElementId(item.Id), "Left", ref.Id)
out.append(stairnum)
TransactionManager.Instance.TransactionTaskDone()
OUT = out
I am getting an error message: ‘List[object]’ object has no attribute ‘Id’
kennyb6
November 27, 2018, 5:57am
4
That means you fixed the error at line 28, and now the error is at stairnum = Autodesk....
One of those items you are feeding it that has .Id
attached is a list, not a single object like it needs to be. Can you show the inputs before the Python node expanded so we can see the list levels?
kennyb6
November 27, 2018, 7:07am
6
Flatten the Select.ByElementId before inserting into Python. It is a nested list so when you run it through a for loop, you get the first element which is a list of levels, instead of the first level.
hmm. New error message now: TypeError: expected StairsNumberSystemReferenceOption, got str
kennyb6
November 27, 2018, 7:19am
8
That’s good, that means we are getting close. So the next problem is with this class: StairsNumberSystemReferenceOption Enumerator .
You want the Left one but it isn’t as simple as feeding a string “Left” because it wants the class. Now you need to make a variable of the class with a value equal to what the value would be to get you Left.
To make the variable, I unfortunately forgot at the moment. Hopefully someone like @Kulkul or @Andreas_Dieckmann , or any of the other great users can help while I try to figure it out again.
kennyb6
November 27, 2018, 7:26am
9
Actually, try StairsNumberSystemReferenceOption.Left
. Honestly I am just guessing but might so it is worth a try.
stairnum = Autodesk.Revit.DB.NumberSystem.Create(doc, view.Id, LinkElementId(item.Id), StairsNumberSystemReferenceOption.Left, ref.Id)
Side note, it is worth learning what kinds of classes are in python, as I had never really learned about enums and the base commands for it.
1 Like
@kennyb6
Thanks for that. Yes I should have know about the enumerator - my bad. I’ve updated the Python script but am getting error messages. This time:
Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed. _
Traceback (most recent call last):
_ File “”, line 33, in
AttributeError: ‘List[object]’ object has no attribute ‘Id’
Any thoughts?
import clr
import math
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB.Architecture import *
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
import Autodesk
out = []
doc = DocumentManager.Instance.CurrentDBDocument
stairnum = []
elements = UnwrapElement(IN[0])
view = UnwrapElement(IN[1])
refs = UnwrapElement(IN[2])
TransactionManager.Instance.EnsureInTransaction(doc)
if not isinstance(elements, list):
elements = [elements]
for item,ref in zip(elements,refs):
stairnum = Autodesk.Revit.DB.NumberSystem.Create(doc, view.Id, LinkElementId(item.Id), StairsNumberSystemReferenceOption.Left, ref.Id)
out.append(stairnum)
TransactionManager.Instance.TransactionTaskDone()
OUT = out
I don’t know if this helps, but I have something in C# which works but hasn’t been adapted to allow for variables:
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
namespace AddTreadNumber
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId("63DDF65A-7B4D-4FA9-AF3A-3CDC9B1E438B")]
public partial class ThisDocument
{
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 AddTreadNumberToAllRuns()
{
var multistoryStairs = this.Document.GetElement(new ElementId(325500)) as MultistoryStairs;
var stairs = this.Document.GetElement(new ElementId(325185)) as Stairs;
if (multistoryStairs == null || stairs == null)
return;
ElementId northElevationViewId = new ElementId(29181);
ISet<ElementId> connectedLevelIds = multistoryStairs.GetStairsPlacementLevels(stairs);
Transaction addTreadNumberTransaction = new Transaction(this.Document, "Add tread number");
addTreadNumberTransaction.Start();
foreach (ElementId levelId in connectedLevelIds)
{
ICollection<ElementId> runIds = stairs.GetStairsRuns();
foreach (ElementId runId in runIds)
{
StairsNumberSystemReferenceOption option = StairsNumberSystemReferenceOption.Center;
LinkElementId hostId = new LinkElementId(runId);
LinkElementId linkedLevelId = new LinkElementId(levelId);
NumberSystem.Create(this.Document, northElevationViewId, hostId, option, linkedLevelId);
}
}
addTreadNumberTransaction.Commit();
}
}
}
18018_Stair Documentation_Part 10_Number system multistory_1.dyn (9.1 KB)
kennyb6
December 7, 2018, 1:19am
11
It is saying that the item
in elements
is a list instead of a singular element. You could iterate one more time through item
with another for loop and see if that helps.
You could also just output elements
real quick to check if it is indeed a nested list.
1 Like