Paste data from the clipboard into a table component

I wanted to be able to paste data copied from Excel into a table component on an Ignition screen, and I saw that this thread
already existed, which gave me the basics of how to do it.

I took that code and modified it so that the data is pasted into the existing dataset instead of replacing the data. It handles cases where the pasted data has too many columns or too many rows like this:
Too many columns: pop up a warningBox to say that they need to paste data with less columns.
Too many rows, but same number of columns as original table dataset: paste all the data and extend the length of table.data to fit.
Too many rows and less columns than original table dataset: pop up a confirm dialog asking if they want to truncate the rows at the bottom, or don’t paste any of the data.

The clipboard data is pasted starting at the selectedRow and selectedColumn. I couldn’t figure out how to get the row and column of the right-click event, I only see x-y coordinates.

Here is the code, which I put on the mouseReleased event handler of my table, since we are in a Windows environment.

if event.popupTrigger:
	def pasteData(event):
		from java.awt import Toolkit
		import system
		from java.awt.datatransfer import DataFlavor
		
		#Get data from the clipboard into a string
		clipboard = Toolkit.getDefaultToolkit().getSystemClipboard()
		clipboardString = clipboard.getContents(None).getTransferData(DataFlavor.stringFlavor)
#		print clipboardString

		#Get the current data's headers
		tableData = event.source.data
		tableHeaders = system.dataset.getColumnHeaders(tableData)
#		print tableHeaders

		#Get the selected cell coordinates
		selectedRow = event.source.selectedRow
		selectedColumn = event.source.selectedColumn
#		print selectedRow, selectedColumn

		#Turn the clipboard data into a dataset with correct column headers
		newClipboardData=[]
		rowlist = clipboardString.split("\n") 
		for clipboardRow in rowlist: 
			if len(clipboardRow):
				cells = clipboardRow.split("\t")
#				print cells
				newClipboardData.append(cells)
#		print newClipboardData

		#Figure out which column headers are needed for the new data from clipboard
		clipboardDataWidth = len(newClipboardData[0])
		clipboardDataHeaders = []
		for header in tableHeaders:
			if (tableHeaders.index(header) >= selectedColumn) and (tableHeaders.index(header) < selectedColumn + clipboardDataWidth):
				clipboardDataHeaders.append(header)
#		print clipboardDataHeaders

		try:
			newClipboardDataSet = system.dataset.toDataSet(clipboardDataHeaders,newClipboardData)
			generateNewData = 1
#			print newClipboardDataSet
		except IndexError:
			generateNewData = 0
			system.gui.warningBox("The data you pasted has too many columns to fit here. Please ensure the number of cells you copied will fit in this location and try again.")

		if generateNewData:
			#Create two lists containing the indexes of rows and columns affected by the clipboard data.
			clipboardRowList = []
			clipboardColumnList = []
			for row in range(newClipboardDataSet.rowCount):
				clipboardRowList.append(selectedRow + row)
			for col in range(newClipboardDataSet.columnCount):
				clipboardColumnList.append(selectedColumn + col)
#			print clipboardRowList, clipboardColumnList
	
			#Loop through the table dataset and if you get to the correct coordinates, substitute the data from the clipboard
			newTableData = []
			#If the pasted data includes extra rows with all columns full, append them. Else only paste up to the existing rowCount.
			if len(tableHeaders) == len(clipboardDataHeaders):
				totalRows = max(newClipboardDataSet.rowCount + selectedRow, tableData.rowCount)
				appendAllData = 1
			else:
				totalRows = tableData.rowCount
				appendAllData = 0
			
			for row in range(totalRows):
				oneRow = []
				for col in range(tableData.columnCount):
#					print row, col
					if (row in clipboardRowList) and (col in clipboardColumnList):
						clipboardValue = newClipboardDataSet.getValueAt(row - selectedRow, col - selectedColumn)
						oneRow.append(clipboardValue)
					else:
						tableValue = tableData.getValueAt(row, col)
						oneRow.append(tableValue)
				newTableData.append(oneRow)
			
			#Check to see if any rows were truncated and give user an option to paste anyway.
			if (appendAllData == 0) and (newClipboardDataSet.rowCount + selectedRow > tableData.rowCount):
				confirmed = system.gui.confirm("%d row(s) will be cut off at the bottom of the pasted data. Paste anyway?\n\n" % (newClipboardDataSet.rowCount + selectedRow - tableData.rowCount)+\
					"(To prevent this, ensure pasted data has the same number of columns as the existing data.)")
			else:
				confirmed = 1
			
			if confirmed:
				#Put the new dataset on the table component.
				event.source.data = system.dataset.toDataSet(tableHeaders, newTableData)

	menu = system.gui.createPopupMenu({"Paste Data":pasteData})
	 
	menu.show(event)