it编程 > 前端脚本 > Python

使用Python pyqt打造任意Excel数据库系统

1人参与 2025-07-28 Python

一、引言

在数字化转型浪潮中,超过76%的基层业务人员仍被困在"sql恐惧症"的泥潭里——他们精通业务逻辑却受限于技术门槛,面对海量数据时只能反复请求it部门协助。本项目通过python+pyqt来构建基于excel风格的查询系统,从而打破这种低效循环:pyqt5提供直观界面可视化组件,pandas库实现"无sql"的数据操作转换,对用户上传的任意电子表格excel文件均可完成复杂数据库查询

二、gui界面设计

使用pyqt5进行界面的搭建,最终界面如下:

1.第一步:上传任意excel文件

直接点击上传即可。

这里可选择上传任意填写好的excel文件,但需要注意

①excel文件是纯数据文件不能包含表头、标题行、合并单元格等特殊格式

②excel中的数据量不受限,但要求第一列必须为查找的主键值(主键值是指数据库表中主键字段(或字段组合)所存储的具体数值或字符串,用于唯一标识表中的每一行记录,确保数据可唯一识别和访问),其余列可填写对应数据。

以成绩表作为演示示例:如若想查询全校所有人的各科成绩信息,则第一列应为该学生的学号(主键),其余各列可放置该学生的全部科目成绩。

2.第二步:选择查询字段

在第一步上传任意excel成功后,会自动根据上传文件更新“请选择主键字段”和“请选择待查询字段”内的选项,并且在“请选择主键字段”这一选项下方出现输入框方便用户输入主键内容。对于“请选择主键字段”这一选项,在第一步中已明确规定:excel中第一列为主键字段,所以这里仅额外增加一个选项(以成绩表为例,这里自动增加“学号”字段);而对于“请选择待查询字段”这一选项,会将excel中除第一列以外的所有列名均作为新增选项(以成绩表为例,这里自动增加“语文”、“数学”、“英语”等其他所有字段),效果如下:

3.第三步:输入主键值并查询

选择好主键字段及待查询字段,并输入待查询主键值后,点击“开始查询”即可。

最终查询效果如下:

可以看到,结果被分为两个区域左边表示查询结果(即学生姓名),右边表示与查询结果相关的其他所有excel数据(即除姓名和学号之外,该生的所有成绩信息)。

4.异常提示

若未进行相应的操作,跳过某个步骤或直接点击“开始查询”,则会出现以下的异常提示。

5.界面设计jiemian.py

最后附上通过pyuic5产生的gui界面代码jiemian.py:

# -*- coding: utf-8 -*-

# form implementation generated from reading ui file 'jiemian.ui'
#
# created by: pyqt5 ui code generator 5.15.11
#
# warning: any manual changes made to this file will be lost when pyuic5 is
# run again.  do not edit this file unless you know what you are doing.


from pyqt5 import qtcore, qtgui, qtwidgets


