Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FilteredElementCollector for to get System families AND "normal" families

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
Dantevw1
14446 Views, 8 Replies

FilteredElementCollector for to get System families AND "normal" families

Is there some way to use the WherePasses for multiple types?

I want to get al user families and system families (walls/doors/beams) in 1 collector.

 

for example: 

FilteredElementCollector collector = new FilteredElementCollector(doc).OfClass(typeof(Family));

Only returns the user families, it does not seem to contain the walls/floors/ceilings/..

is there some way to add these types to the collector? or maybe select multiple classes for the filter? or even maybe merge multiple collectors into 1 for easy usage later on in the code ?

 

8 REPLIES 8
Message 2 of 9
matthew_taylor
in reply to: Dantevw1

Hi,

Consider using RevitLookup to investigate elements. You will see there that the type of a wall type is WallType, so it is reasonable that trying to get a 'Family' wouldn't return this.

.WhereElementIsElementType may be what you're after. It will get you all of the types (including familysymbols) though, not the family objects.

 

You either need to experiment to get what you want, or be specific about what you are trying to achieve. The options and optimisations are endless. 🙂

 

@jeremytammik has some great examples:
http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.9

http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.10

 

There are also some great examples in the SDK, which can be downloaded from here:

http://usa.autodesk.com/adsk/servlet/index?siteID=123112&id=2484975

 

Cheers,

 

-Matt

 

edit: p.s. Walls/Doors/Beams... Types, instances?


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 3 of 9
Dantevw1
in reply to: matthew_taylor

Some background info about what i try to achieve:

I have a list of family names: "myUserFamilyName" , "SomeName", "Basic Wall", and so on.

Based on these names, i want tot try to get a collection of all the instances in the project that are part of these user and/or system families.

 

So for the user families this code passes (though might not be optimal):

 

FilteredElementCollector collector = new FilteredElementCollector(doc).OfClass(typeof(Family));

//Get all the family names (user and system) from a listview
List<string> famNames = lvFamNames.Items.Cast<ListViewItem>().Select(x => x.Text).ToList();

//get a list of the families (these are not the family instances yet)
List<ElementId> familyTypeIdList = new List<ElementId>();
foreach (Family elFromCollect in collector)
{
  foreach (string famName in famNames)
  {
     if (elFromCollect.Name == famName)
     {
         foreach (ElementId elId in elFromCollect.GetFamilySymbolIds())
         {
             familyTypeIdList.Add(elId);
         }

     }
   }
}

This will give me a list of the family types, that then i can use to get all the instances.

But as mentioned, this only works for the user families.

 

Somehow i need to change it, so i will also get the system families, and then get the instances that match the name.

 

I was looking into the ElementMulticlassFilter just now, but for some reason it keeps throwing me exceptions, so might need to dive deeper into this one ^^

Message 4 of 9
matthew_taylor
in reply to: Dantevw1

Hi @Dantevw1,

'Basic Wall' is a wall 'Kind', not a family. You're probably best using a category filter.

 

Try something like this:

 

Dim catIdList As New List(Of DB.BuiltInCategory) From {DB.BuiltInCategory.OST_Walls, _
                                                               DB.BuiltInCategory.OST_Doors, _
                                                               DB.BuiltInCategory.OST_StructuralFraming}
'you'll need to tailor this bit to do what you want:
Dim elementIdsToMatch As ICollection(Of DB.ElementId) = New DB.FilteredElementCollector(doc) _
                                                    .WhereElementIsElementType _
                                                    .OfCategory(DB.BuiltInCategory.OST_Walls).ToElementIds
'you'll need to tailor this bit to do what you want:
Dim doorFamilySymbolIds As IEnumerable(Of DB.ElementId) = New DB.FilteredElementCollector(doc) _
                                                    .OfClass(GetType(DB.FamilySymbol)) _
                                                    .OfCategory(DB.BuiltInCategory.OST_Doors) _
                                                    .Cast(Of DB.FamilySymbol) _
                                                    .Where(Function(fs) fs.Family.Name.Equals("Doors_ExtDbl_Flush", StringComparison.InvariantCultureIgnoreCase)) _
                                                    .Select(Function(fs) fs.Id)

If doorFamilySymbolIds IsNot Nothing Then
            elementIdsToMatch = elementIdsToMatch.Union(doorFamilySymbolIds).ToList
End If


Dim categoryFilter As New DB.ElementMulticategoryFilter(catIdList)
Dim filter As IEnumerable(Of DB.Element) = New DB.FilteredElementCollector(doc) _
                                                    .WhereElementIsNotElementType _
                                                    .WherePasses(categoryFilter) _
                                                    .Where(Function(el) elementIdsToMatch.Contains(el.GetTypeId))

 

At this end, this produced all wall instances, and all door familyinstances whose family name matched my filter.

I'm sure there are ways to optimise it.

 

Cheers,

 

-Matt


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 5 of 9
jeremytammik
in reply to: Dantevw1

Dear Dante,

 

