0

I have a GUI I'm building with PyQt5 and it would be really convenient if I could copy and paste files directly into and from the table widget cells.

The question has already been asked a few times on this site. I tried to apply the accepted answer here as my solution.

My .ui file imported below contains only a table widget of 10 rows and 5 columns made from qtdesigner and nothing else.

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTableWidget, QApplication, QMainWindow, QTableWidgetItem,QFileSystemModel, QFileDialog,QVBoxLayout,QWidget
from PyQt5.QtCore import Qt


from PyQt5.uic import loadUi

import sys, csv, io


class Main_P(QMainWindow):
    
    def __init__(self):
        
        QMainWindow.__init__(self)
        
        loadUi("test_copy&paste.ui",self)
        
        self.tableWidget.installEventFilter(self)
        
        
    def eventFilter(self, source, event):
        if (event.type() == QtCore.QEvent.KeyPress and
            event.matches(QtGui.QKeySequence.Copy)):
            self.copySelection()
            return True
        return super(Main_P, self).eventFilter(source, event)
    
    
    def copySelection(self):
        selection = self.tableWidget.selectedIndexes()
        if selection:
            rows = sorted(index.row() for index in selection)
            columns = sorted(index.column() for index in selection)
            rowcount = rows[-1] - rows[0] + 1
            colcount = columns[-1] - columns[0] + 1
            table = [[''] * colcount for _ in range(rowcount)]
            for index in selection:
                row = index.row() - rows[0]
                column = index.column() - columns[0]
                table[row][column] = index.data()
            stream = io.StringIO()
            csv.writer(stream).writerows(table)
            QtWidgets.qApp.clipboard().setText(stream.getvalue())

        
    
    def keyPressEvent(self, event):
        super().keyPressEvent(event)
        if event.key() == Qt.Key_C and (event.modifiers() & Qt.ControlModifier):
            self.copied_cells = sorted(self.tableWidget.selectedIndexes())
        elif event.key() == Qt.Key_V and (event.modifiers() & Qt.ControlModifier):
            r = self.tableWidget.currentRow() - self.copied_cells[0].row()
            c = self.tableWidget.currentColumn() - self.copied_cells[0].column()
            for cell in self.copied_cells:
                self.setItem(cell.row() + r, cell.column() + c, QTableWidgetItem(cell.data()))
        
        



if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    win = Main_P()
    win.show()
    sys.exit(app.exec_())

I tried to follow the answer as best I could even though it was an answer for a Qtableview and I was using a table widget.

It doesn't work and brings up the error AttributeError: 'Main_P' object has no attribute 'copied_cells' whenever I press ctr+V

How do I go about fixing this?

daniel ajj
  • 83
  • 9
  • The copy feature is already implemented in the `eventFilter`, which already returns `True` in the case of the copy shortcut: `keyPressEvent` won't be called in that case, so there's no `copied_cells`. – musicamante Nov 30 '21 at 15:17
  • Okay, I get that. So is my solution to remove the event filter function? – daniel ajj Dec 01 '21 at 06:19
  • You already get a selection in `copySelection`, just make it an instance attribute: instead of `selection = ...` use `self.copied_cells = ...`. – musicamante Dec 01 '21 at 14:10
  • @musicamante Thank you for your earlier suggestion. I am now able to copy and paste from one table widget to another. However, I am unable to paste data copied from excel into the tablewidget even though I can copy data from the table widget to excel. Any idea why this is? And any idea how to fix it? Thank you. – daniel ajj Dec 16 '21 at 10:28

0 Answers0