Associate family parameter in a family

#7

@awilliams,
Sorry for my belated response, but kudos! awesome script.

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

clr.AddReference('RevitNodes')

import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument

elem = UnwrapElement(IN[0])
paramNames = IN[1]
famNames = IN[2]

if not isinstance(paramNames, list):
	paramNames = [paramNames]
if not isinstance(famNames, list):
	famNames = [famNames]
famParams = doc.FamilyManager.Parameters
for e in elem:
	elemParams = e.Parameters
	
	elemAssoc = []
	famAssoc = []
	
	for param in elemParams:
		for name in paramNames:
			if param.Definition.Name == name:
				elemAssoc.append(param)
	
	for fparam in famParams:
		for fname in famNames:
			if fparam.Definition.Name == fname:
				famAssoc.append(fparam)
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	
	for i,j in zip(elemAssoc, famAssoc):
		doc.FamilyManager.AssociateElementParameterToFamilyParameter(i, j)
		
	TransactionManager.Instance.TransactionTaskDone()

OUT = elem

Now we can run this for multiple items.

No need to use the e.Elementtype at dynamo though …
works for me, but got an issue trying to assign family Description at the nested family instance ‘test’ parameter. Says parameter type not the same … both text, :sweat_smile:But this is a puzzle for me tomorrow. First dinner!

2 Likes

#8

Nice adjustment to work with lists :slight_smile: The e.ElementType portion was because I was associating type parameters in the test case but I used it for instance parameters with my actual use – are you certain that your test parameter is a type parameter? The OOTB Description parameter is a Type parameter - in Revit itself we can’t associate type parameters with instance parameters so that might be the cause of error?

0 Likes

#9

@awilliams, hmmmm perhaps it’s the other way around you say (or as how I understand it):

My family I’m editting (MyFamily)
has several nested (shared) families (MyNestedFamiliy).

So running the script allows me to acces

  • get familytypeparameter ‘mytypeparameter’. … let’s name it MyFamily.mytypeparameter
  • get familytypeparameter ‘Description’ … let’s name it MyFamily.Description

So running the script allows me to connect

  • MyFamily.mytypeparameter to MyNestedFamily.instanceparameter-a
  • MyFamily.Description to MyNestedFamily.instanceparameter-b

Currently mytypeparameter connecting to instanceparameter-a: awesome. np.
Description to instanceparameter-b … error. While doing this manually: np.

A nice puzzle and perhaps it has to do with assigning things to type parameters vs. instance parameters. I’ll dive into this one asap. :smiley:

0 Likes

#10

Knipsel

So:
IN[0] is a list of 200 ‘shared nested families’.
‘start_lagenmaat’ and ‘merk’ are both instance family parameters of those shared parameters.

0 Likes

#11

Oops, I was definitely confusing the instance/type parameter association conflict with formulas (the “Instance Parameters can’t be used in Type Parameter formulas” warning). That is awfully peculiar that your case is working one way but not the other. Maybe it is possible that it has something to do with Shared Parameters vs. Project Parameters? Do you mind sharing your RFAs so I can take a look?

0 Likes

#12

Oeh, I’m getting closer.

It has to do with the input as list. So setting connecting “Description” to “merk” solo: np.
part of a list as shown above: nope.

And sure, hang on let me get it.

0 Likes

#13

awilliams_dynamo.rfa (360 KB)

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

clr.AddReference('RevitNodes')

import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument

elem = UnwrapElement(IN[0])
paramNames = IN[1]
famNames = IN[2]

if not isinstance(paramNames, list):
	paramNames = [paramNames]
if not isinstance(famNames, list):
	famNames = [famNames]
