Place Assembly in Multiple Rooms at Once

I made a python script to place an assembly into a selected room, but I am getting stuck trying to place the same assembly in multiple rooms at once. I know I need to make with work for a list, but not sure how to do that correctly. Any help would be great! Also, if there is any cleanup or better way to write this script, let me know. I am new to python code and basically pieced this together based on error messages and looking at other scripts.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements
from Revit.Elements import *

# Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

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

import System

#The inputs to this node will be stored as a list in the IN variables.
e = IN[0] #Assembly
r = IN[1] #Rooms
t = IN[2] #AssemblyTypes

#The main code is here.
element = UnwrapElement(e)
type = UnwrapElement(t)

doc = DocumentManager.Instance.CurrentDBDocument
id = type.Id
eloc = e.GetLocation()
rloc = r.GetLocation()
x = rloc.X
y = rloc.Y
z = rloc.Z + eloc.Z
xyz = XYZ(x,y,z)

TransactionManager.Instance.EnsureInTransaction(doc)
new = element.PlaceInstance(doc,id,xyz)
TransactionManager.Instance.TransactionTaskDone()

#Assign your output to the OUT variable.
OUT =  new

Welcome to the forums.

Always try searching for similar topics before posting a new one. There may not be one doing exactly what you’re doing, but there are plenty of existing threads in this case that answer how to loop through a list in python.

Thank you for the welcome. I have read a few other posts about this and tried implementing them to no avail. I don’t know if I have to loop the list in one spot, or multiple spots, or create a function and then loop that, or if it is something completely different. I figured a new post would be helpful for anyone else looking to specifically place assemblies because I could not find a post that had a working script to place an assembly instance already.

What have you tried then? I’m not seeing any looping in your code. Does a single assembly in a single room work? Is the issue that you can’t place an assembly at all or that you can’t place more than one?

I shared the code that worked for one assembly to one room. I have tried placing the “loop” in multiple places in the script and kept getting errors. I tried to define a function and got errors too. My hope is to be able to either place one assembly in multiple rooms, or place multiple assemblies in one room. So I am guessing there is a way to set up the “loops” so that it could do either or both, I just have no idea what the next step is. Any help would be greatly appreciated!

The easiest solution is to use a for loop. This will iterate through each item in a list. When dealing with multiple outputs (assemblies per room) you need to also create an output list to append each individual output to.

Try searching the forums for those things and give it another try. Let us know if you run into any issues.

I was able to get it to place multiple assemblies in multiple rooms.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

# Import RevitNodes
clr.AddReference("RevitNodes")
import Revit

# Import Revit elements
from Revit.Elements import *

# Import DocumentManager
clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

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

import System

#The inputs to this node will be stored as a list in the IN variables.
e = IN[0] #Assembly Instance
r = IN[2] #Rooms
t = IN[1] #AssemblyTypes

#The main code is here.
doc = DocumentManager.Instance.CurrentDBDocument
idlist = []
elist = []
rlist = []

#Assembly Type Elements
if isinstance(t, list):
	for a in t:
		type = UnwrapElement(a)
		for ty in type:
			id = ty.Id
		idlist.append(id)
else:
	type = UnwrapElement(t)
	id = type.Id
	idlist.append(id)

#Assembly Instance Locations, Mainly used to add Z value to placement position.
if isinstance(e, list):
	for b in e:
		eloc = b.GetLocation()
		elist.append(eloc)
else:
	eloc = e.GetLocation()
	elist.append(eloc)

if isinstance(r, list):
	for c in r:
		rloc = c.GetLocation()
		x = rloc.X
		y = rloc.Y
		z = rloc.Z + (eloc.Z - rloc.Z)
		xyz = XYZ(x,y,z)
		rlist.append(xyz)
else:
	rloc = r.GetLocation()
	x = rloc.X
	y = rloc.Y
	z = rloc.Z + (eloc.Z - rloc.Z)
	xyz = XYZ(x,y,z)
	rlist.append(xyz)	

output = []

TransactionManager.Instance.EnsureInTransaction(doc)
for p in rlist:
	for q in idlist:
		new = AssemblyInstance.PlaceInstance(doc,q,p)
	output.append(new)
TransactionManager.Instance.TransactionTaskDone()

#Assign your output to the OUT variable.
OUT = idlist, elist, rlist