Dynamo Revit - Python block to make a selection of elements with a specific parameter value

Hi everyone!

I’m simply trying to create a list of elements that have the same value of a given parameter (i.e. the “SOFiSTiK_Assignment” parameter).

I was able with the LookupParameter method to get the parameter values of all the elements in a certain category (structural rebar); but when I add the “if” condition to create the list of elements that have the parameter value equal to “101-1”, the Python block returns an empty list.

How can I create the list of elements (rebars) with the specific parameter value (“101-1” ) of “SOFiSTiK_Assignment”?

I attach the script and the project file (Revit 2020, from my Google drive)… thanks!

Link to the project: 20210307_Tolleranze-lunghezza-ferri.rvt - Google Drive

20210315_Tolleranze-lunghezza-ferri_V0.dyn (8.6 KB)

Hi @edepanicis,

Try this:

Best regards.

Now that I’m reflecting on my code, I realize that I probably made a conceptual error: with the line

if value == sofistikAssignment:

I am running a list (“value”) against a single String. I am providing a similar simpler example of what I want to get asap. Thank you for your help tho!

1 Like

I would do something like this:

value = parameter.AsString()
values.append(value)

if value == IN[1]:
    rebars.append(element)
1 Like

I made another script with a similar purpose: to create a list of rebars with the same value of the parameter “Mark”.

I made another “for” loop which should compare each value of the list “value” (list of the parameter values) against the String “mark”. If the test succeeds, the loop should then append the element with the same index to the list “rebars”.

I don’t know how to make that last loop working tho… How do I tell python that I want the element with the same index of the corresponding value’s index? Anyway I will keep trying, suggestions are welcome! Here’s the code:

#Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

clr.AddReference("RevitApi")
from Autodesk.Revit.DB import *

clr.AddReference("RevitServices")
import RevitServices
from RevitServices import *
from RevitServices.Transactions import TransactionManager as TM
from RevitServices.Persistence import DocumentManager

doc = DocumentManager.Instance.CurrentDBDocument
TM.Instance.EnsureInTransaction(doc)

allRebars = IN[0]
mark = [1]

elements = UnwrapElement(allRebars)

rebars = []
name = []
value = []

#fa il get del valore del parametro "SOFiSTiK_Assignment" per ogni istanza di rebars
for element in elements:

	parametro = element.LookupParameter("Mark")
	name.append(parametro.Definition.Name)
	value.append(parametro.AsString())
	
#se è uguale al valore dell'IN[1],crea la lista di rebar con quel sofistik Assignment
for val in value:
	if val == mark:
		
		rebars.append(elements)

TM.Instance.TransactionTaskDone()

OUT = name, value, parametro, rebars

thank you, trying this rn!

You re getting 4 lists as outputs, but ONLY filtering the rebar list. Is that what you want or do you just want the outputs for each list that are in the rebar list with matching parameter value?

Actually I just want a list of rebars whose parameter value (of a certain parameter) matches a specific value. The other outputs are just a test to control what I was doing :sweat_smile:

1 Like

Will you want the “values” to ever be a list of inputs as well? Say 101-1, 101-3, and 101-5, or do you only want a single value?

For the specific purpose of the script I have in mind, just a single value is enough, for now!

Try this. It just puts everything into a single loop and should get you rebar with your value. It only needs the value as an input it get all rebar internally.

rebars = []
#Do some action in a Transaction
TransactionManager.Instance.EnsureInTransaction(doc)

for rebar in FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rebar).WhereElementIsNotElementType().ToElements():
	if rebar.LookupParameter("SOFiSTiK_Assignment").AsString() == IN[0]:
		rebars.append(rebar)

TransactionManager.Instance.TransactionTaskDone()

OUT = rebars

I don’t have rebar in my project, here is what it would look like in the graph.
image

1 Like

…It works! Now I have to understand why :rofl:
Thank you very much!

1 Like

Could you just briefly explain the

FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Rebar).WhereElementIsNotElementType().ToElements()

bit to me? I know about the collectors but the rest is pretty obscure to me… thanks!

Anyway, I tried changing the script in a way more similar to the original one, and I realized the error was in the if condition… Of course your syntax is way more efficient!

1 Like

Sure thing.

  1. FilteredElementCollector(doc) - Using the indicated (current) document / model to get a collection of elements

  2. .OfCategory(BuiltInCategory.OST_Rebar) - This filters the collector to only get things that are of category Rebar. Essentially this is what takes care of the other two nodes you had in the graph.

  3. WhereElementIsNotElementType() - Another filter to make sure you are collecting only instances and not any Rebar Types. The “All Elements of Category” nodes does this internally as well

  4. ToElements() - This just returns all of the elements that pass those filters as Revit Elements. This is what we are using the “for rebar in” loop on

  5. if rebar.LookupParameter(“Mark”).AsString() == IN[0]: - This is just combining what you were already doing over several lines. Gets the parameter values as a string, then compares it to the input. If the input matches it adds it to the rebar list.

1 Like

It’s all clear. Thank you again for the complete explanation!

1 Like

hi, I have similar situation but mine is shared parameter. It is getting tricky. Can you show how it will be for shared parameters.

Also, if I take elements internally with collector, can I take or concatenate two types of categories, like Speciality Equipment and Sprinklers etc ?

outList = [ ]
#familyType = []

for i in UnwrapElement(elements):
    for j in i.Parameters:
        if j.IsShared and j.Definition.Name == 'Item Number':
            parameterValue = i.get_Parameter(j.GUID)
            outList.append(parameterValue.AsString())

OUT = outList

Unless you have multiple parameters (shared and non) with the same name, there really isn’t a reason to do it any differently. Just use this:

i.LookupParameter("Item Number").AsString()

getting this error,

Yes, that is my bad. It should be looked up on the element “i” not the parameter “j”.

i.LookupParameter("Item Number").AsString()