Get and Set Background-opened Family Parameter values

Hi Everyone,
I’m wanting to get the values of specified parameters within RFA background-opened in a chosen library location, and if they have no value then input a value based on an excel list.

So far I am able to retrieve all RFA with their paths, and background-open them. Now I am stuck at python in trying to get the FamilyParameter values. I’m sure I’m missing something really obvious but I’m stuck.

Here’s my python:

# Retrieve family parameters and selected values
import clr
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

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

docs = IN[0]
param_list = []
param_values = []

for doc in docs:
	uiapp = DocumentManager.Instance.CurrentUIApplication
	familydoc = uiapp.Application.OpenDocumentFile(doc)
	params = familydoc.FamilyManager.GetParameters()
	names = [p.Definition.Name for p in params]
	param_list.append(names)
	
	for p in params:
		if p.Definition.Name == 'Assembly Code':
			#I need help here in retrieving FamilyParameter value
			value = p.???
			param_values.append(value)

OUT = param_list,param_values

Hey,

If you’re happy with a node solution, Orchid has those? The installer is on Github…

Cheers,

Mark

@Mark.Ackerley thank you for the suggestion! I did look into those. However my challenge is in the distribution of this once it’s done. Long story short, I can’t ask all users to install Orchid packages to use this.

1 Like

Ok so since the parameter values are held within family types, I had to figure out how to get at the values once we got into the types. Here is the code for extracting the values. In another node, I will be comparing these values to those from the owner’s standards. I’ll post that second node once that’s ready. Meanwhile, here’s the “get” code for anyone who needs it:

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

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

docs = IN[0]
param_list = []
param_values = []
cats = []
familytypecount = []

for doc in docs:
	#setup familydoc files
	uiapp = DocumentManager.Instance.CurrentUIApplication
	familydoc = uiapp.Application.OpenDocumentFile(doc)
	params = familydoc.FamilyManager.GetParameters()
	ps = familydoc.FamilyManager.get_Parameter(IN[1])
	types = familydoc.FamilyManager.Types
	famMan = familydoc.FamilyManager
	
	#parameters, categories from family files
	names = [p.Definition.Name for p in params]
	param_list.append(names)
	cats.append(familydoc.OwnerFamily.FamilyCategory.Name)
	
	#FAMILY TYPES
	#add "Default" type in families with no types
	familytypecount.append(types.Size)
	if familytypecount < 1:
		TransactionManager.Instance.EnsureInTransaction(familydoc)
		new_fam=famMan.NewType('Default')
		TransactionManager.Instance.ForceCloseTransaction()
	#get Assembly Code from types
	TransactionManager.Instance.EnsureInTransaction(familydoc)
	familyTypesItor = famMan.Types.ForwardIterator()
	familyTypesItor.Reset()
	while (familyTypesItor.MoveNext()):
		#get current value
		familyParam = famMan.get_Parameter(IN[1])
		familyType = familyTypesItor.Current
		param_values.append(familyType.AsString(familyParam))
	TransactionManager.Instance.ForceCloseTransaction()

#output
OUT = cats,param_list,familytypecount,param_values
5 Likes

Great work :slight_smile:

1 Like

What is your IN[1]?

IN[1] is the specific parameter I want to extract current values from. In my case, Assembly Code.

This could be adjusted to grab a list of parameters, or even all parameters from each family.

Thanks Aaron. Very usefull for QTO.
Did you get the other node?

@sergio_ramirezr the scope of my script was changed somewhat by my client. The end result will be similar but with more variables. I’ll post the full script once it’s ready for you.

@Aaron_Wagner This is an old thread but I wanted to check if you had finished the script for updating the parameter values. I am actually trying to do the same thing, updating assembly codes in multiple families without having to open them actively. The values are changing straight from one list to another, so I just have to do direct correlation.

@matthewsalazar below is the code I ended up with. Here are the inputs using data retrieved earlier in the script:
IN[0] = family file
IN[1] = Type Name
IN[2] = Input Parameter Current Value
IN[3] = Assembly Code

Let me know if you need more of the input process too.

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

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

docs = IN[0]
typs = IN[1]
vals = IN[2]

uiapp = DocumentManager.Instance.CurrentUIApplication

for n,doc in enumerate(docs):
	familydoc = uiapp.Application.OpenDocumentFile(doc)
	famMan = familydoc.FamilyManager
	inp = famMan.get_Parameter(IN[3])
	
	#go to matching type
	familyTypesItor = famMan.Types.ForwardIterator()
	familyTypesItor.Reset()
	while (familyTypesItor.MoveNext()):
		familyType = familyTypesItor.Current
		if familyType.Name == typs[n]:
			tc = Transaction(familydoc,"setnow")
			tc.Start()
			famMan.CurrentType = familyType
			tc.Commit()
			tc.Dispose()
			
			ts = Transaction(familydoc,"setnow")
			ts.Start()
			famMan.Set(inp,vals[n])
			ts.Commit()
			ts.Dispose()
	familydoc.Close()

#output all data for error report
OUT = IN[4]

@matthewsalazar I have an entirely different one for opening families loaded in a project, applying the changes and reloading. The one above goes through an entire selected library of RFA and makes the changes.

@Aaron_Wagner Thanks! I was actually able to figure out how to do what I need using the Orchid package. Might play around with the code at some point just to see if I can get it to work as well.