跳至正文
View Categories

1 min read

    主要内容 #

  1. 保存修改后的表格

完成效果 #

本节课程是简化版Excel的第四节,完成本节课程,能实现将用户修改后的QTableView中的数据保存为新的xlsx文件。

收获 #

学习完本节内容,我们会知道如何修改QTableView的内容,并将新内容保存为新xlsx文件。

1.保存修改后的表格 #

用户可以编辑QTableView中的每一个单元格进行修改,修改完成后,点击保存动作会弹出保存文件对话框,本例中输入Example3_new作为保存文件名,仿照Excel,我们也以xlsx格式保存文件。首先将点击保存动作触发的信号关联到槽函数savefile,通过槽函数来完成保存文件的主要步骤。
在savefile函数中,先通过QTableView的.model()方法获取与QTableView绑定的数据模型,然后逐行读取数据模型中的数据。
最终的结果使用嵌套列表储存,该嵌套列表的每个元素仍然是一个子列表,每个子列表中存的是数据模型一整行的数据,整个嵌套列表就储存了数据模型所有行的数据。最后再次使用pandas库的to_excel函数将结果存为xlsx文件。以下就是本例代码:

from PyQt5.QtWidgets import QMainWindow, QWidget, QAction, QFileDialog, QHeaderView, QApplication, QTableView, \
    QMessageBox
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QIcon
from PyQt5.QtCore import Qt
import sys
import pandas as pd


class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.table = QTableView(self)  # 创建一个QTableView表格视图对象
        self.setCentralWidget(self.table)  # 将该表格试图放在主窗口中间
        self.statusBar().showMessage("Ready")  # 添加状态栏
        openAct = QAction(QIcon("D:\\Python_Tips\\Dashima\\pics\\open.png"), "打开", self)  # 添加打开动作,并设置图标
        saveAct = QAction(QIcon("D:\\Python_Tips\\Dashima\\pics\\save.png"), "保存", self)  # 添加保存动作,并设置图标
        openAct.triggered.connect(self.openfile)  # 点击打开动作触发triggered信号,连接到槽函数openfile
        saveAct.triggered.connect(self.savefile)  # 点击保存动作触发triggered信号,连接到槽函数savefile
        menubar = self.menuBar()  # 添加菜单栏
        fileMenu = menubar.addMenu("文件")  # 添加文件菜单
        fileMenu.addAction(openAct)  # 将打开动作添加到文件菜单
        fileMenu.addAction(saveAct)  # 将保存动作添加到文件菜单
        self.toolbar = self.addToolBar("工具栏")   # 添加工具栏
        self.toolbar.addAction(openAct)  # 将打开动作添加到工具栏
        self.toolbar.addAction(saveAct)  # 将保存动作添加到工具栏
        self.setGeometry(300, 300, 500, 400)
        self.setWindowTitle("简化版Excel")
        self.show()

    def openfile(self):  # 槽函数, 用来打开文件
        self.statusBar().showMessage("正在打开文件")  # 更新状态栏信息
        filepath = "D:\\Python_Tips\\Dashima\\pics"  # 设置打开文件路径
        filename, filetype = QFileDialog.getOpenFileName(
            self, "打开文件", filepath, "XLSX (*.xlsx *.XLSX)"
        )  # 弹出打开文件对话框,只选择Excel的xlsx文件
        if filename:  # 如果文件名不为空,即选择了一个文件
            model = self.getModel(filename)  # 获取模型
            self.table.setModel(model)  # 将模型应用到tableview上去
            self.table.horizontalHeader().setVisible(False)  # 隐藏模型的水平表头
            self.table.verticalHeader().setVisible(False)  # 隐藏模型的垂直表头
            # 让表格的所有列自动拉伸,充满界面
            self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.statusBar().showMessage("文件已成功打开")  # 更新状态栏信息

    def getModel(self, filename):  # 用来制作模型
        data = pd.read_excel(filename, header=None)  # 读取Excel文件,header=None表示不设置表头
        datashape = data.shape  # 获取二维数据的形状
        model = QStandardItemModel(datashape[0], datashape[1])  # 根据数据的形状 创建标准数据模型
        for row in range(datashape[0]):  # 按行循环
            for column in range(datashape[1]):  # 按列循环
                item = data.iloc[row, column]  # 获取row行column列的数据
                item = QStandardItem(str(item))  # 转换为QStandardItem对象
                item.setTextAlignment(Qt.AlignCenter)  # 设置数据居中显示
                model.setItem(row, column, item)  # 给模型的第row行,第column列添加数据
        return model  # 返回创建好的模型

    def savefile(self):  # 用来储存文件
        self.statusBar().showMessage("正在保存文件")  # 更新状态栏信息
        filename2, filetype2 = QFileDialog.getSaveFileName(
            self, "读取文件", "D:\\Python_Tips\\Dashima\\pics", "XLSX (*.xlsx *.XLSX)"
        )  # 存为xlsx文件
        newModel = self.table.model()  # 获取当前的数据视图绑定的数据模型
        data = []  # 用来储存模型中的数据
        for row in range(newModel.rowCount()):  # 按行循环,rowCount()获取行数
            rowRes = []  # 储存模型中的每一行数据
            for column in range(newModel.columnCount()):   # 按列循环,columnCount()获取行数
                index = newModel.index(row, column)  # 获得第row行 column列数据的索引
                item = newModel.data(index)  # 获得第row行 column列数据
                if item != '':
                    rowRes.append(item)  # 如果数据不为空,则添加到行数据列表中
            data.append(rowRes)  # 将行数据列表添加到data列表中
        dataFrame = pd.DataFrame(data)  # 转换为pandas的DataFrame对象
        dataFrame.to_excel(filename2, header=False, index=False)  # 存为excel文件
        self.statusBar().showMessage("保存文件成功!")  # 更新状态栏信息


app = QApplication(sys.argv)  # 创建应用程序
ex = Example()  # 创建窗口对象
sys.exit(app.exec_())  # 设置关闭窗口后结束进程

拓展练习:尝试自定义修改QTableView的单元格内容。

小结 #

  • 学习了如何为保存动作的信号关联槽函数。
  • 学习了如何将修改后的QTableView数据保存为新文件。
  • 习题 #

    1. 习题1:尝试用本程序打开并展示自定义的xlsx文件,自行修改之后再保存为新文件。