class ui_form(object):
    def setupui(self, form):
        form.setobjectname("form")
        form.setenabled(true)
        form.resize(600, 500)
        form.setminimumsize(qtcore.qsize(600, 500))
        form.setmaximumsize(qtcore.qsize(600, 500))
        icon = qtgui.qicon()
        icon.addpixmap(qtgui.qpixmap(":/image1.png"), qtgui.qicon.normal, qtgui.qicon.off)
        form.setwindowicon(icon)
        self.label_5 = qtwidgets.qlabel(form)
        self.label_5.setgeometry(qtcore.qrect(390, 50, 141, 31))
        font = qtgui.qfont()
        font.setfamily("adobe arabic")
        font.setpointsize(16)
        self.label_5.setfont(font)
        self.label_5.setobjectname("label_5")
        self.label_8 = qtwidgets.qlabel(form)
        self.label_8.setgeometry(qtcore.qrect(220, 20, 231, 31))
        font = qtgui.qfont()
        font.setfamily("adobe arabic")
        font.setpointsize(18)
        font.setbold(false)
        font.setweight(50)
        self.label_8.setfont(font)
        self.label_8.setobjectname("label_8")
        self.label_10 = qtwidgets.qlabel(form)
        self.label_10.setgeometry(qtcore.qrect(470, 40, 71, 51))
        self.label_10.settext("")
        self.label_10.setpixmap(qtgui.qpixmap(":/image1.png"))
        self.label_10.setobjectname("label_10")
        self.label = qtwidgets.qlabel(form)
        self.label.setgeometry(qtcore.qrect(80, 90, 161, 21))
        font = qtgui.qfont()
        font.setfamily("adobe arabic")
        font.setpointsize(12)
        self.label.setfont(font)
        self.label.setobjectname("label")
        self.pushbutton = qtwidgets.qpushbutton(form)
        self.pushbutton.setgeometry(qtcore.qrect(120, 120, 161, 23))
        self.pushbutton.setobjectname("pushbutton")
        self.label_2 = qtwidgets.qlabel(form)
        self.label_2.setgeometry(qtcore.qrect(80, 170, 161, 21))
        font = qtgui.qfont()
        font.setfamily("adobe arabic")
        font.setpointsize(12)
        self.label_2.setfont(font)
        self.label_2.setobjectname("label_2")
        self.combobox = qtwidgets.qcombobox(form)
        self.combobox.setgeometry(qtcore.qrect(120, 200, 161, 22))
        self.combobox.setobjectname("combobox")
        self.combobox.additem("")
        self.combobox_2 = qtwidgets.qcombobox(form)
        self.combobox_2.setgeometry(qtcore.qrect(330, 200, 161, 22))
        self.combobox_2.setobjectname("combobox_2")
        self.combobox_2.additem("")
        self.label_3 = qtwidgets.qlabel(form)
        self.label_3.setgeometry(qtcore.qrect(80, 300, 221, 151))
        font = qtgui.qfont()
        font.setfamily("adobe arabic")
        font.setpointsize(28)
        self.label_3.setfont(font)
        self.label_3.setframeshape(qtwidgets.qframe.styledpanel)
        self.label_3.settext("")
        self.label_3.setalignment(qtcore.qt.aligncenter)
        self.label_3.setobjectname("label_3")
        self.pushbutton_3 = qtwidgets.qpushbutton(form)
        self.pushbutton_3.setgeometry(qtcore.qrect(80, 470, 471, 23))
        self.pushbutton_3.setobjectname("pushbutton_3")
        self.lineedit = qtwidgets.qlineedit(form)
        self.lineedit.setgeometry(qtcore.qrect(120, 250, 161, 20))
        self.lineedit.setobjectname("lineedit")
        self.textedit = qtwidgets.qtextedit(form)
        self.textedit.setgeometry(qtcore.qrect(320, 300, 231, 151))
        self.textedit.setobjectname("textedit")
        self.label_4 = qtwidgets.qlabel(form)
        self.label_4.setgeometry(qtcore.qrect(80, 280, 161, 16))
        self.label_4.setobjectname("label_4")
        self.label_6 = qtwidgets.qlabel(form)
        self.label_6.setgeometry(qtcore.qrect(320, 280, 161, 16))
        self.label_6.setobjectname("label_6")
        self.label_7 = qtwidgets.qlabel(form)
        self.label_7.setgeometry(qtcore.qrect(120, 230, 161, 16))
        self.label_7.setobjectname("label_7")

        self.retranslateui(form)
        qtcore.qmetaobject.connectslotsbyname(form)

    def retranslateui(self, form):
        _translate = qtcore.qcoreapplication.translate
        form.setwindowtitle(_translate("form", "kebiao_query"))
        self.label_5.settext(_translate("form", "designed by"))
        self.label_8.settext(_translate("form", "数据库查询系统"))
        self.label.settext(_translate("form", "一、上传数据文件"))
        self.pushbutton.settext(_translate("form", "点击上传"))
        self.label_2.settext(_translate("form", "二、选择查询字段"))
        self.combobox.setitemtext(0, _translate("form", "请选择主键字段"))
        self.combobox_2.setitemtext(0, _translate("form", "请选择待查询字段"))
        self.pushbutton_3.settext(_translate("form", "开始查询"))
        self.label_4.settext(_translate("form", "查询结果如下:"))
        self.label_6.settext(_translate("form", "相关查询结果如下:"))
        self.label_7.settext(_translate("form", "请输入主键值:"))
import ziyuan_rc

三、主要程序详解

1.导入所需模块

import sys
from jiemian import *
from pyqt5.qtwidgets import qapplication, qwidget
import pandas as pd
# 保持窗口大小和qtdesigner中的一致
from pyqt5 import qtcore
qtcore.qcoreapplication.setattribute(qtcore.qt.aa_enablehighdpiscaling)

不懂为啥需要导入qtcore的,请看一键曝光:python+pyqt实现的文件目录

2.初始化设置

    def __init__(self):
        super(qwidget, self).__init__()
        self.setupui(self)

        self.pushbutton.clicked.connect(self.shangchuan_wenjian)
        self.pushbutton_3.clicked.connect(self.kaishi)
        self.lineedit.setvisible(false)
        self.label_4.setvisible(false)
        self.label_6.setvisible(false)
        self.label_7.setvisible(false)

        self.shangchuan_flag = false

