Filter out elements on non-user Worksets

Filter out elements on non-user Worksets

PerryLackowski
Advocate Advocate
974 Views
4 Replies
Message 1 of 5

Filter out elements on non-user Worksets

PerryLackowski
Advocate
Advocate

I have set up a filter to grab all the grids, levels, scope boxes, match lines, and reference planes. Once I have the set of elements, I am setting the Workset parameter to the "Shared Levels and Grids" Workset. The trouble is, some of the reference planes are on drafting views, so the Workset property is overridden and can't be set. Is there a way to filter out these reference planes, without doing a string search for "Drafting View" on the Workset names? I'm really looking to filter out the elements that are on any non-user Worksets. Here's my current code (it's built for pyRevit, but the idea is the same in C#):

"""
Pushes content from the following categories
onto the Shared Levels and Grids workset:

Levels
Grids
Scope Boxes
Reference Planes
Match Lines

TESTED REVIT API: 2020

Author: Robert Perry Lackowski

"""

from Autodesk.Revit.DB import Workset, Transaction
from pyrevit import DB
from Autodesk.Revit.DB import FilteredWorksetCollector, WorksetKind
from Autodesk.Revit.DB import FilteredElementCollector, ElementClassFilter, ElementCategoryFilter, LogicalOrFilter
from Autodesk.Revit.DB import BuiltInParameter, BuiltInCategory, ElementId, WorksetId
from Autodesk.Revit.UI import TaskDialog

from pyrevit import script
from pyrevit import revit, DB

output = script.get_output()

doc = __revit__.ActiveUIDocument.Document

if doc.IsWorkshared == False:
    print "Can't push to the Shared Levels and Grids Workset because worksharing has not been enabled."
    TaskDialog.Show("Worksets", "Document is not workshared")
else:
    targetWorksetName = "Shared Levels and Grids"
    
    #find target workset
    workset_collector = FilteredWorksetCollector(doc)\
                        .OfKind(WorksetKind.UserWorkset)
     
    workset = next((ws for ws in workset_collector if ws.Name == targetWorksetName), None)
    workset_id_int = workset.Id.IntegerValue

    #create filter
    filter_set = []
    #filter_set.Add(ElementClassFilter(DB.ReferencePlane)) #reference planes
    filter_set.Add(ElementClassFilter(DB.Grid)) #grids
    filter_set.Add(ElementClassFilter(DB.Level)) #levels
    filter_set.Add(ElementCategoryFilter(BuiltInCategory.OST_VolumeOfInterest)) #scope boxes
    filter_set.Add(ElementCategoryFilter(BuiltInCategory.OST_Matchline)) #Matchlines
    filter_set.Add(ElementCategoryFilter(BuiltInCategory.OST_CLines)) #reference planes
    
    or_filter = LogicalOrFilter(filter_set)
    
    #use filter on new collector
    found_elements = FilteredElementCollector(doc)\
                     .WhereElementIsNotElementType()\
                     .WherePasses(or_filter)\
                     .ToElements()

    print "Attempting to push the following elements to the \"Shared Levels and Grids\" Workset:"
    print "\n\n"
    t = Transaction(doc)
    t.Start('Push to Shared Levels and Grids')
        
    update_count = 0
    total_count = 0
    fail_count = 0
    
    for e in found_elements:
        log_entry = "Category: " + e.Category.Name + "  Name: " + e.Name
        try:
            param = e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM)
            if param.AsInteger() == workset.Id.IntegerValue:
                log_entry += " is already correct."
                total_count += 1
            else:
                param.Set(workset.Id.IntegerValue)
                log_entry += " updated."
                update_count += 1
                total_count += 1
        except:
                log_entry += " failed to update."
                fail_count +=1
        test = log_entry + output.linkify(e.Id)
        print test
    t.Commit()
    
    print "\n\n"
    print "Updated " + str(update_count) + " elements out of " + str(total_count) + " editable elements."
    print str(fail_count) + " elements failed to update."
    print "\n\n"
    print "Reasons an element may fail to update:"
    print "1. Elements may be grouped"
    print "2. Elements may be on a non-user-created workset (for example, reference planes in a drafting view)"

 

0 Likes
Accepted solutions (1)
975 Views
4 Replies
Replies (4)
Message 2 of 5

jeremy_tammik
Alumni
Alumni

Would it be possible to test that by checking for ReferencePlane > OwnerViewId > View > ViewType > DraftingView?

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
Message 3 of 5

PerryLackowski
Advocate
Advocate

That may work! I'll experiment and get back to you.

0 Likes
Message 4 of 5

FAIR59
Advisor
Advisor
Accepted solution

First you'd have to filter the worksets using a FilteredWorksetCollector to find all the user-worksets. With the results you can then make a "multifilter" to filter the elements in the FilteredElementCollector

WorksetKindFilter f = new WorksetKindFilter(WorksetKind.UserWorkset);
FilteredWorksetIterator iter =  new FilteredWorksetCollector(doc)
	.WherePasses(f)
	.GetWorksetIterator();
List<ElementFilter> filters = new List<ElementFilter>();
while (iter.MoveNext())
{
	Workset w = iter.Current;
	filters.Add(new ElementWorksetFilter(w.Id));
}
LogicalOrFilter userworksetFilter = new LogicalOrFilter(filters);
IEnumerable<Element> found_elements = new FilteredElementCollector(doc)
	.WhereElementIsNotElementType()
	.WherePasses(userworksetFilter);

.You'd still have to check if you can change the workset for the elements. Running this on the rac_basic_sample_project (workshared version), the filtered elements include sketchlines, curtainwall-panels / mullions, weakdimensions and many others, essentially subelements that inherit the workset from their parent. 

Message 5 of 5

PerryLackowski
Advocate
Advocate

I was not aware that there are so many valid reasons for a Workset to be un-editable. I will probably just create a simple and verbose version of the script so you can choose to see all the items that the script attempts to change, or just the ones that it changed successfully. Thanks for the insight!

0 Likes