合并多个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()
相关推荐
jeffzhengye2 分钟前
Claude-Real-Video:让 Claude 真正看懂视频,0 Token 成本
python·微信
太平洋月光3 分钟前
stagewise如何结合cursor开发
前端·ai编程
前端Hardy4 分钟前
JavaScript 终于又进化了!ES2026 正式发布,这些新特性你必须知道!
前端
光影少年5 分钟前
react navite 页面跳转、传参、路由监听、导航栏自定义
前端·react native·react.js
IT知识分享9 分钟前
WebP转JPG开发经验:从格式解码到本地批量转换的实践
javascript·python·图片转换
黑土豆16 分钟前
CSS 新特性:Container Queries 到底能解决什么痛点?
前端·css
小柯南敲键盘22 分钟前
Temu多语言商品图翻译实现方案
人工智能·python
问商十三载30 分钟前
2026法律行业AI引擎生成式优化怎么优化?三层专业加固提排名,零成本提33%引用率附适配表
java·前端·人工智能·算法
恋猫de小郭32 分钟前
Flutter 3D 渲染的全新选择和应用场景
android·前端·flutter
威联通安全存储41 分钟前
TS-h1677AXU-RP在工程机械机器人弧焊中的部署
大数据·人工智能·python·机器人