famParams = doc.FamilyManager.Parameters
#tester =[]
for e in elem:
	elemParams = e.Parameters
	
	elemAssoc = []
	famAssoc = []
	
	for param in elemParams:
		for name in paramNames:
			if param.Definition.Name == name:
				elemAssoc.append(param)
	
	for fparam in famParams:
		#tester.append(fparam.Definition.Name)
		for fname in famNames:
			if fparam.Definition.Name == fname:
				famAssoc.append(fparam)
	
	TransactionManager.Instance.EnsureInTransaction(doc)
	for i,j in zip(elemAssoc, famAssoc):
		try:
			doc.FamilyManager.AssociateElementParameterToFamilyParameter(i, j)
			#doc.FamilyManager.CanElementParameterBeAssociated(i,j)		
			error_report = "No errors"
			
		except:
			error_report = "can't assign parameter"
	TransactionManager.Instance.TransactionTaskDone()
	

OUT = elem, error_report
0 Likes

#14

That is very strange :thinking: oddly enough, I just ran the script with your exact same set up, and it worked (unless I’m misunderstanding which condition is causing error for you). I’ll add that I don’t have Revit 2017 so had to upgrade your RFA to 2018.

0 Likes

#15

I don’t think R18 / R17 should be an issue for this non-complex-family.

I’m uploading a screencast … so you see what I’m doing / the result I’m getting …

Perhaps a memory issue? Or scripting limitation? It puzzles me for sure…
.http://autode.sk/2G2dNjf

0 Likes

#16

This is extremely puzzling, lol. I wouldn’t think the version difference would be an issue either but it is the only thing I did differently. I ran it again to double check that I hadn’t just overlooked some that weren’t associating, but it certainly associated all of them. I’m not sure what exactly would cause that – maybe try this below to see if any of the elements are in fact not returning parameters. Not sure if that will help us get anywhere with it though, but I’d imagine that must be what is happening?

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

clr.AddReference('RevitNodes')

import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument

elem = UnwrapElement(IN[0])
paramNames = IN[1]
famNames = IN[2]

if not isinstance(paramNames, list):
	paramNames = [paramNames]
if not isinstance(famNames, list):
	famNames = [famNames]
famParams = doc.FamilyManager.Parameters
#tester =[]
elemP = []
famP = []
for e in elem:
	elemParams = e.Parameters
	
	elemAssoc = []
	famAssoc = []
	
	for param in elemParams:
		for name in paramNames:
			if param.Definition.Name == name:
				elemAssoc.append(param.Definition.Name)
	
	for fparam in famParams:
		#tester.append(fparam.Definition.Name)
		for fname in famNames:
			if fparam.Definition.Name == fname:
				famAssoc.append(fparam.Definition.Name)
	elemP.append(elemAssoc)
	famP.append(famAssoc)

	

OUT = zip(elem,elemP,famP)
0 Likes

#17

oh my… your suggestion… look at the output.

the list order changes … sometimes …
look at [0][1] which has merk, start_lagenmaat which the script will try to pair this up with [0][2] start_lagenmaat, Description … well, that obvious won’t work.

My yesterday’s screencast show several elements not being assigned … well, now we know why. Next step, figuring out why python changes the order of the list.
I’m going to try a zip alternative … unsure if python libraries could cause this issue? (how to check this?)

Coding result parameter order … seems just fine.
TransactionManager.Instance.EnsureInTransaction(doc)
error_report.append(sorted(zip(elemAssoc, famAssoc)))
for pair in ((elemAssoc[c], famAssoc[c]) for c in xrange(min(len(elemAssoc), len(famAssoc)))):

		error_report.append(pair)
	#for i,j in sorted(zip(elemAssoc, famAssoc)):
	#	try:
			#doc.FamilyManager.AssociateElementParameterToFamilyParameter(pair[0], pair[1])
			#doc.FamilyManager.CanElementParameterBeAssociated(i,j)		
	#		error_report.append(pair)
			
	#	except:
	#		error_report.append("can't assign parameter")
	TransactionManager.Instance.TransactionTaskDone()

0 Likes

#18

