使用说明:
1.直接双击软件,找到所有xlsx文件所在文件夹
2.点开始按钮之后,就会开始合并当前文件夹中所有xlsx文件。
tips:只能处理xlsx文件,不能处理xls文件。
主要实现功能:是读取选中的文件夹中所有excel文件,需要自己把需要处理的文件提前处理好放到同一文件夹中,运行代码就可以直接自动合并。然后功能2是会提取每个文件的K列,最后汇总到一个文件中,提取第一个读取到的文件的行名当作汇总表的行名,然后把汇总出来的表行列转换。
工具界面如下:
完整代码如下:(提供可直接双击运行的软件,需要的话后台找我就可以)
import os
import openpyxl
from openpyxl.utils import get_column_letter
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
class ExcelApp:
def __init__(self, root):
self.root = root
self.root.title("Excel合并转置工具")
self.root.geometry("520x180")
self.root.resizable(False, False)
# 路径标签+输入框
tk.Label(root, text="文件夹路径:", font=("微软雅黑", 10)).place(x=20, y=30)
self.path_var = tk.StringVar()
self.path_entry = ttk.Entry(root, textvariable=self.path_var, width=45, font=("微软雅黑", 10))
self.path_entry.place(x=90, y=30)
# 选择目录按钮
self.btn_choose = ttk.Button(root, text="选择目录", command=self.choose_dir)
self.btn_choose.place(x=430, y=28)
# 开始按钮
self.btn_start = ttk.Button(root, text="开始处理", command=self.start_run)
self.btn_start.place(x=220, y=80)
# 状态提示
self.status_var = tk.StringVar(value="就绪")
ttk.Label(root, textvariable=self.status_var, foreground="#0066cc").place(x=220, y=120)
def choose_dir(self):
"""选择文件夹并填入路径"""
folder = filedialog.askdirectory(title="选择存放Excel的文件夹")
if folder:
self.path_var.set(folder)
def start_run(self):
"""核心处理逻辑"""
input_folder = self.path_var.get().strip()
if not os.path.isdir(input_folder):
messagebox.showerror("错误", "请填写或选择有效的文件夹路径!")
return
self.status_var.set("正在处理...")
self.root.update()
# 新建输出文件夹
out_folder = os.path.join(input_folder, "合并后文件")
if not os.path.exists(out_folder):
os.mkdir(out_folder)
origin_file = os.path.join(out_folder, "各单位评分表汇总.xlsx")
trans_file = os.path.join(out_folder, "各单位评分表_转置汇总.xlsx")
# 初始化两个汇总工作簿
wb_origin = openpyxl.Workbook()
wb_origin.remove(wb_origin.active)
wb_trans = openpyxl.Workbook()
wb_trans.remove(wb_trans.active)
file_count = 0
for filename in os.listdir(input_folder):
# 只处理xlsx,跳过临时文件
if filename.startswith("~$") or not filename.lower().endswith(".xlsx"):
continue
file_count += 1
# 提取工作表名称
unit_name = filename.split("-")[0].strip()
sheet_name = unit_name
idx = 1
while sheet_name in wb_origin.sheetnames:
sheet_name = f"{unit_name}_{idx}"
idx += 1
file_path = os.path.join(input_folder, filename)
src_wb = openpyxl.load_workbook(file_path, data_only=False)
src_ws = src_wb.active
# 1. 修改K1单元格为当前工作表名
src_ws["K1"].value = sheet_name
# 2. 复制原表内容(修复样式复制:新建单元格样式)
dest_ori = wb_origin.create_sheet(title=sheet_name)
for row in src_ws.iter_rows():
for cell in row:
new_cell = dest_ori[cell.coordinate]
new_cell.value = cell.value
# 重新创建样式,不再直接copy旧样式
new_cell.font = openpyxl.styles.Font(**cell.font.__dict__)
new_cell.fill = openpyxl.styles.PatternFill(**cell.fill.__dict__)
new_cell.border = openpyxl.styles.Border(**cell.border.__dict__)
new_cell.alignment = openpyxl.styles.Alignment(**cell.alignment.__dict__)
new_cell.number_format = cell.number_format
# 复制合并单元格
for mr in src_ws.merged_cells.ranges:
dest_ori.merge_cells(str(mr))
# 复制数据验证
for dv in src_ws.data_validations.dataValidation:
dest_ori.data_validations.add(dv)
# 复制列宽、行高
for col in range(1, src_ws.max_column + 1):
col_let = get_column_letter(col)
dest_ori.column_dimensions[col_let].width = src_ws.column_dimensions[col_let].width
for row in range(1, src_ws.max_row + 1):
dest_ori.row_dimensions[row].height = src_ws.row_dimensions[row].height
# 3. 数据转置 + 提取D列作为行名
max_r = src_ws.max_row
max_c = src_ws.max_column
row_labels = []
for r in range(1, max_r + 1):
val = src_ws.cell(row=r, column=4).value
row_labels.append(val if val is not None else f"行{r}")
dest_trans = wb_trans.create_sheet(title=sheet_name)
# 转置并重建样式
for o_row in range(1, max_r + 1):
for o_col in range(1, max_c + 1):
new_r = o_col
new_c = o_row
s_cell = src_ws.cell(row=o_row, column=o_col)
t_cell = dest_trans.cell(row=new_r, column=new_c, value=s_cell.value)
# 重建样式,解决样式不可变报错
t_cell.font = openpyxl.styles.Font(**s_cell.font.__dict__)
t_cell.fill = openpyxl.styles.PatternFill(**s_cell.fill.__dict__)
t_cell.border = openpyxl.styles.Border(**s_cell.border.__dict__)
t_cell.alignment = openpyxl.styles.Alignment(**s_cell.alignment.__dict__)
t_cell.number_format = s_cell.number_format
# D列内容作为转置表首行标题并加粗
for c_idx in range(1, len(row_labels) + 1):
cell = dest_trans.cell(row=1, column=c_idx, value=row_labels[c_idx - 1])
cell.font = openpyxl.styles.Font(bold=True)
# 统一转置表列宽
for col in range(1, dest_trans.max_column + 1):
col_let = get_column_letter(col)
dest_trans.column_dimensions[col_let].width = 15
src_wb.close()
# 保存文件
wb_origin.save(origin_file)
wb_origin.close()
wb_trans.save(trans_file)
wb_trans.close()
self.status_var.set(f"处理完成,共 {file_count} 个文件")
messagebox.showinfo("完成", f"处理完毕!\n共处理 {file_count} 个文件\n结果保存在:{out_folder}")
if __name__ == "__main__":
root = tk.Tk()
app = ExcelApp(root)
root.mainloop()