Hi,
I am writing a routine that would unload 3 worksets from our linked models. Based on everything I have found online, I believe I written this correctly. However everytime i run this routine nothing appears to happen. The only thing I can think of that would be limiting me is how i filter down to just those names that is the issue. I have never tried to write anything that is accessing inside a linked model.
public void unloadlinkwrkst(UIApplication uiapp, Document doc) { Autodesk.Revit.ApplicationServices.Application app = uiapp.Application; try { List<Element> lstRvtLinkType = new FilteredElementCollector(doc).OfClass(typeof(RevitLinkType)).ToList(); foreach (Document _linkdoc in app.Documents) { if (!_linkdoc.IsLinked) continue; RevitLinkType _RvtLinkType = null; foreach (Element elmnt in lstRvtLinkType) { _RvtLinkType = elmnt as RevitLinkType; if (_RvtLinkType.Name != _linkdoc.Title) continue; else break; } List<WorksetId> lstWkSet_Close = new List<WorksetId>(); WorksetConfiguration wk = new WorksetConfiguration(); ModelPath _modelpath = _linkdoc.GetWorksharingCentralModelPath(); WorksetTable _worksetTable = _linkdoc.GetWorksetTable(); IList<WorksetPreview> lstPreview = WorksharingUtils.GetUserWorksetInfo(_modelpath); foreach (WorksetPreview item in lstPreview) { Workset wkset = _worksetTable.GetWorkset(item.Id); if (!wkset.IsOpen) { if ((item.Name.CompareTo("Shared Levels and Grids") == 0) || (item.Name.CompareTo("1/4 SCOPEBOX AND MATCHLINE") == 0) || (item.Name.CompareTo("1/8 SCOPEBOX AND MATCHLINE") == 0)) { lstWkSet_Close.Add(item.Id); continue; } } } wk.Close(lstWkSet_Close); _RvtLinkType.LoadFrom(_modelpath, wk); } } catch (Exception e) { TaskDialog.Show("dd", e.Message); return; } return; }
Solved! Go to Solution.
Solved by will.wydock. Go to Solution.
I can't get it to work either and its driving me crazy.
I threw in some task dialog boxes so we can follow the program as it runs. (I'm not very good with the debugger.)
I also believe the
if (!wkset.IsOpen)
should be
if (wkset.IsOpen)
Otherwise, 1stWkSet_Close becomes a list of the worksets that are already closed.
I also simplified your compare where it looks for certain worksets. The program seems to do everything right, but the one line
wk.Close(lstWkSet_Close);
just doesn't seem to do anything. I also tried it inside a transaction.
The odd thing is that this line of code actually opens a closed workset. That doesn't make sense because it is not even including that workset name in the list of worksets. Seems like a big clue, but I don't get it.
Here is what I have, and its still driving me crazy;
List<Element> lstRvtLinkType = new FilteredElementCollector(doc).OfClass(typeof(RevitLinkType)).ToList(); //foreach (Document _linkdoc in app.Documents) foreach (Document _linkdoc in doc.Application.Documents) { TaskDialog.Show("Starting to check Document:", _linkdoc.PathName.ToString()); if (!_linkdoc.IsLinked) { TaskDialog.Show("Revit","Continue"); continue; } TaskDialog.Show("Revit", "setting Linked type to null"); RevitLinkType _RvtLinkType = null; foreach (Element elmnt in lstRvtLinkType) { TaskDialog.Show("Starting to Check Revit Link:", elmnt.Name.ToString()); _RvtLinkType = elmnt as RevitLinkType; if (_RvtLinkType.Name != _linkdoc.Title) continue; else break; } TaskDialog.Show("Revit","Start processing linked workset"); List<WorksetId> lstWkSet_Close = new List<WorksetId>(); WorksetConfiguration wk = new WorksetConfiguration(); ModelPath _modelpath = _linkdoc.GetWorksharingCentralModelPath(); WorksetTable _worksetTable = _linkdoc.GetWorksetTable(); IList<WorksetPreview> lstPreview = WorksharingUtils.GetUserWorksetInfo(_modelpath); TaskDialog.Show("Revit","Start processing worksets in 1st preview"); foreach (WorksetPreview item in lstPreview) { Workset wkset = _worksetTable.GetWorkset(item.Id); //if (!wkset.IsOpen) if (wkset.IsOpen) { TaskDialog.Show("Testing",wkset.Name.ToString()); //if ((item.Name.CompareTo("Shared Levels and Grids") == 0) || (item.Name.CompareTo("Workset2") == 0) || (item.Name.CompareTo("Workset3") == 0)) if ((item.Name.ToString() == "Workset3") || (item.Name.ToString() == "Workset4")) { TaskDialog.Show("Added Workset",wkset.Name.ToString()); lstWkSet_Close.Add(item.Id); continue; } } } String mycount = lstWkSet_Close.Count.ToString(); TaskDialog.Show("Ready to close this many worksets", mycount); wk.Close(lstWkSet_Close); _RvtLinkType.LoadFrom(_modelpath, wk); } } catch (Exception e) { TaskDialog.Show("dd", e.Message); return; } return;
Thank you for you help. I didn't get a chance to use your simplified if statement yet but I was able to figure out that I was missing workset configuration options. I set it to OpenLastViewed so that i could have it remember what was previously open/closed.
WorksetConfiguration wk = new WorksetConfiguration(WorksetConfigurationOption.OpenLastViewed);
As i was running the routine I found that running the wk.Close() would only close the ones that i asked it to close and would reopen others that I had previously closed. I had my worksetlist include the ones that were already closed and then add the ones that i needed to also be closed.
WorksetConfiguration wk = new WorksetConfiguration(WorksetConfigurationOption.OpenLastViewed); ModelPath _modelpath = _linkdoc.GetWorksharingCentralModelPath(); WorksetTable _worksetTable = _linkdoc.GetWorksetTable(); IList<WorksetPreview> lstPreview = WorksharingUtils.GetUserWorksetInfo(_modelpath); foreach (WorksetPreview item in lstPreview) { Workset wkset = _worksetTable.GetWorkset(item.Id); if (!wkset.IsOpen) { lstWkSet_Close.Add(item.Id); } else { if ((item.Name.CompareTo("Shared Levels and Grids") == 0) || (item.Name.CompareTo("1/4 SCOPEBOX AND MATCHLINE") == 0) || (item.Name.CompareTo("1/8 SCOPEBOX AND MATCHLINE") == 0)) { lstWkSet_Close.Add(item.Id); continue; } } } wk.Close(lstWkSet_Close); _RvtLinkType.LoadFrom(_modelpath, wk);
Well that explains it. Seems to make sense now.
Glad you figured it out.
Hi @will.wydock ,
Is this working ?
I am trying to do something similar without success.
The goal, I think is similar, close worksets from a number of linked revit models based on the workset name.
My workflow is as follows:
It seems to be reloading the links but not closing the worksets , I get no errors
Does it need to be wrapped in a Transaction ? I thought revit would complain about that.
Any help/ ideas would be appriciated .
Thanks , Jonathan
Running into the same problem - the code executes but the worksets are all left open. Did you ever find a solution?
I figured it out - you need to construct the WorksetConfiguration like this to close worksets.
workset_config = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
workset_config.Open(open_this_list_of_worksets)
I originally tried the code below, and it did not work - it left all the Worksets open. Seems like maybe a bug? That or the API just isn't clearly explaining how the WorksetConfiguration Class works...
workset_config = WorksetConfiguration(WorksetConfigurationOption.OpenAllWorksets)
workset_config.Close(close_this_list_of_worksets)
So to close Worksets, you need to create a list of the Worksets that you want to remain open.
This vaguely matches the development team's assumption, which says:
I think you need to couple the workset unloading with a reload operation by using RevitLinkType.ReloadFrom( path, WorksetConfiguration ) that will let you specify the list of worksets which should be open after the load.
The similarity lies in the words 'specify the list of worksets which should be open'...
Sorry for resurrecting this thread a second time, but I have another topical issue. I have noticed that if you LoadFrom a Document that is loaded by two separate open models, the operation fails. For example, suppose I have three project files that link to each other - ARCH.rvt, MECH.rvt, ELEC.rvt. If I have the MECH and ELEC files open at the same time and try to perform a LoadFrom on the ARCH file, I receive this error:
'''
Goes to Manage > Manage Links > Manage Worksets and closes the three worksets for each LOADED link.
TESTED REVIT API: 2020
Author: Robert Perry Lackowski
'''
from pyrevit import DB
from Autodesk.Revit.DB import *
from pyrevit import script
output = script.get_output()
import traceback
doc = __revit__.ActiveUIDocument.Document
app = __revit__.ActiveUIDocument.Application.Application
# Decide if you want to hide it or unhide the worksets.
hide_workset = True
revit_link_types = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RvtLinks).OfClass(DB.RevitLinkType).ToElements()
revit_link_instances = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RvtLinks).OfClass(DB.RevitLinkInstance)
for link_type in revit_link_types:
print "links? : " + link_type.LookupParameter("Type Name").AsString()
if link_type.GetLinkedFileStatus() == LinkedFileStatus.Loaded:
link_instance = list(filter(lambda x: (x.GetTypeId() == link_type.Id), revit_link_instances))[0]
link_document = link_instance.GetLinkDocument()
#generate a list of the worksets in the link_document
workset_table = link_document.GetWorksetTable()
model_path = link_document.GetWorksharingCentralModelPath()
lst_preview = WorksharingUtils.GetUserWorksetInfo(model_path)
# initialize list of worksets to enable
open_this_list_of_worksets = []
for objWorksetPreview in lst_preview:
wkset = workset_table.GetWorkset(objWorksetPreview.Id)
if hide_workset:
#gather a list of all the open worksets, EXCLUDING the worksets we want to hide
if wkset.IsOpen and not (wkset.Name == "Shared Levels and Grids" or wkset.Name == 'Match Lines' or wkset.Name == 'Other Model Content'):
open_this_list_of_worksets.append(wkset.Id)
else:
#gather a list of all the open worksets, INCLUDING the ones we hid.
if wkset.IsOpen or wkset.Name == "Shared Levels and Grids" or wkset.Name == 'Match Lines' or wkset.Name == 'Other Model Content':
open_this_list_of_worksets.append(wkset.Id)
# Set the WorksetConfiguration file to close all worksets, then open the ones from the list
workset_config = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
workset_config.Open(open_this_list_of_worksets)
#reload the link with the updated workset configuration
link_type.LoadFrom(model_path, workset_config) #FAILS WHEN LINK IS LINKED INTO TWO OPEN FILES. WORKS THROUGH UI THOUGH...
#delete the workset configuration after use
workset_config.Dispose()
print "Script complete."
Can't find what you're looking for? Ask the community or share your knowledge.