拒绝SQL恐惧:用Python+pyqt打造任意Excel数据库查询系统

一、引言

在数字化转型浪潮中,超过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, QtWidgetsclass 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.translateForm.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 = Trueself.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 = -1for i in range(0, len(self.wenjian_df)):if str(self.wenjian_df.iloc[i,0]) == self.lineEdit.text():hangsuoyin = ibreakchaxunzhi = 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:# 获取原始dfyuanshi_df = pd.read_excel(filepath)if not yuanshi_df.empty:QtWidgets.QMessageBox.information(None, "成功", "上传成功!")return yuanshi_dfelse:QtWidgets.QMessageBox.critical(None, "提示", "请检查操作步骤或上传文件!")else:QtWidgets.QMessageBox.critical(None, "提示", "请选择XLSX工作表类型!")return pd.DataFrame()

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

四、总程序代码Kebiao_query.py

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 = Falsedef shangchuan_wenjian(self):self.wenjian_df = shangchuan()if not self.wenjian_df.empty:self.shangchuan_flag = Trueself.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 = -1for i in range(0, len(self.wenjian_df)):if str(self.wenjian_df.iloc[i,0]) == self.lineEdit.text():hangsuoyin = ibreakchaxunzhi = 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:# 获取原始dfyuanshi_df = pd.read_excel(filepath)if not yuanshi_df.empty:QtWidgets.QMessageBox.information(None, "成功", "上传成功!")return yuanshi_dfelse: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均可!

欢迎留言/私信沟通交流!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/916302.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/916302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

KubeKey安装KubeSphere、部署应用实践问题总结

