批量合并表格

需求场景:

项目评审,有100个项目要请50个专家打分,每个专家最后提交一张评分表。现在需要把50张excel表合并在一起,方便统计每个项目的平均分。但50张表复制粘贴在一张表,这个手工操作量很大,需要一个程序一键实现表格合并。

实现代码:

import os
import pandas as pd
import glob
from pathlib import Path


def merge_tables(
    input_folder,
    output_path,
    merge_direction='vertical',
    file_pattern="*.xlsx",
    keep_other_headers=False  # 新增参数:是否保留除第一张表外其他表的表头
):
    """
    批量合并文件夹内的所有表格文件(新增表头控制功能)

    参数:
    input_folder: 输入文件夹路径
    output_path: 输出文件路径
    merge_direction: 合并方向 - 'vertical'(上下合并) 或 'horizontal'(左右合并)
    file_pattern: 文件匹配模式,如 "*.xlsx", "*.csv" 等
    keep_other_headers: 布尔值,True=保留其他表表头,False=删除其他表表头(默认)
    """

    # 支持的文件格式和对应的读取函数
    read_functions = {
        '.xlsx': pd.read_excel,
        '.xls': pd.read_excel,
        '.csv': pd.read_csv,
        '.tsv': lambda x: pd.read_csv(x, sep='\t'),
        '.txt': lambda x: pd.read_csv(x, sep='\t')
    }

    # 获取所有匹配的文件
    file_patterns = [f"*{ext}" for ext in read_functions.keys()] if file_pattern == "*" else [file_pattern]
    all_files = []
    for pattern in file_patterns:
        all_files.extend(glob.glob(os.path.join(input_folder, pattern)))
    all_files = sorted(set(all_files))  # 去重并排序

    if not all_files:
        print("未找到任何表格文件!")
        return False
    print(f"找到 {len(all_files)} 个文件:\n  " + "\n  ".join([os.path.basename(f) for f in all_files]))

    # 读取所有文件(核心修改:处理其他表的表头)
    dataframes = []
    for idx, file_path in enumerate(all_files):
        try:
            file_ext = Path(file_path).suffix.lower()
            if file_ext in read_functions:
                # 1. 读取当前文件(默认第一行为表头)
                df = read_functions[file_ext](file_path)
                # 2. 处理表头:仅保留第一张表的表头,其他表根据参数决定是否删除表头行
                if idx > 0 and not keep_other_headers:
                    # idx>0 表示非第一张表,且参数为False时,删除第一行(表头行)
                    df = df.iloc[1:].reset_index(drop=True)  # 去掉表头行,重置索引
                    print(f"读取并删除表头: {os.path.basename(file_path)} (形状: {df.shape})")
                else:
                    print(f"读取并保留表头: {os.path.basename(file_path)} (形状: {df.shape})")
                # 3. 添加来源文件列,方便追溯
                df['来源文件'] = os.path.basename(file_path)
                dataframes.append(df)
            else:
                print(f"跳过不支持的文件格式: {os.path.basename(file_path)}")
        except Exception as e:
            print(f"读取文件 {os.path.basename(file_path)} 时出错: {e}")
            continue

    if not dataframes:
        print("没有成功读取任何文件!")
        return False

    # 合并数据(原有逻辑不变)
    try:
        if merge_direction.lower() == 'vertical':
            merged_df = pd.concat(dataframes, axis=0, ignore_index=True)
            print(f"\n纵向合并完成,总行数: {len(merged_df)}")
        elif merge_direction.lower() == 'horizontal':
            max_rows = max(len(df) for df in dataframes)
            for i, df in enumerate(dataframes):
                if len(df) < max_rows:
                    empty_df = pd.DataFrame([[None]*len(df.columns)]*(max_rows-len(df)), columns=df.columns)
                    dataframes[i] = pd.concat([df, empty_df], ignore_index=True)
            merged_df = pd.concat(dataframes, axis=1)
            print(f"\n横向合并完成,总列数: {len(merged_df.columns)}")
        else:
            print("错误的合并方向!请使用 'vertical' 或 'horizontal'")
            return False
    except Exception as e:
        print(f"合并数据时出错: {e}")
        return False

    # 保存结果(原有逻辑不变)
    try:
        output_ext = Path(output_path).suffix.lower()
        if output_ext in ['.xlsx', '.xls']:
            merged_df.to_excel(output_path, index=False)
        elif output_ext == '.csv':
            merged_df.to_csv(output_path, index=False, encoding='utf-8-sig')
        else:
            output_path += '.xlsx' if not output_ext else ''
            merged_df.to_excel(output_path, index=False)
        print(f"合并后的表格已保存到: {output_path}")
        print(f"最终表格形状: {merged_df.shape}")
        return True
    except Exception as e:
        print(f"保存文件时出错: {e}")
        return False


def main():
    """主函数,直接预设参数运行"""
    print("=== 表格批量合并工具(新增表头控制) ===\n")

    # --------------------------
    # 在这里填写你的参数(修改下面的值)
    # --------------------------
    input_folder = r"C:\Users\2025\Desktop\专家报\专家报"  # 输入文件夹路径
    output_path = r"C:\Users\2025\Desktop\专家报\结果.xlsx"  # 输出文件路径
    merge_direction = "vertical"  # 合并方向:'vertical'(上下)/ 'horizontal'(左右)
    file_pattern = "*.xlsx"  # 文件类型:如"*.xlsx"、"*.csv"、"*"(所有支持格式)
    # 新增参数:是否保留除第一张表外其他表的表头
    keep_other_headers = False  # False=删除其他表表头(默认,避免重复);True=保留其他表表头

    # --------------------------
    # 以下代码无需修改
    # --------------------------
    if not os.path.exists(input_folder):
        print(f"错误:输入文件夹不存在 - {input_folder}")
        return

    print(f"表头处理方式:{'保留' if keep_other_headers else '删除'}除第一张表外的其他表头")
    print("开始合并...\n")
    success = merge_tables(
        input_folder=input_folder,
        output_path=output_path,
        merge_direction=merge_direction,
        file_pattern=file_pattern,
        keep_other_headers=keep_other_headers  # 传递新增参数
    )

    print("\n✅ 合并完成!" if success else "\n❌ 合并失败!")


if __name__ == "__main__":
    main()

这段程序里还提供了多个参数以实现横向合并或纵向合并、是否选择删除表头,还支持多种格式(xlsx/csv等),非常方便、好用!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值