拒絕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
英文地址,請注明出處:http://en.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協議的發送和接…