主要将pushbutton绑定于对应的信号函数,并对一些lineedit和label设置visible效果,目的是只有触发某些动作或函数时,才将其显示状态更改为true,否则一直不显示(即false状态);shangchuan_flag作为是否上传任意excel表的标志位。

3.上传文件并更新选项

    def shangchuan_wenjian(self):
        self.wenjian_df = shangchuan()
        if not self.wenjian_df.empty:
            self.shangchuan_flag = true
            self.lineedit.setvisible(true)
            self.label_7.setvisible(true)

            self.columns = self.wenjian_df.columns.tolist()
            self.combobox.clear()
            self.combobox.additem("请选择主键字段")
            self.combobox.additem(self.columns[0])
            self.combobox_2.clear()
            self.combobox_2.additem("请选择待查询字段")
            self.combobox_2.additems(self.columns[1:])

调用自定义函数shangchuan来实现弹窗效果;当文件内容不为空时,设置上传标志位shangchuan_flag为true,并显示lineedit(主键值输入框)和label_7(“请输入主键值”);读取所有文件列名并存储在列表columns中,将列表columns中的第一个值(即第一列的列名)添加至combobox中,其余值添加至combobox_2中。但需要注意:每次添加item(s)前,需要将其原有选项清空clear,否则容易造成选项堆叠重复。

4.查询信息并显示

    def kaishi(self):
        if self.shangchuan_flag==true:
            if self.combobox.currentindex()!=0:
                if self.combobox_2.currentindex()!=0:

                    lieziduan = self.combobox_2.currenttext()
                    liesuoyin = self.wenjian_df.columns.get_loc(lieziduan)

                    # 根据行字段确定行索引
                    hangsuoyin = -1
                    for i in range(0, len(self.wenjian_df)):
                        if str(self.wenjian_df.iloc[i,0]) == self.lineedit.text():
                            hangsuoyin = i
                            break

                    chaxunzhi = self.wenjian_df.iloc[hangsuoyin, liesuoyin]

                    # 匹配剩余未查询值
                    ewai_lst = []
                    for column_name in self.columns:
                        new_column_index = self.wenjian_df.columns.get_loc(column_name)
                        if (new_column_index != liesuoyin) and (new_column_index != 0):
                            ewaizhi = self.wenjian_df.iloc[hangsuoyin, new_column_index]
                            ewai_lst.append(column_name+":"+str(ewaizhi))

                    if pd.isna(chaxunzhi) or hangsuoyin==-1:
                        self.label_4.setvisible(true)
                        self.label_6.setvisible(true)
                        self.label_3.settext("未找到")
                        self.textedit.settext("未找到")
                    else:
                        self.label_4.setvisible(true)
                        self.label_6.setvisible(true)
                        self.label_3.settext(str(chaxunzhi))
                        self.textedit.settext("\n".join(ewai_lst))

                else:
                    qtwidgets.qmessagebox.critical(self, "提示", "请选择主键字段!")
            else:
                qtwidgets.qmessagebox.critical(self, "提示", "请选择待查询字段!")
        else:
            qtwidgets.qmessagebox.critical(self, "提示", "请检查操作步骤或上传文件!")

以shangchaun_flag作为标志位,检查是否上传模板文件;依次判断是否选择每个combobox里的对应选项;若均满足,则根据combobox_2的内容定位列字段名称再根据列字段名称反推列索引根据lineedit内容通过循环查询对应的值,找到后即可退出循环,避免运算复杂度,最终得到行索引最后通过得到的行索引和列索引确定查询值,并通过label_3显示;剩余未查询值,思路方法也是同理,最终显示在textedit中。若遇到查询不到的情况时,显示的内容均设置为“未找到”。当然,哪个combobox有问题,则显示不同的对应提示。

5.自定义函数

def shangchuan():
    filepath, _ = qtwidgets.qfiledialog.getopenfilename(none, "请选择文件", "", "xlsx工作表 (*.xlsx)")  # 获取文件路径
    if filepath:
        # 获取原始df
        yuanshi_df = pd.read_excel(filepath)
        if not yuanshi_df.empty:
            qtwidgets.qmessagebox.information(none, "成功", "上传成功!")
            return yuanshi_df
        else:
            qtwidgets.qmessagebox.critical(none, "提示", "请检查操作步骤或上传文件!")
    else:
        qtwidgets.qmessagebox.critical(none, "提示", "请选择xlsx工作表类型!")
        return pd.dataframe()

一旦需要上传文件时,直接调用此函数即可。

