准备工作
安装依赖:
确保你已经安装了 pymysql 和 tkinter。可以使用以下命令安装 pymysql:
pip install pymysql
创建配置文件:
创建一个名为 config.ini 的配置文件,内容如下:
[database]
host = localhost
user = your_username
password = your_password
database = your_database
tablename =your_tablename
import pymysql
import tkinter as tk
from tkinter import ttk, messagebox
from tkinter import filedialog
import pandas as pd
from datetime import datetime
import configparser
import time# 读取数据库配置
def load_db_config():config = configparser.ConfigParser()config.read('config.ini')# 以字典的形式返回return {'host': config['database']['host'],'user': config['database']['user'],'password': config['database']['password'],'database': config['database']['database'],'tablename': config['database']['tablename'],}def connect_db():global db_dictdb_dict=load_db_config()"""建立数据库连接"""return pymysql.connect(host=db_dict['host'],user=db_dict['user'],password=db_dict['password'],database=db_dict['database'])def fetch_data(start_date, end_date, selected_columns,select_time):"""根据日期范围查询数据"""connection = connect_db()try:with connection.cursor() as cursor:# 构建查询语句columns_str = ', '.join(selected_columns)query = f"SELECT {columns_str} FROM {db_dict['tablename']} WHERE {select_time} BETWEEN %s AND %s"cursor.execute(query, (start_date, end_date))return cursor.fetchall(), selected_columns # 返回数据和字段名称# 异常写入log 日志中except Exception as e:str_log = (time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))) + ' SQl语句异常: ' + str(e) + '\n'with open('log.txt', 'ab+') as f:f.write(str_log.encode())# 事物回滚connection.rollback()# 事物提交connection.commit()# 关闭数据库connection.close()def save_to_csv(data, columns, filename):"""将查询结果保存为CSV文件"""df = pd.DataFrame(data, columns=columns)df.to_csv(filename, index=False, encoding='utf-8-sig')class App:def __init__(self, root):self.root = rootself.root.title("MySQL Data Query")# 日期输入tk.Label(root, text="开始时间:").grid(row=0, column=0)self.start_date = tk.Entry(root)self.start_date.grid(row=0, column=1)self.start_date.insert(0, (datetime.now().strftime('%Y-%m-%d')+" 00:00:00"))tk.Label(root, text="结束时间:").grid(row=1, column=0)self.end_date = tk.Entry(root)self.end_date.grid(row=1, column=1)self.end_date.insert(0, (datetime.now().strftime('%Y-%m-%d')+" 23:59:59"))# 复选框选择字段self.selected_columns = []self.column_vars = {}self.column_vars2 = {}self.fetch_columns()# 显示字段复选框tk.Label(root, text="选择字段:").grid(row=2, column=0)self.column_frame = tk.Frame(root)self.column_frame.grid(row=3, column=0)for column in self.columns:var = tk.BooleanVar()chk = tk.Checkbutton(self.column_frame, text=column, variable=var)chk.pack(anchor='w')self.column_vars[column] = vartk.Label(root, text="查询时间字段:").grid(row=2, column=1)# 下拉框self.comvalue = tk.StringVar() # 窗体自带的文本,新建一个值self.comboxlist = ttk.Combobox(root, textvariable=self.comvalue) # 初始化self.comboxlist["values"] = self.columns# print(self.comboxlist["values"])self.comboxlist.current(0) # 默认选择第一个# comboxlist.bind("<<ComboboxSelected>>", go) # 绑定事件函数,(下拉列表框被选中时,绑定go()函数)self.comboxlist.grid(row=3, column=1, padx=5, pady=5)# 查询按钮self.query_button = tk.Button(root, text="查询", command=self.query_data)self.query_button.grid(row=4, column=0, columnspan=2)# 显示结果的树形视图self.tree = ttk.Treeview(root)self.tree.grid(row=5, column=0, columnspan=2)# 保存按钮self.save_button = tk.Button(root, text="保存为CSV", command=self.save_data)self.save_button.grid(row=6, column=0, columnspan=2)self.data = []self.columns = []def fetch_columns(self):"""从数据库中获取字段名称"""connection = connect_db()try:with connection.cursor() as cursor:cursor.execute(f"SELECT * FROM {db_dict['tablename']} LIMIT 0") # 查询空数据以获取列名self.columns = [desc[0] for desc in cursor.description]finally:connection.close()def query_data(self):"""执行查询并更新树形视图"""start_date = self.start_date.get()end_date = self.end_date.get()# 获取选中的列self.selected_columns = [col for col, var in self.column_vars.items() if var.get()]if not self.selected_columns or not self.comboxlist.get() :messagebox.showwarning("警告", "请至少选择一个字段!")returntry:self.data, _ = fetch_data(start_date, end_date, self.selected_columns,self.comboxlist.get())self.update_treeview()except Exception as e:messagebox.showerror("查询错误", str(e))def update_treeview(self):"""更新树形视图显示查询结果"""# 清空现有数据for item in self.tree.get_children():self.tree.delete(item)# 设置列名self.tree["columns"] = self.selected_columnsfor col in self.selected_columns:self.tree.heading(col, text=col)# 插入数据for row in self.data:self.tree.insert("", "end", values=row)def save_data(self):"""保存查询结果为CSV文件"""if not self.data:messagebox.showwarning("警告", "没有数据可以保存!")returnfilename = filedialog.asksaveasfilename(defaultextension=".csv",filetypes=[("CSV files", "*.csv"),("All files", "*.*")])if filename:save_to_csv(self.data, self.selected_columns, filename)messagebox.showinfo("保存成功", f"数据已保存为 {filename}")if __name__ == "__main__":root = tk.Tk()app = App(root)root.mainloop()
结果:
1.初始界面
2.查询界面
3.保存界面
代码说明
1. 数据库连接:connect_db 函数用于连接到 MySQL 数据库。
2. 查询数据:fetch_data 函数根据用户输入的开始时间和结束时间以及用户选择的字段查询数据。
3. 保存为 CSV:save_to_csv 函数将查询结果保存为 CSV 文件,使用 pandas 库实现。
4. Tkinter GUI:
- 创建一个 App 类来封装应用程序的所有功能。
- 提供两个日期输入框,用户可以输入开始和结束日期。
- 提供复选框以选择要查询的字段。
- 提供下拉框以选择要查询时间字段。
- 查询按钮用于执行查询,并在树形视图中显示结果。
- 保存按钮允许用户将查询结果保存为 CSV 文件。
- 异常处理:在查询过程中,使用 try-except 块处理潜在的错误,并通过弹出窗口向用户反馈。
5.使用方法
确保已安装所有必需的库。
根据实际情况修改数据库连接信息、查询的表名和日期列名。
运行程序,输入查询的时间范围,选择所需字段,然后点击查询按钮以获取数据,并可以保存为 CSV 文件。