EXCEL中提取各sheet表中的固定区域到一个表格中

博主分享了自己从擅长数据分析到选择体制内工作的矛盾经历,回忆起在校期间对数学和文科的热爱,却选择了理科专业及后来的文科硕士。在数据分析的道路上,曾获得相关工作机会,但最终选择了稳定。这段经历充满了对个人职业选择的反思。
=INDIRECT("Sheet"&ROW(F1)&"!F1")

好久不做数据分析了,今天因为要申报一个项目又开始调用其一些公式、函数等等。

再次看csdn感觉还是很有感触。

毕业后选择了一份稳定的体制内工作,数据分析的思维和经历带给我很多很多,只可惜自己是那条路上半途而废的一员。

简洁的代码、编译器,为了一个问题反复思索的图书馆的一个又一个下午。

emmmm~~回想自己求学的经历

明明擅长数学和文科,对物理化学一窍不通,高二分科却报了理科。上了个中规中矩的大学,学了个文理兼收的专业信息管理与信息系统。

做了毕业论文感觉自己好喜欢数据分析,却考上个文科的硕士专业???

读研期间,自学数据分析,获得了几个相关的offer,却考上了个编制?然后选择编制。

这充满矛盾的经历,根源在于自己不知道自己想要什么~~~~

emmmmm~~

