|
场景在工作中,我们有时候会将一个excel中的sheet复制到一个新的excel中。这通常我们如果使用pandas中的dataframe就能轻松实现,但是当我们遇到有合并单元格的多级表头的excel,dataframe处理起来就麻烦多了,我们更倾向于使用openpyxl库与pandas结合起来处理数据。这个时候就会有一个问题:你会发现openpyxl复制的时候,按照网上的方法,通常只会复制数据,将数据格式和合并单元格,边框等都丢掉了,导致复制表格这个操作失败。代码如下:importopenpyxl#打开源Excel文件和工作表source_workbook=openpyxl.load_workbook('source.xlsx')source_sheet=source_workbook.active#创建目标Excel文件和工作表target_workbook=openpyxl.Workbook()target_sheet=target_workbook.active#复制数据和格式forrowinsource_sheet.iter_rows(values_only=True):target_sheet.append(row)12345678910以上代码只复制了数据,但是没有复制数据格式和合并单元格等表格样式。跨工作簿带格式复制分类跨工作簿带格式复制总体上大概分成两种情况:(1)直接从文件中读取,然后复制;(2)已经通过openpyxl库读取到内存中,经过数据处理后,要将sheet复制到一个新的excel中保存。第一类:第一种比较简单,在网上也能看到很多总结,我这里也找到其中一种进行举例:#代码1:带格式复制一个sheet到另一个sheetfromopenpyxlimportload_workbookimportxlwingsasxwapp=xw.App(visible=False,add_book=False)source_workbook=app.books.open('原表.xlsx')target_workbook=app.books.open('target.xlsx')sheet_name=source_workbook.sheets['汇总']#要复制的工作表名称target_worksheet=target_workbook.sheets[0]sheet_name.copy(before=target_worksheet)target_workbook.save()target_workbook.close()source_workbook.close()app.quit()12345678910111213以上代码可以将一个文件名为“原表.xlsx”,sheet名为“汇总”的表格原样复制到文件名为:“target.xlsx”的文件中,大家可以自行测试。第二类:但是当需要对数据处理,再带格式复制到另一个excel文件的时候,第一种情况提供的代码就很棘手了。话不多说,直接上案例。如下图一个名称为“original.xlsx”的工作簿,里面包含两个sheet,sheet名称分别为:“汇总”和“清单”。现在我们想要将original.xlsx工作簿按照“州名”这一列的值进行拆分,生成若干个新的工作簿。拿州名“威斯康星州”举例,生成的新文件为“威斯康星州.xlsx”。如图。要做以上操作,需要先将原表original.xlsx读入,处理这种有合并单元格的表,我感觉openpyxl更擅长。所以我用load_workbook()方法将original.xlsx读入到内存,先拿出“汇总”表做数据处理,拆成一个州一个文件,这时候我需要先暂存在列表了,然后再拿出“清单”表做数据处理,同样保存到一个列表里,最后我遍历两个列表将一个州的汇总和清单表放到一个文件保存。这时候使用网上的教程要不缺少格式,要不缺少合并单元格,要不缺少列宽。我提供的程序可以将原表全部格式原样复制到新表。但需要注意的是,合并单元格的列宽程序无法全部获取,部分列的列宽设置了默认值,可能无法完全跟原表一致。代码如下:defcopy_sheet_to_sheet(old_sht,new_sht):foriinrange(1,old_sht.max_row+1):#最大行+1forjinrange(1,old_sht.max_column+1):#最大列+1src_cell=old_sht.cell(i,j)#getattr(ws.cell(row=m,column=c),"value")new_sht.cell(row=i,column=j).value=src_cell.valueifsrc_cell.has_style:#拷贝格式new_sht.cell(row=i,column=j).font=copy(src_cell.font)new_sht.cell(row=i,column=j).border=copy(src_cell.border)new_sht.cell(row=i,column=j).fill=copy(src_cell.fill)new_sht.cell(row=i,column=j).number_format=copy(src_cell.number_format)new_sht.cell(row=i,column=j).protection=copy(src_cell.protection)new_sht.cell(row=i,column=j).alignment=copy(src_cell.alignment)ifold_sht.merged_cells:#获取合并单元格的边界print(old_sht.merged_cells)formergecellinold_sht.merged_cells:print(str(mergecell))#在新工作簿中创建合并单元格new_sht.merge_cells(str(mergecell))#遍历所有可能的列forcol_idxinrange(1,old_sht.max_column+1):col_letter=get_column_letter(col_idx)ifcol_letterinold_sht.column_dimensions:#列存在且有明确定义的宽度column_width=old_sht.column_dimensions[col_letter].width#print(f"Column{column}haswidth:{column_width}")new_sht.column_dimensions[col_letter].width=column_widthelse:#列存在但没有明确定义的宽度,可以设置一个默认值new_sht.column_dimensions[col_letter].width=14.35123456789101112131415161718192021222324252627282930313233343536
|
|