# 新手进阶Python:办公自动化之**全工具整合桌面应用(一键EXE分发)**
本文将介绍如何将Python办公自动化脚本(邮件机器人、数据处理工具等)整合为带图形界面的桌面应用,并打包成EXE文件。主要内容包括: 使用ttkbootstrap库快速开发美观的Python界面 将原有功能模块整合到统一界面中 实现配置保存、日志展示等实用功能 使用pyinstaller打包成独立EXE程序 模块化开发方法,便于功能扩展 文章提供了完整的代码实现和2分钟快速配置指南,帮助新手开发
大家好!我是CSDN的Python新手博主~
前面我们已经完成了办公看板、AI智能助手、邮件自动机器人、数据清洗报表生成四大核心办公自动化工具,彻底解决了日常办公的重复劳动。
但很多新手同学反馈了一个核心痛点:
- 脚本都是命令行运行,新手改参数不方便
- 发给同事用,对方电脑没装Python,根本跑不起来
- 功能分散在不同脚本里,切换起来麻烦
- 没有可视化界面,操作不直观,容易出错
今天就用极简代码,把我们前面所有的办公自动化工具,整合成一个带图形界面的桌面应用,最后打包成EXE文件,无需安装Python,双击就能用,发给同事也能直接跑!
一、本次你能学到什么
- 用
ttkbootstrap快速开发美观的Python桌面界面(新手友好,比PyQt5门槛低) - 把之前的邮件机器人、数据处理工具完整整合到界面中
- 实现配置保存、日志实时展示、文件选择等实用功能
- 用
pyinstaller一键打包成EXE文件,无Python环境也能运行 - 学会模块化开发,后续可以无限扩展新功能
二、前期准备(2分钟搞定)
1. 安装核心依赖
打开命令行执行,一键安装所有需要的库:
# 界面开发库(基于tkinter,Python自带内核,新手零门槛)
pip install ttkbootstrap
# 打包EXE工具
pip install pyinstaller
# 之前功能用到的依赖,确保都安装
pip install pandas openpyxl imaplib2 email python-dotenv
2. 提前准备
把我们之前写的 email_robot.py、data_processor.py 放到同一个文件夹里,后面直接导入复用,不用重复写代码。
三、核心代码:完整桌面应用(复制就能跑)
新建文件 office_automation_app.py,这是我们的主程序,完整代码如下:
# -*- coding: utf-8 -*-
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from ttkbootstrap.dialogs import Messagebox
import tkinter.filedialog as filedialog
import os
import json
from datetime import datetime
from dotenv import load_dotenv
# 导入我们之前写好的功能模块
from email_robot import run_email_robot
from data_processor import run_data_processor
# 加载配置文件
load_dotenv()
CONFIG_FILE = "app_config.json"
# ---------------------------
# 1. 配置管理(保存/读取用户设置)
# ---------------------------
def load_config():
"""读取用户配置,没有则创建默认配置"""
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
return json.load(f)
# 默认配置
default_config = {
"email": os.getenv("EMAIL", ""),
"auth_code": os.getenv("EMAIL_AUTH_CODE", ""),
"imap_server": "imap.163.com",
"raw_data_path": "raw_data",
"output_path": "processed_reports",
"alert_keywords": ["紧急", "重要", "发票", "合同", "报表"]
}
save_config(default_config)
return default_config
def save_config(config):
"""保存用户配置到文件"""
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(config, f, ensure_ascii=False, indent=2)
# 全局配置
app_config = load_config()
# ---------------------------
# 2. 主应用窗口
# ---------------------------
class OfficeAutomationApp(ttk.Window):
def __init__(self):
super().__init__(themename="cosmo") # 主题:cosmo/flatly/solar/darkly
self.title("Python办公自动化工具箱 v1.0")
self.geometry("900x600") # 窗口大小
self.resizable(True, True)
# 全局变量
self.selected_file = None
self.log_text = None
# 构建界面
self.build_ui()
def build_ui(self):
"""构建完整界面布局"""
# 顶部标题
title_label = ttk.Label(
self, text="办公自动化工具箱", font=("微软雅黑", 20, "bold"), bootstyle=PRIMARY
)
title_label.pack(pady=10)
# 选项卡(分功能模块)
notebook = ttk.Notebook(self)
notebook.pack(fill=BOTH, expand=YES, padx=10, pady=5)
# 选项卡1:邮件自动机器人
email_frame = ttk.Frame(notebook, padding=10)
notebook.add(email_frame, text="邮件自动机器人")
self.build_email_tab(email_frame)
# 选项卡2:数据处理与报表生成
data_frame = ttk.Frame(notebook, padding=10)
notebook.add(data_frame, text="数据处理与报表生成")
self.build_data_tab(data_frame)
# 选项卡3:系统设置
config_frame = ttk.Frame(notebook, padding=10)
notebook.add(config_frame, text="系统设置")
self.build_config_tab(config_frame)
# 底部日志区域
log_frame = ttk.LabelFrame(self, text="运行日志", padding=10)
log_frame.pack(fill=BOTH, expand=YES, padx=10, pady=5)
# 日志文本框
self.log_text = ttk.ScrolledText(log_frame, height=8)
self.log_text.pack(fill=BOTH, expand=YES)
self.log_text.insert(END, f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 程序启动成功!\n")
self.log_text.configure(state=DISABLED) # 只读
# ---------------------------
# 选项卡1:邮件机器人界面
# ---------------------------
def build_email_tab(self, parent):
# 功能说明
desc_label = ttk.Label(
parent, text="一键自动收邮件、下载附件、关键词告警、归档到Excel",
font=("微软雅黑", 10), bootstyle=SECONDARY
)
desc_label.grid(row=0, column=0, columnspan=2, sticky=W, pady=5)
# 运行按钮
run_btn = ttk.Button(
parent, text="🚀 一键运行邮件机器人", bootstyle=PRIMARY,
command=self.run_email_robot_ui, width=30
)
run_btn.grid(row=1, column=0, sticky=W, pady=10)
# 打开附件文件夹按钮
open_folder_btn = ttk.Button(
parent, text="📂 打开附件文件夹", bootstyle=INFO,
command=lambda: os.startfile("mail_attachments") if os.path.exists("mail_attachments") else Messagebox.show_warning("文件夹不存在!")
)
open_folder_btn.grid(row=1, column=1, sticky=W, pady=10, padx=10)
# 打开归档Excel按钮
open_excel_btn = ttk.Button(
parent, text="📊 打开邮件归档Excel", bootstyle=SUCCESS,
command=lambda: os.startfile("邮件自动归档.xlsx") if os.path.exists("邮件自动归档.xlsx") else Messagebox.show_warning("文件不存在!")
)
open_excel_btn.grid(row=2, column=0, sticky=W, pady=5)
def run_email_robot_ui(self):
"""界面调用邮件机器人"""
self.update_log("开始运行邮件机器人...")
try:
# 调用之前写好的函数
run_email_robot()
self.update_log("邮件机器人运行完成!附件已下载,归档已完成")
Messagebox.show_info("运行成功", "邮件机器人运行完成!")
except Exception as e:
self.update_log(f"邮件机器人运行失败:{str(e)}")
Messagebox.show_error("运行失败", f"错误:{str(e)}")
# ---------------------------
# 选项卡2:数据处理界面
# ---------------------------
def build_data_tab(self, parent):
# 功能说明
desc_label = ttk.Label(
parent, text="自动读取原始数据、清洗、生成统计报表、插入图表、一键美化",
font=("微软雅黑", 10), bootstyle=SECONDARY
)
desc_label.grid(row=0, column=0, columnspan=4, sticky=W, pady=5)
# 1. 选择数据文件
file_frame = ttk.Frame(parent)
file_frame.grid(row=1, column=0, columnspan=4, sticky=W, pady=5)
ttk.Label(file_frame, text="原始数据文件:", font=("微软雅黑", 10)).pack(side=LEFT, padx=5)
self.file_path_label = ttk.Label(file_frame, text="未选择文件", bootstyle=DANGER)
self.file_path_label.pack(side=LEFT, padx=5)
select_file_btn = ttk.Button(
file_frame, text="选择文件", bootstyle=INFO,
command=self.select_data_file
)
select_file_btn.pack(side=LEFT, padx=10)
# 2. 统计参数设置
param_frame = ttk.LabelFrame(parent, text="统计参数设置", padding=10)
param_frame.grid(row=2, column=0, columnspan=4, sticky=W+E, pady=10)
# 分组列
ttk.Label(param_frame, text="分组列名:", font=("微软雅黑", 10)).grid(row=0, column=0, sticky=W, pady=5, padx=5)
self.group_col_entry = ttk.Entry(param_frame, width=20)
self.group_col_entry.grid(row=0, column=1, sticky=W, padx=5)
self.group_col_entry.insert(0, app_config.get("group_col", "产品"))
# 统计值列
ttk.Label(param_frame, text="统计值列名:", font=("微软雅黑", 10)).grid(row=0, column=2, sticky=W, pady=5, padx=5)
self.value_col_entry = ttk.Entry(param_frame, width=20)
self.value_col_entry.grid(row=0, column=3, sticky=W, padx=5)
self.value_col_entry.insert(0, app_config.get("value_col", "销售额"))
# 图表类型
ttk.Label(param_frame, text="图表类型:", font=("微软雅黑", 10)).grid(row=0, column=4, sticky=W, pady=5, padx=5)
self.chart_type_combo = ttk.Combobox(param_frame, values=["柱状图", "折线图", "饼图"], width=10)
self.chart_type_combo.grid(row=0, column=5, sticky=W, padx=5)
self.chart_type_combo.current(0)
# 3. 运行按钮
run_btn = ttk.Button(
parent, text="🚀 一键生成报表", bootstyle=PRIMARY,
command=self.run_data_processor_ui, width=30
)
run_btn.grid(row=3, column=0, sticky=W, pady=10)
# 打开报表文件夹按钮
open_folder_btn = ttk.Button(
parent, text="📂 打开报表文件夹", bootstyle=INFO,
command=lambda: os.startfile(app_config["output_path"]) if os.path.exists(app_config["output_path"]) else Messagebox.show_warning("文件夹不存在!")
)
open_folder_btn.grid(row=3, column=1, sticky=W, pady=10, padx=10)
def select_data_file(self):
"""选择原始数据文件"""
file_path = filedialog.askopenfilename(
title="选择原始数据文件",
filetypes=[("Excel文件", "*.xlsx"), ("CSV文件", "*.csv"), ("所有文件", "*.*")]
)
if file_path:
self.selected_file = file_path
self.file_path_label.config(text=os.path.basename(file_path), bootstyle=SUCCESS)
self.update_log(f"已选择数据文件:{file_path}")
def run_data_processor_ui(self):
"""界面调用数据处理工具"""
if not self.selected_file:
Messagebox.show_warning("警告", "请先选择原始数据文件!")
return
# 获取参数
group_col = self.group_col_entry.get().strip()
value_col = self.value_col_entry.get().strip()
chart_type_map = {"柱状图": "bar", "折线图": "line", "饼图": "pie"}
chart_type = chart_type_map[self.chart_type_combo.get()]
if not group_col or not value_col:
Messagebox.show_warning("警告", "请填写分组列名和统计值列名!")
return
self.update_log("开始运行数据处理工具...")
try:
# 调用之前写好的函数
file_name = os.path.basename(self.selected_file)
# 把文件复制到raw_data文件夹
if not os.path.exists(app_config["raw_data_path"]):
os.mkdir(app_config["raw_data_path"])
target_path = os.path.join(app_config["raw_data_path"], file_name)
with open(self.selected_file, "rb") as f1, open(target_path, "wb") as f2:
f2.write(f1.read())
# 运行数据处理
output_file = run_data_processor(file_name, group_col, value_col, chart_type)
self.update_log(f"数据处理完成!报表已保存至:{output_file}")
Messagebox.show_info("运行成功", "报表生成完成!")
except Exception as e:
self.update_log(f"数据处理失败:{str(e)}")
Messagebox.show_error("运行失败", f"错误:{str(e)}")
# ---------------------------
# 选项卡3:系统设置界面
# ---------------------------
def build_config_tab(self, parent):
# 邮箱设置
email_frame = ttk.LabelFrame(parent, text="邮箱配置", padding=10)
email_frame.pack(fill=X, pady=5)
# 邮箱地址
ttk.Label(email_frame, text="邮箱地址:", font=("微软雅黑", 10)).grid(row=0, column=0, sticky=W, pady=5, padx=5)
self.email_entry = ttk.Entry(email_frame, width=30)
self.email_entry.grid(row=0, column=1, sticky=W, padx=5)
self.email_entry.insert(0, app_config["email"])
# 授权码
ttk.Label(email_frame, text="邮箱授权码:", font=("微软雅黑", 10)).grid(row=0, column=2, sticky=W, pady=5, padx=5)
self.auth_code_entry = ttk.Entry(email_frame, width=30, show="*")
self.auth_code_entry.grid(row=0, column=3, sticky=W, padx=5)
self.auth_code_entry.insert(0, app_config["auth_code"])
# IMAP服务器
ttk.Label(email_frame, text="IMAP服务器:", font=("微软雅黑", 10)).grid(row=1, column=0, sticky=W, pady=5, padx=5)
self.imap_entry = ttk.Entry(email_frame, width=30)
self.imap_entry.grid(row=1, column=1, sticky=W, padx=5)
self.imap_entry.insert(0, app_config["imap_server"])
# 告警关键词
ttk.Label(email_frame, text="告警关键词(逗号分隔):", font=("微软雅黑", 10)).grid(row=1, column=2, sticky=W, pady=5, padx=5)
self.keywords_entry = ttk.Entry(email_frame, width=30)
self.keywords_entry.grid(row=1, column=3, sticky=W, padx=5)
self.keywords_entry.insert(0, ",".join(app_config["alert_keywords"]))
# 保存设置按钮
save_btn = ttk.Button(
parent, text="💾 保存设置", bootstyle=SUCCESS,
command=self.save_config_ui, width=20
)
save_btn.pack(pady=10)
# 主题切换
theme_frame = ttk.LabelFrame(parent, text="界面主题", padding=10)
theme_frame.pack(fill=X, pady=5)
ttk.Label(theme_frame, text="选择主题:", font=("微软雅黑", 10)).pack(side=LEFT, padx=5)
self.theme_combo = ttk.Combobox(
theme_frame,
values=["cosmo", "flatly", "solar", "darkly", "vapor", "minty"],
width=15
)
self.theme_combo.pack(side=LEFT, padx=5)
self.theme_combo.current(0)
change_theme_btn = ttk.Button(
theme_frame, text="切换主题", bootstyle=INFO,
command=self.change_theme
)
change_theme_btn.pack(side=LEFT, padx=10)
def save_config_ui(self):
"""保存用户设置"""
global app_config
app_config = {
"email": self.email_entry.get().strip(),
"auth_code": self.auth_code_entry.get().strip(),
"imap_server": self.imap_entry.get().strip(),
"raw_data_path": "raw_data",
"output_path": "processed_reports",
"alert_keywords": [kw.strip() for kw in self.keywords_entry.get().split(",") if kw.strip()],
"group_col": self.group_col_entry.get().strip(),
"value_col": self.value_col_entry.get().strip()
}
save_config(app_config)
# 更新环境变量,给邮件机器人用
os.environ["EMAIL"] = app_config["email"]
os.environ["EMAIL_AUTH_CODE"] = app_config["auth_code"]
self.update_log("系统设置已保存!")
Messagebox.show_info("保存成功", "系统设置已保存!")
def change_theme(self):
"""切换界面主题"""
new_theme = self.theme_combo.get()
self.style.theme_use(new_theme)
self.update_log(f"界面主题已切换为:{new_theme}")
# ---------------------------
# 工具函数:更新日志
# ---------------------------
def update_log(self, msg):
"""实时更新日志区域"""
self.log_text.configure(state=NORMAL)
self.log_text.insert(END, f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {msg}\n")
self.log_text.see(END) # 自动滚动到底部
self.log_text.configure(state=DISABLED)
# ---------------------------
# 程序入口
# ---------------------------
if __name__ == "__main__":
app = OfficeAutomationApp()
app.mainloop()
四、运行效果(直接看得到)
- 运行代码后,会弹出一个美观的桌面应用窗口,分为3个核心选项卡:
- 邮件自动机器人:一键运行、打开附件、打开归档Excel
- 数据处理与报表生成:选择文件、设置参数、一键生成报表
- 系统设置:配置邮箱、切换主题、保存参数
- 底部有实时运行日志,每一步操作都有记录,出错了能快速定位
- 所有按钮都有友好的提示,无需懂代码,点点鼠标就能用
- 支持主题切换,浅色/深色主题都有,界面美观不卡顿
五、一键打包成EXE(无Python环境也能运行)
代码跑通之后,我们把它打包成EXE文件,发给同事、领导都能直接用,无需安装Python。
1. 打包命令
在命令行执行(确保在代码所在的文件夹里):
pyinstaller -F -w -i app.ico office_automation_app.py
参数说明:
-F:打包成单个EXE文件,方便分发-w:运行时不显示命令行黑窗口,只显示界面-i app.ico:可选,给EXE设置图标(需要准备一个ico格式的图标文件)
2. 打包完成
执行完成后,文件夹里会生成一个 dist 文件夹,里面的 office_automation_app.exe 就是我们的成品!
- 双击就能运行,无需安装Python
- 把之前的
email_robot.py、data_processor.py、app_config.json和EXE放在同一个文件夹里,就能正常使用 - 发给任何Windows电脑都能直接打开
六、可以直接扩展的进阶功能
你可以在这篇基础上随便加,非常适合写进博客:
- 新增功能模块:把之前的AI智能助手、定时任务、看板数据查看都做成新的选项卡
- 增加登录界面:给应用加账号密码,只有授权用户能使用
- 定时任务功能:在界面上设置定时任务,每天自动跑邮件机器人、生成日报
- 数据可视化界面:在界面上直接展示报表图表,不用打开Excel
- 多语言支持:增加中英文切换,适配不同用户
七、博客总结文案(可直接复制)
本篇我们完成了办公自动化工具箱的最终形态:把之前所有分散的脚本,整合成了一个带图形界面的桌面应用,最后打包成了可分发的EXE文件。
从最开始的单功能脚本,到现在的完整桌面应用,我们完成了一整套企业级办公自动化解决方案:
- 底层:数据自动清洗、报表自动生成
- 中间层:邮件自动处理、AI智能交互
- 顶层:可视化桌面应用、一键分发
代码全程新手友好,注释详细,复制就能跑,打包就能用,彻底解决了日常办公的重复劳动,哪怕是完全不懂代码的同事,也能轻松使用。
至此,我们的Python办公自动化系列就完成了从0到1的全流程实战,新手可以基于这个系列,快速打造属于自己的办公自动化神器,告别无效加班!
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)