запись QTableWidget в .csv или .xls

Можно ли записать содержимое QTableWidget в csv? Я нашел вопрос о записи в .xls с помощью xlwt, но, похоже, не могу заставить его работать, используя мой код.

def saveFile(self):
    filename = unicode(QtGui.QFileDialog.getSaveFileName(self, 'Save File', '', ".xls(*.xls)"))    
    wbk = xlwt.Workbook()
    self.sheet = wbk.add_sheet("sheet")
    self.write()
    wbk.save(filename)    


def write(self):
    for col in range (self.coordinates.columnCount()):
        for row in range(self.coordinates.rowCount()):
            text=str(self.coordinates.item(row,col).text())
            self.sheet.write(row,col,text)

Я получаю следующую ошибку:

  File "C:\Users\Tory\Desktop\DIDSON.py", line 186, in saveFile
    self.write()
  File "C:\Users\Tory\Desktop\DIDSON.py", line 192, in write
    text=str(self.coordinates.item(row,col).text())
AttributeError: 'NoneType' object has no attribute 'text'

Почему это? self.coordinates — это виджет QTableWidget. Мне удалось успешно сохранить сами элементы на листе, хотя я все же хотел бы сохранить их как .csv...


person Victoria Price    schedule 26.09.2012    source источник
comment
Почему вы устанавливаете и увеличиваете row и col? Вы можете просто использовать i и x, или я что-то упустил? Было бы полезно для отладки, если бы вы не пытались/исключали, а просто позволяли трассировке печатать и публиковать ее в вопросе.   -  person BrtH    schedule 27.09.2012
comment
И еще, почему вы берете данные из QTableWidget? Если у вас есть данные для помещения в таблицу, почему бы вам не записать эти необработанные данные в csv/xls?   -  person BrtH    schedule 27.09.2012
comment
Первый комментарий - не совсем уверен, на самом деле. Буду пересматривать. Второй вопрос: таблица «записывает» координаты щелчка мыши с изображения, поэтому я хотел бы, чтобы пользователь мог видеть координаты, а затем сохранять готовую версию.   -  person Victoria Price    schedule 27.09.2012


Ответы (1)


Чтобы ответить на вопрос о AttributeError: это, вероятно, происходит из-за того, что в таблице есть пустые строки или столбцы.

Пустая ячейка не имеет назначенного QTableWidgetItem, поэтому table.item() вернет None (который, очевидно, не имеет атрибута 'text').

Чтобы сохранить таблицу в формате csv, попробуйте приведенный ниже пример (который также может открывать файлы csv и, надеюсь, устраняет любые потенциальные проблемы с юникодом):

import sys, csv
from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self, rows, columns):
        QtGui.QWidget.__init__(self)
        self.table = QtGui.QTableWidget(rows, columns, self)
        for column in range(columns - 1):
            for row in range(rows - 1):
                item = QtGui.QTableWidgetItem('Text%d' % row)
                self.table.setItem(row, column, item)
        self.buttonOpen = QtGui.QPushButton('Open', self)
        self.buttonSave = QtGui.QPushButton('Save', self)
        self.buttonOpen.clicked.connect(self.handleOpen)
        self.buttonSave.clicked.connect(self.handleSave)
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.table)
        layout.addWidget(self.buttonOpen)
        layout.addWidget(self.buttonSave)

    def handleSave(self):
        path = QtGui.QFileDialog.getSaveFileName(
                self, 'Save File', '', 'CSV(*.csv)')
        if not path.isEmpty():
            with open(unicode(path), 'wb') as stream:
                writer = csv.writer(stream)
                for row in range(self.table.rowCount()):
                    rowdata = []
                    for column in range(self.table.columnCount()):
                        item = self.table.item(row, column)
                        if item is not None:
                            rowdata.append(
                                unicode(item.text()).encode('utf8'))
                        else:
                            rowdata.append('')
                    writer.writerow(rowdata)

    def handleOpen(self):
        path = QtGui.QFileDialog.getOpenFileName(
                self, 'Open File', '', 'CSV(*.csv)')
        if not path.isEmpty():
            with open(unicode(path), 'rb') as stream:
                self.table.setRowCount(0)
                self.table.setColumnCount(0)
                for rowdata in csv.reader(stream):
                    row = self.table.rowCount()
                    self.table.insertRow(row)
                    self.table.setColumnCount(len(rowdata))
                    for column, data in enumerate(rowdata):
                        item = QtGui.QTableWidgetItem(data.decode('utf8'))
                        self.table.setItem(row, column, item)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window(10, 5)
    window.resize(640, 480)
    window.show()
    sys.exit(app.exec_())
person ekhumoro    schedule 26.09.2012
comment
open может принимать имена файлов в формате Unicode и поступать правильно. Вы можете удалить .encode(sys.getfilesystemencoding()) частей. - person Avaris; 27.09.2012
comment
@Аварис. Это может работать правильно, в зависимости от платформы и конкретной используемой версии/сборки Python, но это не гарантируется. Однако я согласен с тем, что его всегда можно отключить для Windows (которую, я думаю, использует OP). - person ekhumoro; 27.09.2012
comment
Это не гарантировано? Документы говорят, что использование имени файла в формате Unicode по крайней мере то же самое, что явно кодировать его с помощью sys.getfilesystemencoding(). - person Avaris; 28.09.2012
comment
@Аварис. Извините, я пропустил, что вы конкретно имели в виду open. Я имел в виду, что вообще на автоматическое преобразование юникодовых путей полагаться нельзя. Но в любом случае, единственная причина, по которой это было в моем примере, - это копирование и вставка из некоторого существующего кода, поэтому я просто уберу его, чтобы избежать дальнейшей путаницы... - person ekhumoro; 28.09.2012
comment
Большое спасибо, это было очень полезно! - person Victoria Price; 18.10.2012