Announcements
Autodesk Community will be read-only between April 26 and April 27 as we complete essential maintenance. We will remove this banner once completed. Thanks for your understanding

Script to select SketchText and have a dialog box pop up to change the Text?

rwillardphil
Enthusiast

Script to select SketchText and have a dialog box pop up to change the Text?

rwillardphil
Enthusiast
Enthusiast

I am an expert 3D designer and a complete novice with programming.....  but want to do the following:

 

I have a Sketch and Extrusion with the word "LEFT 40" that I would like to quickly change to "RIGHT 60" (and a bunch of different extruded text in my design).

 

Using Scripts would it be possible to have a script do the following steps:

  1. Prompt me to select a sketch, I would select the sketch,
  2. It would grab the "only" text entity in that sketch
  3. Pop up a dialog box that I can change the text from "LEFT 40" to "RIGHT 60".

I want to change the Text in a sketch text entity, without editing each sketch, double clicking the text and changing it.

 

That is the core of what I want it to do, it would be awesome if it could do the following also:

 

  • The script selects all the sketches in sequence and grabs the sketch text entity, lets me modify it and then moves to the next sketch.
  • Also allows me to change the text height in the popup.

 

If you guys think this would be possible, then I am going to dive into it and work on it, but if not, I will not spend the time.

Any script examples that you may think would be helpful or similar, that would be helpful.

 

Thanks.

1 Like
Reply
Accepted solutions (1)
2,254 Views
13 Replies
Replies (13)

ekinsb
Alumni
Alumni
Accepted solution

Changing the string associated with sketch text is certainly possible with the API.  Below is a simple example that I wrote to validate it's working as expected.

 

def editText():
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        design = app.activeProduct
        rootComp = adsk.fusion.Component.cast(design.rootComponent)
        
        # Get the sketch named "TextTest"
        sk = rootComp.sketches.itemByName('TextTest')
        
        # Get the first sketch text.
        skText = sk.sketchTexts.item(0)
        
        # Change the text.
        skText.text = "New Text"
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
1 Like

rwillardphil
Enthusiast
Enthusiast

Brian,

 

Thanks for setting this up for me.  It didn't work copied straight.  I had to replace:

 

def editText():
 
with
 
def run(context):

 

Can you tell me what the difference is and why the previous was working for you and not me?

 

So I started with what you did and changed it to this:

 

 

 

 

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        design = app.activeProduct
        rootComp = design.rootComponent
        
        # Visual to prompt user to select a sketch from the Tree
        ui.messageBox('Select Sketch to Change (From Tree)')

        # This allows user to select a sketch
        selection = ui.selectEntity("Select sketch to change", "Sketches")   
        
        # Gets the name of the Sketch
        sketch = selection.entity.name

        #Prompts the user for the new Text   
        (returnValue, cancelled) = ui.inputBox('What Letter', 'New Letter', )
        
        # Grab the sketch and first text entity 
        sk = rootComp.sketches.itemByName(sketch) 
        skText = sk.sketchTexts.item(0)

        # Change the text.
        skText.text = returnValue


    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

It is pretty much doing what I wanted.  A couple of questions I still have (I am continuing to figure it out, just haven't been able to yet)

 

  1. HIs there a way to have "inputBox" to ask for more, like the Height, or do I need to just do another prompt?
  2. Is there a command that combines the  "messageBox" and "selectEntity" lines to give a visual prmpt to select the Sketch?
  3. How can I create a Loop to select an bunch of sketches/text in a row, until I do something to stop it?

Thanks for helping me out on this, I am much further along than I thought I would be today.

 

1 Like

ekinsb
Alumni
Alumni

The "run" function is called by Fusion when the script starts.  I just wrote this as a seperate function.  You could have left your "run" function and pasted in my code below it and then called my function from the run function.  Something like what's shown below.

 

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
		
        editText()
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.forma​t_exc()))
			
			
def editText():
	# The rest of the code...

 

Regarding all of the other enhancements you want to make.  That would all be possible by creating a command.  It's a pretty big step up in complexity from what you've already done but it's what you want to do when you need you need more complex interaction with the user. There's a topic in the API help that provides an overview.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
2 Likes

rwillardphil
Enthusiast
Enthusiast

Brian,

 

Thanks for your help.

0 Likes

Anonymous
Not applicable

Why can't I make it to work?

just want to be able to change the text in the sub-component.

 

thanks in advance

 

import adsk.core, adsk.fusion, adsk.cam, traceback

 

def run(context):

ui = None

try:

app = adsk.core.Application.get()

ui = app.userInterface

 

editText()

except:

if ui:

ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

def editText():

ui = None

try:

app = adsk.core.Application.get()

ui = app.userInterface

design = app.activeProduct

