Vision Table onCellEdited system.gui.confirm popup two times

	if system.gui.confirm(u'你确定是要将铜片数量修改么?'):
		CorePlate=self.data.getValueAt(rowIndex,'CorePlate')
		query="""
		UPDATE [dbo].[CorePlate]
		   SET  [Count] =?
		 WHERE CorePlate=?
		"""
		args=[newValue, CorePlate]
		system.db.runPrepUpdate(query,args,"MaluProduction")

Before the people edit the data of a power table, I need popup a confirm window, upside is my current logic, but that will popup two times, how to make this logic popup only 1 time?

1 Like

how you have resolved this problem?
I would also like to do the same.

can you please share some code.
Thanks

This confirmation is also popping up twice for me, any solution yet?

This has to do with how focus can mess with the commit system that the onCellEdited event uses. There is a workaround though. If you move the code out of onCellEdited and into a custom method, you can call it using system.util.invokeLater().
Here’s an example where self.showPopup just contains the same code that used to be in onCellEdited():

1 Like

Thanks for your help. I just tried your tip, but the window is still popping up twice and I’m getting an error with it, perhaps I’m doing it wrong, I’ve never experimented with custom functions. Here is what I have in “onCellEdited”:

def onCellEdited(self, rowIndex, colIndex, colName, oldValue, newValue):
	"""
	Called when the user has edited a cell in the table. It is up to the
	implementation of this function to alter the underlying data that drives
	the table. This might mean altering the dataset directly, or running a SQL
	UPDATE query to update data in a database.

	Arguments:
		self: A reference to the component that is invoking this function.
		rowIndex: Index of the row that was edited, relative to the underlying
		          dataset
		colIndex: Index of the column that was edited, relative to the
		          underlying dataset
		colName: Name of the column in the underlying dataset
		oldValue: The old value at the location, before it was edited
		newValue: The new value input by the user.
	"""
	system.util.invokeLater(self.showPopup(rowIndex, colIndex, colName, oldValue, newValue)) #I'm assuming this is how I pass these values into the custom function, but please correct me if it's wrong
	

Here is what I have in the custom method,(parameters are: colIndex, colName, oldValue, newValue):

def showPopup(self, rowIndex, colIndex, colName, oldValue, newValue):	
	"""
	Arguments:
		self: a reference to the component instance this method is invoked on.
	"""
	customer = self.data.getValueAt(rowIndex, 'Customer')
	product = self.data.getValueAt(rowIndex, 'ProductName')
	
	newText = str(newValue)
	
	if system.gui.confirm(u'Really submit entry "' + newText + '" as ' + colName + ', for customer: ' + customer + ', product: ' + product +'? You cannot undo this action!'):
		# Get the id of the row we edited.
		id = self.data.getValueAt(rowIndex, 'Spec_Index')
	 	
		# Create our query and arguments. The extension function gives us a colName variable,
		# which we can use in our query. The query will then take two arguments.
		# The value that we are updating and the id of the row we edited.
		query = "UPDATE Product_Specs SET %s = ? WHERE Spec_Index = ?" % (colName)
		args = [newValue, id]
		 
		# Run the query with the specified arguments.
		
		system.db.runPrepUpdate(query, args)
		
		# Requery the database, so we can ensure it properly updated the table.
		system.db.refresh(self, "data")

The error is the following:
image
image

Oh right if you need to pass in arguments you are better off using system.util.invokeAsynchronous() I should have suggested that from the start. That function takes in the function as the first argument, then a list of values or dictionary of arguments. Using what you want to pass in, it should look more like:

system.util.invokeAsynchronous(self.showPopup,[rowIndex, colIndex, colName, oldValue, newValue])

Edit:
pturmel is right, this should be called using system.util.invokeLater() not invokeAsynchronous. However this comes with the issue that it cannot have passed in parameters. The script itself would likely have to need some refactoring to have the function itself gather the right info itself or placed directly in the script here so that it has access to the function’s variables.

2 Likes

Perfect, this solved it for me, Thanks @osolorzano!

Ewww! That’s not safe to call from a background thread!

1 Like

I’m having the same problem but don’t need to pass parameters anywhere -
Version 7.9.17; Vision Power Table; Extension Functions; onCellEdited
I just want a confirmation from the user.

response = system.gui.confirm( '<html>SKU <b>%s</b> is not in the database.<br><b>Add %s to the Database?' %(sku,sku), 'Add SKU %s to the Database?' %sku, False )

The code works fine on the first run; after asking the user for a second confirmation, I get database duplicate record error on the second run (easy to try/except out of that).
I added:

if newValue == oldValue:
	return

but it still runs twice.
I’ll try @osolorzano suggestion to invokeLater, just seems unnecessary.

system.util.invokeLater fixes it for me.

I solved this by adding a Boolean custom property to my PowerTable. I named it "isEditing".

I start onCellEdited with

if self.isEditing:
return
self.isEditing = True

Then at every other point I end the function:

self.isEditing = False