文档:https://openpyxl.readthedocs.io/en/stable/tutorial.html#
源代码:https://foss.heptapod.net/openpyxl/openpyxl
openpyxl
中有一个 Workbook
类,可以使用 Workbook()
创建工作簿对象(该对象内部默认包含一个名为 sheet
的工作表)。
在 openpyxl
中,“活动状态 active
” 和 “非活动状态 inactive
”,通常用来描述工作簿(Workbook
)中的工作表(Worksheet
):
活动状态(Active
): 工作簿中的一个工作表被标记为活动工作表时,表示当前正在对该工作表进行操作或访问。可以通过 workbook.active
属性来获取该活动工作表。默认情况下,新创建的工作簿的第一个工作表就是是活动的。
"""获取活动工作表"""
from openpyxl import Workbook
workbook = Workbook()
active_sheet = workbook.active # 获取活动工作表
非活动状态(Inactive
): 工作簿中的其他工作表,即不是当前正在操作或访问的工作表,被认为是非活动的。可以通过工作簿对象的 Wookbook.worksheets
属性来获取所有工作表列表,并通过索引来访问非活动工作表。
"""获取非活动工作表"""
from openpyxl import Workbook
workbook = Workbook()
inactive_sheet = workbook.worksheets[1] # 获取第二个工作表(假设存在第二个工作表)
通常,活动状态和非活动状态在进行 Excel
文件的读取、写入和编辑操作时很重要。例如,如果您想往工作表中添加数据,你需要确保正在操作的是活动工作表。
而如果要切换到其他工作表,你可以 create_sheet([表格名称])
创建新的工作表,并且重新设置 Workbook.active
属性,或者直接通过 Worksheets
列表来选择。
另外,还可以使用 Worksheet.title
属性来获取或修改现有工作表的名称。
"""查看工作表并且修改指定活动工作表"""
from openpyxl import Workbook
# 创建工作簿对象并且查看默认的活动工作表
workbook = Workbook()
worksheet1 = workbook.active # 获取默认的活动工作表
print(workbook.active) # 查看默认的活动工作表
# 创建另一些非活动工作表
worksheet2 = workbook.create_sheet('Sheet2')
worksheet3 = workbook.create_sheet('Sheet3')
worksheet4 = workbook.create_sheet('Sheet4')
# 将其他工作表设置为活动工作表
workbook.active = worksheet2 # 重新设置默认的活动工作表
print(workbook.active) # 查看此时设定的活动工作表
# 获取所有工作表的名称
for sheet_name in workbook.sheetnames:
print(sheet_name)
# 修改某个工作表的名称
print(worksheet1) # 改名前
worksheet1.title = "Sheet1"
print(worksheet1) # 改名后
一旦为工作表命名,您就可以将其作为工作簿的键,使用 工作表名称-工作表 键值对的形式来获取一个工作表:
"""使用键值来获取工作表"""
# 设置活动工作表
from openpyxl import Workbook
# 创建工作簿对象并且查看默认的活动工作表
workbook = Workbook()
worksheet1 = workbook.active # 获取默认的活动工作表
worksheet1.title = "Sheet1" # 修改默认工作表的默认名称
# 创建另一些非活动工作表
worksheet2 = workbook.create_sheet('Sheet2')
worksheet3 = workbook.create_sheet('Sheet3')
worksheet4 = workbook.create_sheet('Sheet4')
# 通过键值对获取工作表对象
print(workbook['Sheet1'].title)
print(workbook['Sheet2'].title)
print(workbook['Sheet3'].title)
print(workbook['Sheet4'].title)
您还可以在 单个 工作簿中,使用 Workbook.copy_worksheet()
方法来创建工作表的副本,该工作表会自动插入到调用调用对象对应的工作簿中(默认名字为 [源工作表名称] copy
)。
"""为本工作簿的工作表创建副本"""
from openpyxl import Workbook
wb = Workbook()
source = wb.active
wb.active.title = "mySheet"
target = wb.copy_worksheet(source)
target = wb.copy_worksheet(wb['mySheet Copy'])
print(wb.sheetnames)
但是仅复制单元格(包括值、样式、超链接和注释)和某些工作表属性(包括尺寸、格式和属性),不会复制所有其他工作簿/工作表属性(包括图像、图表)
注意
1
:您无法直接使用copy_worksheet()
在工作簿之间直接复制工作表,但可以用其他方式…from openpyxl import load_workbook, Workbook # 加载源工作簿的工作表 workbook1 = load_workbook(r"C:\Users\Limou_p350ml9\Desktop\Test\新建文件夹\pythontest\workbook1.xlsx") source_sheet = workbook1.active # 创建一个新的目标工作簿并获取其默认活动工作表 workbook2 = Workbook() destination_sheet = workbook2.active # 将源工作表的值复制到目标工作簿中的新工作表 for row in source_sheet.iter_rows(): destination_sheet.append([cell.value for cell in row]) # 保存目标工作簿 workbook2.save(r"C:\Users\Limou_p350ml9\Desktop\Test\新建文件夹\pythontest\workbook2.xlsx")
注意
2
:如果后续打开现有工作簿时,以“只读或只写模式打开”,则无法复制工作表。
使用数字行和字母列组合可以作为工作表的键直接访问一个单元格,如果不存在则将创建一个,并且可以通过赋值给单元格填入数据。
此外还可以使用 Worksheet.cell()
方法,该方法使用整型行数和整型列数访问一个单元格(个人更加常用),并且可以使用参数 value
来填充单元格数据。
而访问单元格的值必须使用 Cell.value
属性才能获取到对应值(当然,也可以通过这个属性来修改单元格存储的数据)。
"""通过键值对和方法访问和修改一个单元格"""
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws['A4'] = 4
ws['B3'].value = "limou"
a = ws.cell(row=4, column=2, value=10)
print(ws['A4'])
print(ws['B3'])
print(a)
print(ws['A4'].value)
print(ws['B3'].value)
print(a.value)
注意:我们上述提及的工作表,基本都是在内存中创建的工作表(不是直接加载现有的工作表),本身是不包含单元格的,单元格只有在一次被访问时才会被创建出来。
由于此功能,遍历查询内存中工作表对象的单元格,而不是直接访问它们的值时,
Workbook
将会自动在内存中创建它们,即使您没有为它们分配任何值。"""通过遍历导致创建单元格空间""" from openpyxl import Workbook wb = Workbook() ws = wb.active for x in range(1,101): for y in range(1,101): ws.cell(row=x, column=y)
此操作会在内存中创建
100x100
个单元,毫无意义。
利用键值对和切片,可以访问一段单元格范围(亦或是一行和一列单元格),也可以直接使用 Worksheet.iter_rows()
和 Worksheet.iter_cols()
方法获取(个人更加常用)
"""通过切片和方法访问多个单元格"""
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
cell_range = ws['A1':'C2'] # [A1, C2)
col_range = ws['C:E'] # C列 和 D列 全部
row_range = ws[5:10] # 5行 和 9行 全部
colC = ws['C'] # C列 的全部
row10 = ws[10] # 10行 的全部
for row in ws.iter_rows(min_row=1, max_col=3, max_row=2):
"""
min_row=1 表示从 1行 开始
max_row=2 表示到 2行 结束
max_col=3 表示从 0列 到 3列 结束
"""
for cell in row:
print(cell)
for col in ws.iter_cols(min_row=1, max_col=3, max_row=2):
"""
min_row=1 表示从 1行 开始
max_col=3 表示到 3行 结束
max_row=2 表示从 0列 到 2列 结束
"""
for cell in col:
print(cell)
同理得到每一个单元格元素时,可以使用 Cell.valus
属性来修改多个单元格内的值。
注意:出于性能原因,该
Worksheet.iter_cols()
方法在表格文件为只读模式打开下不可用。
补充:如果您仅仅需要工作表中的值,则可以使用
Worksheet.values
属性,这将迭代工作表中所有行,您可以使用嵌套的for
语句来返回所有单元格的值。# 仅遍历工作表文件的所有值 from openpyxl import Workbook wb = Workbook() ws = wb.active for row in ws.values: for value in row: print(value)
可以使用 openpyxl.load_workbook()
打开一个现有的表格文件。
关闭表格前需要保存工作簿,而最简单、最安全的方法是使用 Workbook.save()
方法。
而关闭文件一般是由 openpyxl
自动关闭表格文件的,不需要用户显示调用关闭表格文件的方法,但是有些情况下,用户可能需要提前关闭工作表文件(很大概率是为了将内存中表格文件的数据写入到磁盘中),可以考虑使用上下文管理器 with
。
"""保存工作表文件"""
from openpyxl import Workbook
wb = Workbook()
wb.save('balances.xlsx')
补充:在
openpyxl
中,创建一个表格文件可以使用Workbook.save()
方法来创建,因此save()
操作会直接覆盖现有文件而不发出警告也是比较合理的。
在 openpyxl
中,如果您希望将工作簿保存为 Excel
模板文件(即后缀为 .xltx
的文件),您可以在代码中设置工作簿对象的 template
属性为 True
,然后保存文件,这样生成的文件将以模板的形式存在。
"""保存为模板文件"""
from openpyxl import load_workbook
wb = load_workbook('document.xlsx')
wb.template = True
wb.save('document_template.xltx')
补充:
Excel
模板文件通常用于创建具有相同格式和布局的新工作簿。当你在Excel
中打开一个模板文件时,它会创建一个新的工作簿副本,保留了模板中的格式和样式,但不包含原始数据。当你保存一个工作簿为 Excel 模板文件(
.xltx
)时,模板文件将保留以下内容:
格式和样式: 包括单元格的字体、颜色、对齐方式、边框等格式和样式设置。
公式: 如果模板中包含公式,这些公式也会被保留。
工作表结构: 包括工作表的名称、列宽、行高等。
图表和图形: 如果模板中包含图表或图形,它们也会被保留。
其他工作簿级别的设置: 例如,模板中的一些工作簿级别的设置,如打印设置等,也可能会被保留。
需要注意的是,保存为模板的文件并不会包含具体的数据内容。当你基于这个模板创建新的工作簿时,新工作簿会保留模板的格式和结构,但不会包含原始模板中的实际数据。
这种保存为模板的方式允许用户在创建新工作簿时保留特定的格式和样式,以便更方便地应用于同类模板的文档。
以上结果来源谷歌搜索,暂时不做验证,因为我对
Excel
不同格式的文件了解不多,并且我按照上述程序的流程保存模板后,其原始数据依旧存在,因此这块内容待补充…
如果您想要将文件保存到流中,例如:在使用 Pyramid
、Flask
或 Django
等 Web
应用程序时,您只需提供 tempfile.NamedTemporaryFile()
所创建出的对象即可。
# 传递流
from tempfile import NamedTemporaryFile
from openpyxl import Workbook
# 创建一个新的工作簿
wb = Workbook()
# 使用 NamedTemporaryFile 创建一个临时文件对象(在内存中)
with NamedTemporaryFile() as tmp:
# 将工作簿保存到临时文件
wb.save(tmp.name)
# 将文件指针移到文件开头
tmp.seek(0)
# 读取临时文件中的内容
stream = tmp.read()
“另存为流” 意味着将文件保存到一个类文件对象(file-like object
)中,该对象可以像文件一样进行读取,但实际上是存储在内存中而不是磁盘上的一份资源。
这对于在 Web
应用程序中生成临时文件并将其直接返回给客户端而言是一种有效的方式(不必做缓慢的 IO
操作)。
在上述代码例子中:
NamedTemporaryFile()
用于创建一个临时文件对象,该对象在被关闭时将自动删除wb.save(tmp.name)
将工作簿保存到临时文件中tmp.seek(0)
将文件指针移到文件的开头,以便从头开始读取文件内容tmp.read()
读取文件的内容,并将其存储在变量 stream
中。