合并多个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()
相关推荐
hikktn1 小时前
ORA-01861 日期格式错误的根治方案:从 SQL 层到 Java 层的标准化治理
java·python·sql
lg_cool_1 小时前
使用conda管理python运行环境并关联vscode
vscode·python·conda
fobwebs1 小时前
Chrome谷歌浏览器多开教程,如何在电脑上同时登录多个GMAIL账号
前端·chrome·多开·同时登录多个gmail
Regentsoft丽晶软件1 小时前
2026总部看全局、区域看趋势、门店看自己:服装全渠道BI看板的三层架构
经验分享·数据分析·产品运营·bi
宸津-代码粉碎机1 小时前
Spring AI企业级实战|智能记忆摘要+自动遗忘机制落地,彻底解决上下文爆炸与Token冗余
java·大数据·人工智能·后端·python·spring
乘浪初心1 小时前
python调用API接口,免费API调取,学习如何调取API接口并反馈你输入的内容
开发语言·python·api·免费
AI玫瑰助手1 小时前
Python模块:import导入模块与模块的搜索路径
android·开发语言·python
前端 贾公子1 小时前
小程序蓝牙打印探索与实践 (最终章)
前端·微信小程序·小程序
chushiyunen1 小时前
vue export default
前端·javascript·vue.js