【问题标题】:writing a QTableWidget to a .csv or .xls将 QTableWidget 写入 .csv 或 .xls
【发布时间】:2012-09-18 11:57:46
【问题描述】:

是否可以将 QTableWidget 的内容写入 csv?我发现了一个关于使用 xlwt 写入 .xls 的问题,但似乎无法使用我的代码使其工作。

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 ...

【问题讨论】:

  • 为什么要设置和递增rowcol?您可以只使用ix,还是我错过了什么?如果您不尝试/除外,这对于调试很有用,但只需让跟踪打印并将其发布在问题中。
  • 还有,你为什么要从 QTableWidget 获取数据?如果您有数据要放入表中,为什么不将这些原始数据写入 csv/xls?
  • 第一条评论——实际上并不确定。会修改。第二个问题,表格“记录”图像中的鼠标点击坐标,所以我希望用户能够看到坐标,然后保存完成的版本。

标签: python pyqt qtablewidget xlwt


【解决方案1】:

回答AttributeError的问题:可能是因为表中有一些空行或空列。

空单元格没有分配QTableWidgetItem,因此table.item() 将返回None(显然没有'text' 属性)。

要将表格另存为 csv,请尝试以下示例(它也可以打开 csv 文件,并有望解决任何潜在的 unicode 问题):

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_())

【讨论】:

  • open 可以采用 unicode 文件名并做正确的事情。您可以删除.encode(sys.getfilesystemencoding()) 部分。
  • @Avaris。它可能做正确的事,这取决于平台和使用中的特定 python 版本/构建 - 但不能保证。但是,我同意对于 Windows(我认为 OP 正在使用)始终可以删除它。
  • 不保证? Docs 说使用 unicode 文件名至少与使用 sys.getfilesystemencoding() 显式编码相同。
  • @Avaris。抱歉,我错过了您专门指的是open。我的意思是,一般来说,不能依赖 unicode 路径的自动转换。但无论如何,它出现在我的示例中的唯一原因是从一些现有代码中复制和粘贴 - 所以我将其取出以避免进一步混淆......
  • 非常感谢,这非常有帮助!
猜你喜欢
  • 1970-01-01
  • 2018-05-23
  • 2012-08-02
  • 2017-10-02
  • 1970-01-01
  • 2013-07-01
  • 2018-07-25
  • 2014-12-03
  • 1970-01-01
相关资源
最近更新 更多