https://m.toutiao.com/is/i8HoUedJ/?= 你是否曾对处理繁琐的Excel文档感到手足无措?你是否渴望找到一种简单而高效的方法来查询和分析这些海量数据?别担心,我们将向你介绍一个超越传统的解决方案——基于PyQt开发的Excel文档查询软件! 在这个快速发展的世界里,Excel仍然是众多企业和个人使用最广泛的电子表格工具。然而,面对庞大的数据表格,常规的筛选和排序功能往往显得力不从心。现在,借助PyQt框架,你将能够轻松开发一款功能强大、操作简便的Excel文档查询软件,用来管理集群指定目录下的所有excel表格,从而解放你的生产力。 接下来介绍如何编写这样的工具,或许程序功能不是很高端,但是开启自定义编程工具的开始,正所谓千里之行始于足下,勇敢迈出的每一步,都是踏上成功之路的关键。每一次迈进的脚步,都让我们离目标更近一步。 首先,构思软件需要有什么样的界面和功能,下面画一个很简洁的图来展示整个工具的作用和界面 环境准备: python版本:3.10.2 编译器:pycharm(任意一个可编辑代码的工具就成,pycharm代码自动补全的功能比较好) pyqt5版本: 5.15.10 PyQt5-tools版本:PyQt5-tools openpyxl版本: 3.1.2 pandas版本:2.1.3 安装模块: pip install pandas pip install openpyxlpip install pyqt5pip install PyQt5-tools 好的,执行完上面的部分硬件要求以及具备。看起来还是蛮简单的哈。如果想实现一个最简单的pyqt的界面实现可以用以下代码实现:一个空白的界面,没有任何功能
由于前端UI涉及到各个控件的位置的摆放,可以使用PyQt5-tools 工具进行设计,通过该工具可将需要的控件一个一个拖进界面中,之后生成py代码。省去了大部分人工写代码,毕竟专业的事还是用专业的工具的好,生成的图片可在PyQt5-tools工具中直接看到(如何使用PyQt-tools工具可通过:Python Pyqt5快速上手教程_pyqt5教程-CSDN博客 查看) 下面是 直接在PyQt5-tools中展示的软件界面: 将ui文件保存后执行经过简单处理后得到以下py代码,之后代码都在这个基础上完成。 from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QLineEdit, QComboBox,QTableWidget,QSizePolicyfrom PyQt5.QtWidgets import QFrame,QPushButton,QMenuBar,QStatusBar,QMainWindow,QVBoxLayout,QHBoxLayout,QScrollAreafrom PyQt5 import QtCoreclass Ui_MainWindow(QMainWindow): def __init__(self): super().__init__() self.setupUi() def setupUi(self): self.resize(1000, 680) # 设置主窗口初始尺寸 # 创建一个容器用于放置其他组件,放置在主窗口的中心位置 self.centralwidget = QWidget(self) self.setCentralWidget(self.centralwidget) # 创建一个分组框组件 self.groupBox = QGroupBox(self.centralwidget) layout1 = QVBoxLayout() hlayout1 = QHBoxLayout() layout1.addLayout(hlayout1) self.groupBox.setLayout(layout1) self.groupBox.setStyleSheet('QGroupBox { margin: 1px; border: 1px solid lightgrey; }') #指定了 QGroupBox 的内边距为 3 像素 self.comboBox = QComboBox(self.groupBox) # 创建一个下拉框组件 # 设置调整策略为 AdjustToContents,自使用内部名字长度 self.comboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents) hlayout1.addWidget(self.comboBox) self.comboBox.setFixedHeight(23)#设置高度 self.comboBox.setFixedWidth(260)#设置宽度 self.lineEdit = QLineEdit(self.groupBox) # 创建输入选择框 self.lineEdit.setFixedHeight(23) hlayout1.addWidget(self.lineEdit) self.pushButton = QPushButton(self.groupBox) # 创建按钮1 self.pushButton.setFixedHeight(23) self.pushButton.setFixedWidth(75) hlayout1.addWidget(self.pushButton) self.pushButton_2 = QPushButton(self.groupBox) # 创建按钮2 self.pushButton_2.setFixedHeight(23) self.pushButton_2.setFixedWidth(75) hlayout1.addWidget(self.pushButton_2) # 创建一个分组框组件,并设置位置和尺寸 self.groupBox_2 = QGroupBox(self.centralwidget) self.line = QFrame(self.centralwidget)#加了条直线,主要是为了美观 self.line.setGeometry(10, 160, 571, 20) self.line.setFrameShape(QFrame.HLine) self.line.setFrameShadow(QFrame.Sunken) self.groupBox_3 = QGroupBox(self.centralwidget)#创建第三个分组框组件 layout2 = QVBoxLayout() hlayout2 = QHBoxLayout() layout2.addLayout(hlayout2) self.groupBox_3.setLayout(layout2) self.tableWidget = QTableWidget(self.groupBox_3) # 创建编辑表格数据的控件 self.tableWidget.setColumnCount(0) self.tableWidget.setRowCount(0) hlayout2.addWidget(self.tableWidget) # 创建一个 QMenuBar 对象 self.menubar,并将其设置为当前窗口的菜单栏 self.menubar = QMenuBar(self) # 设置 self.menubar 的位置和尺寸 self.menubar.setGeometry(0, 0, 604, 21) # 将 self.menubar 设置为当前窗口的菜单栏 self.setMenuBar(self.menubar) # 创建一个 QStatusBar 对象 self.statusbar,用于显示当前窗口的状态栏 self.statusbar = QStatusBar(self) # 将 self.statusbar 设置为当前窗口的状态栏 self.setStatusBar(self.statusbar) self.retranslateUi(self)#是一个自动生成的方法,用于更新界面上的文本内容 QtCore.QMetaObject.connectSlotsByName(self)#是一个用于将信号和槽函数连接起来的方法。在使用 Qt Designer 工具创建界面时,可以在界面中指定某个控件的槽函数。 def resizeEvent(self, event): #设置各个控件随窗口大小而改变 window_size = self.size() self.groupBox.setGeometry(10, 0, window_size.width() - 40, 41) self.groupBox_2.setGeometry(10, 42, window_size.width() - 40, 121) self.line.setGeometry(10, 160, window_size.width() - 40, 20) self.groupBox_3.setGeometry(10, 175, window_size.width() - 40, window_size.height() - 230) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate('MainWindow', '表格管理工具')) self.pushButton.setText(_translate('MainWindow', '搜索')) self.pushButton_2.setText(_translate('MainWindow', '导出'))if __name__ == '__main__': import sys# 引入 sys 模块,用于退出应用程序 app = QApplication([])# 创建一个 QApplication 实例 widget = Ui_MainWindow()# 创建一个 Ui_MainWindow 对象实例 widget.show()# 显示窗口 sys.exit(app.exec_())# 运行应用程序,直到退出 程序界面如下,可大致分为4个功能部分: 需要实现的功能如下:
1.选择输入框:第一个功能实现鼠标点击选择输入框,代码如下:
2.下拉列表:当选择好目录后,需要将该目录下的所有excel表格名称都放到1 位置的下拉列表中,所以可在上面的代码中写入调用方法,通过下面代码可实现将指定目录下的所有目录名添加到下拉列表中: import re #导入re模块,置顶写def setcombox(self,directory): self.comboBox.blockSignals(True)#阻止comboBox触发信号 self.comboBox.clear()#在为combox添加值之前清除combox内的所有内容 self.file_dir = {} pattern = re.compile(r'^[^~].*\.xlsx?$') for item in os.listdir(directory): if pattern.search(item): self.comboBox.addItem(item)#将过滤好的文件名字加入到comboxBox file_data = pd.read_excel(directory +'/'+item) #读取目录下的文件 self.file_dir[item] = file_data#将文件以文件名:文件内容的方式放入到file_dir自动中 self.comboBox.blockSignals(False)#开启comboBox触发信号 界面效果 3.列名和输入框,经展示的列表的列名和输入框显示出来,一般将列表的第一列设为列名
已经在上面方法中编写了连接函数,下面是连接函数的内容,这里面有个自定义属性的方法,obj.setProperty('属性名', 值),可以用这种方式为控件添加属性,用的时候可以obj.property('my_attribute') 来获取自定义属性的值。 def show_data(self): #comboxBox的currentText()方法可以得到下拉列表当前显示的内容 #根据当前显示的内容读取之前定义的字典self.file_dir中对应的表格内容 data = self.file_dir[self.comboBox.currentText()] #得到对应表格内容 self.groupBox_2.setProperty('my_attribute', data) #将展示数据传入自定义属性 titles = data.columns #数据类型为dataframe,可用这种方式获取第一行,一般标题为第一行 # 获取 groupBox 中的布局 the_vbox = self.groupBox_2.layout() if the_vbox: for widget in self.groupBox_2.findChildren(QWidget): # 清除groupBox内所有子元素 widget.deleteLater() else: the_vbox = QVBoxLayout() self.groupBox_2.setLayout(the_vbox) the_grid_layout = QGridLayout() # 使用QGridLayout代替QHBoxLayout the_vbox.addLayout(the_grid_layout) num = 0 grid_row = 0 grid_column = 0 for item in titles: label = QLabel('%s:' % item, self.groupBox) lineedit = QLineEdit(self.groupBox) lineedit.setProperty('my_attribute', item) # 为了区分和标记表格,添加一个自定义属性my_attribute,并将标题赋值给它 lineedit.setFixedHeight(30) the_grid_layout.addWidget(label,grid_row,grid_column) the_grid_layout.addWidget(lineedit,grid_row,grid_column+1) num += 1 if num % 5 == 0: grid_row += 1 grid_column = 0 else: grid_column += 2 #控制列数,每次label和lineedit占用两列所以+2 上面代码实现效果 4,数据展示:好的,现在通过上面代码已经实现了搜索项的展示,下面需要将表格内容展示在主页面位置,在上面函数的尾部写上连接方法,代码实现如下:
def on_text_changed(self, *args): ''' 作为combox触发函数内调用 :param data: dataframe类型数 :return: ''' data = args[0] self.tableWidget.setColumnCount(0) self.tableWidget.setRowCount(0) num_rows, num_cols = data.shape[0], data.shape[1] # 设置QTableWidget的行数和列数 self.tableWidget.setRowCount(num_rows) self.tableWidget.setColumnCount(num_cols) extra_width = 170 # 设置额外宽度 self.tableWidget.resizeColumnsToContents() # 自适应每列宽度 for column in range(self.tableWidget.columnCount()): width = self.tableWidget.columnWidth(column) self.tableWidget.setColumnWidth(column, width + extra_width) self.tableWidget.horizontalHeader().setStretchLastSection(True) # 设置每列的列名 column_names = data.columns self.tableWidget.setHorizontalHeaderLabels(column_names) for i in range(num_rows): for j in range(num_cols): item = QTableWidgetItem(str(data.iloc[i, j])) self.tableWidget.setItem(i, j, item) self.tableWidget.setAlternatingRowColors(True) # 开启交错颜色 执行代码实现界面如下: 5.内容搜索,内容搜索,需要将所有标题输入框内的内容求合集后,展示在数据展示区,
编写搜索按钮的连接函数,即可实现搜索功能 self.pushButton.clicked.connect(self.on_pushButton_clicked)def on_pushButton_clicked(self): line_edits = self.groupBox_2.findChildren(QLineEdit)#获取groupBox_2子属性中全部QLineEdit控件 #将所有QLineEdit列表中每个控件内的值和自定义属性my_attribute的值组成元组(obj1,obj2)并放入到列表select_list中 select_list = [(item.text().strip(), item.property('my_attribute')) for item in line_edits] search_list = [] #定义一个空列表,用来接收所有的搜索到的值 dataframe = self.groupBox_2.property('my_attribute') #获取为self.groupBox_2 自定义的属性值,该值是上面代码放入的表格的dataframe类型数据 for item, line in select_list:#遍历self.groupBox_2控件内所有QLineEdit内的值 item_list = self.search_term(dataframe, line, item) #将表格数据df,列名line,搜索项item传入搜索函数,用来获取搜索到的行号 search_list.append(item_list)#将搜索到的行号全部追加到search_list 列表中 common_elements = set(search_list[0]).intersection(*search_list[1:]) new_df = dataframe.iloc[list(common_elements)] return self.on_text_changed(new_df) 6.信息导出,最后实现信息的导出, 首先写一个可弹出的对话框类:
#为self.pushButton_2 添加连接方法,还是在原来的类Ui_MainWindow中写self.pushButton_2.clicked.connect(self.openDialog)def openDialog(self): rows = self.tableWidget.rowCount()#获取self.tableWidget的行数 cols = self.tableWidget.columnCount()#获取self.tableWidget的列数 if rows != 0: data = [[] for _ in range(rows)] #设置data列表 for row in range(rows): for col in range(cols): item = self.tableWidget.item(row, col) #获取self.tableWidget 中的内容 if item is not None: data[row].append(item.text()) else: data[row].append('') header = [] #设置表格标题 for col in range(cols): header.append(self.tableWidget.horizontalHeaderItem(col).text()) data = pd.DataFrame(data, columns=header) dialog = MyDialog(data) #初始化MyDialog 方法 dialog.setWindowTitle('导出表格') # 设置对话框的标题 dialog.setWindowFlags(dialog.windowFlags() & ~QtCore.Qt.WindowContextHelpButtonHint) # 移除问号图标 dialog.textEdit.setText(dialog.dir) dialog.exec_()#塞程序的执行,直至对话框关闭 最终软件界面如下 一个小工具就这些写完了, 还是蛮简单的哈 |
|
来自: 山峰云绕 > 《Python代码知识游戏黑客编程与英语》