Create stair number system

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)

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’

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?

Thanks @kennyb6

Does this help?

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

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.

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)

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