Hi @JohnBuehler .
This is possible with TableCommandInput Object.
http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-C3F746B3-6488-4B74-A441-31AFDEFD1648
You can find a sample here.
http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-e5c4dbe8-ee48-11e4-9823-f8b156d7cd97

Due to the large volume of the sample, this is what it looks like if you only use the part that relates to TableCommandInput.
#FusionAPI_python Script
import adsk.core, adsk.fusion, traceback
_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)
# command Info
_cmdInfo = ['test', 'test', 'test']
_handlers = []
_rowNumber = 0
def addRowToTable(tableInput):
global _rowNumber
# Get the CommandInputs object associated with the parent command.
cmdInputs = adsk.core.CommandInputs.cast(tableInput.commandInputs)
# Create three new command inputs.
valueInput = cmdInputs.addValueInput('TableInput_value{}'.format(_rowNumber), 'Value', 'cm', adsk.core.ValueInput.createByReal(_rowNumber))
stringInput = cmdInputs.addStringValueInput('TableInput_string{}'.format(_rowNumber), 'String', str(_rowNumber))
spinnerInput = cmdInputs.addIntegerSpinnerCommandInput('spinnerInt{}'.format(_rowNumber), 'Integer Spinner', 0 , 100 , 2, int(_rowNumber))
# Add the inputs to the table.
row = tableInput.rowCount
tableInput.addCommandInput(valueInput, row, 0)
tableInput.addCommandInput(stringInput, row, 1)
tableInput.addCommandInput(spinnerInput, row, 2)
# Increment a counter used to make each row unique.
_rowNumber = _rowNumber + 1
# Event handler that reacts to any changes the user makes to any of the command inputs.
class MyCommandInputChangedHandler(adsk.core.InputChangedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
eventArgs = adsk.core.InputChangedEventArgs.cast(args)
inputs = eventArgs.inputs
cmdInput = eventArgs.input
# table input Click Button Event
tableInput = inputs.itemById('table')
if cmdInput.id == 'tableAdd':
addRowToTable(tableInput)
elif cmdInput.id == 'tableDelete':
if tableInput.selectedRow == -1:
_ui.messageBox('Select one row to delete.')
else:
tableInput.deleteRow(tableInput.selectedRow)
except:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Event handler that reacts when the command definitio is executed which
# results in the command being created and this event being fired.
class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
# Get the command that was created.
cmd = adsk.core.Command.cast(args.command)
# Connect to the input changed event.
onInputChanged = MyCommandInputChangedHandler()
cmd.inputChanged.add(onInputChanged)
_handlers.append(onInputChanged)
# Get the CommandInputs collection associated with the command.
inputs = cmd.commandInputs
# Create table input
tableInput = inputs.addTableCommandInput('table', 'Table', 3, '1:1:1')
addRowToTable(tableInput)
# Add inputs into the table.
addButtonInput = inputs.addBoolValueInput('tableAdd', 'Add', False, '', True)
tableInput.addToolbarCommandInput(addButtonInput)
deleteButtonInput = inputs.addBoolValueInput('tableDelete', 'Delete', False, '', True)
tableInput.addToolbarCommandInput(deleteButtonInput)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def run(context):
try:
global _app, _ui
_app = adsk.core.Application.get()
_ui = _app.userInterface
cmdDefs :adsk.core.CommandDefinitions = _ui.commandDefinitions
global _cmdInfo
cmdDef :adsk.core.CommandDefinition = cmdDefs.itemById(_cmdInfo[0])
if cmdDef:
cmdDef.deleteMe()
cmdDef = cmdDefs.addButtonDefinition(_cmdInfo[0],_cmdInfo[1],_cmdInfo[2])
global _handlers
onCommandCreated = MyCommandCreatedHandler()
cmdDef.commandCreated.add(onCommandCreated)
_handlers.append(onCommandCreated)
cmdDef.execute()
adsk.autoTerminate(False)
except:
if _ui:
_ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))