Open workset

Can I determine if an element is in open workset? Or, do I need that at all? Sry if the question is dumb. Does dynamo make changes only to those elements that are in open workset?

I believe so, as Revit allows such (open a model with all worksets closed and modify a parameter value in a schedule view).

If you want to limit things you’ll have to query the worksets list, filter out inactive worksets, and test the element’s workset against that list.

1 Like

Revit 2022.1, Dynamo Revit 2.12.1
IronPython2 (Doesn’t work in CPython3)


def main(element):
    document = element.Document

    if not document.IsWorkshared:
        return "Document is not workshared!"

    workset_table = document.GetWorksetTable()
    workset = workset_table.GetWorkset(element.WorksetId)

    return (workset.Name, workset.IsOpen, workset.IsEditable)


OUT = main(UnwrapElement(IN[0]))

3 Likes

Seems to be working fine for me in CPython3… perhaps another worksharing issue?

I can’t make it to work

Hi, colleague uses both Element and Document classes with Properties and methods of some

copy the revit boiler plate code
before function definition

sincerely
christian.stan

You’re trying to operate on a list instead of an element. Try

OUT = [main(elem) for elem in UnwrapElement(IN[0])]

2 Likes

You’re trying to operate on a list instead of an element.

Truth is, I was trying to replicate a code that I don’t understand.

def main(element): #defines the function 
    document = element.Document #gets the document the element is in

    if not document.IsWorkshared: #check of the document is workshared
        return "Document is not workshared!" # return a message if so

    workset_table = document.GetWorksetTable() #get the workset table from the document 
    workset = workset_table.GetWorkset(element.WorksetId) #get  workset from the workset table, using the workset id property of the element to define which workset to get

    return (workset.Name, workset.IsOpen, workset.IsEditable) #return thr workset’s name, if ithr workset is ope , and if the workset is editable, using the respective properties of each. 


OUT = [main(UnwrapElement(i)) for i in IN[0] ] #uses list comprehension to iterate over the list, calling the custom function main on each item

Hopefully these comments work well for you to sort things out. I also recommend looking over the Dynamo Python Primer, and getting some basic Python education now that you’re utilizing it in one of your tools, and that technical debt is something you own maintenance on for each version of Revit until you decide to deprecate it.

2 Likes

Thanks for your comments. Now, I think I understand how Python finds data: TakeInput.FindAnythingRelated(ByThisCriteria) Am I right?

I’m trying to literate myself. Is the code bellow the same as the one Tomas wrote? Please confirm.

I dont understand this:

return (workset.Name, workset.IsOpen, workset.IsEditable)

By your explanation, it is a single value, a string to be shown only if the Booleans are true. What if they are not true? What will be returned?

And, what am I going to do with a string value anyway? I needed a Boolean.

If it helps there is a node in the Crumple package for workset checkout status, could be worth interrogating.

1 Like

What I posted was the same, I just added annotations to the end of each line so you could understand what each line of the code does. You appear to have edited the code to remove the annotations and modified it to another language (there was no else statement before, as it’s not required in the context).

Below is the same as Tomas’ code, but with ‘what the code is doing’ appended on the end of each line.

def main(element): #defines the function 
    document = element.Document #gets the document the element is in

    if not document.IsWorkshared: #check of the document is workshared
        return "Document is not workshared!" # return a message if so

    workset_table = document.GetWorksetTable() #get the workset table from the document 
    workset = workset_table.GetWorkset(element.WorksetId) #get  workset from the workset table, using the workset id property of the element to define which workset to get

    return (workset.Name, workset.IsOpen, workset.IsEditable) #return thr workset’s name, if ithr workset is ope , and if the workset is editable, using the respective properties of each. 


OUT = [main(UnwrapElement(i)) for i in IN[0] ] #uses list comprehension to iterate over the list, calling the custom function main on each item

Not really. While the comments in the code provide the ‘what’, they don’t outline the ‘how’ in any way.
I can try to outline some of this, but you’ll want to do a BUNCH more research on it as this is my opinion, not hard facts.

In the context of the forum you can consider Revit, Dynamo, and Python as Object Oriented programing at their core. This means that they utilize Objects and Classes to define functions which can be called in a particular order to define what the application does.

Classes are a defined way to structure data that first defines an object (ie: a Point), then provides means for creating an object (ie: by coordinates), then allows associating properties to that object (ie: the X, Y, and Z value), and further allows modifications to that object (ie: altering the X, Y, and Z value).

  • The object (the point) is an instance of the class (point).
  • The means of creating it (ByCoordinates) is a constructor.
  • The means of modifying is called a Method.
  • The information about it is called a Property