使用KubeSphere的KubeKey 安装K8s 集群过程中,碰到了一些问题,现在都一一解决了,以此记录一下。 kubekey 安装k8s 集群报错 execute task timeout, Timeout1m error: Pipeline[CreateClusterPipeline] execute failed: Module[GreetingsModul…

基于粒子群优化的PID控制在药液流量控制系统中的应用

基于粒子群优化的PID控制在药液流量控制系统中的应用 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家,觉得好请收藏。点击跳转到网站。 1. 引言 在现代工业控制系统中,精确的流量控制是许多生产过程的关键环节。本文针对药液流量控制…

不用电脑要不要关机?

1. 短时间不用(午休、临时外出):建议「睡眠」或「休眠」睡眠:电脑暂停工作,唤醒速度快,耗电较少适合需要快速恢复工作的场景休眠:整机断电,唤醒速度比睡眠慢,但完全不耗电…

【Spring AI】SiliconFlow-硅基流动

硅基流动 https://docs.siliconflow.cn/cn/userguide/introduction

swagger基本注解@Tag、@Operation、@Parameters、@Parameter、@ApiResponse、@Schema

swagger基本注解 Tag 介绍:用于给接口分组,用途类似于为接口文档添加标签。用于:方法、类、接口。常用属性: name:分组的名称 RestController RequestMapping("/sysUser") Tag(name "管理员接口&quo…

Unity 实现帧率(FPS)显示功能

一、功能介绍本教程实现一个 FPS 显示脚本,支持 TextMeshProUGUI 组件。脚本会每秒更新一次帧率,并显示在 UI 上,便于开发和调试时观察性能变化。二、完整代码将以下代码保存为 FPS.cs 脚本:using UnityEngine; using TMPro;[Requ…

【星野AI】minimax非活动时间充值优惠漏洞

点开发现有活动即将开启。把手机时间修改为20250729,或者其它活动内时间。发现活动的充值接口未进行时间校验。叠加新人首充优惠,充值六元,获得1800钻。在非活动时间获取了优惠。

Python 程序设计讲义(22):循环结构——for 循环

Python 程序设计讲义(22):循环结构——for 循环 目录Python 程序设计讲义(22):循环结构——for 循环一、for 循环的语法二、for 循环执行的流程三、for 循环应用举例while 循环的循环次数往往是不确定的&am…

自动驾驶---视觉语言模型(VLM)引导的模型预测控制器(MPC)

1 背景之前大家普遍认为的端到端就是传感器输入,控制输出,这也确实是真正的端到端,但目前车企走的更多的是轨迹生成。自动驾驶端到端控制瓶颈主要有以下两点:可解释性缺失:传统端到端模型(如纯VLM控制器&am…

最优估计准则与方法(5)加权最小二乘估计(WLS)_学习笔记

前言 最优估计理论中研究的最小二乘估计(LS)为线性最小二乘估计(LLS),包括古典最小二乘估计(CLS)[1]、加权最小二乘估计(WLS)和递推最小二乘估计(RLS&#x…

Linux——线程互斥

文章目录一、有关概念原子性错误认知澄清加锁二、锁的相关函数全局锁局部锁初始化销毁加锁解锁三、锁相关如何看待锁一个线程在执行临界区的代码时,可以被切换吗?锁是本身也是临界资源,它如何做到保护自己?(锁的实现&a…

扣子(Coze)宣布开源两大核心项目——Coze Studio(扣子开发平台)和Coze Loop(扣子罗盘),附安装步骤

2025年7月26日,字节跳动旗下AI开发平台“扣子(Coze)”宣布开源两大核心项目——Coze Studio(扣子开发平台)和Coze Loop(扣子罗盘),采用Apache 2.0协议,支持免费商用及本地化部署。 开源内容 Coze Studio:提供可视化AI智能体开发工具,支持零代码/低代码拖拽式工作流编…

InfluxDB Flux 查询协议实战应用(二)

四、实战案例解析4.1 服务器性能监控数据查询在服务器性能监控场景中,InfluxDB 和 Flux 查询协议能够发挥重要作用,帮助运维人员实时了解服务器的运行状态,及时发现性能问题。假设我们的服务器性能监控数据存储在名为server-monitoring的存储…

二层隧道协议(PPP、PPTP、L2TP)

PPP —— 点对点链路上的“链路层会话层”协议,解决拨号认证、IP 分配和多协议封装。PPTP —— 在 IP 网络里开一条“PPP-over-GRE”隧道,把 PPP 封装进公共网络,速度快但已不安全。L2TP —— 在 IP/UDP 里再开一条“PPP-over-UDP”隧道&…

openmv特征点检测

AGAST 角点检测器和 FAST 角点检测器: 两者都是计算机视觉中快速检测图像角点的算法,核心目的是高效找到图像中 "有辨识度的点",但细节略有不同: (1)FAST 角点检测器 • 特点:速度极快…

基于深度学习的CT图像3D重建技术研究

基于深度学习的CT图像3D重建技术研究 摘要 本文详细探讨了使用深度学习技术进行CT(计算机断层扫描)图像3D重建的全过程。我们从CT成像基本原理出发,系统介绍了数据预处理、深度学习模型构建、训练优化以及三维可视化等关键技术环节。研究采用了先进的深度学习架构如3D U-Net…

JVM相关面试八股

什么是双亲委派模型? 如果一个类加载器在接到加载类的请求时,它首先不会自己尝试去加载这个类,而是把这个请求任务委托给父类加载器去完成,依次递归,如果父类加载器可以完成类加载任务,就返回成功&#xff…

Javaweb————HTTP消息体拆分讲解

❤️❤️❤️一.HTTP请求消息结构 (1)请求行 💙 请求方法 💙URL地址 💙协议名 (2)请求头 报文头包含若千个属性格式为“属性名:属性值”, 服务端据此获取客户端的基本信息 (3&…

GitHub的免费账户的存储空间有多少?

GitHub的免费账户在存储空间方面的具体限制如下: 一、普通仓库(非LFS)存储限制 公共仓库 总存储:无明确总容量限制,但建议单个仓库不超过1GB以确保性能。若仓库过大(如超过5GB),可能会收到GitHub的优化提示邮件。 文件大小:单个文件最大100MB,超过100MB的文件会被直…

Java学习|黑马笔记|Day23】网络编程、反射、动态代理

【DAY23】 文章目录【DAY23】一.网络编程1)三要素1.1)IPInetAddress类的使用1.2)端口号1.3)协议2.1)UDP协议发送数据2.2)UDP协议接收数据2.3)UDP的三种通信方式3.1)TCP协议的发送和接…