Thank you for your query.

 

If you are searching for instances, I would start off by saying so up front:

 

  collector
    .WhereElementIsNotElementType()
    .OfClass( typeof( FamilyInstance ) )

Instances of built-in families are not stored as FamilyInstance objects, but have theor own dedicated classes such as Wall, Floor, etc.

 

You can combine any number of filtered element collector filters using Boolean operation.

 

Here are two samples of using Boolean combination of (many) different filters to retrieve certain structural or MEP specific elements:

 

 

I hope this helps.

 

Best regards,

 

Jeremy



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

Message 6 of 9
jeremytammik
in reply to: Dantevw1

Message 7 of 9
maximas2000
in reply to: jeremytammik

here it is my function :

 

 

' variables :
'*************

' ---------------------------------------------------
Public  uiapp As UIApplication
Public app As Application
Public uidoc As UIDocument
Public doc As Document
Public sel As Selection
Public ActView As View
' ---------------------------------------------------



' Enums : '*********
Public Enum yr_enumFindIn inDoc inSelection inCurrentView inView End Enum Public Enum yr_enumCategory Beams Columns Foundations Floors Roofs Walls Doors Windows Rooms Stairs Dimensions Grids Levels End Enum ' GetRvtData ' ********** ' gets the essential data for revit before making a function ' 'GetRvtData(cmd) ' uiapp, app, uidoc, doc, sel, ActView Public Sub GetRvtData(cmd As ExternalCommandData) ' --------------------------------------------------- uiapp = cmd.Application app = uiapp.Application uidoc = cmd.Application.ActiveUIDocument doc = uidoc.Document sel = uidoc.Selection ActView = doc.ActiveView ' --------------------------------------------------- End Sub

Public Function CategoryNameOf(ElemCat As yr_enumCategory) As String
Dim catName As String Select Case ElemCat Case yr_enumCategory.Beams : catName = "Structural Framing" Case yr_enumCategory.Columns : catName = "Structural Columns" Case yr_enumCategory.Foundations : catName = "Structural Foundations" Case yr_enumCategory.Floors : catName = "Floors" Case yr_enumCategory.Roofs : catName = "Roofs" Case yr_enumCategory.Walls : catName = "Walls" Case yr_enumCategory.Doors : catName = "Doors" Case yr_enumCategory.Windows : catName = "Windows" Case yr_enumCategory.Rooms : catName = "Rooms" Case yr_enumCategory.Stairs : catName = "Stairs" Case yr_enumCategory.Dimensions : catName = "Dimensions" Case yr_enumCategory.Grids : catName = "Grids" Case yr_enumCategory.Levels : catName = "Levels" Case Else : catName = String.Empty End Select Return catName End Function
' FamiliesOfCategory (accepted but no result with walls)
' *******************
' find all families of a specified category (walls, doors, beams, columns, ....) as a list of string
Public Shared Function FamiliesOfCategory(cmd As ExternalCommandData, Cat As yr_enumCategory, FindIn As yr_enumFindIn, Optional ViewName As String = "") As List(Of Element) GetRvtData(cmd) ' uiapp, app, uidoc, doc, sel, ActView Dim fam As Family = Nothing Dim categ As Category = Nothing Dim FamList As List(Of Element) = New List(Of Element) Dim familyFilter As ElementClassFilter = New ElementClassFilter(GetType(Family)) Dim collector As FilteredElementCollector = New FilteredElementCollector(doc) Dim elems As ICollection(Of Element) = collector.OfClass(GetType(Family)).ToElements() For Each elem As Element In elems fam = TryCast(elem, Family) categ = fam.FamilyCategory If (categ IsNot Nothing) And (categ.Name.ToLower = CategoryNameOf(Cat).ToLower) Then FamList.Add(elem) End If Next Return FamList End Function

' Usage :

'Dim AllFamilies As List(Of Element) = yr.Find.FamiliesOfCategory(cmd, Walls, inDoc)
Dim AllFamilies As List(Of Element) = yr.Find.FamiliesOfCategory(cmd, Columns, inDoc)
'Dim AllFamilies As List(Of Element) = yr.Find.FamiliesOfCategory(cmd, Beams, inDoc)
'Dim AllFamilies As List(Of Element) = yr.Find.FamiliesOfCategory(cmd, Foundations, inDoc)

 

Dim prompt As String = "The Families are :" + vbLf + vbLf
For Each elem As Element In AllFamilies
prompt += elem.Name + vbLf
Next


TaskDialog.Show("Revit", prompt)

 

 

not valid for walls 😞

Message 8 of 9

System families do not have MaterialQuantities:

 

doc.Settings.Categories.Cast<Category>().Where(x => x.CategoryType == CategoryType.Model).Where(x => x.HasMaterialQuantities).OrderBy(x => x.Name);

Message 9 of 9

...and are cuttable .Where(x => !x.IsCuttable).Where(x => x.HasMaterialQuantities)

 

There are not many 'normal' categories in the end.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Rail Community