Hi,
I'm looking to create a python script which will select objects based on their parameter values, the objects will then be the highlighted active selection in the Revit UI for the user to do something with.
To start this off, I'm writing a basic script to select an object. I'm writing this as a Python script within Dynamo.
So in Dynamo I use the 'Select Model Element' node which returns an object, I'm now trying to select that object in python using:
selob = Selection.SetElementIds(selobject.Id)
But when I run the script I get the error:
TypeError SetElementIds() takes exactly 2 arguements (1 given).
But looking at the API documentation for the Selection Class, the SetElementsIds method only appears to require one arguement.
http://www.revitapidocs.com/2015/cf8c11bb-f0c7-6d50-cbdf-41d0a010d9d6.htm
Am I missing something?
Thanks.
Solved! Go to Solution.
Solved by BobbyC.Jones. Go to Solution.
Solved by thomas. Go to Solution.
I cannot answer all aspects of your question, but I can address two:
1. Why does your error message include a typo? It says "arguements"... I find that hard to believe.
2. You are passing in a single element id. The SetElementsIds method argument is a generic list of element ids, List<ElementId>. To pass in a single id, you can create an empty list, add the id to it, and pass in that.
Unfortunately I cannot say why the error message mentions two arguments... that may be a Python-specific quirk.
Do you want to start by trying to pass in the list instead of the single id on its own?
Cheers,
Jeremy
Thanks for your response.
I amended the code to add a list:
import clr import System clr.AddReference('ProtoGeometry') from Autodesk.DesignScript.Geometry import * clr.AddReference('RevitAPI') import Autodesk from Autodesk.Revit.DB import * clr.AddReference('RevitAPIUI') from Autodesk.Revit.UI.Selection import * clr.AddReference('RevitNodes') import Revit clr.ImportExtensions(Revit.GeometryConversion) clr.ImportExtensions(Revit.Elements) clr.AddReference('RevitServices') import RevitServices from RevitServices.Persistence import DocumentManager import sys pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib' sys.path.append(pyt_path) doc = DocumentManager.Instance.CurrentDBDocument uiapp = DocumentManager.Instance.CurrentUIApplication app = uiapp.Application adoc = doc.ActiveView uidoc = uiapp.ActiveUIDocument #The inputs to this node will be stored as a list in the IN variables. dataEnteringNode = IN selobject = UnwrapElement(IN[0]) # Object to select sellist = [] sellist.append(selobject.Id) selob = Selection.SetElementIds(sellist) #Assign your output to the OUT variable. OUT = [selob]
But get the same error: (I've copied and pasted this from the error window)
Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File "<string>", line 39, in <module>
TypeError: SetElementIds() takes exactly 2 arguments (1 given)
Don't know if thats any help?
Thank!
Yup, helps.
I forwarded this to the Dynamo development team for help.
Cheers,
Jeremy
Give something like this a try:
uidoc = self.ActiveUIDocument
doc = self.ActiveUIDocument.Document
app = self.Application
# Select some elements in Revit before invoking this command
# Get the element selection of current document.
selectedIds = uidoc.Selection.GetElementIds()
if 0 == selectedIds.Count:
TaskDialog.Show("Revit","You haven't selected any elements.")
else:
TaskDialog.Show("Revit","Elements Selected.")
The exception you're getting is caused by calling a method on an invalid object.
To get your code working you need to do the following:
1. Import the System.Collection.Generic library
2. Create a ElementId List object and add the element id's to it - in IronPython the syntax is List[class]()
3. Get the active UI document then pass the ElementId list to the SetElementIds method
Here's a working example:
import clr clr.AddReference("RevitNodes") import Revit clr.ImportExtensions(Revit.Elements) clr.AddReference("RevitServices") import RevitServices from RevitServices.Persistence import DocumentManager from System.Collections.Generic import * # Import RevitAPI clr.AddReference("RevitAPI") import Autodesk from Autodesk.Revit.DB import * doc = DocumentManager.Instance.CurrentDBDocument uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument element = UnwrapElement(IN[0]) elementIdList = List[ElementId]() elementIdList.Add(element.Id) sel = uidoc.Selection.SetElementIds(elementIdList)
Also, you should post these questions on the Dynamo.org forum as you would get a quicker response.
MD - Briliant thanks!
I see the problem was the use of an 'ICollection', I've not come across one of those before.
Whats the difference between an ICollection and a list?
Cheers.
An ICollection is an interface that defines a small set of properties and methods that are useful for manipulating a collection of objects: Count, Add(), Remove(), Clear(), etc...
A .net List is a class that contains a list of objects. It implements the ICollection interface, as well as a couple of others.
I'm not familiar with python so I'm not sure what .net type, nor the interfaces it implements, this translates too:
sellist = []
But in thomas's example
elementIdList = List[ElementId]()
elmentIdList.Add(element.Id)
a new List object for holding ElementId's is instantiated and an ElementId is added to it. Since the List object implements ICollection, it can be passed as an argument to the Selection.SetElementsIDs() method since it expects an ICollection as its argument.
I tried this method and it works for me when i select a single element in revit, but i would like to select multiple elements instead...
Is that possible or the script doesn't work for multiple selection?
I thought it should because you make a list and just add all the id's to the list and it will select them all.
Kind Regards,
F Verwoert
Thanks for this explanation Thomas!
ps. you might want to change point 1 in your explanation to make the word Collection plural.
Cheers!
Paolo
Hello i am currently having problem selecting multiple elements using python. Could you please help me with a code
Related to selection objects using python:
I want to use python using a hotkey in revit to take my active selection (probably grab the x,y?) and move it to a point that I select in a viewport,. such as another object.
It really depends on how your running the Python code... if its in Dynamo, then you could use Dynamo player to do this... or you could try PyRevit (I've not used that) perhaps create a command, I'd suggest that C# would be the best method (if you know how to use that) as it would be easy to create a command.
Not sure you can assign a hot key in Dynamo player though, but in c# or PyRevit you can use the keyboard shortcuts to run your command.
Upon running, it would grab the current selection (using uidoc.Selection.GetElementIds() as per the above posts), then use ElementTransformUtils to move the elements to a new location.
https://www.revitapidocs.com/2015/3cf8c9dc-f4d1-12f0-d7a9-e126331cd858.htm
Hope thats of use!
Thanks for the suggestions.
I've decided to just start with grabbing the info or rather recognizing what elements I have selected when I run the graph in Dynamo.
Figured to start with the starting point haha
For whatever reason, Dynamo doesn't actually run the graph again or rather it doesnt refresh the data when I rerun it.
I get the list of elements I had selected when the graph was ran, but when I select something else or even simply have nothing selected, the output doesn't change.
I even added a random number generator just to see if it generates a new number when the graph is ran again and in fact it doesn't!
Here is my starting point. (Works but the output doesn't change when ran again.)
...btw I used chatGPT to generate the code haha.
The reason that you can't rerun the graph is that Dynamo doesn't bother to run if nothing has changed... I've had this problem in the past...
The simplest way I managed to 'fix' the issue was to add a bool to the graph, it doesn't have to do anything, but by changing it Dynamo will rerun.
On the Python Script node, click the plus button to add a new input (you won't need to change your code as it doesn't have to do anything), add a Bool (i.e. True / False selector) to that. That should work, but you'll have to change the True / False each time...
Looking at the code, PRINT wont work as there is no where to print to...
Try this:
Before the for element in selected_Elements bit create a blank list called, say, results:
results = []
then change the PRINT statement to add the output to the results list:
results.append("Element ID" + element_id)
results.append("Element Name" + element_name)
Then add the results list to output, replace OUT = selected_elements with
OUT = results
Best of luck!
Yea the code needs to be cleaned up for sure.
What I want to do is use the Dynamo Player. The graph/code works now as is but again it can't be reran because Dynamo doesn't notice any changes.
Can't find what you're looking for? Ask the community or share your knowledge.