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: 

Set Element Workset

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
will.wydock
5752 Views, 8 Replies

Set Element Workset

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

Code:
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();
		   }
		 	}
		}

8 REPLIES 8
Message 2 of 9
studio-a-int
in reply to: will.wydock

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()

 

 

Message 3 of 9
will.wydock
in reply to: will.wydock

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#

Message 4 of 9
RPTHOMAS108
in reply to: will.wydock

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.

Message 5 of 9
will.wydock
in reply to: RPTHOMAS108

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)
Message 6 of 9
JimJia
in reply to: will.wydock

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() );

 


Jim Jia
Autodesk Forge Evangelist
https://forge.autodesk.com
Developer Technical Services
Autodesk Developer Network
Email: Jim.Jia@autodesk.com
Message 7 of 9
so-chong
in reply to: will.wydock

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();
	        }
	   }
        }

 

Message 8 of 9
stever66
in reply to: will.wydock

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();
           }
             }

            
            
        }

Message 9 of 9
PerryLackowski
in reply to: stever66

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()

 

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