合并多个excel文件到一个文件中

复制代码
使用说明:
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()
相关推荐
妙码生花7 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12271 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
Databend1 小时前
2KB histogram 背后:Databend 如何低成本追踪长尾延迟
大数据·数据分析·agent
咪库咪库咪1 小时前
Vue3-生命周期
前端
莪_幻尘2 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4532 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端
林瞅瞅2 小时前
Nuxt3 项目部署 Nginx 防盗链后特定 JS 文件 403 问题修复方案
前端
kyriewen3 小时前
别再每次都 Google 了:我整理了前端日常最常踩的 10 个 Git 坑,附速查表
前端·javascript·git
一颗奇趣蛋3 小时前
Web 视频开发完全指南:从入门到精通
前端
非洲农业不发达3 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端