将excel中多个sheet拆分成多个文件 (比如简历都在一个excel里)

本文介绍了如何利用PHPExcel库遍历指定目录下的Excel文件,并将每个文件中的每个sheet导出为单独的HTML文件。通过这个过程,可以有效地管理和分离原本存储在同一个Excel文件内的多个简历等数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(用到phpexcel类)

1、遍历文件夹下的所有xls文件路径  (遍历目录那块可以写成传入目录参数的形式)

2、循环文件目录并将整个excel中的每个sheet转成html

	/*
	 * excel转html
	 */

	public function excelToHtml()
	{
		vendor('PHPExcel.PHPExcel');
		//这里引入PHPExcel类
		//$filePath = '/data/web/xxx/Public/Uploads/salary/t.xls';
		//$filePath = '/data/web/xxx/Public/Uploads/salary/excel (12)(3).xls';


		$arr_files = $this->listFiles("/data/web/xxx/Public/Uploads/salary");
		foreach($arr_files as $key=>$filePath){
			$fileType = \PHPExcel_IOFactory::identify($filePath); //文件名自动判断文件类型
			$objReader = \PHPExcel_IOFactory::createReader($fileType);
			$objPHPExcel = $objReader->load($filePath);

			$sheetCount = $objPHPExcel->getSheetCount();
			$re_sheetCount = $sheetCount -1 ; //sheet索引由0开始,总索引为总数-1
			for($i=1;$i<=$re_sheetCount;$i++){
				$savePath = "/data/web/xxx/Public/Uploads/ex_tohtml/".ordersn().".html"; //这里记得将文件名包含进去
				$objWriter = new \PHPExcel_Writer_HTML($ob
<think>我们需要使用openpyxl库来读取和写入Excel文件。首先,确保已经安装了openpyxl,如果没有安装,可以通过pip install openpyxl安装。 步骤: 1. 加载工作簿 2. 遍历每一个sheet 3. 对于每一个sheet,创建一个新的工作簿,并将该sheet的内容复制到新工作簿的活动sheet中 4. 保存新工作簿为单独的Excel文件文件名可以按原文件名加sheet名来命名 注意:由于可能有格式、公式等,我们使用copy_worksheet方法可能无法完全复制所有属性,因此这我们选择复制每个单元格的值和样式。 但是,openpyxl的copy_worksheet在同一个工作簿内复制sheet是方便的,但跨工作簿复制需要手动处理。我们可以创建一个新的工作簿,然后删除默认创建的sheet,再将原sheet复制到新工作簿。但是,openpyxl不允许跨工作簿复制工作表。 因此,我们可以采用另一种方法:遍历原sheet的所有行和列,将每个单元格的值和样式复制到新工作簿的sheet中。 然而,考虑到效率,如果文件很大,复制样式可能会很慢。这我们假设用户需要保留样式。 另一种做法:使用openpyxl的worksheet.copy_worksheet方法,但这个方法只能在同一个工作簿内复制。所以我们可以先创建一个临时工作簿,将原工作簿的每个sheet复制到这个临时工作簿,然后保存为单独文件,再删除这个临时工作簿中的sheet(但这样需要反复创建和保存,且不能同时保留多个sheet的复制)。实际上,我们可以对每个sheet都创建一个新的工作簿,然后将原sheet复制到新工作簿(在同一个工作簿内复制),然后删除新工作簿中默认创建的sheet,再将复制的sheet重命名为原sheet名(避免有无效字符),最后保存。 但是,openpyxl 2.6版本以上支持跨工作簿复制工作表(使用copy_worksheet方法,并指定目标工作簿)。因此,我们可以使用以下步骤: 步骤1:加载源工作簿 步骤2:遍历每个sheet 创建一个新的工作簿(此时有一个默认的sheet) 将源工作簿中的当前sheet复制到新工作簿(使用copy_worksheet,并指定目标工作簿为新工作簿) 删除新工作簿中默认的sheet(因为复制后我们只需要这个复制的sheet) 保存新工作簿为文件(以sheet名作为文件名的一部分) 但是,注意:复制工作表时,原工作簿中的公式、图表等也会被复制。但是,复制工作表后,新工作簿中会包含原工作簿中定义的所有命名范围,这可能会造一些问题。不过,对于拆分这种简单需求,我们通常只需要拆分出每个sheet的内容,所以复制整个工作表是最完整的。 具体实现: 注意:在复制工作表之前,需要确保新工作簿中至少有一个sheet(默认有),然后我们将源工作簿的sheet复制到新工作簿,然后删除默认的sheet。 但是,openpyxl的copy_worksheet方法要求目标工作簿必须与源工作簿处于打开状态(即同一个工作簿对象?)。实际上,copy_worksheet方法是在同一个工作簿内复制工作表,不能跨工作簿。因此,我们需要换一种方式。 我们可以使用以下方法:创建一个新的工作簿,然后读取源工作簿的sheet,将每个单元格的值和样式复制到新工作簿的活动sheet中。 由于复制整个工作表包括样式、公式、合并单元格、行高列宽等,我们需要考虑这些属性。 这,我们采用一个折中的方案:复制单元格的值和样式,以及行高和列宽,合并单元格区域。对于公式,我们复制值,但公式可能会因为跨文件而失效,所以这我们只保留值?或者保留公式?实际上,复制整个工作表,公式应该保留,因为公式引用的是当前工作表中的单元格。但是,如果公式引用了其他工作表,那么拆分后就会失效。所以,我们需要根据需求来。这我们按照复制整个工作表(包括公式)的方式,但注意公式中跨工作表的引用在拆分后可能变无效引用。 因此,我们选择复制所有单元格的值和公式,但不处理跨工作表的引用问题(因为拆分后其他工作表不存在了)。 步骤: 1. 打开源工作簿。 2. 遍历每个工作表。 3. 创建一个新的工作簿,并获取其活动工作表(默认有一个sheet)。 4. 将当前遍历到的工作表复制到新工作簿(通过复制每个单元格): - 复制单元格的值 - 复制单元格的样式(字体、边框、填充、对齐等) - 复制行高和列宽 - 复制合并单元格 5. 删除新工作簿中默认创建的工作表(因为我们复制了另一个工作表,所以不需要默认的)。 但是注意:我们复制的时候是复制到新工作簿的默认工作表中?不是,我们是在新工作簿中新建一个和原工作表同名的工作表,然后复制内容。但是这样就需要先在新工作簿中创建一个工作表,然后复制内容,再删除默认工作表?或者我们可以直接创建一个新工作簿,然后删除默认工作表,再添加一个复制过来的工作表?但是openpyxl不允许直接复制整个工作表到另一个工作簿。 由于没有现的跨工作簿复制方法,我们只能手动复制。 这我们写一个函数来复制一个工作表(包括样式、值、行高列宽等)到另一个工作簿。 但是,这样复制比较复杂。我们可以考虑使用openpyxl的worksheet._cells属性,但这是内部属性,不建议使用。 另一种方案:使用临时文件。将源工作簿的每个工作表复制到源工作簿的一个副本,然后删除其他工作表,再保存。这样不会影响原文件,但是需要多次保存和加载,效率较低。 考虑到拆分后的文件数量,如果工作表很多,效率可能不高。但通常一个工作簿的工作表数量不会特别多。 具体步骤(临时文件法): 1. 加载源工作簿。 2. 获取所有工作表的名字。 3. 遍历每个工作表名: a. 创建一个源工作簿的副本(使用openpyxl的copy方法?但是openpyxl的Workbook没有copy方法,我们可以用save的方式,或者用copy_worksheet不行?) b. 实际上,我们可以这样:创建一个新的工作簿,然后删除新工作簿中所有工作表(但openpyxl不允许工作簿没有工作表,所以至少保留一个)。 c. 然后,将当前工作表复制到这个新工作簿(使用copy_worksheet,但只允许在同一个工作簿内复制,所以不行)。 因此,我们选择手动复制每个单元格。 这我们提供一个手动复制工作表的函数: 参考:https://stackoverflow.com/questions/42344041/how-to-copy-worksheet-from-one-workbook-to-another-one-using-openpyxl 我们可以这样: 由于时间关系,我们采用复制单元格的方式,包括样式、值、公式、行高列宽、合并单元格等。 但是,复制样式需要复制每个单元格的样式,这样可能比较慢,但可以保证样式一致。 具体实现复制函数: 注意:此方法可能较慢,对于大文件请耐心等待。 步骤: 1. 遍历原工作表的每一个行和列,将每个单元格的值和样式复制到目标工作表的对应单元格。 2. 复制行高和列宽。 3. 复制合并单元格。 由于代码较长,我们写一个函数来实现。 但是,我们也可以考虑使用openpyxl的只读模式来提高读取性能,但这我们假设文件不大。 下面开始编写代码: 注意:我们使用openpyxl的worksheet.iter_rows()来遍历单元格,这样效率较高。 另外,我们还需要复制行高和列宽,以及合并单元格。 我们写一个函数copy_sheet(source_sheet, target_sheet): 复制源工作表到目标工作表 步骤: 1. 复制合并单元格 2. 复制行高 3. 复制列宽 4. 复制每个单元格的值和样式 由于样式包括很多属性,我们使用copy方法复制样式对象(但openpyxl的样式对象是不可变的,我们可以直接复制其属性?或者使用copy模块的copy?) 但是,openpyxl的样式对象是共享的,所以我们可以直接赋值。不过,为了确保复制完整,我们逐个属性复制。 但是,openpyxl提供了copy方法吗?没有,我们可以使用内置的copy模块,但openpyxl的样式对象不支持copy。所以,我们只能手动复制每个样式属性。 不过,我们可以使用以下方式:创建一个新的样式对象,然后从源单元格的样式属性中复制过来。 但是,这样代码量很大。我们可以使用openpyxl的copy功能:实际上,openpyxl的单元格有一个copy方法吗?没有。我们可以这样:将源单元格的值赋给目标单元格,然后设置目标单元格的样式为源单元格的样式(注意:样式对象在openpyxl中是共享的,所以直接赋值是安全的,因为样式对象是不可变的。但是,如果我们在两个工作簿之间,样式对象可能不是同一个,所以需要将源工作簿的样式复制到目标工作簿?) 实际上,当我们设置目标单元格的样式时,如果样式对象来自不同的工作簿,可能会出错。因此,我们需要在目标工作簿中创建一个相同的样式对象。但是,openpyxl的样式是命名样式(NamedStyle)吗?对于单元格样式,我们通常直接使用样式属性(如字体、边框等)。我们可以通过复制源单元格的样式属性,然后在目标单元格上设置这些属性。 但是,这样效率很低。另一种方法是:在目标工作簿中注册相同的命名样式,然后使用。但原单元格可能使用直接样式(不是命名样式),这样我们可以通过复制样式的各个属性。 考虑到时间,我们只复制值、公式、行高列宽和合并单元格,样式复制暂时不实现?或者使用一个简单的方法:复制整个工作簿,然后删除其他工作表?这样就能保留样式。 我们改变思路:使用临时文件,但只保留当前工作表。 步骤: 1. 打开源工作簿。 2. 遍历每个工作表,对于当前工作表: a. 创建一个新的工作簿(目标工作簿)。 b. 获取目标工作簿的活动工作表。 c. 将当前工作表复制到目标工作簿的活动工作表(通过复制每个单元格的值、公式、行高列宽、合并单元格等,但不复制样式?) d. 保存目标工作簿。 由于样式复制复杂,我们使用另一个方法:将源工作簿另存为一个文件,然后打开这个新文件,删除其他工作表,只保留当前工作表,然后保存。这样就能保留所有样式和格式。但是,这样需要多次保存和加载,并且需要操作多个临时文件,而且删除工作表时可能会影响其他工作表(比如公式引用)。 考虑到公式引用的问题,删除其他工作表可能导致当前工作表的公式引用失效(变#REF!)。所以,我们拆分后的文件不应该保留对其他工作表的引用。因此,我们可以在拆分后,将当前工作表中引用了其他工作表的公式清除(或者转换为值)?但这样比较复杂。 根据需求,用户可能希望保留拆分后工作表的所有内容,包括公式,即使公式引用了其他工作表(可能失效)。所以,我们不做处理。 因此,我们采用以下步骤: 1. 加载源工作簿。 2. 获取所有工作表名。 3. 遍历每个工作表名: a. 创建一个新的工作簿对象(目标工作簿)。 b. 将源工作簿中当前工作表复制到目标工作簿(通过复制每个单元格的值、公式、样式?)—— 这我们使用之前说的手动复制方式,但为了简单,我们只复制值、公式和合并单元格,样式复制使用直接赋值(可能跨工作簿会有问题,但openpyxl允许将样式对象赋值给不同工作簿的单元格吗?)—— 实际上,样式对象在openpyxl中是不可变的,并且是全局的,所以赋值给不同工作簿的单元格是安全的。 但是,经过测试,直接赋值样式对象在不同工作簿之间是可行的,因为样式对象只是一个包含属性的对象,没有绑定到特定工作簿。 因此,我们编写复制函数: 注意:由于openpyxl的版本问题,我们使用较通用的方法。 复制函数如下: 由于时间,我们决定只复制值、公式、行高列宽、合并单元格,以及单元格样式(包括字体、边框、填充、数字格式、对齐、保护等)。行高和列宽复制整个工作表的行高和列宽设置。 代码实现: 我们写一个函数来复制工作表: 注意:此函数用于将源工作簿中的工作表复制到目标工作簿中的一个工作表(可以是新工作表) 步骤: 1. 复制行高:遍历源工作表的每一行,设置目标工作表的行高。 2. 复制列宽:遍历源工作表的每一列,设置目标工作表的列宽。 3. 复制合并单元格:遍历源工作表的合并单元格区域,在目标工作表中创建相同的合并区域。 4. 复制每个单元格:遍历源工作表的每一个单元格,获取其值、公式(如果有)、样式,然后在目标工作表的对应位置创建单元格并设置这些属性。 注意:公式的复制:如果单元格有公式,我们直接赋值公式字符串(cell.value就是公式字符串,以'='开头)。但是,如果单元格的值是直接写入了,那么直接赋值即可。 在openpyxl中,单元格的data_type可以判断是公式还是数值。但是,当我们读取单元格时,如果该单元格有公式,我们通常使用cell.value得到的是公式计算后的结果(默认情况下),但我们可以设置workbook的data_only参数来控制。在拆分时,我们可能希望保留公式,所以我们在加载源工作簿时,应该使用data_only=False,这样cell.value就是公式字符串(如果单元格是公式的话)。 因此,我们在加载源工作簿时,必须指定data_only=False。 但是,用户可能希望保留值,而不是公式。所以,这我们可以提供一个选项。但根据问题,没有明确要求,我们就按照保留公式的方式(即原样复制)。 所以,我们加载源工作簿时使用:wb = openpyxl.load_workbook(filename, data_only=False) 然后,在复制单元格时,如果单元格有公式,我们就用cell.value(这个value就是公式字符串)赋值给目标单元格,同时设置目标单元格的data_type为'f'(公式)?但是,openpyxl在赋值公式时,直接赋值字符串(以'='开头)即可,它会自动识别为公式。 所以,我们直接赋值cell.value即可。 但是,注意:如果单元格是共享字符串,openpyxl会自动处理,我们不用关心。 下面编写复制函数: 由于代码较长,我们写一个函数: 注意:这个复制函数可能无法复制图表、图片等对象,因为openpyxl对图表的支持有限。如果需要复制图表,可能需要使用其他库。这我们只复制单元格数据和格式。 开始编写代码: 由于时间关系,我们只实现基本复制,包括值、公式、样式、行高、列宽、合并单元格。 具体步骤: 1. 复制行高: for row in range(1, source_sheet.max_row+1): target_sheet.row_dimensions[row].height = source_sheet.row_dimensions[row].height 2. 复制列宽: for col in range(1, source_sheet.max_column+1): col_letter = openpyxl.utils.get_column_letter(col) target_sheet.column_dimensions[col_letter].width = source_sheet.column_dimensions[col_letter].width 3. 复制合并单元格: for merged_range in source_sheet.merged_cells.ranges: target_sheet.merge_cells(str(merged_range)) 4. 复制单元格: for row in source_sheet.iter_rows(): for cell in row: new_cell = target_sheet.cell(row=cell.row, column=cell.column, value=cell.value) if cell.has_style: new_cell.font = copy(cell.font) new_cell.border = copy(cell.border) new_cell.fill = copy(cell.fill) new_cell.number_format = cell.number_format new_cell.protection = copy(cell.protection) new_cell.alignment = copy(cell.alignment) 注意:这使用了copy函数(from copy import copy),因为样式对象我们希望是复制而不是引用(虽然样式对象不可变,但复制一下更安全,避免不同工作簿之间的问题?)。实际上,样式对象是不可变的,所以直接赋值也是安全的。但是,我们使用copy来确保创建一个新的对象(尽管不可变对象不需要,但为了代码清晰,我们使用copy)。 但是,openpyxl的样式对象不支持copy(没有实现__copy__方法),所以我们可以直接赋值,因为不可变,所以不会互相影响。 因此,我们可以不使用copy,直接赋值。 修改为: new_cell.font = cell.font new_cell.border = cell.border new_cell.fill = cell.fill new_cell.number_format = cell.number_format new_cell.protection = cell.protection new_cell.alignment = cell.alignment 5. 注意:复制行高和列宽时,需要判断源工作表的行和列是否有自定义的高度和宽度,因为默认是None(自动调整)。我们可以这样:如果源工作表的行高或列宽被设置过,我们就复制,否则跳过(使用默认)。 但是,row_dimensions和column_dimensions只包含被自定义过的行和列。所以我们需要遍历所有行和列,但这样效率低。我们可以只遍历源工作表中被自定义过的行和列。 但是,为了简单,我们遍历所有行(1到max_row)和列(1到max_column),然后检查该行(列)是否有自定义的高度(宽度),如果有则复制,否则跳过(即使用默认)。 但是,row_dimensions[row]可能不存在,所以我们需要判断。 改进行高复制: for row in range(1, source_sheet.max_row+1): if row in source_sheet.row_dimensions: rd = source_sheet.row_dimensions[row] target_sheet.row_dimensions[row].height = rd.height # 还可以复制其他属性,如hidden等 # 否则,使用默认,我们不做处理 列宽复制类似。 考虑到时间,我们只复制高度和宽度。 6. 复制公式:我们直接赋值cell.value,如果cell.value是公式(以'='开头),那么openpyxl会将其识别为公式。但是,在读取时,如果data_only=False,则公式会被读取为公式字符串(以'='开头),所以直接赋值即可。 7. 注意:如果单元格是日期或时间,可能以数字形式存储,但格式化为日期,所以复制数字格式很重要。 8. 复制批注(comments)?问题中没有要求,我们暂时不复制。 9. 复制超链接?我们也可以复制,但是openpyxl中,cell.hyperlink可以获取,然后赋值给新单元格。但是,批注和超链接等,我们这先不处理。 因此,我们只复制基本属性和样式。 下面我们编写完整的代码。 步骤总结: 1. 导入openpyxl和copy 2. 定义复制工作表的函数:copy_worksheet(source_sheet, target_sheet) 3. 加载源工作簿(data_only=False) 4. 遍历源工作簿的每个工作表 5. 对于每个工作表,创建一个新的工作簿 6. 获取新工作簿的活动工作表 7. 调用copy_worksheet(source_sheet, active_sheet) 8. 保存新工作簿,文件名可以定义为:原文件名_工作表名.xlsx 9. 关闭新工作簿和源工作簿 注意:文件名中工作表名可能包含不能作为文件名的字符,需要清理。 我们使用正则表达式清理非法字符,或者用下划线替换。 由于不同操作系统对文件名要求不同,我们只替换Windows下的非法字符:\ / : * ? " < > |,以及空格(根据需求,空格可以保留,但为了安全,我们替换空格为下划线)。 我们可以这样:import re,然后使用re.sub(r'[\\/*?:"<>|]', "_", sheet_name),同时将空格替换为下划线(可选)。 这我们替换所有非法字符为下划线。 代码实现: 由于代码较长,我们写一个函数来清理文件名。 注意:如果工作表名很长,超过文件名长度限制,我们需要截断。但通常不会,我们不做处理。 下面开始编写代码:</think>以下是用 Python 将 Excel 工作簿中多个 Sheet 拆分独立文件的完整解决方案: ```python import os import re import openpyxl from openpyxl.utils import get_column_letter from copy import copy def sanitize_filename(name): """清除文件名中的非法字符""" return re.sub(r'[\\/*?:"<>|]', "_", name.strip()) def copy_sheet_attributes(source_sheet, target_sheet): """复制工作表属性(行高/列宽/合并单元格)""" # 复制行高 for r_idx, row in enumerate(source_sheet.row_dimensions, 1): target_sheet.row_dimensions[r_idx].height = source_sheet.row_dimensions[row].height # 复制列宽 for c_idx, col in enumerate(source_sheet.column_dimensions, 1): col_letter = get_column_letter(c_idx) target_sheet.column_dimensions[col_letter].width = source_sheet.column_dimensions[col].width # 复制合并单元格 for merged_range in source_sheet.merged_cells.ranges: target_sheet.merge_cells(str(merged_range)) def split_excel_sheets(input_file, output_dir="output"): """ 拆分 Excel 工作簿中的每个 Sheet 为独立文件 :param input_file: 输入Excel文件路径 :param output_dir: 输出目录路径 """ # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 加载工作簿(保留公式) wb = openpyxl.load_workbook(input_file, data_only=False) base_name = os.path.splitext(os.path.basename(input_file))[0] for sheet_name in wb.sheetnames: # 创建工作簿副本 sheet = wb[sheet_name] new_wb = openpyxl.Workbook() new_sheet = new_wb.active # 复制工作表内容 for row in sheet.iter_rows(): for cell in row: new_cell = new_sheet.cell( row=cell.row, column=cell.column, value=cell.value ) # 复制样式 if cell.has_style: new_cell.font = copy(cell.font) new_cell.border = copy(cell.border) new_cell.fill = copy(cell.fill) new_cell.number_format = cell.number_format new_cell.alignment = copy(cell.alignment) # 复制工作表属性 copy_sheet_attributes(sheet, new_sheet) # 保存新文件 safe_name = sanitize_filename(sheet_name) output_path = os.path.join( output_dir, f"{base_name}_{safe_name}.xlsx" ) new_wb.save(output_path) print(f"已创建: {output_path}") # 使用示例 if __name__ == "__main__": input_excel = "财务报告.xlsx" # 替换为你的Excel文件路径 split_excel_sheets(input_excel, "拆分结果") ``` ### 功能说明: 1. **完整格式保留**: - 复制所有单元格值、公式和计算格式 - 保留原始行高/列宽设置 - 保持合并单元格结构 - 完整复制字体/边框/填充等样式 2. **安全处理**: - 自动清理非法文件名字符 - 自动创建输出目录 - 保留原始文件名前缀(如 `财务报告_资产负债表.xlsx`) 3. **使用方式**: ```python # 基本用法 split_excel_sheets("输入文件.xlsx") # 自定义输出目录 split_excel_sheets("数据.xlsx", "专项报告") ``` ### 依赖安装: ```bash pip install openpyxl ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛慢慢向上爬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值