-1

So I am trying to write a code where a csv file is loaded into a QTableWidget on each tab, which can then be edited and saved over the top of it. However when I save, the program crashes for various reasons. Although the auto loading is not set up, I'm trying to tackle one problem at a time!

I have seen so many posts that seem to ask the same question but when implementing them they do not seem to work, some because they use tableview instead of QTableWidget and some probably because I am failing to properly implement it as I am new to coding.

class MyTabs(QWidget):

def __init__(self, parent):
    super(QWidget, self).__init__(parent)
    layout = QVBoxLayout(self)

    # Initialize tab screen
    self.tabs = QTabWidget()
    self.tabmon = QWidget()
    self.tabtue = QWidget()

    # Add tabs
    self.tabs.addTab(self.tabmon, "Monday")
    self.tabs.addTab(self.tabtue, "Tuesday")

    #Save Button

    self.buttonSavemon = QtWidgets.QPushButton('Save', self)
    self.buttonSavemon.clicked.connect(self.handleSavemon)

    self.buttonSavetue = QtWidgets.QPushButton('Save', self)
    self.buttonSavetue.clicked.connect(self.handleSavetue)

    #Initiate Tables
    self.createTable()

    # Create Monday tab
    self.tabmon_layout = QVBoxLayout(self.tabmon)
    self.tabmon_layout.addWidget(self.tablewidgetmon)
    self.tabmon_layout.addWidget(self.buttonSavemon)

    # Create Tuesday tab
    self.tabtue_layout = QVBoxLayout(self.tabtue)
    self.tabtue_layout.addWidget(self.tablewidgettue)
    self.tabtue_layout.addWidget(self.buttonSavetue)

    # Add tabs to widget
    layout.addWidget(self.tabs)

def createTable(self):
    #Monday Table
    self.tablewidgetmon = QTableWidget()
    self.tablewidgetmon.setRowCount(10)
    self.tablewidgetmon.setColumnCount(2)
    self.tablewidgetmon.setHorizontalHeaderLabels(["Time", "File Name"])

    #Tuesday Table
    self.tablewidgettue = QTableWidget()
    self.tablewidgettue.setRowCount(12)
    self.tablewidgettue.setColumnCount(2)
    self.tablewidgettue.setHorizontalHeaderLabels(["Time", "File Name"])

def handleSavemon(self):
    with open('monschedule.csv', 'wb') as stream:
        writer = csv.writer(stream)
        for row in range(self.tablewidgetmon.rowCount()):
            rowdata = []
            for column in range(self.tablewidgetmon.columnCount()):
                item = self.tablewidgetmon.item(row, column)
                if item is not None:
                    rowdata.append(
                        unicode(item.text()).encode('utf8'))
                else:
                    rowdata.append('')
            writer.writerow(rowdata)

def handleSavetue(self):
    with open('tueschedule.csv', "w") as fileOutput:
        writer = csv.writer(fileOutput)
        for rowNumber in range(self.tablewidgettue.rowCount()):
            fields = [
                self.tablewidgettue.data(
                    self.tablewidgettue.index(rowNumber, columnNumber),
                    QtCore.Qt.DisplayRole
                )
                for columnNumber in range(self.tablewidgettue.columnCount())
            ]
            writer.writerow(fields)

I have tried two methods to save here, with the Monday function seeming the most promising, however giving me an error because the data is string.

From viewing the csv files afterwards it seems it has wiped the original file clean but not saved the new data.

newcoder
  • 5
  • 3

2 Answers2

1

You are opening the file as a binary file instead of a text file. That's why the writerow function expects a byte-like object.

To fix it, remove the 'b' flag in the open call:

with open('monschedule.csv', 'w') as stream:

By the way, the line rowdata.append(unicode(item.text()).encode('utf8')) should be rowdata.append(item.text())

Dimitry Ernot
  • 6,256
  • 2
  • 25
  • 37
0

Try it:

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore    import *
from PyQt5.QtGui     import *
from PyQt5.QtWidgets import *
import csv


class MyTabs(QWidget):
    def __init__(self, parent=None):
        super(QWidget, self).__init__(parent)
        layout = QVBoxLayout(self)

        # Initialize tab screen
        self.tabs = QTabWidget()
        self.tabmon = QWidget()
        self.tabtue = QWidget()

        # Add tabs
        self.tabs.addTab(self.tabmon, "Monday")
        self.tabs.addTab(self.tabtue, "Tuesday")

        #Save Button

        self.buttonSavemon = QtWidgets.QPushButton('Save', self)
        self.buttonSavemon.clicked.connect(self.handleSavemon)

        self.buttonSavetue = QtWidgets.QPushButton('Save', self)
        self.buttonSavetue.clicked.connect(self.handleSavetue)

        #Initiate Tables
        self.createTable()

        # Create Monday tab
        self.tabmon_layout = QVBoxLayout(self.tabmon)
        self.tabmon_layout.addWidget(self.tablewidgetmon)
        self.tabmon_layout.addWidget(self.buttonSavemon)

        # Create Tuesday tab
        self.tabtue_layout = QVBoxLayout(self.tabtue)
        self.tabtue_layout.addWidget(self.tablewidgettue)
        self.tabtue_layout.addWidget(self.buttonSavetue)

        # Add tabs to widget
        layout.addWidget(self.tabs)

    def createTable(self):
        #Monday Table
        self.tablewidgetmon = QTableWidget()
        self.tablewidgetmon.setRowCount(10)
        self.tablewidgetmon.setColumnCount(2)
        self.tablewidgetmon.setHorizontalHeaderLabels(["Time", "File Name"])

        #Tuesday Table
        self.tablewidgettue = QTableWidget()
        self.tablewidgettue.setRowCount(12)
        self.tablewidgettue.setColumnCount(2)
        self.tablewidgettue.setHorizontalHeaderLabels(["Time", "File Name"])


    def handleSavemon(self):
#        with open('monschedule.csv', 'wb') as stream:
        with open('monschedule.csv', 'w') as stream:                  # 'w'
            writer = csv.writer(stream, lineterminator='\n')          # + , lineterminator='\n'
            for row in range(self.tablewidgetmon.rowCount()):
                rowdata = []
                for column in range(self.tablewidgetmon.columnCount()):
                    item = self.tablewidgetmon.item(row, column)
                    if item is not None:
#                        rowdata.append(unicode(item.text()).encode('utf8'))
                        rowdata.append(item.text())                   # +
                    else:
                        rowdata.append('')

                writer.writerow(rowdata)


    def handleSavetue(self):
        with open('tueschedule.csv', "w") as fileOutput:
            writer = csv.writer(fileOutput)
            for rowNumber in range(self.tablewidgettue.rowCount()):
# +                
                fields = [
                    self.tablewidgettue.item(rowNumber, columnNumber).text() \
                            if self.tablewidgettue.item(rowNumber, columnNumber) is not None else ""
                    for columnNumber in range(self.tablewidgetmon.columnCount())
                ]                

                writer.writerow(fields)


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

enter image description here

S. Nick
  • 12,879
  • 8
  • 25
  • 33
  • Thankyou! The 'wb' and Unicode section I get, my mistake for blindly copying code. the line terminator has made it work perfectly, I'm interested, what does that function mean? Since I'm new its nice to understand it – newcoder Aug 08 '19 at 21:05
  • @newcoder see https://docs.python.org/3/library/csv.html#csv.Dialect.lineterminator – S. Nick Aug 08 '19 at 21:11