[英]How to copy worksheet from one workbook to another one using openpyxl?
I have a large amount of EXCEL files (ie 200) I would like to copy one specific worksheet from one workbook to another one.我有大量 EXCEL 个文件(即 200 个)我想将一个特定的工作表从一个工作簿复制到另一个工作簿。 I have done some investigations and I couldn't find a way of doing it with Openpyxl
我做了一些调查,但找不到使用 Openpyxl 的方法
This is the code I have developed so far这是我到目前为止开发的代码
def copy_sheet_to_different_EXCEL(path_EXCEL_read,Sheet_name_to_copy,path_EXCEL_Save,Sheet_new_name):
''' Function used to copy one EXCEL sheet into another file.
def path_EXCEL_read,Sheet_name_to_copy,path_EXCEL_Save,Sheet_new_name
Input data:
1.) path_EXCEL_read: the location of the EXCEL file along with the name where the information is going to be saved
2.) Sheet_name_to_copy= The name of the EXCEL sheet to copy
3.) path_EXCEL_Save: The path of the EXCEL file where the sheet is going to be copied
3.) Sheet_new_name: The name of the new EXCEL sheet
Output data:
1.) Status= If 0, everything went OK. If 1, one error occurred.
Version History:
1.0 (2017-02-20): Initial version.
'''
status=0
if(path_EXCEL_read.endswith('.xls')==1):
print('ERROR - EXCEL xls file format is not supported by openpyxl. Please, convert the file to an XLSX format')
status=1
return status
try:
wb = openpyxl.load_workbook(path_EXCEL_read,read_only=True)
except:
print('ERROR - EXCEL file does not exist in the following location:\n {0}'.format(path_EXCEL_read))
status=1
return status
Sheet_names=wb.get_sheet_names() # We copare against the sheet name we would like to cpy
if ((Sheet_name_to_copy in Sheet_names)==0):
print('ERROR - EXCEL sheet does not exist'.format(Sheet_name_to_copy))
status=1
return status
# We checking if the destination file exists
if (os.path.exists(path_EXCEL_Save)==1):
#If true, file exist so we open it
if(path_EXCEL_Save.endswith('.xls')==1):
print('ERROR - Destination EXCEL xls file format is not supported by openpyxl. Please, convert the file to an XLSX format')
status=1
return status
try:
wdestiny = openpyxl.load_workbook(path_EXCEL_Save)
except:
print('ERROR - Destination EXCEL file does not exist in the following location:\n {0}'.format(path_EXCEL_read))
status=1
return status
#we check if the destination sheet exists. If so, we will delete it
destination_list_sheets = wdestiny.get_sheet_names()
if((Sheet_new_name in destination_list_sheets) ==True):
print('WARNING - Sheet "{0}" exists in: {1}. It will be deleted!'.format(Sheet_new_name,path_EXCEL_Save))
wdestiny.remove_sheet(Sheet_new_name)
else:
wdestiny=openpyxl.Workbook()
# We copy the Excel sheet
try:
sheet_to_copy = wb.get_sheet_by_name(Sheet_name_to_copy)
target = wdestiny.copy_worksheet(sheet_to_copy)
target.title=Sheet_new_name
except:
print('ERROR - Could not copy the EXCEL sheet. Check the file')
status=1
return status
try:
wdestiny.save(path_EXCEL_Save)
except:
print('ERROR - Could not save the EXCEL sheet. Check the file permissions')
status=1
return status
#Program finishes
return status
You cannot use copy_worksheet()
to copy between workbooks because it depends on global constants that may vary between workbooks.您不能使用
copy_worksheet()
在工作簿之间进行复制,因为它取决于可能因工作簿而异的全局常量。 The only safe and reliable way to proceed is to go row-by-row and cell-by-cell.唯一安全可靠的方法是逐行和逐个单元地进行。
You might want to read the discussions about this feature您可能想阅读有关此功能的讨论
I had a similar requirement to collate data from multiple workbooks into one workbook.我有一个类似的要求,将多个工作簿中的数据整理到一个工作簿中。 As there are no inbuilt methods available in openpyxl.
由于 openpyxl 中没有可用的内置方法。
I created the below script to do the job for me.我创建了以下脚本来为我完成这项工作。
Note: In my usecase all worbooks contain data in same format.注意:在我的用例中,所有工作簿都包含相同格式的数据。
from openpyxl import load_workbook
import os
# The below method is used to read data from an active worksheet and store it in memory.
def reader(file):
global path
abs_file = os.path.join(path, file)
wb_sheet = load_workbook(abs_file).active
rows = []
# min_row is set to 2, to ignore the first row which contains the headers
for row in wb_sheet.iter_rows(min_row=2):
row_data = []
for cell in row:
row_data.append(cell.value)
# custom column data I am adding, not needed for typical use cases
row_data.append(file[17:-6])
# Creating a list of lists, where each list contain a typical row's data
rows.append(row_data)
return rows
if __name__ == '__main__':
# Folder in which my source excel sheets are present
path = r'C:\Users\tom\Desktop\Qt'
# To get the list of excel files
files = os.listdir(path)
for file in files:
rows = reader(file)
# below mentioned file name should be already created
book = load_workbook('new.xlsx')
sheet = book.active
for row in rows:
sheet.append(row)
book.save('new.xlsx')
I've just found this question.我刚刚发现了这个问题。 A good workaround, as mentioned here , could consists in modifying the original
wb
in memory and then saving it with another name.一个很好的解决方法,正如这里提到的,可以包括修改内存中的原始
wb
,然后用另一个名称保存它。 For example:例如:
import openpyxl
# your starting wb with 2 Sheets: Sheet1 and Sheet2
wb = openpyxl.load_workbook('old.xlsx')
sheets = wb.sheetnames # ['Sheet1', 'Sheet2']
for s in sheets:
if s != 'Sheet2':
sheet_name = wb.get_sheet_by_name(s)
wb.remove_sheet(sheet_name)
# your final wb with just Sheet1
wb.save('new.xlsx')
My workaround goes like this:我的解决方法是这样的:
You have a template file let's say it's "template.xlsx".您有一个模板文件,假设它是“template.xlsx”。 You open it, make changes to it as needed, save it as a new file, close the file.
您打开它,根据需要对其进行更改,将其另存为新文件,然后关闭该文件。 Repeat as needed.
根据需要重复。 Just make sure to keep a copy of the original template while testing/messing around.
只需确保在测试/乱搞时保留原始模板的副本。
I had the same problem.我有同样的问题。 For me style, format, and layout were very important.
对我来说,风格、格式和布局非常重要。 Moreover, I did not want to copy formulas but only the value (of the formulas).
此外,我不想复制公式,而只想复制(公式的)值。 After a lot of trail, error, and stackoverflow I came up with the following functions.
经过大量的跟踪、错误和stackoverflow,我想出了以下函数。 It may look a bit intimidating but the code copies a sheet from one Excel file to another (possibly existing file) while preserving:
它可能看起来有点吓人,但代码将工作表从一个 Excel 文件复制到另一个(可能存在的文件),同时保留:
It is useful when you want to gather sheets from many workbooks and bind them into one workbook.当您想从许多工作簿中收集工作表并将它们绑定到一个工作簿中时,它很有用。 I copied most attributes but there might be a few more.
我复制了大部分属性,但可能还有一些。 In that case you can use this script as a jumping off point to add more.
在这种情况下,您可以使用此脚本作为起点来添加更多内容。
###############
## Copy a sheet with style, format, layout, ect. from one Excel file to another Excel file
## Please add the ..path\\+\\file.. and ..sheet_name.. according to your desire.
import openpyxl
from copy import copy
def copy_sheet(source_sheet, target_sheet):
copy_cells(source_sheet, target_sheet) # copy all the cel values and styles
copy_sheet_attributes(source_sheet, target_sheet)
def copy_sheet_attributes(source_sheet, target_sheet):
target_sheet.sheet_format = copy(source_sheet.sheet_format)
target_sheet.sheet_properties = copy(source_sheet.sheet_properties)
target_sheet.merged_cells = copy(source_sheet.merged_cells)
target_sheet.page_margins = copy(source_sheet.page_margins)
target_sheet.freeze_panes = copy(source_sheet.freeze_panes)
# set row dimensions
# So you cannot copy the row_dimensions attribute. Does not work (because of meta data in the attribute I think). So we copy every row's row_dimensions. That seems to work.
for rn in range(len(source_sheet.row_dimensions)):
target_sheet.row_dimensions[rn] = copy(source_sheet.row_dimensions[rn])
if source_sheet.sheet_format.defaultColWidth is None:
print('Unable to copy default column wide')
else:
target_sheet.sheet_format.defaultColWidth = copy(source_sheet.sheet_format.defaultColWidth)
# set specific column width and hidden property
# we cannot copy the entire column_dimensions attribute so we copy selected attributes
for key, value in source_sheet.column_dimensions.items():
target_sheet.column_dimensions[key].min = copy(source_sheet.column_dimensions[key].min) # Excel actually groups multiple columns under 1 key. Use the min max attribute to also group the columns in the targetSheet
target_sheet.column_dimensions[key].max = copy(source_sheet.column_dimensions[key].max) # https://stackoverflow.com/questions/36417278/openpyxl-can-not-read-consecutive-hidden-columns discussed the issue. Note that this is also the case for the width, not onl;y the hidden property
target_sheet.column_dimensions[key].width = copy(source_sheet.column_dimensions[key].width) # set width for every column
target_sheet.column_dimensions[key].hidden = copy(source_sheet.column_dimensions[key].hidden)
def copy_cells(source_sheet, target_sheet):
for (row, col), source_cell in source_sheet._cells.items():
target_cell = target_sheet.cell(column=col, row=row)
target_cell._value = source_cell._value
target_cell.data_type = source_cell.data_type
if source_cell.has_style:
target_cell.font = copy(source_cell.font)
target_cell.border = copy(source_cell.border)
target_cell.fill = copy(source_cell.fill)
target_cell.number_format = copy(source_cell.number_format)
target_cell.protection = copy(source_cell.protection)
target_cell.alignment = copy(source_cell.alignment)
if source_cell.hyperlink:
target_cell._hyperlink = copy(source_cell.hyperlink)
if source_cell.comment:
target_cell.comment = copy(source_cell.comment)
wb_target = openpyxl.Workbook()
target_sheet = wb_target.create_sheet(..sheet_name..)
wb_source = openpyxl.load_workbook(..path\\+\\file_name.., data_only=True)
source_sheet = wb_source[..sheet_name..]
copy_sheet(source_sheet, target_sheet)
if 'Sheet' in wb_target.sheetnames: # remove default sheet
wb_target.remove(wb_target['Sheet'])
wb_target.save('out.xlsx')
I would using openpyxl.worksheet.copier.WorksheetCopy我会使用 openpyxl.worksheet.copier.WorksheetCopy
import pandas as pd
import openpyxl
from openpyxl.worksheet.copier import WorksheetCopy
wb1 = openpyxl.load_workbook("file1.xlsx",read_only=True)
ws1 = wb1.worksheets[-1] # last worksheet
wb2 = openpyxl.load_workbook("file2.xlsx")
ws2 = wb2.create_worksheet('new')
copier = WorkSheetCopy(ws1, ws2)
copier.copy_sheet()
writer = pd.ExcelWriter("output.xlsx", engine="openpyxl")
writer.book = wb2
writer.save()
我使用的解决方法是将当前工作表保存为 Pandas 数据框并将其加载到您需要的 excel 工作簿中
For speed I am using data_only
and read_only
attributes when opening my workbooks.为了速度,我在打开工作簿时使用
data_only
和read_only
属性。 Also iter_rows()
is really fast, too. iter_rows()
也非常快。
@Oscar's excellent answer needs some changes to support ReadOnlyWorksheet and EmptyCell @Oscar 的出色答案需要进行一些更改以支持 ReadOnlyWorksheet 和 EmptyCell
# Copy a sheet with style, format, layout, ect. from one Excel file to another Excel file
# Please add the ..path\\+\\file.. and ..sheet_name.. according to your desire.
import openpyxl
from copy import copy
def copy_sheet(source_sheet, target_sheet):
copy_cells(source_sheet, target_sheet) # copy all the cel values and styles
copy_sheet_attributes(source_sheet, target_sheet)
def copy_sheet_attributes(source_sheet, target_sheet):
if isinstance(source_sheet, openpyxl.worksheet._read_only.ReadOnlyWorksheet):
return
target_sheet.sheet_format = copy(source_sheet.sheet_format)
target_sheet.sheet_properties = copy(source_sheet.sheet_properties)
target_sheet.merged_cells = copy(source_sheet.merged_cells)
target_sheet.page_margins = copy(source_sheet.page_margins)
target_sheet.freeze_panes = copy(source_sheet.freeze_panes)
# set row dimensions
# So you cannot copy the row_dimensions attribute. Does not work (because of meta data in the attribute I think). So we copy every row's row_dimensions. That seems to work.
for rn in range(len(source_sheet.row_dimensions)):
target_sheet.row_dimensions[rn] = copy(source_sheet.row_dimensions[rn])
if source_sheet.sheet_format.defaultColWidth is None:
print('Unable to copy default column wide')
else:
target_sheet.sheet_format.defaultColWidth = copy(source_sheet.sheet_format.defaultColWidth)
# set specific column width and hidden property
# we cannot copy the entire column_dimensions attribute so we copy selected attributes
for key, value in source_sheet.column_dimensions.items():
target_sheet.column_dimensions[key].min = copy(source_sheet.column_dimensions[key].min) # Excel actually groups multiple columns under 1 key. Use the min max attribute to also group the columns in the targetSheet
target_sheet.column_dimensions[key].max = copy(source_sheet.column_dimensions[key].max) # https://stackoverflow.com/questions/36417278/openpyxl-can-not-read-consecutive-hidden-columns discussed the issue. Note that this is also the case for the width, not onl;y the hidden property
target_sheet.column_dimensions[key].width = copy(source_sheet.column_dimensions[key].width) # set width for every column
target_sheet.column_dimensions[key].hidden = copy(source_sheet.column_dimensions[key].hidden)
def copy_cells(source_sheet, target_sheet):
for r, row in enumerate(source_sheet.iter_rows()):
for c, cell in enumerate(row):
source_cell = cell
if isinstance(source_cell, openpyxl.cell.read_only.EmptyCell):
continue
target_cell = target_sheet.cell(column=c+1, row=r+1)
target_cell._value = source_cell._value
target_cell.data_type = source_cell.data_type
if source_cell.has_style:
target_cell.font = copy(source_cell.font)
target_cell.border = copy(source_cell.border)
target_cell.fill = copy(source_cell.fill)
target_cell.number_format = copy(source_cell.number_format)
target_cell.protection = copy(source_cell.protection)
target_cell.alignment = copy(source_cell.alignment)
if not isinstance(source_cell, openpyxl.cell.ReadOnlyCell) and source_cell.hyperlink:
target_cell._hyperlink = copy(source_cell.hyperlink)
if not isinstance(source_cell, openpyxl.cell.ReadOnlyCell) and source_cell.comment:
target_cell.comment = copy(source_cell.comment)
With a usage something like使用类似
wb = Workbook()
wb_source = load_workbook(filename, data_only=True, read_only=True)
for sheetname in wb_source.sheetnames:
source_sheet = wb_source[sheetname]
ws = wb.create_sheet("Orig_" + sheetname)
copy_sheet(source_sheet, ws)
wb.save(new_filename)
i found a way playing around with it我找到了一种玩弄它的方法
import openpyxl
xl1 = openpyxl.load_workbook('workbook1.xlsx')
# sheet you want to copy
s = openpyxl.load_workbook('workbook2.xlsx').active
s._parent = xl1
xl1._add_sheet(s)
xl1.save('some_path/name.xlsx')
查看此代码,该代码简化了从一个电子表格复制和粘贴到另一个电子表格的过程: https : //github.com/dabomb1004/Excel-CopyPaste
It actually can be done in a very simple way !它实际上可以用非常简单的方式完成! It just need 3 steps:
它只需要3个步骤:
Open a file using load_workbook使用 load_workbook 打开一个文件
wb = load_workbook('File_1.xlsx') wb = load_workbook('File_1.xlsx')
Select a sheet you want to copy Select 一张你要复印的表
ws = wb.active ws = wb.active
use name of the new file to save the file使用新文件的名称来保存文件
wb.save('New_file.xlsx') wb.save('New_file.xlsx')
This code will save sheet of first file (File_1.xlsx) to the secound file (New_file.xlsx).此代码会将第一个文件 (File_1.xlsx) 的工作表保存到第二个文件 (New_file.xlsx)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.