Turn all worksets off, then one on

Using Archi-lab.net, in Revit 2023.

I’m trying to do a walk-through of Worksets.

Intent of the flow here is to turn all worksets off in a view, and then turn on a single one using a picklist of the worksets in the project, so I can what workset geometry is on, and then if necessary, select and place on the correct workset for the object.

When I run the first time, it turns all worksets off (Hidden). When I select an individual workset from the picklist, it turns it on.
But then when I select another workset, it turns that on but the previous one also stays on.
And on on.

I just end up with a graph that turns all off, then turns them on one by one.

What am I not understanding here in how Dynamo works…?

Hello @JohnSmithUN5MX,

On a rerun, dynamo will only execute nodes if one of the inputs of the node has changed.
As you set another workset with the dropdown, your second setVisibility node will execute again. But the first setVisibility node will not.

Run the graph with dynamo player. On the player the behavior is different, the full graph will run everytime. It’s the same behavior as you get with dynamo if you close the graph and reopen after a run.

Kind regards

OK, thanks.

Going to have to play with that.

Knowing what to look for, I’ve revised the graph to have the list of worksets sorted through in a Python node,with the one I have selected removed from the list, and then that list of worksets (less 1) set to Hidden.

The selected Workset, is itself set to be Visible.

My first Python routine in my first Dynamo script :slight_smile:

Thanks for the help.

3 Likes

Nice one - first working python script is always a good moment!

If it helps, this is how you can do all of it in Python/API alone. Input 0 is a list of views (or a single view), Input 1 is the name of the workset to try to keep on:

# Made by Gavin Crump
# Free for use
# BIM Guru, www.bimguru.com.au

# Boilerplate text
import clr

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager 
from RevitServices.Transactions import TransactionManager 

clr.AddReference("RevitAPI")
import Autodesk 
from Autodesk.Revit.DB import *

# Current doc/app/ui
doc = DocumentManager.Instance.CurrentDBDocument

# Define list/unwrap list functions
def uwlist(input):
    result = input if isinstance(input, list) else [input]
    return UnwrapElement(result)

# Preparing input from dynamo to revit
views       = uwlist(IN[0])
name_keepOn = IN[1]

# Constants
WORKSETS_HIDDEN = WorksetVisibility.Hidden
WORKSETS_SHOW   = WorksetVisibility.Visible

# Get worksets
worksets_all = FilteredWorksetCollector(doc).\
			   OfKind(WorksetKind.UserWorkset).\
			   ToWorksets()

# Function to turn off worksets in view if not given name
def view_worksetsOffButOne(view, worksetName, worksets = worksets_all):
	# Track if we found the workset
	worksetFound = False
	# For each workset in all worksets
	for ws in worksets:
		# If it's name is match, show it
		if ws.Name == worksetName:
			view.SetWorksetVisibility(ws.Id , WORKSETS_SHOW)
			worksetFound = True
		# Otherwise, hide it
		else:
			view.SetWorksetVisibility(ws.Id , WORKSETS_HIDDEN)
	# Return if we found it
	return worksetFound

# Do some action in a Transaction
workset_found = []

TransactionManager.Instance.EnsureInTransaction(doc)

for v in views:
	outcome = view_worksetsOffButOne(v, name_keepOn)
	workset_found.append(outcome)

TransactionManager.Instance.TransactionTaskDone()

# Preparing output to Dynamo
OUT = workset_found

Might be interesting to begin looking at coding style as well (how you name/structure things) as it will help you build clean code as you learn. I’ve been developing my own lately and wish I’d begun doing it earlier (I’ve had to refactor a lot of messy code I built due to not having this earlier). Some examples to note:

  • WORD_WORD for global contants (things I use many times, often enums)
  • word_word for global variables
  • wordWord for local variables (in functions)
  • class_actionAction for functions (more than 2 action words to avoid clash with globals)
  • for wide blocks of code using \ to read a statement over multiple lines
  • for generic iterables, use i/j/k in depth. For simple loops it’s not a big deal but it helps immensely to read/understand nested loop structures
  • get in the habit of building functions versus putting large blocks of text indented in loop structures. Better for code reusability and will help in later languages like C# where most things run through a main function calling on other ones. This is one I wish I’d also done earlier
  • most importantly, lots of # comments! Everyone likes well commented code
  • you can do a mutliline comment for instructions using triple apostrophes either end of the block

These are of course my own rules for style, but I’ve found they help me keep my code readable and also avoid clashes with variable names (local/global scope).

Hope that helps the learning journey!

2 Likes

I recommend keeping the first character lower case for your names variables - this also makes the transition of code to C# (add-in or Dynamo node) easier as it avoids a warning. :slight_smile:

2 Likes

No problem on the advice.

Keeping it small works for me better, but interesting to see how it might all be done in Python, I may well need this in the future (always good to have some flexibility in approaches).

I’ve done programming in the past, in Lisp and VBA for Autocad, but I’m new to Python and the Revit API. I’m also pretty rusty on the housekeeping!

An ongoing learning journey.

2 Likes