点击查看代码
import os
import pandas as pd
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
# --------------- 核心功能函数(移除自动加序号,报错定位问题)---------------
def batch_rename_files(excel_path, file_folder, log_text):
"""
通用批量重命名核心函数(支持所有文件类型,移除自动加序号,报错定位问题)
:param excel_path: Excel文件路径
:param file_folder: 文件文件夹路径
:param log_text: 日志显示文本框
"""
log_text.delete(1.0, tk.END) # 清空日志
try:
# 第一步:建立「双重映射表」(移除图片后缀限制,处理所有文件)
log_text.insert(tk.END, "🔍 正在扫描文件文件夹...\n")
log_text.update()
file_mapping = {}
for file_name in os.listdir(file_folder):
# 跳过文件夹,只处理文件
file_full_path = os.path.join(file_folder, file_name)
if os.path.isdir(file_full_path):
continue
# 为所有文件建立映射(支持带后缀/不带后缀匹配)
file_mapping[file_name] = file_name
file_name_no_ext = os.path.splitext(file_name)[0]
file_mapping[file_name_no_ext] = file_name
# 第二步:读取Excel表格
log_text.insert(tk.END, "📖 正在读取Excel文件...\n")
log_text.update()
df = pd.read_excel(excel_path, header=None, engine="openpyxl")
process_results = []
# 第三步:遍历表格处理(移除自动加序号,直接重命名)
log_text.insert(tk.END, "🚀 开始批量重命名...\n")
log_text.insert(tk.END, "------------------------\n")
log_text.update()
for idx, (_, row) in enumerate(df.iterrows(), 1):
original_name = str(row[0]).strip() if pd.notna(row[0]) else ""
new_name_no_ext = str(row[1]).strip().replace(".0", "") if pd.notna(row[1]) else ""
if not original_name or not new_name_no_ext:
process_results.append("跳过")
log_text.insert(tk.END, f"⏭️ 第{idx}行:数据为空,跳过\n")
continue
if original_name in file_mapping:
original_full_name = file_mapping[original_name]
original_path = os.path.join(file_folder, original_full_name)
ext = os.path.splitext(original_full_name)[1] # 自动获取原文件后缀
new_full_name = f"{new_name_no_ext}{ext}"
new_path = os.path.join(file_folder, new_full_name) # 移除自动加序号
# 直接重命名,不处理重复(重复会触发异常)
os.rename(original_path, new_path)
process_results.append("成功")
log_text.insert(tk.END, f"✅ 第{idx}行:{original_full_name} → {os.path.basename(new_path)}\n")
else:
process_results.append("失败")
log_text.insert(tk.END, f"⚠️ 第{idx}行:未找到对应文件({original_name})\n")
log_text.update()
# 补全结果列表并写入Excel
while len(process_results) < len(df):
process_results.append("无数据")
df[2] = process_results
df.to_excel(excel_path, index=False, header=None, engine="openpyxl")
# 结果统计与提示
log_text.insert(tk.END, "------------------------\n")
log_text.insert(tk.END, f"📝 处理结果已写入Excel C列!\n")
log_text.insert(tk.END, f"🎉 批量重命名完成!共处理{len(df)}行数据\n")
success_count = process_results.count("成功")
fail_count = process_results.count("失败")
skip_count = process_results.count("跳过")
log_text.insert(tk.END, f"📊 统计:成功{success_count} | 失败{fail_count} | 跳过{skip_count}\n")
messagebox.showinfo("成功", f"批量重命名完成!\n成功:{success_count} | 失败:{fail_count} | 跳过:{skip_count}")
except FileExistsError as e:
# 专门捕获文件重名错误,精准提示
error_msg = f"文件重名无法重命名:{str(e)},请检查Excel中B列的新文件名是否重复!"
log_text.insert(tk.END, f"❌ 错误:{error_msg}\n")
messagebox.showerror("重名错误", error_msg)
except FileNotFoundError as e:
error_msg = f"文件未找到:{str(e)},请检查Excel A列的原文件名是否正确!"
log_text.insert(tk.END, f"❌ 错误:{error_msg}\n")
messagebox.showerror("文件不存在", error_msg)
except PermissionError:
error_msg = "权限不足/文件被占用!请检查:1.文件是否被打开 2.是否以管理员身份运行 3.文件夹是否有写入权限"
log_text.insert(tk.END, f"❌ 错误:{error_msg}\n")
messagebox.showerror("权限/占用错误", error_msg)
except Exception as e:
error_msg = f"处理出错:{str(e)},请根据错误信息排查问题!"
log_text.insert(tk.END, f"❌ 错误:{error_msg}\n")
messagebox.showerror("未知错误", error_msg)
# --------------- Tkinter界面函数(无修改)---------------
def select_excel_file(entry):
"""选择Excel文件并填充到输入框"""
file_path = filedialog.askopenfilename(
title="选择Excel文件",
filetypes=[("Excel文件", "*.xlsx"), ("所有文件", "*.*")]
)
if file_path:
entry.delete(0, tk.END)
entry.insert(0, file_path)
def select_file_folder(entry):
"""选择文件文件夹并填充到输入框(通用命名)"""
folder_path = filedialog.askdirectory(title="选择文件文件夹")
if folder_path:
entry.delete(0, tk.END)
entry.insert(0, folder_path)
def start_process(excel_entry, folder_entry, log_text):
"""开始处理按钮的回调函数"""
excel_path = excel_entry.get().strip()
file_folder = folder_entry.get().strip()
# 验证路径
if not excel_path:
messagebox.warning("提示", "请先选择Excel文件!")
return
if not file_folder:
messagebox.warning("提示", "请先选择文件文件夹!")
return
if not os.path.exists(excel_path):
messagebox.warning("提示", "选择的Excel文件不存在!")
return
if not os.path.exists(file_folder):
messagebox.warning("提示", "选择的文件文件夹不存在!")
return
# 执行通用重命名
batch_rename_files(excel_path, file_folder, log_text)
# --------------- 主界面搭建(无修改)---------------
def create_main_window():
root = tk.Tk()
root.title("通用文件批量重命名工具(支持PDF/Word/Excel/图片等)")
root.geometry("800x700")
root.resizable(True, True)
# 样式配置
style = ttk.Style(root)
style.configure("TLabel", font=("微软雅黑", 10))
style.configure("TButton", font=("微软雅黑", 10))
style.configure("TEntry", font=("微软雅黑", 10))
style.configure("Warning.TLabel", font=("微软雅黑", 10, "bold"), foreground="#D83A56")
style.configure("Accent.TButton", font=("微软雅黑", 10, "bold"), foreground="black", background="#E0E0E0")
# 1. Excel文件选择区域
ttk.Label(root, text="Excel文件路径:").grid(
row=0, column=0, padx=10, pady=10, sticky="w"
)
excel_entry = ttk.Entry(root, width=60)
excel_entry.grid(row=0, column=1, padx=5, pady=10, sticky="we")
ttk.Button(
root, text="选择文件",
command=lambda: select_excel_file(excel_entry)
).grid(row=0, column=2, padx=5, pady=10)
# 2. 文件文件夹选择区域(通用命名)
ttk.Label(root, text="文件文件夹路径:").grid(
row=1, column=0, padx=10, pady=10, sticky="w"
)
folder_entry = ttk.Entry(root, width=60)
folder_entry.grid(row=1, column=1, padx=5, pady=10, sticky="we")
ttk.Button(
root, text="选择文件夹",
command=lambda: select_file_folder(folder_entry)
).grid(row=1, column=2, padx=5, pady=10)
# 先定义log_text(修复变量作用域)
ttk.Label(root, text="处理日志:").grid(
row=5, column=0, padx=10, pady=5, sticky="w"
)
log_text = tk.Text(root, width=90, height=20, font=("微软雅黑", 9))
log_scroll = ttk.Scrollbar(root, orient="vertical", command=log_text.yview)
log_text.configure(yscrollcommand=log_scroll.set)
log_text.grid(row=6, column=0, columnspan=2, padx=10, pady=5, sticky="nsew")
log_scroll.grid(row=6, column=2, padx=0, pady=5, sticky="ns")
# 3. 开始处理按钮
ttk.Button(
root, text="开始批量重命名", style="Accent.TButton",
command=lambda: start_process(excel_entry, folder_entry, log_text)
).grid(row=2, column=0, columnspan=3, pady=20)
# 4. 注意事项区域(适配通用文件)
ttk.Label(root, text="⚠️ 注意事项", style="Warning.TLabel").grid(
row=3, column=0, columnspan=3, padx=10, pady=(0, 5), sticky="w"
)
notice_text = tk.Text(root, width=90, height=4, font=("微软雅黑", 9), bg="#F8F9FA", state="disabled")
notice_text.grid(row=4, column=0, columnspan=3, padx=10, pady=(0, 10), sticky="we")
notice_text.configure(state="normal")
notice_content = """1. Excel表格A列:填写需要重命名的文件原文件名(支持带后缀如"报告1.pdf" 或 不带后缀如"报告1")
2. Excel表格B列:填写文件的新文件名(仅需名称,不要带后缀!程序会自动继承原文件的.pdf/.docx/.xlsx等后缀)
3. 处理完成后,Excel表格C列会自动写入「成功/失败/跳过」(执行时关闭Excel,避免占用)
4. 若新文件名重复会直接报错,请确保B列新文件名无重复!""" # 新增重名提示
notice_text.insert(tk.END, notice_content)
notice_text.configure(state="disabled")
# 调整列/行权重
root.grid_columnconfigure(1, weight=1)
root.grid_rowconfigure(6, weight=1)
return root
# --------------- 程序入口 ---------------
if __name__ == "__main__":
main_window = create_main_window()
main_window.mainloop()