合并同名Sheet的多份xlsx文件时内容被覆盖,求修复方案
修复Excel工作表合并(追加而非覆盖)的问题
我来帮你定位代码里的问题,然后给出正确的实现方案!你的核心需求是把多个Excel文件里的同名工作表数据追加到同一个输出文件的对应工作表中,但当前代码的逻辑完全搞反了,导致每次覆盖而不是合并。
原代码的问题分析
- 错误替换工作簿:每次循环输入文件时,你把
writer.book设置为当前输入文件的book,这相当于直接把输出工作簿替换成了当前输入文件的内容——之前处理过的文件数据全被覆盖了! - 空DataFrame写入:你定义的
df = pandas.DataFrame()是空的,写入时只会在当前输入文件的工作表末尾添加空行,完全没有实际合并数据的逻辑。 - 工作表操作逻辑错误:你没有读取输入文件里的实际数据,只是直接操作
writer.sheets,等于在做无用功。
修正后的代码实现
下面是调整后的完整代码,完全实现“同名工作表数据追加”的需求:
def combine_sheets(self, inputFiles): logging.info('combining input files to one spreadsheet') # 定义输出文件路径 outputFile = os.path.join(self.processingDir, 'combined_ncoa_report.xlsx') # 先创建一个空的工作簿作为输出基础(避免文件不存在的问题) from openpyxl import Workbook output_book = Workbook() # 删除openpyxl默认创建的空Sheet output_book.remove(output_book.active) output_book.save(outputFile) # 使用openpyxl引擎以追加模式打开输出文件,支持覆盖已有工作表的内容(追加数据) writer = pandas.ExcelWriter( outputFile, engine='openpyxl', mode='a', if_sheet_exists='overlay' ) try: for inputFile in inputFiles: file_name = os.path.split(inputFile)[-1] logging.info(f'reading spreadsheet {file_name}') # 读取当前输入文件的所有工作表 xls = pandas.ExcelFile(inputFile) for sheetname in xls.sheet_names: # 读取当前工作表的实际数据 df = xls.parse(sheetname) # 判断输出文件中是否已存在该工作表,确定追加的起始行 if sheetname in writer.book.sheetnames: # 已有工作表,从当前最大行开始追加(不重复写表头) startrow = writer.book[sheetname].max_row header = False else: # 新工作表,从第0行开始,写入表头 startrow = 0 header = True # 将数据写入输出文件的对应工作表 df.to_excel( writer, sheet_name=sheetname, startrow=startrow, index=False, header=header ) logging.info(f'Appended data to sheet "{sheetname}" from {file_name}') # 保存并关闭写入器 writer.close() logging.info(f'Combined spreadsheet saved successfully at {outputFile}') except Exception as e: logging.error(f'Error combining sheets: {str(e)}') raise
关键逻辑说明
- 初始化空输出工作簿:先创建一个空的Excel文件,避免后续以追加模式打开时文件不存在的报错。
- 追加模式打开输出文件:使用
mode='a'和if_sheet_exists='overlay'参数,让pandas可以在已存在的工作表末尾追加数据。 - 读取每个输入文件的工作表数据:对每个输入文件的每个工作表,读取实际数据到DataFrame,而不是操作空的DataFrame。
- 动态判断表头与起始行:如果是第一次创建工作表,写入表头;如果是追加,跳过表头,从已有数据的下一行开始写入。
这样修改后,就能完美实现你想要的“多个Excel文件同名工作表数据合并追加”的效果啦!
内容的提问来源于stack exchange,提问作者Chad Smith