In Dynamo:

  • Classes are shown as shelfs (ie, the Point section of your library).
  • Constructors are shown with a green :heavy_plus_sign:
  • Methods are shown with a red :zap:
  • Properties are shown with a blue :question:
  • Instances of the class are shown in the preview of the nodes themselves

In Python:

  • Classes are called by typing their name (usually start with an Uppercase letter - why we don’t use upper case letters to start variables). ie: Point
  • Constructors are called by typing the name of the class, a dot, then the text of the particular constructor you are after, followed by parenthesis containing any parameters required for the function. ie: pnt = Point.ByCoordinates(0,0,0)
  • Methods are utilized by taking an instance of the class, a dot, and then the text of the particular modifier you’re after, followed by parenthesis containing any parameters required for the function. ie: vect = pnt.AsVector()
  • Properties are utilized by taking an instance of the class, a dot, and the name of the property you want to get to.

So we can start to unwind the ‘how’ of the code above (new comments discussing ‘how’ the Python is working instead of what the code is doing here);

def main(element): #defines the function 'main' which takes an element as the input
    document = element.Document #takes the instance of the element and pulls it's document property and stores it as the 'document' variable

    if not document.IsWorkshared: #if the document's IsWorkshared property is not true
        return "Document is not workshared!" #return a message to the user, which ends the definition, no further code is executed

    workset_table = document.GetWorksetTable() #take the Document instance stored as the document variable and use the method GetWorksetTable() which takes no overrides, returns a WorksetTable object, and store that as the workset_table variable
    workset = workset_table.GetWorkset(element.WorksetId) #take the workset table and use the GetWorkset method, passing the WorksetId property of the element as the override, to return a workset object
    return (workset.Name, workset.IsOpen, workset.IsEditable) #return a list consisting of the Name property of the workset variable, the IsOpen property of the workset variable and the IsEditable property of the workset variable.


OUT = [main(UnwrapElement(i)) for i in IN[0] ] #utilize list comprehension to iterate over all the items in IN[0] from the Dynamo environment, to call the definition main on the result of the element returned by calling the UnwapElement method on the Dynamo object.

I recommend typing a few of these up as they really help you understand what code is doing, and how you can write your own.

Not quite - my explaination indicated that if the document was workshared it would return the name, IsOpen, and IsEditable properties for the workset, otherwise if it was NOT worksahred it would return the message.

The results of IsEditable and IsOpen should be booleans. If you only want ‘IsOpen’ edit the definition to only return that property.

1 Like

hi, here is at a less precise level than Mr. Jacob

import sys
import clr

clr.AddReference("RevitAPI")
import Autodesk
from Autodesk.Revit.DB import Element,Document #Class your use

elt=UnwrapElement(IN[0])
doc=elt.Document #Class Element is use here with property Document

bool=doc.IsWorkshared # Class Document is use here with property IsWorkshared
OUT = bool

cordially
christian.stan

I wasn’t asking if your code was the same as the one Tomas wrote. You only added comments. I was asking about my code.

You say that there is no need for “else” in “if” statement, but then you say that one of two messages should be returned, depending on the conditions:

document.IsWorkshared
workset.IsOpen
workset.IsEditable

How is that not an if else statement?

// define the function
def main(element):  

    // declare variables
    document = element.Document 
    workset_table = document.GetWorksetTable() 
    workset = workset_table.GetWorkset(element.WorksetId)

    // if else syntax
    if (not document.IsWorkshared or not workset.IsOpen or not workset.IsEditable) :
        return "Document is not workshared!" 
    else 
        return workset.Name

// Execute function
OUT = [main(UnwrapElement(i)) for i in IN[0] ]

Or for my needs, it would be:

// define the function
def main(element):  

    // declare variables
    document = element.Document 
    workset_table = document.GetWorksetTable() 
    workset = workset_table.GetWorkset(element.WorksetId)

    // if else syntax
    if (not document.IsWorkshared or not workset.IsOpen or not workset.IsEditable) :
        return false
    else 
        return true

// Execute function
OUT = [main(UnwrapElement(i)) for i in IN[0] ]

In a definition the lure can only be one return value; what happens after that is effectively non-functional. As such the ‘else’ need not apply, because if the value is triggered the return is set. While you can ask all the things in a single if statement like you are in your example, it does become much more difficult to read as your code base grows.

Lastly, the use of // in Python indicates floor division, and is not valid for a comments. It might not toss an error in your current context, but I do not recommend it, instead utilise the # to preface the comments. :slight_smile:

2 Likes

allright, thank you.

1 Like