Setting Top Level Parameter with Python (Structural Column)

I am trying to set the top level parameter of a structural column with python in dynamo.

I am able to get the nodes to work in dynamo pretty easily:

I am struggling with doing this in python though, looking for a bit of help.

Python code

for i in range(len(cols)):
    if colMerges[i] and i != x :
        x = i+1
        test.append(i)
        cols[i].LookupParameter('Top Level').Set(levelList[i+2])
        test.append(levelList[i+1])
    else:
        pass

# Assign your output to the OUT variable.
OUT = test

It’s a little hard to see in the image I pasted above, but the error code reads as follows:

image

This made me think maybe the set parameter needs a string (not the actual revit level), which I tested and the set function “works” with a string parameter, but the column does not change its modelled height.

Any ideas where I am going wrong?

I may be incorrect, but I believe when you are changing actual Revit geometry, you have to enclose your code within a transaction.

2 Likes

As @staylor said, you need to put your .set method within a transaction, for example:

TransactionManager.Instance.EnsureInTransaction(doc)
cols[i].LookupParameter('Top Level').Set(levelList[i+2])
TransactionManager.Instance.TransactionTaskDone()

It also looks like you’re missing your imports, which I think might be the source of the error generated as it is not a transaction error.

This is a good place to go to get to grips with boilerplate code and what each bit does

2 Likes

Thank you and @staylor for your help . I have now wrapped my column updates in a transaction and made a more simple example for reference.

There still seems to be a problem with the .set function. Throwing in the level, I get the same error as noted before:

where it seems that .set command wants a string.

Running the following code does not error out, but also does not update the modelled column height.

col.LookupParameter('Top Level').Set('Level 4')

Updated python code:

#######OK NOW YOU CAN CODE########

# The inputs to this node will be stored as a list in the IN variables.
col = UnwrapElement(IN[0])
levelList = IN[1]

TransactionManager.Instance.EnsureInTransaction(doc)

toplevel = col.LookupParameter('Top Level')
col.LookupParameter('Top Level').Set(levelList)
#col.LookupParameter('Top Level').Set('Level 4')
        
TransactionManager.Instance.TransactionTaskDone()

# Assign your output to the OUT variable.
OUT = toplevel

input the level id and not the name of the level.

levelList = UnwrapElement(IN[1]).Id

2 Likes

Thank you, working now.

2 Likes

Also, the code seems to work without wrapping the work in a transaction, any ideas why? I need to read up more on when you need to wrap work in a transaction.

Not entirely sure on that myself. I was always under the impression that whenever changing Revit geometry, you had to wrap that part of the code in a transaction. That could be just for specific modifications. Guess I need to research that more myself, just so I don’t mislead anyone in the future.

1 Like

Agreed, I thought that editing anything in Revit requires a transaction…

Anyone more experienced than me have any idea?

@jacob.small

Dynamo has it’s own transaction which is kicking off, and as this isn’t doing that much work it’s being performed in that context.

Generally speaking you’ll want things in their own transaction to enable error handling, prevent corruption on massive datasets, and other issues around robustness of your automation.

2 Likes