I honestly have no idea what would cause instances of the same element types to return the parameters in a different order. Looking at the for loop for elemAssoc and famAssoc, I would assume it would return the parameters in the same order because of the input search names. And I’m not sure why it would be occurring for you, but not for me, with the same file, lol. In any case, would you try this script? It creates a dictionary for element and family parameters to create the elemAssoc and famAssoc lists, so they should return in the same order

0 Likes

Check if a families nested family has its parameters associated from a project environment
#19

@3Pinter sorry I just removed the Python script in my previous post because I tested it and it failed with your rfa; I’ve modified it and this here appears to be working!

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

clr.AddReference('RevitNodes')

import Revit
clr.ImportExtensions(Revit.GeometryConversion)
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument


elements = IN[0]
epSearch = IN[1]
fpSearch = IN[2]

if not isinstance(elements, list):
	elements = [elements]
if not isinstance(epSearch, list):
	epSearch = [epSearch]
if not isinstance(fpSearch, list):
	fpSearch = [fpSearch]

for e in elements:
	e = UnwrapElement(e)
	elemParams = e.Parameters

	epNames = []
	fpNames = []
	elemAssoc = []
	famAssoc = []
	
	for ep in elemParams:
		epNames.append(ep.Definition.Name)
		
	epDict = dict(zip(epNames,elemParams))
	elemAssoc = [epDict.get(ep, "none") for ep in epSearch]
	
	famParams = doc.FamilyManager.Parameters
	
	for fp in famParams:
		fpNames.append(fp.Definition.Name)
		
	fpDict = dict(zip(fpNames,famParams))
	famAssoc = [fpDict.get(fp,"none") for fp in fpSearch]
	

	TransactionManager.Instance.EnsureInTransaction(doc)
	
	for i,j in zip(elemAssoc,famAssoc):
		try:
			doc.FamilyManager.AssociateElementParameterToFamilyParameter(i, j)
			error_report = "No errors"
			
		except:
			error_report = "can't assign parameter"
	TransactionManager.Instance.TransactionTaskDone()


OUT = elements,error_report
7 Likes

Associate a list of family parameter in a family
#20

@awilliams, awesome! it works!

it still baffles me, was trying to sorted() all kinds of lists to order things but they were … etc.etc. Now, that dictionary-piece: impressive. I’ll have a look at it to understand what you did.

Again: awesome!

0 Likes

#21

Yeah this one was baffling, especially so because we experienced different results with the same file :thinking: I’m thinking it could be something related to this, but the github link in the post doesn’t work, so I’m not sure what exactly that issue was… I still would have thought the elemAssoc/famAssoc would have been built in the order of the input parameter names. :face_with_raised_eyebrow: I figured the dictionary method would avoid the parameters going out of that order, because the dictionary maps the parameter name to the parameter element.

Glad its finally working!

0 Likes

#22

Hello everybody,

I am new to dynamo programming and I do not know Python as well but I was trying to associate an element (generic model form) Material parameter with a Material parameter inside the Family Types dialog while in Family editor mode. I would like to use this script but I do not know how I could change it to make it work.
Could I get any help from you guys?

0 Likes

#23

I made it after some tries :slight_smile:
Is there a way also to use this to fill the data from the Family Types Parameters?

0 Likes

#24

I have a lot of nodes dealing with family document issues… try to see if you can use some of that

0 Likes

#25

Yes I found them and they have worked just fine. Thank you for your quick response, this forum is great.

0 Likes

#26

I want/need to take this one step further.

Best practice is when you make a family that you set the material to a parameter. So the material parameter is connected (with the grey box) to a instance or type material parameter so you can adjust the material of the extrusion in the parameter fields.

I am greating a window out of profiles and lines and assign a material to it… But i want to assign a parameter to that material slot.

Is this possible…
This is the family with the created window family in it…i want the parameter frame_material connected to the material parameter of that family…

the next step is to connect the frame_material parameter to the kozijn_material in the host family

kozijn_generator_joris.rfa (2.6 MB)

0 Likes