Hi,
I am working on a macro for 2015+ that will move families based on categories to the appropriate workset. The routine builds but i am unable to get it to run correctly
public void Shared_LEVELWS() { Document doc = this.ActiveUIDocument.Document; if(doc.IsWorkshared==false) { TaskDialog.Show("Worksets", "Document is not workshared"); } if(doc.IsWorkshared==true) { //Select the shared grid workset IList<Workset> worksetList = new FilteredWorksetCollector(doc).OfKind(WorksetKind.UserWorkset).ToWorksets(); int sharedGridWorksetId=0; foreach (Workset workset in worksetList) { if (workset.Name.Contains("Shared Levels and Grids")) { sharedGridWorksetId = workset.Id.IntegerValue; } } //Reference planes List<Element> elements = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CLines).ToElements().ToList(); //Grids List<Element> grids = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Grids).ToElements().ToList(); //Scope box List<Element> scopeBoxes = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_VolumeOfInterest).ToElements().ToList(); //Level List<Element> levels = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).ToElements().ToList(); elements.AddRange(grids); elements.AddRange(scopeBoxes); elements.AddRange(levels); if (elements == null) return; using (Transaction tx = new Transaction(doc,"Change Workset")) { tx.Start(); foreach (Element e in elements) { Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM); //set workset to Shared Levels and Grids wsparam.Set(sharedGridWorksetId); } tx.Commit(); } } }
Solved! Go to Solution.
Solved by stever66. Go to Solution.
if you run a Python script (inside Dynamo or PythonShell) it is a very simple few lines of code:
#WORKSET_ID is the Id of the workset you would like the elements to "move"
# START TRANSACTION
t = Transaction(doc, 'SET WORKSET FOR ELEMENTS')
t.Start()
[i.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM).Set(WORKSET_ID) for i in elements]
# END TRANSACTION
t.Commit()
I am testing this out in macro form, but eventually I will be adding it to my addin Ribbon. So I would like it to remain in C#
When you filter by document and not within a view you need to exclude element types, I believe element types have their own worksets that you can't change. Not sure if this is your only issue but is something that stands out.
Report any exceptions you get and what lines they occur on.
Here is the error I am receiving
A problem has been detected.
AutodeskRevitExceptions.InvalidOperationException: The
parameter is read-only.
at MacroModule.executeMacro_(MacroModule* , AString*
macroNa me)
at MacroModule.executeMacro(MacroModule* , AString)
at
UlMacroGeneralManager.runMacro(lJlMacroceneralManager*,
MacroModule* pModule, AString* macroName)
Dear wwydok,
Please refer to following codes, it show how to change element's workset:
You can also go to Jeremy's blog(http://thebuildingcoder.typepad.com/blog/2013/01/change-element-workset.html)
Reference r = uidoc.Selection.PickObject( ObjectType.Element ); Element e = doc.GetElement( r.ElementId ); if( e == null ) return; WorksetId wid = e.WorksetId; TaskDialog.Show( "Workset id", wid.ToString() ); Parameter wsparam = e.get_Parameter( BuiltInParameter.ELEM_PARTITION_PARAM ); if( wsparam == null ) return; // Find all user worksets FilteredWorksetCollector worksets = new FilteredWorksetCollector( doc ) .OfKind( WorksetKind.UserWorkset ); using( Transaction tx = new Transaction( doc ) ) { tx.Start( "Change workset id" ); foreach( Workset ws in worksets ) { wsparam.Set( ws.Id.IntegerValue ); } tx.Commit(); } wid = e.WorksetId; TaskDialog.Show( "worksetid", wid.ToString() );
Hi,
I have changed your code here and there.
This macro runs correctly on my computer, i hope the same goes for you.
Good luck and cheers,
so-chong
public void Shared_testWorkset() { Document doc = this.ActiveUIDocument.Document; if(doc.IsWorkshared==false) { TaskDialog.Show("Worksets", "Document is not workshared"); } if(doc.IsWorkshared==true) { String targetWorksetName = "Shared Levels and Grids"; //Find target workset FilteredWorksetCollector worksetCollector = new FilteredWorksetCollector(doc); worksetCollector.OfKind(WorksetKind.UserWorkset); Workset workset = worksetCollector.FirstOrDefault<Workset>(ws => ws.Name == targetWorksetName); // reference planes FilteredElementCollector rpCollector = new FilteredElementCollector(doc); rpCollector.OfClass(typeof(ReferencePlane)); // grids FilteredElementCollector collector2 = new FilteredElementCollector(doc); ICollection<Element> collection2 = collector2.OfClass(typeof(Grid)).ToElements(); // scope boxes FilteredElementCollector collection5 = new FilteredElementCollector(doc); collection5.OfCategory(BuiltInCategory.OST_VolumeOfInterest); //levels FilteredElementCollector collector4 = new FilteredElementCollector(doc); ICollection<Element> collection4 = collector4.OfClass(typeof(Level)).ToElements(); using (Transaction tx = new Transaction(doc,"Change Workset")) { tx.Start(); foreach (Element e in collection4) { Level level = e as Level; Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM); wsparam.Set(workset.Id.IntegerValue); } foreach (Element e in collection2) { Grid grid = e as Grid; Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM); wsparam.Set(workset.Id.IntegerValue); } foreach (Element e in rpCollector) { Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM); wsparam.Set(workset.Id.IntegerValue); } foreach (Element e in collection5) { Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM); wsparam.Set(workset.Id.IntegerValue); } tx.Commit(); } } }
Put the line that assigns the new workset inside a "try-catch" block so any elements that can't have their workset changed are passed over without crashing the program.
I also added some dialog boxes to help show whats going on, but you can delete those or comment them out:
//UIDocument uiDoc = this.ActiveUIDocument; //dont need this
Document doc = this.ActiveUIDocument.Document;
if(doc.IsWorkshared==false)
{
TaskDialog.Show("Worksets", "Document is not workshared");
}
if(doc.IsWorkshared==true)
{
//Select the shared grid workset
IList<Workset> worksetList = new FilteredWorksetCollector(doc).OfKind(WorksetKind.UserWorkset).ToWorksets();
int sharedGridWorksetId=0;
foreach (Workset workset in worksetList)
{
if (workset.Name.Contains("Shared Levels and Grids"))
{
sharedGridWorksetId = workset.Id.IntegerValue;
}
}
TaskDialog.Show("Revit", sharedGridWorksetId.ToString());
//Reference planes
List<Element> elements = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_CLines).ToElements().ToList();
//Grids
List<Element> grids = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Grids).ToElements().ToList();
//Scope box
List<Element> scopeBoxes = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_VolumeOfInterest).ToElements().ToList();
//Level
List<Element> levels = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).ToElements().ToList();
elements.AddRange(grids);
elements.AddRange(scopeBoxes);
elements.AddRange(levels);
String mystring = "";
foreach (Element e in elements)
{
mystring = mystring + e.Name.ToString() + " " + e.WorksetId.ToString() + "\r\n";
}
TaskDialog.Show("Revit", mystring);
if (elements == null)
return;
using (Transaction tx = new Transaction(doc,"Change Workset"))
{
tx.Start();
foreach (Element e in elements)
{
//Parameter wsparam =e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM);
//set workset to Shared Levels and Grids
//wsparam.Set(sharedGridWorksetId);
try
{
e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM).Set(sharedGridWorksetId);
TaskDialog.Show("Changed", e.Name.ToString());
}
catch
{
}
}
tx.Commit();
}
}
}
I just converted this to Python for use with the pyRevit extension. Here's my version, for anyone else who finds this thread.
Edit: Just caught stever66's good suggestion about the Try/Catch. Updated it below.
"""
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.1
Author: Robert Perry Lackowski
"""
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
from Autodesk.Revit.DB import Workset, Transaction
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)
#create a 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
or_filter = LogicalOrFilter(filter_set)
#apply the filter
found_elements = FilteredElementCollector(doc)\
.WhereElementIsNotElementType()\
.WherePasses(or_filter)\
.ToElements()
#start a transaction
t = Transaction(doc)
t.Start('Push to Shared Levels and Grids')
print "Pushing the following elements to the \"Shared Levels and Grids\" Workset:"
#Apply the workset to every element
for e in found_elements:
try:
param = e.get_Parameter(BuiltInParameter.ELEM_PARTITION_PARAM)
param.Set(workset.Id.IntegerValue)
category_and_name = "Category: " + e.Category.Name + " Name: " + e.Name + " updated."
except:
category_and_name = "Category: " + e.Category.Name + " Name: " + e.Name + " failed to update."
print category_and_name
t.Commit()