Copy Family and Type names to text parameters for all instances

Copy Family and Type names to text parameters for all instances

danail.momchilov
Contributor Contributor
2,214 Views
8 Replies
Message 1 of 9

Copy Family and Type names to text parameters for all instances

danail.momchilov
Contributor
Contributor

Hi, guys! First of all, let me start with the fact that I am new to writing code in Python and working with the Revit API. In this case, I tried to create a code that takes the strings from family and type names for all family instances of certain categories and then copies them to text shared text parameters, that can be used in schedules. I am using the Revit Python shell to run the script. As you will see, I have divided the code in two sections - the second one is for the system family categories, like walls, floors, roofs, etc, that only need Type names to bo transfered, while the first is for all other categories, that need both family and type name transfered. The problem is the it all seems to work fine, but for some of the categories it simply does not give results. For instance, I do not realise why it works for walls, but not for floors, and it also does work for ceilings and not for roofs, etc. Could you please help me find what the problem is? Thanks in advance! Here is the code(also available as attatchment):


__title__= 'FamilyName\nTypeName'
__doc__= 'Transfers family name and Type name into shared parameters\n that can be used in schedules.'
__author__= 'Dani & Bimo'

# Import from Autodesk API
from Autodesk.Revit.DB import FilteredElementCollector, BuiltInCategory

doc = __revit__.ActiveUIDocument.Document

element_collector = FilteredElementCollector(doc).WhereElementIsNotElementType()
element_filter = ElementCategoryFilter(BuiltInCategory.OST_PlumbingFixtures.OST_Casework.OST_Columns.OST_Windows.OST_Furniture)
category = element_collector.WherePasses(element_filter).ToElements()

t = Transaction(doc, "Update Family/Type Name")

t.Start()

for instance in category:
TypeName = instance.Name
TypeNameDuplicate = instance.LookupParameter('TypeNameDuplicate')
if TypeNameDuplicate:
TypeNameDuplicate.Set(TypeName)

for i in category:
type_id = i.GetTypeId()
element_type = doc.GetElement(type_id)
family = element_type.Family
name = family.Name
FamilyNameDuplicate = i.LookupParameter('FamilyNameDuplicate')
if FamilyNameDuplicate:
FamilyNameDuplicate.Set(name)

t.Commit()

system_collector = FilteredElementCollector(doc).WhereElementIsNotElementType()
system_filter = ElementCategoryFilter(BuiltInCategory.OST_Walls.OST_Ceilings.OST_Curtain_Systems.OST_CurtainWallMullions.OST_Floors.OST_ModelText.OST_Railings.OST_Roofs.OST_Stairs)
system_category = system_collector.WherePasses(system_filter).ToElements()

t.Start()

for system_instance in system_category:
SystemTypeName = system_instance.Name
TypeNameDuplicate = system_instance.LookupParameter('TypeNameDuplicate')
if TypeNameDuplicate:
TypeNameDuplicate.Set(SystemTypeName)

t.Commit()



0 Likes
Accepted solutions (1)
2,215 Views
8 Replies
Replies (8)
Message 2 of 9

jeremytammik
Autodesk
Autodesk

Welcome to the Revit API!

 

I cannot imagine that the following returns a valid built-in category enumeration value:

  

BuiltInCategory.OST_Walls.OST_Ceilings.OST_Curtain_Systems.OST_CurtainWallMullions.OST_Floors.OST_ModelText.OST_Railings.OST_Roofs.OST_Stairs

  

I would certainly expect that to cause a problem.

 

You probably need to create a logical OR filter combining individual built-in category filters for each one of those enumeration values.

 

Here are two samples showing how to do so in C#:

 

http://thebuildingcoder.typepad.com/blog/2010/06/retrieve-mep-elements-and-connectors.html

http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html

 

 

 

 



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

Message 3 of 9

danail.momchilov
Contributor
Contributor

Hi, Jeremy! And thank you for your answer. Unfortunattely, that is not the cause of the problem, as in Python, that is a valid syntax. I have already tried collecting the problematic categories separately, like floors and roofs for example and the result is still the same. It is still curious that if I try to print their Type Names, the correct result is shown! It just seems the fail to override the value. I am mostly interested in Roofs and Floors, as those are the categories it will be used for most of the time (along with walls and ceilings, that already work). 

0 Likes
Message 4 of 9

H.echeva
Advocate
Advocate

Hello,

 

As Jeremy pointed out that filter syntax is strange and if it works in Python I wish it worked in C#!

 

Did you check that the shared parameter is properly assigned to all the categories that you want in Revit?

I know it is silly, but sometimes the problem is the silliest thing.

 

Regards

Message 5 of 9

danail.momchilov
Contributor
Contributor

Hi,

 

unfortunattely, that is not the case. And I wish it would have been! As you know, Python has a much more simplified syntax than C#, which makes it possible to do things like that. I will still try to collect the family instances differently, to see if that might still be the cause. I could upload the test file if you are interested, but you will still need the Revit Python Shell to run the code.

 

Regards

0 Likes
Message 6 of 9

jeremytammik
Autodesk
Autodesk

Wow, I was unaware of that Python syntax feature. Very cool. Does it create an OR combination of the listed values? I searched for "python enum concatenation" and found no explanation of this feature.

 

In general, resolving questions like this is a very simple matter of installing RevitLookup, selecting the elements you are interested in, determining their characteristic properties, e.g., category, .NET classname, etc., and putting together the appropriate filter for them.

 

In a case such as yours, I would suggest implementing separate filters first for floors and roofs, and then using a logical OR filter to combine them with the other filters that already work as expected.

 



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

Message 7 of 9

jeremytammik
Autodesk
Autodesk

I believe you are completely misunderstanding the enum syntax that you are using, and it is not doing what you expect.

 

What do you in fact expect?

 

For me, it just returns the last enum value and ignores all the previous ones:

 

$ python3
Python 3.7.4 (v3.7.4:e09359112e, Jul  8 2019, 14:54:52)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from enum import Enum
>>>
>>> class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
...
>>> print (Color.RED.GREEN.BLUE)
Color.BLUE

  

 



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

Message 8 of 9

danail.momchilov
Contributor
Contributor

I believe you are right actually. I just tried to sort only floors and roofs in a separate script and it worked. I really think I tried that and it did not give the correct result but maybe I was missing something else. Now I feel stupid for saying I was sure that is not the problem...... but like I said, I am quite a newbie. So thanks anyway, I just sorted it the right way and it all worked fine. I seem to have overestimated how intuitive python actually is 🙂

0 Likes
Message 9 of 9

danail.momchilov
Contributor
Contributor
Accepted solution

Actually the true solution is simply using  'ElementMulticategoryFilter' . That's all:

 

cat_list = [BuiltInCategory.OST_Rooms, BuiltInCategory.OST_Walls, BuiltInCategory.OST_Windows, BuiltInCategory.OST_Doors]
typed_list = List[BuiltInCategory](cat_list)
filter = ElementMulticategoryFilter(typed_list)
output = FilteredElementCollector(doc).WherePasses(filter).ToElements()