如何用Pandas合并含分部门子表、带空行与合并单元格的Excel表格?
用Pandas合并多部门Excel表格并按部门分类的解决方案
针对你描述的带合并单元格、空行的多部门Excel表格,以下是具体的Pandas处理方案,核心是先处理合并单元格,再定位各部门数据区域,最后批量合并所有文件数据。
前期准备
确保安装依赖库:
pip install pandas openpyxl
核心处理逻辑
- 填充合并单元格:OpenPyXL读取Excel时,合并单元格仅左上角有值,需先将值填充到所有合并单元格内,避免Pandas读取时出现空值。
- 定位部门数据块:通过识别非空的表头行、部门行,确定每个部门数据的起始与结束位置(以空行或下一个部门行为界)。
- 批量处理+合并数据:遍历所有每日Excel文件,提取各部门数据并添加部门标识,最终合并为统一的DataFrame。
完整代码实现
import pandas as pd from openpyxl import load_workbook import os def fill_merged_cells(ws): """填充工作表中的所有合并单元格""" merged_ranges = ws.merged_cells.ranges for merged_range in merged_ranges: # 获取合并区域左上角单元格的值 top_left_cell = ws[merged_range.min_row][merged_range.min_col-1] cell_value = top_left_cell.value # 遍历合并区域内的所有单元格,填充值 for row in range(merged_range.min_row, merged_range.max_row+1): for col in range(merged_range.min_col, merged_range.max_col+1): ws.cell(row=row, column=col).value = cell_value def extract_department_data(ws): """从单个工作表中提取C1、H1、C2三个部门的数据""" df_list = [] # 将工作表数据转为列表,方便遍历 data = list(ws.values) # 遍历查找各部门的起始位置 i = 0 while i < len(data): row = data[i] # 跳过空行 if all(cell is None or str(cell).strip() == '' for cell in row): i += 1 continue # 判断是否为表头行(假设表头非空且包含业务字段,可根据实际调整) if any(cell is not None and str(cell).strip() != '' for cell in row): header = row # 下一行是部门名称行 if i+1 >= len(data): break dept_row = data[i+1] dept_name = next((cell for cell in dept_row if cell is not None and str(cell).strip() in ['C1', 'H1', 'C2']), None) if dept_name: # 找到数据起始行(i+2),直到下一个空行或下一个部门行 start_row = i+2 end_row = start_row while end_row < len(data): current_row = data[end_row] # 判断是否到了下一个部门或空行 if all(cell is None or str(cell).strip() == '' for cell in current_row): break # 检查是否是新的部门行 if any(cell is not None and str(cell).strip() in ['C1', 'H1', 'C2'] for cell in current_row): break end_row += 1 # 提取数据行 dept_data = data[start_row:end_row] # 转为DataFrame df = pd.DataFrame(dept_data, columns=header) # 添加部门列 df['部门'] = dept_name df_list.append(df) # 跳到当前部门结束行,继续遍历 i = end_row continue i += 1 return pd.concat(df_list, ignore_index=True) if df_list else pd.DataFrame() def process_all_excels(folder_path): """处理指定文件夹下的所有Excel文件""" all_data = pd.DataFrame() # 遍历文件夹下的所有xlsx文件 for filename in os.listdir(folder_path): if filename.endswith('.xlsx') or filename.endswith('.xls'): file_path = os.path.join(folder_path, filename) print(f"正在处理文件:{filename}") # 加载Excel文件 wb = load_workbook(file_path, data_only=True) # 遍历每个工作表 for sheet_name in wb.sheetnames: ws = wb[sheet_name] # 填充合并单元格 fill_merged_cells(ws) # 提取部门数据 dept_df = extract_department_data(ws) # 添加文件名列(可选,用于溯源) dept_df['文件名'] = filename # 合并到总数据 all_data = pd.concat([all_data, dept_df], ignore_index=True) return all_data # 使用示例 if __name__ == '__main__': # 替换为你的Excel文件所在文件夹路径 excel_folder = './daily_excels' final_df = process_all_excels(excel_folder) # 按部门拆分保存(可选) for dept in ['C1', 'H1', 'C2']: dept_df = final_df[final_df['部门'] == dept] dept_df.to_excel(f'./{dept}_合并数据.xlsx', index=False) # 保存所有合并数据 final_df.to_excel('./所有部门合并数据.xlsx', index=False)
关键说明
- 合并单元格处理:通过
fill_merged_cells函数遍历所有合并区域,将左上角单元格的值填充到整个合并区域,确保Pandas读取时列值完整。 - 数据区域定位:通过遍历行,跳过空行,识别表头和部门行,再通过判断后续行是否为空或包含新部门标识来确定数据结束位置,适配不同部门行数不同的情况。
- 可扩展性:如果部门名称有变化,只需修改代码中
['C1', 'H1', 'C2']的部门列表即可。 - 异常处理:实际使用时可添加try-except块,处理文件读取失败、格式异常等情况。
内容的提问来源于stack exchange,提问作者jingchun liu
相关产品推荐
相关产品推荐

