Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Selecting objects with Python

17 REPLIES 17
SOLVED
Reply
Message 1 of 18
Kevin.Bell
13718 Views, 17 Replies

Selecting objects with Python

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.

17 REPLIES 17
Message 2 of 18
jeremytammik
in reply to: Kevin.Bell

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



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 18
Kevin.Bell
in reply to: jeremytammik

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?

Message 4 of 18
jeremytammik
in reply to: Kevin.Bell

Thank!

 

Yup, helps.

 

I forwarded this to the Dynamo development team for help.

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 5 of 18
Kevin.Bell
in reply to: jeremytammik

Excellent, thanks.

Message 6 of 18
stever66
in reply to: Kevin.Bell

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.")

Message 7 of 18
thomas
in reply to: Kevin.Bell

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.

 

HighlightModelElement.gif

Message 8 of 18
Kevin.Bell
in reply to: thomas

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.

Message 9 of 18
BobbyC.Jones
in reply to: Kevin.Bell

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.

 

 

 

 

--
Bobby C. Jones
Message 10 of 18
Kevin.Bell
in reply to: BobbyC.Jones

Thanks Bobby!

Message 11 of 18
fverwoert
in reply to: Kevin.Bell

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

Message 12 of 18
paolomod3nese
in reply to: thomas

Thanks for this explanation Thomas!

ps. you might want to change point 1 in your explanation to make the word Collection plural.

 

Cheers!

Paolo

Message 13 of 18

Hello i am currently having problem selecting multiple elements using python. Could you please help me with a code

Message 14 of 18
CWagnerLYWJP
in reply to: Kevin.Bell

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. 

Message 15 of 18
Kevin.Bell
in reply to: Kevin.Bell

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!

Message 16 of 18
CWagnerLYWJP
in reply to: Kevin.Bell

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.

 

CWagnerLYWJP_0-1684182941349.png

 

Message 17 of 18
Kevin.Bell
in reply to: Kevin.Bell

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!

Message 18 of 18
CWagnerLYWJP
in reply to: Kevin.Bell

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.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community