Getting Even More Out Of Your Power Tables

Power Tables are, as the name suggests, very powerful. By getting creative with the extension functions, and diving into the underlying Java objects, you can do even more with them. Inductive Automation has a great Knowledgebase article on Power Table extension functions that will give you a good overview of what you can do. Here we will dive a little deeper.

Drag And Drop

At first glance, the drag and drop functionality of Power Tables is already very useful. On the source and destination Power Tables (having the same amount of columns), make sure Row Dragging Enabled is set to True. Then, in the destination Power Table, enable the onRowsDropped extension function, and enter something like the following code:

# turn the first row of the rowData into a list
newRow = [rowData.getValueAt(0, columnIndex) for columnIndex in range(rowData.columnCount)] = system.dataset.addRow(, dropIndexLocation, newRow)

This is a simple way to drag a row from the source Power Table to the destination Power Table. But let’s say that you wanted to drag just one cell instead of a whole row. You’ll notice that the extension function parameters do not include which column was selected on the source Power Table and which column in the destination Power Table you dropped at. Well, we can get both of these in a different way.

sourceCellValue =, sourceTable.selectedColumn)
dropLocation = self.getTable().getDropLocation()
dropRow = dropLocation.getRow()
dropColumn = dropLocation.getColumn() = system.dataset.setValue(, dropLocation.getRow(), dropLocation.getColumn(), sourceCellValue)

For the source Power Table, we get the selectedRow and selectedColumn just from the obvious attributes of the Power Table. For the destination Power Table, we have to dive into the underlying JideTable using self.getTable(). As you can see in the JideTable documentation, there is really a lot we can do with the underlying JideTable.


Using some basic functionality in the configureCell extension function, we can make the Power Table not look like a Power Table at all! Here, I have made it look like a checker board:

import java.awt.Color as Color
colors = [Color(255, 0, 0), Color(0, 0, 0)]
color = colors[(rowIndex + colIndex) % 2]
attributes = {'background': color}
if textValue == 'w': attributes['iconPath'] = 'whiteChecker.png'
elif textValue == 'r': attributes['iconPath'] = 'redChecker.png'
return attributes
I leave it for an exercise for the reader to implement Ignition Power Table Checkers.

In fact, within configureCell, you can set the renderer for the cell to be any JComponent (listed in the Subclasses here). Here we test out a bunch of different JComponents.

import java.awt.Color as Color
import javax.swing.JColorChooser as JColorChooser
import javax.swing.JFileChooser as JFileChooser
import javax.swing.JLabel as JLabel
import javax.swing.JList as JList
import javax.swing.JProgressBar as JProgressBar
import javax.swing.JSlider as JSlider
components = [JColorChooser(), JFileChooser(), JLabel('A JLabel'), JList(['This', 'is', 'a', 'JList']), JProgressBar(), JSlider()]
return {'renderer': components[(rowIndex + colIndex) % len(components)]}
Yes, this is still a Power Table.

As you can see in the configureCell extension function, there are other attributes you can set, too, including foreground, border, font, horizontalAlignment, verticalAlignment, text, and toolTipText.

Editing a Cell

As Chris Powell mentions in this blog post, “even if you have ‘Editable’ selected in the Column Attributes Data, it does not really edit anything.” To actually edit the cell, you have to enable the onCellEdited extension function, and tell Ignition what you want to happen when the user edits the cell. The simplest scenario would be to do the following: = system.dataset.setValue(, rowIndex, colIndex, newValue)

Although, you might want to do some other things when the user edits the cell, like validate the data. Suppose the column was a phone number field. Your onCellEdited function might look like this:

if colName == 'phone number':
        import re
	newValue = re.sub('[ ()\-\+\.]', '', newValue) # remove whitespace and typical phone number chars
	if re.match('[0-9]{10,11}', newValue):
		if len(newValue) == 11: newValue = '-'.join([newValue[0], newValue[1:4], newValue[4:7], newValue[7:11]])
		else: newValue = '-'.join([newValue[0:3], newValue[3:6], newValue[6:10]])
	else: return = system.dataset.setValue(, rowIndex, colIndex, newValue)

And for even easier editing, let’s have the text autoselect when we start editing. In your initialize extension function, use the following:


Power tables are extremely useful. What novel uses have you found for Power Tables in your project?

One thought on “Getting Even More Out Of Your Power Tables

  1. Thanks for the useful tips and ideas.

    “What novel uses have you found for Power Tables in your project?”
    It turns out that the folks looking at data in my PowerTables are often looking up addition information in other sources. I used the “onPopupTrigger” to display a popup menu with ‘intelligent’ copy functions:
    Copy Cell
    Copy Column
    Copy Row
    Save As
    Copy WHERE (not included in the sample code)
    Paste (not included in the sample code – pretty simple compared to your drag-drop stuff)

    The “Copy WHERE” option that places a correctly structured WHERE clause with the primary keys of database tables (e.g. part_number=’partCellData’ and lot_number=’lotCellData’ and etc.) into the copy buffer.
    The database folks love that one.

    This will generate a popup menu to give the user options for getting data
    from the table into the system clipboard or export to a file
    Change Management
    Date Who What
    ———– ————— —————————————————
    02-Sep-2016 Lynn Martineau Original version

    def copyCell( event ):

    def copyRow( event ):
    myData =
    header = system.dataset.getColumnHeaders(myData)
    copyData = ”
    for col in header:
    copyData = copyData + col + ‘\t’
    copyData = copyData + ‘\r\n’
    for col in range(myData.columnCount):
    copyData = copyData + str(myData.getValueAt( rowIndex, col )) + ‘\t’

    def copyCol( event ):
    myData = self.viewDataset
    copyData = colName + ‘\r\n’
    for row in range( myData.rowCount ):
    copyData = copyData + str(myData.getValueAt(row, colName)) + ‘\r\n’

    def saveAs( event ):
    filePath = system.dataset.exportExcel(, 1, self.viewDataset)
    if filePath != None:“file://”+filePath)
    system.gui.errorBox(‘Error Saving File %s’%filePath, ‘Save Error’)

    partAttribute = rowIndex, ‘PART_ATTRIBUTE’ )

    menuItems = []
    menuFunctions = []

    menuItems.append(‘Copy Cell Data (%s)’%str(value))

    menuItems.append(‘Copy Row (%s)’%partAttribute)

    menuItems.append(‘Copy Column (%s)’%colName)

    menuItems.append(‘Save As’)

    menu = system.gui.createPopupMenu( menuItems, menuFunctions )

Leave a Reply

Your email address will not be published. Required fields are marked *