rootComp = design.rootComponent

occ = rootComp.occurrences.itemByName('Cover:1')

# Get the sketch named "TextTest"

sk = occ.sketches.itemByName('ID')

 

# Get the first sketch text.

skText = sk.sketchTexts.item(0)

 

# Change the text.

skText.text = "New Text"

except:

if ui:

ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

0 Likes

BrianEkins
Mentor
Mentor

You're trying to get sketches from an Occurrence object.  Instead, you need to be getting the component that the occurrence references and get the sketches from it.

 

sk = occ.component.sketches.itemByName('ID')

 

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
3 Likes

Anonymous
Not applicable

Thank you for this demo!

 

However, I just tried it and it doesn't update the extruded text, only the sketch... Any thoughts @ekinsb ?

0 Likes

Anonymous
Not applicable
That worked, thanks!
1 Like

ubaidim
Observer
Observer

Is it at all possible to have this fully automatic? I am looking to have serial numbers/names so may not be sequential. I have a design, i need a 100 of them but all with personalised text. Anyway of the script reading from excel or copied clipboard info and saving an stl like per row for example?

0 Likes

kandennti
Mentor
Mentor

Hi @ubaidim -San.

 

We have created a sample script that exports an STL file while changing the SketchText.
CSV files are used for the characters to be changed.

# Fusion360API Python script

import traceback
import adsk.core as core
import adsk.fusion as fusion    
import csv
import re
import pathlib

def run(context):
    ui: core.UserInterface = None
    try:
        app: core.Application = core.Application.get()
        ui = app.userInterface

        # select sketch text
        msg: str = 'Select Target Text'
        selFilter: str = 'Texts'
        sel: core.Selection = select_ent(msg, selFilter)
        if not sel: return

        targetText: fusion.SketchText = sel.entity

        # select csv
        csvPath = select_csvfile()
        if len(csvPath) < 1: return

        txts = ["_".join(s) for s in read_csv(csvPath)]

        # export folder
        expDir = select_export_dir()
        if len(expDir) < 1: return

        # update & export
        export_stl_with_updated_texts(
            targetText,
            txts,
            expDir,
        )

        # fin
        ui.messageBox("Done", "Fusion360")

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def export_stl_with_updated_texts(
    sktText: fusion.SketchText,
    textList: list[str],
    exportDir: str,
) -> None:

    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct
    root: fusion.Component = des.rootComponent
    expMgr: fusion.ExportManager = des.exportManager

    baseName = root.name

    backup = sktText.text

    for txt in textList:
        sktText.text = txt

        expFileName = re.sub(
            r'[\\|/|:|?|.|"|<|>|\|]',
            '-',
            f"{baseName}_{txt}"
        )

        expPath = str(
                pathlib.Path(exportDir) / expFileName
        )

        stlOpt: fusion.STLExportOptions = expMgr.createSTLExportOptions(
            root,
            expPath,
        )

        try:
            expMgr.execute(stlOpt)

            app.log(f"Export : {expPath}")
        except:
            pass

    sktText.text = backup


def select_export_dir() -> str:

    app: core.Application = core.Application.get()
    ui: core.UserInterface = app.userInterface

    dialog: core.FolderDialog = ui.createFolderDialog()
    dialog.title = "Export Folder"

    res: core.DialogResults = dialog.showDialog()
    if res == core.DialogResults.DialogOK:
        return dialog.folder
    else:
        return ""


def read_csv(
    path: str,
) -> list:

    with open(path) as f:
        reader = csv.reader(f)
        lst = [row for row in reader]

    return lst


def select_csvfile() -> str:

    app: core.Application = core.Application.get()
    ui: core.UserInterface = app.userInterface

    dialog: core.FileDialog = ui.createFileDialog()
    dialog.title = "Import CSV File"
    dialog.isMultiSelectEnabled = False
    dialog.filter = 'CSV File(*.csv)'

    res: core.DialogResults = dialog.showOpen()
    if res == core.DialogResults.DialogOK:
        return dialog.filename
    else:
        return ""


def select_ent(
    msg: str,
    filter: str
) -> core.Selection:

    try:
        app: core.Application = core.Application.get()
        ui: core.UserInterface = app.userInterface
        sel = ui.selectEntity(msg, filter)
        return sel
    except:
        return None

0 Likes

ubaidim
Observer
Observer

Hi. This is great. How do i use the script?

0 Likes

kandennti
Mentor
Mentor

@ubaidim -San.

 

Please follow the instructions here to create a new script and copy-paste the code above.

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-9701BBA7-EC0E-4016-A9C8-964AA4838954 

 

After executing the script, follow these steps
1) Select the sketch text to be replaced
2) Select the CSV file to import
3) Select a folder to export

0 Likes