Python Looping through different lengths list and setting parameters

Hi All,

I’m just trying to create a python script to change the checked by parameter on my sheets. I’ve managed to create a python script that changes all of the sheets but what I really want is just change some of sheets.

What I have is filteredelementcollecter to get all the sheets in the project then have a list of sheet numbers coming in to node that I want to change. The idea is to loop through all the sheets and if sheet number is the same change the checked by parameter. Please see Python scripts below.

I think by the warning it’s something to do with data types but I’m not sure where I’m going wrong. I’ve also have a sneaky suspicion that I might need to use a while loop with a counter since the list of drawings number aren’t the same.

Thank you

Version:0.9 StartHTML:00000097 EndHTML:00004624 StartFragment:00000199 EndFragment:00004586 import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
#The inputs to this node will be stored as a list in the IN variables.
dataEnteringNode = IN
import clr

#Import Revit Nodes
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)

# Import RevitAPI
clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import *

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

#Get the project document.
doc = DocumentManager.Instance.CurrentDBDocument

SheetNo=IN[0]
Checkby = IN[1]
NewCHK = []

#Filter for Sheets.
collector = FilteredElementCollector(doc)
Sheets = collector.OfCategory(BuiltInCategory.OST_Sheets).ToElements()
counter = len(Sheets)
TransactionManager.Instance.EnsureInTransaction(doc)

for sheet in (0,len(Sheets)):
Numbers = sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString()
if Numbers == SheetNo:
Checked = sheet.get_Parameter(BuiltInParameter.SHEET_CHECKED_BY).Set(Checkby)
NewCHK.append(Checked)
else:
continue
TransactionManager.Instance.TransactionTaskDone()

OUT = NewCHK
#Sheets, NoList, Checked,
#Assign your output to the OUT variable.

Your for loop is not actually going through all of your sheets.
Let’s say that your “Sheets” variable contains 10 sheets. The way you have your for loop currently structured is this:

for sheet in (0, len(Sheets))

This is equivalent to:

for sheet in (0, 10)

You probably meant to create a range like this:

for sheet in range(len(Sheets))

This would create a list of [0, 1, 2...9], however for sheet in (0, 10) only iterates a tuple which contains the two values 0 and 10. Therefore, you are not actually using the get_Parameter() method of your sheet, but rather using the same method on an integer, hence the AttributeError.

Do something like this:

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

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

doc = DocumentManager.Instance.CurrentDBDocument
collector = FilteredElementCollector(doc)
sheets = collector.OfCategory(BuiltInCategory.OST_Sheets).ToElements()
temp_out = []

TransactionManager.Instance.EnsureInTransaction(doc) # Only necessary if we are modifying the document
for sheet in sheets:
	nums = sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString()
	temp_out.append(nums)
TransactionManager.Instance.TransactionTaskDone()

OUT = temp_out

You may also want to make your sheet numbers strings before you bring them into the script, e.g. ["1002", "1003"]. This way, you can instead do a test like:

sheet_no = ["1002", "1003"]
sheet_current = "1003"
if sheet_current in sheet_no:
      # Set sheet as checked

You also don’t need the else: continue statement as the loop will continue to iterate regardless of its inclusion.

Thanks for your reply it makes sense but this method will just output a list of sheets, it won’t filter out the sheets coming in IN[0] also it’s not setting the new value for the checked by which I assume you would need to be put in a transaction as you are changing the document. Probably the best way would be to filter out the sheets before passing it through the loop.

Correct, the example I gave doesn’t do exactly what you’re trying to do, but it’s an example of how to structure the for loop. I don’t have a file on hand that I’d be able to modify i.e. set parameter values. Something like this would work with a little modification to tailor it to your own inputs, also assuming that doc is already defined and that the Revit API and other modules have been imported:

sheet_no_all = ["1002", "1003"]
checked_by = "XX"
sheets_checked = []
collector = FilteredElementCollector(doc)
sheets = collector.OfCategory(BuiltInCategory.OST_Sheets).ToElements()
for sheet in sheets:
    sheet_no_current = sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString()
    if sheet_no_current in sheet_no_all:
        sheet.get_Parameter(BuiltInParameter.SHEET_CHECKED_BY).Set(checked_by)
        sheets_checked.append(sheet)
OUT = sheets_checked

Thank you very much its solved. I assume if I were to do this method with another parameter that’s shared but not a built in parameter I can just remove “BuiltInParameter” and put in the name.

Thank you again

You can get parameters by many different means. Actually, Element.get_Parameter() has been deprecated for many years now in favor of other properties and methods. The first is the Element.Parameter property which accepts one of the following:

  • Guid
  • BuiltInParameter (which you are currently using)
  • Definition

You would have to replace the BuiltInParameter with the GUID of the shared parameter in order to use it in the same manner. However, there are two other methods which accept strings:
Element.LookupParameter(string) and Element.GetParameters(string). The Element.Parameter property is the most stable out of the 3 options as it will get the exact same parameter every time, regardless of the name. Element.LookupParameter() returns the first parameter found with the name you provide and Element.GetParameters() returns a list of parameters with names matching the one you provide.

2 Likes

Thank you for taking time out to explain this for me. It’s much appreciated.

1 Like