Automating creation of electrical panel schedules

Hi,

I am wanting to write a python script that generates panel schedules for all the electrical panels in a model. I took a look at revitapi docs and see that the ‘PanelScheduleSheetInstance’ Class has the tools necessary to accomplish this. My problem is that I am having difficulty putting the pieces together.

I have identified the method that gives me what I wantCapture

but I am not fully understanding how to incorporate this method into the python script. Still fairly new to python in dynamo so any help is appreciated!

Here is what I have so far. Basically I just need someone to show me how to correctly incorporate this create method into the python script. Thanks!

Capture

Are you trying to create the panel schedule itself or place an existing schedule on a sheet? You have the method for placing an existing panel schedule on a sheet (which takes the active document, the existing schedule Id, and the sheet.) If you’re wanting to create a new schedule from a panel you’ll want to use one of these Create methods.
CreateInstanceView (using default template)
CreateInstanceView (using specific template)

1 Like

For now it sounds like the CreateInstanceView method is the one I need. I see that the method takes Document and ElementId as inputs, but what exactly is this ‘Document’? Is that just the revit file in which I am working?

Yes. It’s the Revit “document” (file) that you’re working in. Document.Current is a standard node you can use but you can also pull it directly from Python. A lot of custom nodes include the document.
image

import clr
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
doc = DocumentManager.Instance.CurrentDBDocument

OUT = doc
1 Like

Nick,

Here is my first attempt at creating a single schedule. However, I am getting the following error.

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 6, in
ImportError: Cannot import name PanelScheduleView

You don’t need to import the method directly. Import everything like this:

from Autodesk.Revit.DB import *

You can then create a new schedule like this:

panelSchedule = Electrical.PanelScheduleView.CreateInstanceView(doc, panelId)

1 Like

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 27, in
TypeError: expected ElementId, got List[object]

I assigned OUT to Electrical.PanelScheduleView.CreateInstanceView(doc, panelId) and received the above error. Not sure what to make of it…

Hi @andellano

It looks like you are inputting multiple panels, thus the “TypeError: expected ElementId, got List[object]”-warning. In order for this to work with multiple panels, you need to loop through your list of panel id’s.

You could set it up as shown below:

import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument

panels = UnwrapElement(IN[0])
output = []

for i in panels:
	TransactionManager.Instance.EnsureInTransaction(doc)
		
	output.append(Electrical.PanelScheduleView.CreateInstanceView(doc, i.Id))
		
	TransactionManager.Instance.TransactionTaskDone()
	
#Assign your output to the OUT variable.
OUT = output

1 Like

Not sure why I am getting a list error based on my dynamo graph. As you can see I am only inputting a single element Id into the python script.

output.append(Electrical.PanelScheduleView.CreateInstanceView(doc, i.Id))

In your above code. Where did you define ‘Id’? Is that simply another method you’re calling?

Thanks for the reply!

Hey @andellano,

I’ve commented the code here, and now taken into account, that the input may be a single item or a list of items:

import clr
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

#Import ToDSType(bool) extensions method
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)
clr.ImportExtensions(Revit.GeometryConversion)

doc = DocumentManager.Instance.CurrentDBDocument

#Input should be the elements and not the element id's

#Use the ifinstance() built in python function to check if the input is a list or a single object. 
#This is a common way to solidify the code incase inputs can be either a list of items or a single item:

#Read more here: https://docs.python.org/2/library/functions.html#isinstance

#if its a list object, iterate through it, and unwrap the elements.
if isinstance(IN[0], list): 
	panels = [UnwrapElement(i) for i in IN[0]]

#if its a single item, it will be unwrapped in a list with a single item	
else:
	panels = [UnwrapElement(IN[0])]

#Create an empty list to hold the output
output = []

#Iterate through the list with a for loop
for i in panels:
	TransactionManager.Instance.EnsureInTransaction(doc) #We're making changes to the document, thus a transaction is needed
		
	output.append(Electrical.PanelScheduleView.CreateInstanceView(doc, i.Id).ToDSType(False)) 
	#The create method used takes the document and an element ID as inputs. 
	#So we're iterating through each panel and call the Id property of the family instance by using dot notation.
	#Use the .ToDSType(False) as we're creating new non-Revit owned elements
	
	#See here for family instance properties http://www.revitapidocs.com/2018.1/9235095b-b7ae-b6e5-6cc2-2b8d397644de.htm
	#See here for Dynamo python migration https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration#revitapi
		
	TransactionManager.Instance.TransactionTaskDone()
	
#Assign your output to the OUT variable.
OUT = output 

Personally, I’d always use the actual element as input, and the call the ID from inside the code, but it can ofcause also be set up with the element ID as input.

Hope it helps :slight_smile:

1 Like

You need to be careful here. You are still inputting a list of a single item. You can see in your output that you have a List of a single item (at index 0) and that you have two levels available, not just one. There is definitely a difference between a singleton and a list containing only one item.
image

So this script definitely works.

Just curious though, did you know that Revit has built-in functionality to do this? Use the PS keyboard shortcut.

2 Likes

@stedel, thank you! I’ve been working and supporting Revit for almost 10 years now…I never knew about the PS shortcut. And here I was preparing to get into Dynamo to solve the issue.