本文主要是介绍Python实现Excel批量样式修改器(附完整代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一...
前言
一个基于 python tkinter 和 openpyxl 的 Excel 文件批量美化工具,支持拖拽操作和灵活的样式配置。
功能特性
核心功能
- 批量处理:支持同时处理多个 Excel 文件
- 拖拽支持:直接拖拽文件到界面即可添加
- 样式自定义:可自定义表头和数据行的字体、字号、背景色
- 居中对齐:支持表头和数据行的水平居中设置
- 背景色控制:可选择是否修改背景色
- Sheet 选择:支持处理所有 Sheet 或指定特定 Sheet
界面特性
- 直观的图形用户界面
- 实时进度显示
- 详细的操作日志
- 颜色选择器
- Sheet 列表查看功能
系统要求
Python 3.6+
依赖库:
tkinter
(Python 内置)openpyxl
tkinterdnd2
安装说明
克隆或下载项目
git clone <repository-url> cd 13-Excel批量样式修改器
安装依赖
pip install openpyxl tkinterdnd2
运行程序
python main.py
使用指南
基本操作流程
1.启动程序
- 双击
main.py
或在命令行运行 - 程序界面将自动打开
2.参数设置
- 表头行号:设置表头所在的行号(默认第1行)
- 字体设置:选择表头和数据行的字体类型和大小
- 背景色设置:点击"选色"按钮选择背景颜色
- 居中选项:勾选是否需要水平居中
- 背景色控制:选择是否修改背景色
3.Sheet 选择
- 处理所有Sheet:默认选项,处理文件中的所有工作表
- 指定Sheet:输入特定的Sheet名称,多个用逗号分隔
- 查看Sheet:点击按钮查看文件中所有可用的Sheet列表
4.添加文件
- 拖拽添加:直接将 Excel 文件拖拽到文件列表区域
- 手动添加:点击"添加文件"按钮选择单个或多个文件
- 批量添加:点击"添加目录"按钮选择包含 Excel 文件的文件夹
5.开始处理
- 点击"开始美化"按钮
- 观察进度条和日志输出
- 等待处理完成
高级功能
Sheet 选择功能
- 查看 Sheet 列表:添加文件后,点击"查看Sheet"按钮可以查看第一个文件中的所有Sheet名称
- 指定 Sheet 处理:在"Sheet名称"输入框中输入要处理的Sheet名称
- 多 Sheet 处理:使用逗号分隔多个Sheet名称,如:
Sheet1, 数据表, Swww.chinasem.cnummary
样式配置技巧
- 表头样式:通常使用较大字号和深色背景,便于区分
- 数据行样式:使用较小字号和浅色背景,保持可读性
- 颜色搭配:建议使用对比度适中的颜色组合
技术实现
核心技术栈
- GUI框架:tkinter + tkinterdnd2(拖拽支持)
- Excel处理:openpyxl
- 多线程:threading(避免界面冻结)
关键函数说明
beautify_onjse_file()
def beautify_one_file(file_path: str, header_row: int, header_font, header_fill, data_font, data_fill, center_header: bool, center_data: bool, change_header_bg: bool = True, change_data_bg: bool = True, sheet_names: list = None):
核心美化函数,负责处理单个Excel文件的样式修改。
参数说明:
file_path
:Excel文件路径header_row
:表头行号header_font/data_font
:字体样式对象header_fill/data_fill
:背景填充对象center_header/center_data
:是否居中对齐change_header_bg/change_data_bg
:是否修改背景色sheet_names
:指定处理的Sheet列表
get_sheet_names()
def get_sheet_names(file_path: str):
获取Excel文件中所有Sheet名称的辅助函数。
设计模式
- MVC模式:界面、逻辑、数据分离
- 观察者模式:GUI事件响应
- 工厂模式:样式对象创建
完整代码
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Excel 批量美化小工具 tkinter + openpyxl,支持拖拽 """ import os import sys import threading from tkinter import * from tkinter import ttk, filedialog, messagebox from tkinter.scrolledtext import ScrolledText try: from tkinterdnd2 import DND_FILES, TkinterDnD except ImportError: messagebox.showerror("依赖缺失", "请先 pip install tkinterdnd2") sys.exit(1) from openpyxl import load_workbook from openpyxl.styles import Alignment, Font, PatternFill # ---------- 工具函数 ---------- def get_sheet_names(file_path: str): """获取Excel文件中所有Sheet的名称""" try: wb = load_workbook(file_path, read_only=True) sheet_names = [ws.title for ws in wb.worksheets] wb.close() return sheet_names except Exception as e: return [] def rgb_to_hex(r, g, b): """将 rgb 整数转 16 进制字符串""" return f"{r:02X}{g:02X}{b:02X}" def hex_to_rgb(hex_color: str): """#RRGGBB 转 (r,g,b)""" hex_color = hex_color.lstrip("#") return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4)) # ---------- 核心逻辑 ---------- def beautify_one_file(file_path: str, header_row: int, header_font, header_fill, data_font, data_fill, center_header: bool, center_data: bool, change_header_bg: bool = True, change_data_bg: bool = True, sheet_names: list = None): """美化单个文件""" wb = load_workbook(file_path) # 如果指定了sheet_names,只处理指定的Sheet;否则处理所有Sheet if sheet_names: worksheets = [ws for ws in wb.worksheets if ws.title in sheet_names] else: worksheets = wb.worksheets for ws in worksheets: max_col = ws.max_column # ----- 表头 ----- for col in range(1, max_col + 1): cell = ws.cell(row=header_row, column=col) cell.font = header_font if change_header_bg: cell.fill = header_fill if center_header: cell.alignment = Alignment(horizontal='center', vertical='center') # ----- 数据行 ----- for row in range(header_row + 1, ws.max_row + 1): for col in range(1, max_col + 1): cell = ws.cell(row=row, column=col) cell.font = data_font if change_data_bg: cell.fill = data_fill if center_data: cell.alignment = Alignment(horizontal='center', vertical='center') wb.save(file_path) # ---------- GUI ---------- class ExcelBeautifier(TkinterDnD.Tk): def __init__(self): super().__init__() self.title("Excel 批量美化工具") self.geometry("700x600") self.resizable(False, False) self.file_list = [] # ---- 顶部参数区 ---- params = LabelFrame(self, text="参数设置", padx=10, pady=10) params.pack(fill=X, padx=10, pady=5) # 表头行号 row_frm = Frame(params) row_frm.pack(anchor=W) Label(row_frm, text="表头所在行号:").pack(side=LEFT) self.header_row_var = IntVar(value=1) Spinbox(row_frm, from_=1, to_=100, textvariable=self.header_row_var, width=5).pack(side=LEFT) # 表头字体/字号/颜色/居中/背景色控制 self.header_font_name = StringVar(value="微软雅黑") self.header_font_size = IntVar(value=12) self.header_hex = StringVar(value="#4472C4") # 默认蓝色 self.center_header = BooleanVar(value=True) self.change_header_bg = BooleanVar(value=True) # 数据行字体/字号/颜色/居中/背景色控制 self.data_font_name = StringVar(value="微软雅黑") self.data_font_size = IntVar(value=10) self.data_hex = StringVar(value="#FFFFFF") self.center_data = BooleanVar(value=False) self.change_data_bg = BooleanVar(value=True) # Sheet选择模式 self.sheet_mode = StringVar(value="all") # "all" 或 "specific" self.sheet_names_input = StringVar(value="") def _add_line(parent, label, font_name, font_size, hex_var, center_var, bg_var): frm = Frame(parent) frm.pack(anchor=W, pady=2) Label(frm, text=label, width=10, anchor=W).pack(side=LEFT) Label(frm, text="字体:").pack(side=LEFT) ttk.Combobox(frm, textvariable=font_name, values=["微软雅黑", "宋体", "Arial", "Calibri"], width=10, state="readonly").pack(side=LEFT) Label(frm, text="字号:").pack(side=LEFT) Spinbox(frm, from_=6, to_=30, textvariable=font_size, width=5).pack(side=LEFT) Label(frm, text="背景色:").pack(side=LEFT) Entry(frm, textvariable=hex_var, width=8).pack(side=LEFT) Button(frm, text="选色", command=lambda: self.choose_color(hex_var)).pack(side=LEFT, padx=2) Checkbutton(frm, text="改变背景色", variable=bg_var).pack(side=LEFT, padx=2) Checkbutton(frm, text="水平居中", variable=center_var).pack(side=LEFT) _add_line(params, "表头:", self.header_font_name, self.header_font_size, self.header_hex, self.center_header, self.change_header_bg) _add_line(params, "数据:", self.data_font_name, self.data_font_size, self.data_hex, self.center_data, self.change_data_bg) # Sheet选择区域 sheet_frm = Frame(params) sheet_frm.pack(anchor=W, pady=5) Label(sheet_frm, text="Sheet选择:", width=10, anchor=W).pack(side=LEFT) Radiobutton(sheet_frm, text="处理所有Sheet", variable=self.sheet_mode, value="all", command=self.on_sheet_mode_change).pack(side=LEFT) Radiobutton(sheet_frm, text="指定Sheet", variable=self.sheet_mode, value="specific", command=self.on_sheet_mode_change).pack(side=LEFT, padx=10) Label(sheet_frm, text="Sheet名称:").pack(side=LEFT) self.sheet_entry = Entry(sheet_frm, textvariable=self.shphpeet_names_input, width=20, state=DISABLED) self.sheet_entry.pack(side=LEFT, padx=2) Button(sheet_frm, text="查看Sheet", command=self.show_sheets).pack(side=LEFT, padx=2) Label(sheet_frm, text="(多个用逗号分隔)", font=("微软雅黑", 8)).pack(side=LEFT) # ---- 文件列表区 ---- list_frame = LabelFrame(self, text="待处理文件(支持拖拽)", padx=10, pady=10) list_frame.pack(fill=BOTH, expand=True, padx=10, pady=5) self.listbox = Listbox(list_frame, selectmode=EXTENDED) self.listbox.pack(side=LEFT, fill=BOTH, expand=True) javascript scroll = Scrollbar(list_frame, orient=VERTICAL) scroll.pack(side=RIGHT, fill=Y) self.listbox.config(yscrollcommand=scroll.set) scroll.config(command=self.listbox.yview) # 拖拽绑定 self.listbox.drop_target_register(DND_FILES) self.listbox.dnd_bind('<<Drop>>', self.on_drop) # ---- 按钮区 ---- btn_bar = Frame(self) btn_bar.pack(fill=X, padx=10, pady=5) Button(btn_bar, text="添加文件", command=self.add_files).pack(side=LEFT, padx=2) Button(btn_bar, text="添加目录", command=self.add_folder).pack(side=LEFT, padx=2) Button(btn_bar, text="移除选中", command=self.remove_selected).pack(side=LEFT, padx=2) Button(btn_bar, text="清空列表", command=self.clear_list).pack(side=LEFT, padx=2) Button(btn_bar, text="开始美化", command=self.start_task, bg="#4472C4", fg="white").pack(side=RIGHT, padx=2) # ---- 日志/进度 ---- bottom = Frame(self) bottom.pack(fill=X, padx=10, pady=5) self.log = ScrolledText(bottom, height=8, state=DISABLED) self.log.pack(fill=X) self.progress = ttk.Progressbar(bottom, orient=HORIZONTAL, mode='determinate') self.progress.pack(fill=X, pady=5) # ---------- 交互 ---------- def on_sheet_mode_change(self): """Sheet选择模式改变时的回调""" if self.sheet_mode.get() == "specific": self.sheet_entry.config(state=NORMAL) else: self.sheet_entry.config(state=DISABLED) self.sheet_names_input.set("") # 清空输入 def show_sheets(self): """显示选中文件的Sheet列表""" if not self.file_list: messagebox.showinfo("提示", "请先添加Excel文件!") return # 获取第一个文件的Sheet列表作为示例 file_path = self.file_list[0] sheet_names = get_sheet_names(file_path) if not sheet_names: messagebox.showerror("错误", f"无法读取文件:{os.path.basename(file_path)}") return # 显示Sheet列表 sheet_list = "\n".join([f"• {name}" for name in sheet_names]) messagebox.showinfo( f"Sheet列表 - {os.path.basename(file_path)}", f"该文件包含以下Sheet:\n\n{sheet_list}\n\n提示:如需处理多个Sheet,请用逗号分隔" ) def choose_color(self, var: StringVar): from tkinter.colorchooser import askcolor _, hex_code = askcolor(color=var.get(), parent=self) if hex_code: var.set(hex_code.upper()) def on_drop(self, event): files = self.tk.splitlist(event.data) self.add_file_list(files) def add_files(self): files = filedialog.askopenfilenames(filetypes=[("Excel 文件", "*.xlsx")]) self.add_file_list(files) def add_folder(self): folder = filedialog.askdirectory() if not folder: return files = [os.path.join(folder, f) for f in os.listdir(folder) if f.lower().endswith(".xlsx")] self.add_file_list(files) def add_file_list(self, files): for f in files: if f not in self.file_list: self.file_list.append(f) self.listbox.insert(END, os.path.basename(f)) def remove_selected(self): for idx in reversed(self.listbox.curselection()): self.listbox.delete(idx) self.file_list.pop(idx) def clear_list(self): self.listbox.delete(0, END) self.file_list.clear() def log_msg(self, msg: str): self.log.config(state=NORMAL) self.log.insert(END, msg + "\n") self.log.see(END) self.log.config(state=DISABLED) self.update() # ---------- 任务 ---------- def start_task(self): if not self.file_list: messagebox.showwarning("提示", "请先添加待处理文件!") return # 禁用按钮防止重复点击 for child in self.winfo_children(): if isinstance(child, Frame): for btn in child.winfo_children(): if isinstance(btn, Button): btn.config(state=DISABLED) self.progress["maximum"] = len(self.file_list) self.progress["value"] = 0 threading.Thread(target=self.worker, daemon=True).start() def worker(self): hdr_font = Font(name=self.header_font_name.get(), size=self.header_font_size.get(), bold=True) hdr_rgb = hex_to_rgb(self.header_hex.get()) hdr_fill = PatternFill(start_color=rgb_to_hex(*hdr_rgb), end_color=rgb_to_hex(*hdr_rgb), fill_type="solid") dat_font = Font(name=self.data_font_name.get(), size=self.data_font_size.get(), bold=False) dat_rgb = hex_to_rgb(self.data_hex.get()) dat_fill = PatternFill(start_color=rgb_to_hex(*dat_rgb), end_color=rgb_to_hex(*dat_rgb), fill_type="solid") # 处理Sheet选择 sheet_names = None if self.sheet_mode.get() == "specific": sheet_input = self.sheet_names_input.get().strip() if sheet_input: sheet_names = [name.strip() for name in sheet_input.split(',') if name.strip()] for idx, file_path in enumerate(self.file_list, 1): self.log_msg(f"[{idx}/{len(self.file_list)}] 处理中:{os.path.basename(file_path)}") try: beautify_one_file( file_path, self.header_row_var.get(), hdr_font, hdr_fill, dat_font, dat_fill, self.center_header.get(), self.center_data.get(), self.change_header_bg.get(), self.change_data_bg.get(), sheet_names ) self.log_msg(" 完成!") except Exception as e: self.log_msg(f" 错误:{e}") self.progress["value"] = idx self.log_msg(">>> 全部任务结束!") # 恢复按钮 for child in self.winfo_children(): if isinstance(child, Frame): for btn in child.winfo_children(): if isinstance(btn, Button): btn.config(state=NORMAL) # ---------- 启动 ---------- if __name__ == "__main__": ExcelBeautifier().mainloop()
界面布局
┌─────────────────────────────────────────┐
│ 参数设置 │
├─────────────────────────────────────────┤
│ 表头行号: [1] &nbjavascriptsp; │
│ 表头: [字体] [字号] [背景色] [选项] │
│ 数据: [字体] [字号] [背景色] [选项] │
│ Sheet选择: ○全部 ○指定 [输入框] [查看] │
├─────────────────────────────────────────┤
│ 待处理文件列表 │
│ (支持拖拽添加文件) │
├─────────────────────────────────────────┤
│ [添加文件] [添加目录] [移除] [清空] [开始] │
├─────────────────────────────────────────┤
│ 操作日志 │
│ [进度条] │
└─────────────────────────────────────────┘
效果图
使用示例
示例1:基础美化
- 设置表头行号为 1
- 表头:微软雅黑,12号,蓝色背景,居中
- 数据:微软雅黑,10号,白色背景,不居中
- 拖拽Excel文件到列表
- 点击"开始美化"
示例2:指定Sheet处理
- 完成基础设置
- 选择"指定Sheet"单选按钮
- 在输入框中输入:
工作表1, 数据统计
- 点击"查看Sheet"确认Sheet名称
- 开始处理
示例3:不修改背景色
- 完成基础设置
- 取消勾选"改变背景色"选项
- 只修改字体样式和对齐方式
- 开始处理
注意事项
- 文件备份:处理前建议备份原始文件
- 文件格式:仅支持
.xlsx
格式的Excel文件 - 文件占用:确保Excel文件未被其他程序打开
- Sheet名称:输入Sheet名称时注意大小写和空格
- 内存使用:处理大量文件时注意内存占用
常见问题
Q: 程序提示"依赖缺失"
A: 请安装 tkinterdnd2:pip install tkinterdnd2
Q: 无法拖拽文件
A: 确保已正确安装 tkinterdnd2 库
Q: 处理时出现错误
A: 检查文件是否被占用,确认文件格式为 .xlsx
Q: Sheet名称输入无效
A: 点击"查看Sheet"按钮确认正确的Sheet名称
Q: 程序界面冻结
A: 大文件处理时属于正常现象,请耐心等待
版本历史
v2.0.0 (最新)
- 新增Sheet选择功能
- 新增背景色控制选项
- 新增Sheet列表查看功能
- 修复多线程处理问题
- 优化界面布局
v1.0.0
- 初始版本发布
- 基础批量美化功能
- 拖拽文件支持
- 样式自定义功能
开发环境设置
- Fork 项目
- 创建功能分支
- 提交更改
- 创建 Pull Request
代码规范
- 遵循 PEP 8 编码规范
- 添加适当的注释和文档
- 保持代码简洁易读
到此这篇关于Python实现Excel批量样式修改器(附完整代码)的文章就介绍到这了,更多相关Python修改Excel样式内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Python实现Excel批量样式修改器(附完整代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!