Search code examples
pythoncsvpyqt5qtablewidget

Export QTableWidget to CSV including headers


The block of code below works and saves whatever is in my table-widget to a csv file, but it does not include the horizontal headers from the table-widget.

How do I include those?

path = QFileDialog.getSaveFileName(self.tableWidget, 'Save CSV', os.getenv('HOME'), 'CSV(*.csv)')

if path[0] != '':
    with open(path[0], 'w') as csv_file:
        writer = csv.writer(csv_file, dialect='excel',lineterminator='\n')
        for row in range(self.tableWidget.rowCount()):
            row_data = []
            for column in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(row, column)
                if item is not None:
                    row_data.append(item.text())
                else:
                    row_data.append('')
            writer.writerow(row_data)

Solution

  • You can use QTableWidget.horizontalHeaderItem() to get a list of the header labels and QTableWidget.setHorizontalHeaderLabels() to set them. When writing the CSV file, the headers can be written as a initial row before writing all the other rows.

    Here is a simple demo that opens and saves CSV files that have headers:

    import sys, os, csv
    from PyQt5 import QtCore, QtWidgets   
    
    class Window(QtWidgets.QWidget):
        def __init__(self):
            super().__init__()
            self.tableWidget = QtWidgets.QTableWidget()
            self.buttonOpen = QtWidgets.QPushButton('Open')
            self.buttonOpen.clicked.connect(self.handleOpen)
            self.buttonSave = QtWidgets.QPushButton('Save')
            self.buttonSave.clicked.connect(self.handleSave)
            layout = QtWidgets.QGridLayout(self)
            layout.addWidget(self.tableWidget, 0, 0, 1, 2)
            layout.addWidget(self.buttonOpen, 1, 0)
            layout.addWidget(self.buttonSave, 1, 1)
    
        def handleSave(self):
            path, ok = QtWidgets.QFileDialog.getSaveFileName(
                self, 'Save CSV', os.getenv('HOME'), 'CSV(*.csv)')
            if ok:
                columns = range(self.tableWidget.columnCount())
                header = [self.tableWidget.horizontalHeaderItem(column).text()
                          for column in columns]
                with open(path, 'w') as csvfile:
                    writer = csv.writer(
                        csvfile, dialect='excel', lineterminator='\n')
                    writer.writerow(header)
                    for row in range(self.tableWidget.rowCount()):
                        writer.writerow(
                            self.tableWidget.item(row, column).text()
                            for column in columns)
    
        def handleOpen(self):
            path, ok = QFileDialog.getOpenFileName(
                self, 'Open CSV', os.getenv('HOME'), 'CSV(*.csv)')
            if ok:
                self.tableWidget.clear()
                with open(path) as csvfile:
                    reader = csv.reader(csvfile)
                    header = next(reader)
                    self.tableWidget.setColumnCount(len(header))
                    self.tableWidget.setHorizontalHeaderLabels(header)
                    for row, values in enumerate(reader):
                        self.tableWidget.insertRow(row)
                        for column, value in enumerate(values):
                            self.tableWidget.setItem(
                                row, column, QtWidgets.QTableWidgetItem(value))
    
    if __name__ == '__main__':
    
        app = QtWidgets.QApplication(sys.argv)
        window = Window()
        window.setWindowTitle('Test')
        window.setGeometry(600, 100, 460, 280)
        window.show()
        sys.exit(app.exec_())