需求场景:
项目评审,有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等),非常方便、好用!
1802

被折叠的 条评论
为什么被折叠?



