TextElement.SetWidth for 1000s of texts

Hi, struggling to get this script to run nicely. Getting drafting views and then gathering text notes by the view. Then increasing the size of the text note. I’ve got it to work with a few drafting views. But when I try get it to work across 100 drafting views it takes forever and fails. Any ideas to make it more concrete. Possibly my list logic is out. Says success with it but then hasn’t actually done anything in Revit with a lot of views. Thanks for any help. Been trying differnt lacing. feel like i’m close, possibly a at levels issue with TextElement.SetWidth?

This worked with 22 drafting views but upped it to 100 drafting views and it failed actually increasing the text note size in revit

Have you tried extracting the contents of the TextElement.SetWidth node to see how it is handling the lists?

Thanks Ewan,

I extracted it into my script but its a little to complicated. Found a simpler option doing some research though. However it is failing when you have to do 100s of text notes. I’m not sure if its becoming a Revit issue of what it can handle.

This is the node i found. Its supposed to have “element : Element” but i kept getting an error for some reason so changed it to “TextElement”

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

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument
element = UnwrapElement(IN[0])
width = IN[1]

TransactionManager.Instance.EnsureInTransaction(doc)

element.Width = width

TransactionManager.Instance.TransactionTaskDone()

OUT = element

Have you set the lacing on longest on your custom node Text.Width ?

No luck, didn’t increase the text widths in Revit

It’s probably the first item : Empty list the culprit.

Add a Flatten node after Select.ByCategorie

hmmmm no luck :frowning:

Is there a way to get it to do 200 text notes at a time? Complete 200 then start the next 200 till its finished?

Hey,

This works for me… Needed a loop?

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

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument
element = UnwrapElement(IN[0])
width = IN[1]

TransactionManager.Instance.EnsureInTransaction(doc)

for e in element:

	e.Width = width

TransactionManager.Instance.TransactionTaskDone()

OUT = element

Hi Mark, a loop? I tried your code but got null values. Not sure how I adjust below for your changes

image

Hey,

I didn’t run it in a custom node, just in the graph… Then the Python can tell you what the problem is…
“for e in element” is a ‘For’ loop, it means the Python will iterate through each item in Element.

Hope that helps,

Mark

EDIT: Sorry you’re right, anything over 100 fails for me. A list chop node will split the list down, I’ll have a go at getting the Python to run on the sub-lists.

This is as far as I got… Perhaps @Jonathan.Olesen can help? :slight_smile:

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

clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.Elements)

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

doc = DocumentManager.Instance.CurrentDBDocument
element = UnwrapElement(IN[0])
width = IN[1]

for ele in range(0,len(element)):

	for e in range(0,len(element[ele])):

		TransactionManager.Instance.EnsureInTransaction(doc)
		
		element[ele][e].Width = width

		TransactionManager.Instance.TransactionTaskDone()

OUT = element 

Cheers,

Mark

Hey guys,

Just out of curiosity, which Revit/Dynamo versions are you running?

I just tested this in Revit 2019/Dynamo 2.0.1 with 1020 text nodes across five drafting views and it worked without hickups:

I would post the script as formatted text, but I’m on this buggy Revit version which wont allow me to use my Delete-key or Copy+paste for that matter :stuck_out_tongue_closed_eyes:

I’ve attached the graph instead.

Edit: Note that I’m converting the width input to internal units since I’m using the metric system, so if you’re using imperial you should change the UnitUtils.ConvertToInternalUnits(IN[1], DisplayUnitType.DUT_MILLIMETERS) to simply IN[1].

TextNoteWidth.dyn (7.0 KB)

1 Like

Hi Martin,

I get the error below in dynamo 1.33 and 2.0.0. Been nervous to go to 2.0 encase something breaks my graphs. I get a similar error @Mark.Ackerley with your code.

Thanks Martin,

As I said, fine up to 100 then it just doesn’t do anything… I guess manually doing batches 100 at a time would be manageable? But I’d like to see how it could be automated :slight_smile:

Mark

I could have done all the texts long ago filtering them by bits of drafting views at a time. So keen to see how it would work for any number though. So much satisfaction haha

1 Like

That’s weird! I’ve tested with pretty much the same snippet with Dynamo 1.3.3 (added a boolean toggle to be able to reset). It’s processing all 1000 TextNotes across 10 drafting views:

import clr

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

clr.AddReference('RevitServices')
import RevitServices 
from RevitServices.Persistence import *
from RevitServices.Transactions import *

doc = DocumentManager.Instance.CurrentDBDocument
   
text = UnwrapElement(IN[0])
width = UnitUtils.ConvertToInternalUnits(IN[1], DisplayUnitType.DUT_MILLIMETERS)
bool = IN[2]

TransactionManager.Instance.EnsureInTransaction(doc)

if bool == True:
	for i in text:
		min = i.GetMinimumAllowedWidth()
		max = i.GetMaximumAllowedWidth()
		
		if i.Width < min:
			i.Width = min
		elif i.Width > max:
			i.Width = max
		else:
			i.Width = width
			
		OUT = 0

else:
	OUT = 'Set bool to true'
		
TransactionManager.Instance.TransactionTaskDone()

You could easily chop the list into lists of a 100 items and then do the excersize with a nested loop, but I don’t know if it would be that simple. Maybe you need to break out of the loop, completely, and then continue.

1 Like

The issue as i see it is that you use a single width and @vanman has a list of widths… So using a counter or zip to go through width items as well should help you immensely :slight_smile:

Hello, I believe your first suggestion should work if only you change the SetWidth node to level2 for both inputs.
Give it a try if you have not already solved it.

Hi @MartinSpence
Just fyi, if you update your Revit 2019 to 2019.1 then the copy/paste etc and the preformatting problem are resolved :slight_smile: