Set text box width

Hi all. I am using a graph from another post but want to add something to it. The post I am referring to is this one: https://forum.dynamobim.com/t/combining-multiple-text-notes-into-one/20349

It talks about combining multiple text notes into one. This is usually needed when converting AutoCAD details to Revit and that is what I am using it for. One thing that I would like to improve is adding a way to set the text box width. Currently it create a big long text box to fit all the text that you combine and then you have to zoom out and adjust the text box down. Below is an example of the long text box:

Text box

Is there a way to set a text box width for the new text box it creates? Here is the graph.

I am using Revit 2023 with Dynamo v.2.16.4 and the Springs package.

Thank you and cheers!

There may be custom nodes that do this already, but you can set the width directly with the API:
TextNote Class

Thank you Nick. I was able to use the API and test it with just the Python code alone. When I select one text box, it works. When I select multiple text boxes it doesn’t work which makes sense because the code isn’t set up to handle a list, at least I think that’s why it won’t work. It also gives me an error when I put the Python code in my current graph. I tried using ChatGPT to tell me where to insert the code and it told me to put it where you see in the image. Here is a pic of my graph and where AI told me to put it.

I’m getting an error on the Python code which is : "AttributeError " ‘list’ object has no attribute “Width’ [’ File “”, line 20, in \n]”

Line 20 is “textNote.Width = newWidth”

I’m assuming this is the sequence of things to happen but not sure:

  1. Select all text boxes that need to be combined
  2. Text is copied to a new text box
  3. Old text boxes are deleted
  4. New text box width is changed

The Python code I’m using is

import clr
clr.AddReference('RevitAPI')
clr.AddReference('RevitServices')

from Autodesk.Revit.DB import *
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

# Get document
doc = DocumentManager.Instance.CurrentDBDocument

# Inputs
textNote = UnwrapElement(IN[0])
newWidth = IN[1]

# Start transaction manually
TransactionManager.Instance.EnsureInTransaction(doc)

# Modify the width
textNote.Width = newWidth

# End transaction
TransactionManager.Instance.TransactionTaskDone()

# Output
OUT = textNote

Alternatively I explained to ChatGPT exactly what I wanted and it gave me this code which works! Any thoughts?

# Import Revit and Dynamo APIs
import clr
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import TextNote, XYZ

# Input from Dynamo
textNotes = IN[0]  # List of selected TextNote elements
boxWidth = IN[1]   # Desired width of final text box

doc = DocumentManager.Instance.CurrentDBDocument

# Unwrap Revit elements
textNotesUnwrapped = [t.InternalElement for t in textNotes]

if not textNotesUnwrapped:
    OUT = "No TextNotes selected."
else:
    # Create a function to extract position (use Origin point of TextNote)
    def get_position(note):
        pos = note.Coord
        return (round(-pos.Y, 4), round(pos.X, 4))  # Negative Y so highest appears first

    # Sort text boxes: top to bottom (-Y), then left to right (X)
    sortedNotes = sorted(textNotesUnwrapped, key=get_position)

    # Combine text in sorted reading order
    combinedText = "\n".join([note.Text for note in sortedNotes])

    # Choose the top-left note to keep (first in sorted list)
    keeperNote = sortedNotes[0]
    notesToDelete = sortedNotes[1:]

    # Start modifying in a transaction
    TransactionManager.Instance.EnsureInTransaction(doc)

    # Modify the keeper text note
    keeperNote.Text = combinedText
    keeperNote.Width = boxWidth

    # Delete the others
    for note in notesToDelete:
        doc.Delete(note.Id)

    TransactionManager.Instance.TransactionTaskDone()

    OUT = keeperNote

You are correct. Your original code was setup for a single text note and was failing on a list. You can fix that by looping for each item in your list.

for textNote in textNotes:
   textNote.Width = newWidth

ChatGPT did something similar by joining all the text notes into one and then adjusting the width by using a similar in-line notation.

combinedText = "\n".join([note.Text for note in sortedNotes])

In this case, the text is being looped through and added to a list before being joined back together. The part in brackets is the same as:

for note in sortedNotes:
   newList.append(note.Text)