<think> 我们已知用户的需求是:将多个Excel文件中的sheet合并到一个Excel文件中。 参考之前的引用,有多种方法可以实现,包括使用WPS的合并表格功能(引用[1])、使用宏(VBA)(引用[2][3])、使用Java(引用[4])等。但是用户现在是在使用Python的pandas,因此我们需要提供Python的解决方案。 根据用户之前的问题,我们已经知道如何使用pandas追加数据到已有的Excel文件中而不覆盖。现在需要合并多个Excel文件(每个文件可能有多个sheet)到一个Excel文件(每个文件变成新文件中的一个sheet)。 注意:每个Excel文件可能有多个sheet,但根据引用[2][3]中的描述,用户可能希望将每个文件的指定sheet(例如第二个sheet)合并,也可能希望合并所有sheet。这里我们考虑两种情况: 情况1:每个Excel文件只有一个sheet,或者我们希望将每个文件的所有sheet都合并到目标文件中(即目标文件中每个sheet对应一个原始文件的内容,且使用原sheet名,如果重名则可能覆盖,所以需要处理重名问题)。 情况2:每个Excel文件有多个sheet,但我们只希望合并每个文件的指定sheet(例如每个文件的第二个sheet)到目标文件的一个sheet中(这时可能需要将这些指定的sheet合并成一个sheet,或者每个指定的sheet作为目标文件的不同sheet)。 然而,用户的问题描述是“将多个Excel文件中的sheet合并到一个Excel文件”,这里可能有两种理解: A. 将每个Excel文件的所有sheet都合并到目标Excel文件中(每个原始文件的每个sheet都成为目标文件的一个独立的sheet)。 B. 将所有Excel文件的指定sheet(比如每个文件的第一个sheet)合并到一个新的sheet中(即数据叠加),或者每个文件的指定sheet分别作为目标文件中的一个sheet每个文件一个sheet)。 根据引用[1][2][3]的描述,常见的情况是: - 引用[1]:将多个Excel文件合并到一个Excel文件中(每个文件成为独立的sheet)。 - 引用[2]:将多个Excel文件的指定sheet(第二个sheet)复制到一个新的Excel文件中,每个原始文件的第二个sheet成为新文件的一个sheet(即每个文件一个sheet)。 - 引用[3]:将多个Excel文件合并为一个Excel文件的多个sheet页(每个文件一个sheet)。 因此,我们主要针对两种常见需求提供解决方案: 需求1(对应情况A):将多个Excel文件的所有sheet合并到一个Excel文件中(目标文件中每个sheet对应一个原始文件的sheet,如果不同文件中有同名sheet,则会发生覆盖,因此我们需要处理重名问题)。 需求2(对应情况B):将多个Excel文件中指定的某个sheet(比如每个文件的第二个sheet)合并到一个Excel文件中作为独立的sheet。 另外还有一种需求(需求3):将多个Excel文件中指定sheet的数据内容合并到同一个sheet中(即数据追加),但用户的问题描述更倾向于将每个文件的sheet独立保存为目标文件的不同sheet,所以我们先解决需求1和需求2。 由于用户之前使用了pandas,我们继续使用pandas和openpyxl来实现。 注意:合并多个Excel文件时,可能会遇到内存问题,特别是当文件很大或文件很多时。因此,我们需要注意内存使用,并在可能的情况下优化。 下面分别给出两种需求的代码: 需求1:合并多个Excel文件的所有sheet一个Excel文件(处理重名问题) 步骤: 1. 创建一个空的ExcelWriter对象(使用openpyxl引擎)。 2. 遍历每个Excel文件,读取所有sheet。 3. 对于每个sheet,将其写入目标Excel文件,同时检查sheet名是否重复。如果重复,则重命名(例如在名字后面加上序号)。 需求2:合并多个Excel文件中指定的某个sheet(比如每个文件的第二个sheet)到一个Excel文件(每个文件对应一个独立的sheet,并且可以重命名sheet以避免冲突) 步骤: 1. 创建一个空的ExcelWriter对象。 2. 遍历每个Excel文件,读取指定的sheet(例如第二个sheet,或者按名称指定)。 3. 将每个读取的sheet写入目标Excel文件,并且为了避免重名,我们可以使用文件名作为sheet名的一部分(或者序号)。 下面我们分别实现这两个需求的函数。 注意:由于可能存在大量的文件,我们将使用逐个读取并写入的方式,避免内存同时存储所有数据。 我们先实现需求1:合并所有sheet 由于目标文件中sheet名必须唯一,因此我们需要处理重名情况。我们可以这样处理:如果遇到重复的sheet名,则在后面加上序号(例如"Sheet1_1", "Sheet1_2")。 但是,还有一种常见的需求:将每个原始文件的sheet合并到目标文件时,希望保留原始文件名作为sheet名前缀(或后缀)以避免冲突。我们可以提供这个选项。 因此,我们设计函数如下: 方案1:合并所有sheet每个原始文件的所有sheet都复制到目标文件,并且使用文件名作为前缀来避免冲突) 方案2:直接复制,如果遇到同名sheet则自动重命名(加上序号)。 这里我们选择方案2(自动重命名)作为需求1的解决方案,同时提供方案1(加前缀)的选项。 实现需求1的函数: ```python import pandas as pd import os from openpyxl import load_workbook def merge_all_sheets_to_one_excel(file_paths, output_file, use_filename_as_prefix=False): """ 将多个Excel文件的所有sheet合并到一个新的Excel文件中 参数: file_paths: 要合并的Excel文件路径列 output_file: 输出的Excel文件路径 use_filename_as_prefix: 是否使用文件名作为sheet名前缀(避免重名),默认False(自动重命名重复的sheet) 返回: None """ # 创建一个ExcelWriter对象 with pd.ExcelWriter(output_file, engine='openpyxl') as writer: # 用于记录每个sheet名出现的次数 sheet_name_count = {} for file_path in file_paths: # 读取Excel文件中的所有sheet excel_file = pd.ExcelFile(file_path) # 获取文件名(不带扩展名)用于前缀 filename = os.path.splitext(os.path.basename(file_path))[0] for sheet_name in excel_file.sheet_names: # 读取sheet df = pd.read_excel(file_path, sheet_name=sheet_name) # 处理sheet名 target_sheet_name = sheet_name if use_filename_as_prefix: # 加上文件名前缀 target_sheet_name = f"{filename}_{sheet_name}" else: # 不添加前缀,但需要处理重名 # 检查这个sheet名是否已经出现过 count = sheet_name_count.get(target_sheet_name, 0) + 1 sheet_name_count[target_sheet_name] = count if count > 1: target_sheet_name = f"{target_sheet_name}_{count-1}" # 第一次重复时,原来的已经用了,所以从第二次开始重命名 # 注意:这里我们不需要更新计数器,因为下一次遇到同样的原名,计数器还会增加。 # 写入sheet df.to_excel(writer, sheet_name=target_sheet_name, index=False) ``` 注意:上面的自动重名策略为:当遇到重复的sheet名时,在原名后面加上序号(序号从1开始,但为了避免覆盖原名字,我们第一次重命名时使用原名字+'_1',第二次用原名字+'_2')。 但是,上面的计数器策略在遇到相同的原始sheet名时,会递增计数,然后重命名。然而,如果同一个文件内就有相同的sheet名,那么pd.ExcelFile.sheet_names是不会重复的,所以不用担心同一个文件内重复。但是不同文件之间可能会出现重复。 另外,注意我们使用`pd.ExcelFile`来读取文件的所有sheet名,然后逐个读取sheet,这样可以避免一次性将所有数据读入内存(但每个sheet会分别读入内存,所以大文件仍然可能内存不足,需要优化)。 但是,上面的计数方法在同一个文件内的sheet名不会重复,但不同文件之间会重复。我们使用一个字典记录每个原始sheet名出现的总次数。注意,我们第一次出现时使用原名,第二次出现时改为原名+'_1',第三次出现时改为原名+'_2'。所以需要调整计数方式:第一次出现不添加后缀,第二次出现(即计数为2)时添加后缀'_1',第三次出现(计数为3)时添加后缀'_2'。因此,后缀应该是计数减1。 但是,这样会导致第一个使用原名的sheet在后续重命名时不会影响到。比如: 第一次出现sheet1 -> sheet1(计数器为1) 第二次出现sheet1 -> 计数器变为2,那么重命名为sheet1_1 第三次出现sheet1 -> 计数器变为3,重命名为sheet1_2 这样是合理的。 但是,如果使用文件名作为前缀,则每个sheet名都会变成“文件名_原sheet名”,这样就不会重复了。 需求2:合并多个Excel文件中指定的某个sheet每个文件只取一个sheet)到目标文件,每个文件对应一个sheet。 我们可以指定每个文件要提取sheet名(sheet_name)或sheet索引(sheet_index)。注意,如果按索引,每个文件的索引应该一致(比如第二个sheet就是索引1)。 函数设计: ```python def merge_specific_sheets_to_one_excel(file_paths, output_file, sheet_ref, use_filename_as_sheetname=False): """ 将多个Excel文件中指定的sheet提取出来,合并到一个Excel文件中(每个原始文件对应一个sheet) 参数: file_paths: 要合并的Excel文件路径列 output_file: 输出的Excel文件路径 sheet_ref: 可以是整数(索引,从0开始)或字符串(sheet名) use_filename_as_sheetname: 是否使用文件名作为目标sheet名(避免重名),默认False(使用原sheet名,如果重复则自动重命名) 返回: None """ # 创建一个ExcelWriter对象 with pd.ExcelWriter(output_file, engine='openpyxl') as writer: # 用于记录sheet名出现的次数 sheet_name_count = {} for i, file_path in enumerate(file_paths): # 读取Excel文件 excel_file = pd.ExcelFile(file_path) # 获取文件名(不带扩展名) filename = os.path.splitext(os.path.basename(file_path))[0] # 获取指定的sheet if type(sheet_ref) is int: # 按索引获取sheet名 if sheet_ref < len(excel_file.sheet_names): sheet_name = excel_file.sheet_names[sheet_ref] else: print(f"Warning: 文件 '{file_path}' 没有索引为 {sheet_ref} 的sheet,跳过。") continue else: # 按名称 sheet_name = sheet_ref if sheet_name not in excel_file.sheet_names: print(f"Warning: 文件 '{file_path}' 不存在名为 '{sheet_ref}' 的sheet,跳过。") continue # 读取数据 df = pd.read_excel(file_path, sheet_name=sheet_name) # 确定目标sheet名 if use_filename_as_sheetname: target_sheet_name = filename else: target_sheet_name = sheet_name # 检查重名 count = sheet_name_count.get(target_sheet_name, 0) + 1 sheet_name_count[target_sheet_name] = count if count > 1: target_sheet_name = f"{target_sheet_name}_{count-1}" # 写入 df.to_excel(writer, sheet_name=target_sheet_name, index=False) ``` 注意:在需求2中,我们按每个文件只读取一个sheet,然后写入目标文件的一个sheet。 以上两个函数可以满足用户的需求。 但是,还有一种常见需求(需求3):将多个Excel文件的指定sheet的数据合并到同一个sheet中(纵向或横向拼接)。这个需求在引用[1]中的“合并表格”功能提到可以将多个sheet的数据放到一个sheet中。我们可以再提供一个函数。 需求3:将多个Excel文件的指定sheet的数据合并到同一个sheet(追加数据) ```python def merge_specific_sheets_to_one_sheet(file_paths, output_file, sheet_ref, output_sheet_name='Combined'): """ 将多个Excel文件中指定的sheet的数据合并到一个sheet中(纵向叠加) 参数: file_paths: 要合并的Excel文件路径列 output_file: 输出的Excel文件路径 sheet_ref: 可以是整数(索引,从0开始)或字符串(sheet名) output_sheet_name: 输出的sheet名,默认'Combined' 返回: None """ # 创建一个空的DataFrame用于存储合并后的数据 combined_df = pd.DataFrame() for file_path in file_paths: # 读取Excel文件 excel_file = pd.ExcelFile(file_path) # 获取指定的sheet if type(sheet_ref) is int: if sheet_ref < len(excel_file.sheet_names): sheet_name = excel_file.sheet_names[sheet_ref] else: print(f"Warning: 文件 '{file_path}' 没有索引为 {sheet_ref} 的sheet,跳过。") continue else: sheet_name = sheet_ref if sheet_name not in excel_file.sheet_names: print(f"Warning: 文件 '{file_path}' 不存在名为 '{sheet_ref}' 的sheet,跳过。") continue # 读取数据 df = pd.read_excel(file_path, sheet_name=sheet_name) # 纵向拼接 combined_df = pd.concat([combined_df, df], ignore_index=True) # 写入输出文件 combined_df.to_excel(output_file, sheet_name=output_sheet_name, index=False) ``` 这个函数将每个文件指定的sheet的数据读取后,纵向拼接(使用concat),然后写入一个sheet。 注意:这个函数可能会因为读取所有数据到内存而导致内存不足,特别是文件很大时。我们可以优化为逐个读取并追加写入到Excel文件,避免一次性占用过多内存。优化如下: ```python def merge_specific_sheets_to_one_sheet(file_paths, output_file, sheet_ref, output_sheet_name='Combined'): """ 优化版:逐个读取文件并追加写入目标文件,避免一次性加载所有数据 """ # 先创建一个空文件,或者如果文件已存在则追加 # 我们需要判断输出文件是否存在,如果存在则追加,否则创建 if not os.path.exists(output_file): # 先创建一个空DataFrame写入,然后后面追加 pd.DataFrame().to_excel(output_file, sheet_name=output_sheet_name, index=False) # 使用openpyxl加载工作簿 book = load_workbook(output_file) # 检查输出sheet是否存在 if output_sheet_name in book.sheetnames: sheet = book[output_sheet_name] startrow = sheet.max_row # 注意:如果第一行是标题,我们追加时不需要再写标题 header = False else: # 如果不存在这个sheet,则创建(但我们已经创建了空文件,所以这种情况不应该发生) # 重新创建ExcelWriter会覆盖?所以我们改为:如果不存在则先写入一个空DataFrame并创建该sheet,然后再追加 # 这里我们重新考虑:上面已经创建了文件,所以应该存在sheet。如果不存在,说明创建失败,我们重新创建 # 为了避免这种情况,我们重新处理:先删除之前创建的空文件,然后重新开始 # 简化:我们不管上面创建的文件,直接追加数据。如果输出sheet不存在,则先写一次(带标题) # 这里我们改成:在创建文件后,如果输出sheet不存在,则先写入一次(带标题),然后后面追加(不带标题) # 由于我们使用openpyxl,所以我们可以先创建一个新的sheet(但是这里我们要求必须已经有了) # 因此,我们修改逻辑:先确保输出sheet存在 startrow = 0 header = True # 使用ExcelWriter追加写入 with pd.ExcelWriter(output_file, engine='openpyxl') as writer: writer.book = book writer.sheets = {ws.title: ws for ws in book.worksheets} # 重新设置startrow(因为上面已经获取了) # 注意:上面我们是从已有的sheet中获取了startrow,但writer在写入时不会自动更新,所以我们需要在循环中记录当前行 # 我们改为:读取每个文件的数据,然后写入到输出sheet,每次写入后更新startrow current_row = startrow for i, file_path in enumerate(file_paths): # 读取Excel文件 excel_file = pd.ExcelFile(file_path) # 获取指定的sheet if type(sheet_ref) is int: if sheet_ref < len(excel_file.sheet_names): sheet_name = excel_file.sheet_names[sheet_ref] else: print(f"Warning: 文件 '{file_path}' 没有索引为 {sheet_ref} 的sheet,跳过。") continue else: sheet_name = sheet_ref if sheet_name not in excel_file.sheet_names: print(f"Warning: 文件 '{file_path}' 不存在名为 '{sheet_ref}' 的sheet,跳过。") continue # 读取数据 df = pd.read_excel(file_path, sheet_name=sheet_name) # 如果是第一次且需要写标题,或者当前行是0(即之前没有数据)则写标题,否则不写 if i == 0 and startrow == 0: write_header = True else: write_header = False # 写入数据(追加) df.to_excel( writer, sheet_name=output_sheet_name, startrow=current_row, index=False, header=write_header ) # 更新当前行(加上数据行数和标题行?) current_row += len(df) + (1 if write_header else 0) # 注意:因为write_header只在第一次且startrow=0(即整个为空)时写一次标题,所以后面都不写标题。因此,追加的行数就是len(df)行。 # 但是,第一次写入了标题,所以数据行数上面已经加了1(因为len(df)不包括标题行,但写入时标题行也算一行) # 所以,我们需要考虑: # 第一次写入:行数=len(df)+1(因为标题行) # 后续写入:行数=len(df) # 但是,我们在每次写入后已经增加了当前行,所以这里更新: # 第一次:current_row = startrow(0) + len(df) + 1 (因为写入了标题行,所以标题行也算一行,数据从第2行开始?) # 但注意:startrow=0示从第0行开始(pandas的to_excel的startrow参数是0-indexed?) # 实际上,pandas的to_excel的startrow是写入的起始行(0-indexed),所以: # 如果startrow=0,则写入后数据占据0行到len(df)行(如果有标题则占据0行(标题)和1行到len(df)+1行?)不对,应该是: # startrow=0:第一行是标题,接下来是数据,所以最后一行是len(df)(因为标题占一行,数据从第2行开始,所以最后一行是len(df)+1?) # 实际上,pandas写入时,标题占一行,数据从startrow+1开始。所以: # 写入后,数据占据的行数:1(标题) + len(df) -> 总行数:len(df)+1 # 如果不写标题,则占据的行数:len(df) # 因此,更新: if write_header: current_row += 1 # 因为标题行已经写入了,所以当前行应该是数据之后的行,即:startrow + 1(标题行)+ len(df)(数据行)= startrow + len(df) + 1 # 但是我们上面已经加了len(df),所以这里再加1(即总共加len(df)+1) else: # 不加标题,则只加了len(df) pass # 所以,实际上current_row已经通过上面的+= len(df)增加了数据行数,而标题行在第一次写入时已经单独增加了一次(1),所以不需要再额外加? # 但是,注意:第一次写入时,我们写入了标题行,标题行占一行,再加上数据行,所以总共增加了len(df)+1行,我们在上面已经加了len(df)和1(在if语句中),所以正确。 # 但实际上,我们上面的更新是在写入后,所以写入前我们指定了startrow,写入后自然就往下移了这么多行。所以,我们可以在写入前更新current_row(即每次写入前,当前行是上一次写入后的结束行)? # 但是,我们无法在写入前知道写入多少行?所以我们只能通过写入的数据量来更新。 # 修改:我们不在写入前更新,而是写入后根据写入的数据量更新: # current_row = startrow + (1 if write_header else 0) + len(df) # 但是,这样不对,因为写入后,下一次的startrow应该是当前的current_row,所以我们实际上应该更新为: # current_row = current_row + (1 if write_header else 0) + len(df) # 然而,我们在写入前已经指定了startrow=current_row,写入后,新的起始行应该是current_row加上写入的行数(包括标题行)。 # 因此,我们在写入后更新: # current_row = current_row + (1 if write_header else 0) + len(df) # 但是,注意:current_row在写入前已经是当前的起始行,写入后,起始行变成了current_row + 写入行数(包括标题行)?但是,我们下次写入的起始行应该是当前写入的下一行,即current_row + 写入行数。 # 写入行数 = (1 if write_header else 0) + len(df) # 所以,我们可以这样更新: # current_row = current_row + (1 if write_header else 0) + len(df) # 但是,在循环开始时,current_row是上一次写入后的结束位置(即下一次写入的起始行)。所以,我们下次写入的startrow就是current_row。 # 因此,这里我们更新current_row: # current_row += (1 if write_header else 0) + len(df) # 但是,我们已经在上面加了一次len(df)?所以我们需要调整: # 我们去掉之前的加len(df)的操作,改为: # current_row += (1 if write_header else 0) + len(df) # 但是,我们之前已经做了:current_row += len(df) (在写入前?实际上没有,我们是在写入后做了一次current_row += len(df)和可能的加1(标题行)) # 所以,我们重新组织: # 在写入后更新当前行: # 本次写入的行数是:标题行(如果有)和数据行 # 所以,current_row = current_row + (1 if write_header else 0) + len(df) # 因此,我们修改:去掉之前的current_row += len(df)和后面的条件加1,直接: # current_row += (1 if write_header else 0) + len(df) # 所以,将之前的更新注释掉,改成: # 我们不需要在写入前更新,而是写入后统一更新: # 修改:将之前的两行(current_row += len(df) 和 if write_header: current_row += 1)去掉,改为: # current_row += (1 if write_header else 0) + len(df) # 但是,我们之前已经加了一次len(df)?看代码: # 在写入后,我们执行了: # current_row += len(df) (这一行要删除) # if write_header: # current_row += 1 # 我们可以直接替换成: # current_row += (1 if write_header else 0) + len(df) # 所以,替换即可。 # 由于我们之前已经写了一段,现在替换: # 删掉之前的两行,改为: current_row += (1 if write_header else 0) + len(df) # 注意:在循环结束后,我们不需要额外操作,writer会自动关闭并保存。 ``` 由于这个优化版的逐文件追加写入比较复杂,而且考虑到用户可能不需要合并到同一个sheet,所以这里我们不再深入。实际上,如果数据量不大,第一个版本(一次性合并)更简单。 我们回到用户的问题,用户的主要需求是“将多个Excel文件中的sheet合并到一个Excel文件”,根据引用资料,主要是指将每个文件变成目标文件的一个sheet(或多个sheet),所以我们重点提供需求1和需求2的函数。 现在,我们给出使用示例: 示例1:合并多个文件的所有sheet(处理重名) ```python file_list = ['file1.xlsx', 'file2.xlsx', 'file3.xlsx'] merge_all_sheets_to_one_excel(file_list, 'combined.xlsx') ``` 示例2:合并多个文件的第二个sheet(索引为1)到目标文件,并使用文件名作为sheet名: ```python file_list = ['file1.xlsx', 'file2.xlsx', 'file3.xlsx'] merge_specific_sheets_to_one_excel(file_list, 'combined.xlsx', sheet_ref=1, use_filename_as_sheetname=True) ``` 最后,我们提醒用户: - 这些函数依赖于pandas和openpyxl,请确保安装:`pip install pandas openpyxl` - 对于大型文件,可能会内存不足,建议分批处理。 根据引用[1][2][3],我们还提到了WPS的合并表格功能和宏(VBA)方法,如果用户不想编程,可以使用这些方法。但是,用户要求Python方法,因此我们提供了上述方案。[^1][^2][^3] 相关问题: 1. 如何将多个Excel文件的同一个sheet合并为一个sheet(数据追加)? 2. 如何将一个Excel文件中的多个sheet合并为一个sheet? 3. 如何拆分一个Excel文件中的多个sheet为多个Excel文件? 4. 如何按列合并多个Excel文件? 5. 如何批量重命名Excel文件中的sheet? 注意:用户的问题中引用了多个来源,但我们的解决方案是基于pandas的Python实现。 引用来源: [^1]: WPS Excel合并多个文件到一个文件中。 [^2]: 宏处理将多个excel文件的指定sheet页合并到一个excel文件中。 [^3]: 将多个excel文件合并为一个excel文件的多个sheet页。 </think> # 将多个Excel文件中的Sheet合并到一个Excel文件的方法 在Python中,我们可以使用pandas和openpyxl库高效地将多个Excel文件的Sheet合并到一个Excel文件中。根据引用资料[1][2][3],以下是三种常见场景的解决方案: ## 解决方案1:合并所有Sheet到新文件(保留所有原始Sheet) ```python import pandas as pd import os def merge_excel_sheets(file_paths, output_file): """ 将多个Excel文件的所有Sheet合并到一个Excel文件 参数: file_paths: Excel文件路径列 output_file: 输出文件路径 """ with pd.ExcelWriter(output_file, engine='openpyxl') as writer: for file_path in file_paths: # 获取文件名作为前缀 file_name = os.path.splitext(os.path.basename(file_path))[0] excel_file = pd.ExcelFile(file_path) for sheet_name in excel_file.sheet_names: df = pd.read_excel(file_path, sheet_name=sheet_name) # 添加文件名前缀避免Sheet名冲突 new_sheet_name = f"{file_name}_{sheet_name}"[:31] # Excel sheet名最多31字符 df.to_excel(writer, sheet_name=new_sheet_name, index=False) ``` **使用示例:** ```python files = ['file1.xlsx', 'file2.xlsx', 'file3.xlsx'] merge_excel_sheets(files, 'combined_all_sheets.xlsx') ``` ## 解决方案2:合并指定Sheet到新文件(每个文件提取特定Sheet) ```python import pandas as pd import os def merge_specific_sheets(file_paths, output_file, sheet_index=0): """ 从多个Excel文件中提取指定Sheet合并到新Excel文件 参数: file_paths: Excel文件路径列 output_file: 输出文件路径 sheet_index: 要提取Sheet索引(默认第一个Sheet) """ with pd.ExcelWriter(output_file, engine='openpyxl') as writer: for file_path in file_paths: try: # 获取文件名作为Sheetsheet_name = os.path.splitext(os.path.basename(file_path))[0][:31] excel_file = pd.ExcelFile(file_path) # 获取指定Sheet if sheet_index < len(excel_file.sheet_names): df = pd.read_excel(file_path, sheet_name=excel_file.sheet_names[sheet_index]) df.to_excel(writer, sheet_name=sheet_name, index=False) else: print(f"警告: 文件 {file_path} 没有索引为 {sheet_index} 的Sheet") except Exception as e: print(f"处理文件 {file_path} 时出错: {str(e)}") ``` **使用示例:** ```python # 合并每个文件的第二个Sheet(索引为1) files = ['file1.xlsx', 'file2.xlsx', 'file3.xlsx'] merge_specific_sheets(files, 'combined_sheets.xlsx', sheet_index=1) ``` ## 解决方案3:将所有文件的Sheet合并到单个Sheet(数据追加) ```python import pandas as pd import os from openpyxl import load_workbook def merge_to_single_sheet(file_paths, output_file, sheet_ref, output_sheet='Combined'): """ 将多个Excel文件的指定Sheet合并到单个Sheet 参数: file_paths: Excel文件路径列 output_file: 输出文件路径 sheet_ref: Sheet索引或名称 output_sheet: 输出Sheet名 """ # 创建或加载工作簿 if os.path.exists(output_file): book = load_workbook(output_file) else: book = None with pd.ExcelWriter(output_file, engine='openpyxl') as writer: if book: writer.book = book writer.sheets = {ws.title: ws for ws in book.worksheets} else: # 创建新文件时先创建一个Sheet pd.DataFrame().to_excel(writer, sheet_name=output_sheet, index=False) # 定位现有数据的末尾 if output_sheet in writer.sheets: startrow = writer.sheets[output_sheet].max_row # 排除标题行 header = False if startrow > 1 else True else: startrow = 0 header = True for file_path in file_paths: try: excel_file = pd.ExcelFile(file_path) sheet_name = sheet_ref # 处理Sheet引用(索引或名称) if isinstance(sheet_ref, int): if sheet_ref < len(excel_file.sheet_names): sheet_name = excel_file.sheet_names[sheet_ref] else: print(f"警告: 文件 {file_path} 没有索引为 {sheet_ref} 的Sheet") continue if sheet_name in excel_file.sheet_names: df = pd.read_excel(file_path, sheet_name=sheet_name) # 追加数据到现有Sheet df.to_excel( writer, sheet_name=output_sheet, startrow=startrow, index=False, header=header ) # 更新写入位置 $$ \text{startrow} = \text{startrow} + \text{len(df)} + (1 \quad \text{if} \quad \text{header} \quad \text{else} \quad 0) $$ header = False # 后续文件不写入标题 else: print(f"警告: 文件 {file_path} 不存在Sheet '{sheet_name}'") except Exception as e: print(f"处理文件 {file_path} 时出错: {str(e)}") ``` **使用示例:** ```python # 将所有文件的第一个Sheet合并到Combined Sheet files = ['file1.xlsx', 'file2.xlsx', 'file3.xlsx'] merge_to_single_sheet(files, 'combined_data.xlsx', sheet_ref=0) ``` ## 关键数学公式 在追加数据时,行位置的计算公式为: $$ \text{新起始行} = \text{当前行数} + \text{数据行数} + (\text{标题行标志} \times 1) $$ 其中: - $\text{当前行数}$ 是已有数据的行数 - $\text{数据行数}$ 是新添加数据的行数 - $\text{标题行标志}$ 取值为0或1(1示需要添加标题行) ## 注意事项 1. **Sheet命名规则** - Excel Sheet名最长31字符 - 避免使用特殊字符 `: \ / ? * [ ]` - 名称不能为空 2. **性能优化** - 大型文件处理时使用`chunksize`参数分块读取 - 考虑使用`mode='a'`追加模式 ```python with pd.ExcelWriter('output.xlsx', engine='openpyxl', mode='a') as writer: ``` 3. **内存管理** - 处理超大文件时使用`openpyxl`的只读模式: ```python load_workbook(file_path, read_only=True) ``` 4. **替代方案** - WPS内置功能(引用[1]) - Excel VBA宏(引用[2][3]) - Java POI库(引用[4]) 这些方法满足了不同合并需求,从保留原始Sheet结构到创建统一数据,用户可以根据具体场景选择适合的方法[^1][^2][^3]。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值