四、总程序代码

import sys
from jiemian import *
from pyqt5.qtwidgets import qapplication, qwidget
import pandas as pd
# 保持窗口大小和qtdesigner中的一致
from pyqt5 import qtcore
qtcore.qcoreapplication.setattribute(qtcore.qt.aa_enablehighdpiscaling)

class mainwindow(qwidget, ui_form):
    def __init__(self):
        super(qwidget, self).__init__()
        self.setupui(self)

        self.pushbutton.clicked.connect(self.shangchuan_wenjian)
        self.pushbutton_3.clicked.connect(self.kaishi)
        self.lineedit.setvisible(false)
        self.label_4.setvisible(false)
        self.label_6.setvisible(false)
        self.label_7.setvisible(false)

        self.shangchuan_flag = false

    def shangchuan_wenjian(self):
        self.wenjian_df = shangchuan()
        if not self.wenjian_df.empty:
            self.shangchuan_flag = true
            self.lineedit.setvisible(true)
            self.label_7.setvisible(true)

            self.columns = self.wenjian_df.columns.tolist()
            self.combobox.clear()
            self.combobox.additem("请选择主键字段")
            self.combobox.additem(self.columns[0])
            self.combobox_2.clear()
            self.combobox_2.additem("请选择待查询字段")
            self.combobox_2.additems(self.columns[1:])

    def kaishi(self):
        if self.shangchuan_flag==true:
            if self.combobox.currentindex()!=0:
                if self.combobox_2.currentindex()!=0:

                    lieziduan = self.combobox_2.currenttext()
                    liesuoyin = self.wenjian_df.columns.get_loc(lieziduan)

                    # 根据行字段确定行索引
                    hangsuoyin = -1
                    for i in range(0, len(self.wenjian_df)):
                        if str(self.wenjian_df.iloc[i,0]) == self.lineedit.text():
                            hangsuoyin = i
                            break

                    chaxunzhi = self.wenjian_df.iloc[hangsuoyin, liesuoyin]

                    # 匹配剩余未查询值
                    ewai_lst = []
                    for column_name in self.columns:
                        new_column_index = self.wenjian_df.columns.get_loc(column_name)
                        if (new_column_index != liesuoyin) and (new_column_index != 0):
                            ewaizhi = self.wenjian_df.iloc[hangsuoyin, new_column_index]
                            ewai_lst.append(column_name+":"+str(ewaizhi))

                    if pd.isna(chaxunzhi) or hangsuoyin==-1:
                        self.label_4.setvisible(true)
                        self.label_6.setvisible(true)
                        self.label_3.settext("未找到")
                        self.textedit.settext("未找到")
                    else:
                        self.label_4.setvisible(true)
                        self.label_6.setvisible(true)
                        self.label_3.settext(str(chaxunzhi))
                        self.textedit.settext("\n".join(ewai_lst))

                else:
                    qtwidgets.qmessagebox.critical(self, "提示", "请选择主键字段!")
            else:
                qtwidgets.qmessagebox.critical(self, "提示", "请选择待查询字段!")
        else:
            qtwidgets.qmessagebox.critical(self, "提示", "请检查操作步骤或上传文件!")

def shangchuan():
    filepath, _ = qtwidgets.qfiledialog.getopenfilename(none, "请选择文件", "", "xlsx工作表 (*.xlsx)")  # 获取文件路径
    if filepath:
        # 获取原始df
        yuanshi_df = pd.read_excel(filepath)
        if not yuanshi_df.empty:
            qtwidgets.qmessagebox.information(none, "成功", "上传成功!")
            return yuanshi_df
        else:
            qtwidgets.qmessagebox.critical(none, "提示", "请检查操作步骤或上传文件!")
    else:
        qtwidgets.qmessagebox.critical(none, "提示", "请选择xlsx工作表类型!")
        return pd.dataframe()

if __name__ == '__main__':
    app = qapplication(sys.argv)
    w = mainwindow()
    w.show()
    sys.exit(app.exec_())

仅以成绩表作为示例,上传其他任意excel均可!

以上就是使用python pyqt打造任意excel数据库系统的详细内容,更多关于python excel数据查询的资料请关注代码网其它相关文章!

(0)

您想发表意见!!点此发布评论

推荐阅读

Python包管理工具核心指令uv sync深入解析

07-28

Python程序打包成EXE的四种方法详解与实战

07-28

Python打造智能批量重命名工具的详细指南

07-28

Python+PyQt实现一键生成文件目录

07-28

flask库中sessions.py的使用小结

07-27

Python中函数的定义、调用及作用说明

07-28

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论