如何使用 openpyxl 处理 Excel 单元格?Cell 对象介绍
关注 1421
本节并不包含 Microsoft Excel 单元格的格式,以及单元格的获取,遍历,移动,合并等操作,如果你想了解相关内容,可以查看如何使用 openpyxl 获取和设置 Excel 单元格格式,如何使用 openpyxl 处理 Excel 工作表?Worksheet 对象介绍两节。与 Excel 单元格链接,批注相关的内容,请查看内容分类一段列出的章节。
openpyxl Excel 单元格对象 Cell
openpyxl
包中的Cell
类,属于模块openpyxl.cell.cell
,可用于获取和设置 Excel 单元格的值或其他相关信息。通常情况下,你可以通过Worksheet
和ReadOnlyWorksheet
对象的[]
运算符来快速的获取单元格对应的Cell
对象。
只读工作表对象ReadOnlyWorksheet
会返回ReadOnlyCell
或EmptyCell
来表示一个非空单元格或空单元格,他们属于模块openpyxl.cell.read_only
,不支持对单元格的写入操作。
创建 Excel 单元格
你可以使用Cell
对象的构造器,创建新的 Excel 单元格,这些新的单元格需要工作表对象通过append
方法进行添加,否则他们不会真正的存在于工作表对象。
Cell(worksheet, row=None, column=None, value=None, style_array=None)
- worksheet 参数
worksheet
参数为被创建的单元格所隶属的工作表对象。- row 参数
row
参数用于说明被创建的单元格将位于工作表的第几行,指定该参数通常没有意义,因为Cell
对象的位置会被工作表对象修改。- column 参数
column
参数用于说明被创建的单元格将位于工作表的第几列,指定该参数通常没有意义,因为Cell
对象的位置会被工作表对象修改。- value 参数
value
参数为被创建的单元格的值。- style_array 参数
style_array
参数是一个包含了单元格格式信息的 Python 数组。
此外,WriteOnlyCell
函数(属于模块openpyxl.cell.cell
),可用于创建只写的 Excel 单元格对象,不要被他的名字迷惑,WriteOnlyCell
函数的返回值依然是一个Cell
对象,该函数只是简化了创建Cell
对象的参数。
WriteOnlyCell(ws=None, value=None)
- ws 参数
ws
参数为被创建的单元格所隶属的工作表对象。- value 参数
value
参数为被创建的单元格的值。
不能直接用已经创建的 Cell 对象替代工作表对象中的 Cell 对象
你可以将Cell
对象添加至工作表对象,但不能使用类似于worksheet['A1']=cell
这样的表达式,将工作表对象中的Cell
对象替换为新建的Cell
对象。
工作表
关于如何为 Excel 工作表添加数据,你可以查看为 Excel 工作表添加数据(值)一段。
在下面的示例中,我们尝试在创建Cell
对象时,为其指定位置,但这不会产生实际的效果。
# 打开 Data.xlsx 中的工作表 Values
from openpyxl import load_workbook
wb = load_workbook('Data.xlsx')
ws = wb['Values']
from datetime import date
from openpyxl import Workbook
from openpyxl.cell.cell import Cell, WriteOnlyCell
# 创建 Cell 并添加至工作表对象
ws.append((Cell(ws, 1, 1, '单元格 A1'), 1.23, '2024-11-11'))
ws.append((Cell(ws, value='单元格 B1'), 4.56, date(2024, 1, 1)))
Cell(ws, 5, 5, value='我是不会被添加的')
# 保存至 Excel 文件 Add.xlsx
wb.save('Add.xlsx')
w_ws = Workbook(True).create_sheet()
# 创建 Cell 并添加至只写工作表对象
w_ws.append([Cell(w_ws, 2, 2, '2 2'), Cell(w_ws, 1, 1, '1 1')])
w_ws.append([WriteOnlyCell(w_ws, '只写')])
# 保存至 Excel 文件 New.xlsx
w_ws.parent.save('New.xlsx')
获取和设置 Excel 单元格的值
Cell
对象的value
属性,可用于获取或设置 Excel 单元格的值,这些值的类型可以是 Python 字符串,数字或日期时间等,对于空单元格,他们对应空值None
。Cell
对象的internal_value
属性与value
属性没有本质区别,但internal_value
不支持写入操作。
ReadOnlyCell
对象同样拥有value
和internal_value
属性,他们均只支持读取操作。EmptyCell
对象(没有internal_value
属性),其value
属性会返回空值None
。
cell|readonlycell.value|internal_value
emptycell.value
cell.value = value
- value 值
value
是需要为单元格设置的值,如果希望目标成为一个空单元格,那么value
应该是 Python 空值None
。
在下面的示例中,我们尝试通过Cell
,ReadOnlyCell
和EmptyCell
来显示或设置一些 Excel 单元格的内容。
# 打开 Data.xlsx 中的工作表 Values
import openpyxl
workbook = openpyxl.load_workbook('Data.xlsx')
worksheet = workbook['Values']
# 显示一些单元格,A2 将成为一个空单元格
worksheet['A2'].value = None
print(f"A1:{type(worksheet['A1'].value)} {worksheet['A1'].value}")
print(f"B1:{type(worksheet['B1'].value)} {worksheet['B1'].value}")
print(f"C1:{type(worksheet['C1'].value)} {worksheet['C1'].value}")
print(f"D4:{type(worksheet['D4'].internal_value)} {worksheet['D4'].internal_value}")
workbook.save('Value.xlsx')
# 以只读方式打开 Data.xlsx 中的工作表 Values
r_workbook = openpyxl.load_workbook('Data.xlsx', True)
r_worksheet = r_workbook['Values']
# 读取单元格 A1,D4
print(f"A1:{r_worksheet['A1']} {type(r_worksheet['A1'].internal_value)} {r_worksheet['A1'].internal_value}")
print(f"D4:{r_worksheet['D4']} {type(r_worksheet['D4'].value)} {r_worksheet['D4'].value}")
A1:<class 'int'> 1
B1:<class 'str'> 字符串
C1:<class 'datetime.datetime'> 2024-01-01 00:00:00
D4:<class 'NoneType'> None
A1:<ReadOnlyCell 'Values'.A1> <class 'int'> 1
D4:<EmptyCell> <class 'NoneType'> None
获取 Excel 单元格的数据类型
虽然,你可以通过 Python 的type
类获得Cell
,ReadOnlyCell
对象的value
属性的具体类型,但Cell
和ReadOnlyCell
对象的data_type
变量,可以更方便的粗略的得知 Excel 单元格对应的数据类型,该变量是一个 Python 字符串,可能为以下的某个值。
- 'n' 值
'n'
表示单元格中的数据是数字,这包括整数,小数或使用科学计数法表示的数,其对应Cell
对象的value
属性的 Python 类型可能是int
,float
。此外,'n'
也可以表示空单元格,其对应Cell
对象的value
属性返回 Python 空值None
。- 's' 值
's'
表示单元格中的数据是字符串,其对应Cell
对象的value
属性的 Python 类型是str
。- 'b' 值
'b'
表示单元格中的数据表示的是真(TRUE
)或假(FALSE
),其对应Cell
对象的value
属性的 Python 类型是bool
。- 'd' 值
'd'
表示单元格中的数据是日期时间,其对应Cell
对象的value
属性的 Python 类型可能是datetime.datetime
,datetime.date
,datetime.time
。- 'f' 值
'f'
表示单元格中的数据是公式,其对应Cell
对象的value
属性的 Python 类型是str
。'f'
可能出现在将load_workbook
函数的data_only
参数设置为False
的情况下,也就是在打开 Excel 文件时,openpyxl
包读取单元格公式,而不是公式的计算结果。- 'e' 值
'e'
表示单元格中的数据是错误信息,该值可能出现在将load_workbook
函数的data_only
参数设置为True
的情况下,也就是在打开 Excel 文件时,openpyxl
包读取单元格公式的计算结果,而不是公式。如果data_only
参数为False
,那么openpyxl
包不会判断公式是否存在错误,Cell
对象的data_type
变量也就不会为'e'
,除非单元格的值被设置为某种表示错误的字符串,比如'#NULL!'
。
至于EmptyCell
对象,也就是以只读方式打开的空单元格,其data_type
变量的值为'n'
。
cell|readonlycell|emptycell.data_type
Cell 对象的 value 属性所接受的数据类型
以上说明的仅是读取 Excel 文件之后,Cell
对象的data_type
变量与value
属性之间的某种关系。在openpyxl
包中,你可以将某种其他 Python 类型的数据赋值给Cell
对象的value
属性,比如,bytes
,当然,这不表示value
属性会接受任意类型的数据,如果给出的值的类型不被接受,异常Cannot convert … to Excel
将被抛出。
读写 Excel 文件
想要了解load_workbook
函数,你可以查看使用 openpyxl 包读取 Excel 文件一段。
在下面的示例中,由于我们将load_workbook
函数的data_only
参数设置为了True
,因此,Excel 文件中拥有公式的单元格,其对应的Cell
对象的data_type
变量的值不是'f'
。
# 打开 Data.xlsx 中的工作表 Types,并读取公式的计算结果
import openpyxl
workbook = openpyxl.load_workbook('Data.xlsx', data_only=True)
worksheet = workbook['Types']
# 用于显示单元格信息的函数
def show(cell):
print(f'{cell.data_type} {cell.value} {type(cell.value)}')
# 显示区域 A1:L1 中的单元格的信息
for row in worksheet['A1:L1']:
for cell in row:
show(cell)
# 将类型为 bytes 的值,传递给属性 value
worksheet['A2'].value = bytes(b'A good day')
show(worksheet['A2'])
n 1 <class 'int'>
n 1.2 <class 'float'>
n 1.3e-12 <class 'float'>
b True <class 'bool'>
s 你好 <class 'str'>
s 很棒的一天 <class 'str'>
n 2.2 <class 'float'>
d 2024-01-01 00:00:00 <class 'datetime.datetime'>
d 07:30:00 <class 'datetime.time'>
d 2024-01-01 07:30:00 <class 'datetime.datetime'>
e #NAME? <class 'str'>
n None <class 'NoneType'>
s A good day <class 'str'>
将值转换为 Excel 单元格的有效文本内容
虽然一些值在 Python 中不会被视为错误,但在 Excel 中他们可能并不适合成为单元格中的文本,Cell
对象的check_string
方法,可用于将一个值转换为单元格中的有效文本内容并返回。如果给出的值在转换为字符串后,包含一些不被允许的字符,比如退格符,那么将导致异常… cannot be used in worksheets
。
cell.check_string(value)
- value 参数
value
参数包含了需要被转换为有效文本内容的值。
另外,Cell
对象的check_error
方法,会尝试将给出的值转换为字符串并返回。如果在转换的过程中遇到异常UnicodeDecodeError
,那么check_error
将返回字符串'#N/A'
。
cell.check_error(value)
- value 参数
value
参数包含了需要检测UnicodeDecodeError
异常的值。
# 打开 Data.xlsx 中的工作表 Values
from openpyxl import load_workbook
workbook = load_workbook('Data.xlsx')
worksheet = workbook['Values']
a1 = worksheet['A1']
# 尝试转换为有效的文本内容
a1.check_string(b'\0 is invalid')
openpyxl.utils.exceptions.IllegalCharacterError: is invalid cannot be used in worksheets.
获取 Excel 单元格位于第几行或第几列
Cell
,ReadOnlyCell
对象的row
,column
变量,可用于获取 Excel 单元格位于第几行或第几列(1
表示第一行或第一列),其中Cell
对象还拥有额外的col_idx
属性,其返回值与column
相同。
cell|readonlycell.row
cell|readonlycell.column
cell.col_idx
不要尝试通过 Cell 对象的 row,column 变量移动单元格
你无法通过修改Cell
对象的row
或column
变量来移动其对应的单元格,这不会改变Cell
对象在工作表对象中的位置。在将Workbook
对象保存为 Microsoft Excel 文件之后,文件中的单元格可能会出现在新的位置或消失不见,这取决于新的位置是否已经存在单元格,以及被移动单元格与已存在单元格之间的关系。
总之,要正确移动单元格,应使用Worksheet
对象的move_range
方法。
下面,我们尝试使用row
和column
移动单元格,在保存后的文件Move.xlsx
中,单元格B2
将覆盖单元格A1
,单元格A2
可以顺利的移动至C3
,因为C3
是一个空单元格。
# 打开 Data.xlsx 中的工作表 Values
from openpyxl import load_workbook
workbook = load_workbook('Data.xlsx')
worksheet = workbook['Values']
# B2 将覆盖 A1
b2 = worksheet['B2']
b2.row = 1
b2.column = 1
# A2 可以顺利的移动至 C3
a2 = worksheet['A2']
a2.row = 3
a2.column = 3
workbook.save('Move.xlsx')
# B2 和 A2 在 worksheet 中的位置并没有改变
print(worksheet['B2'] == b2)
print(worksheet['A2'] == a2)
True
True
获取 Excel 单元格的列索引和地址
Cell
,ReadOnlyCell
对象的column_letter
,coordinate
属性,可用于获取 Excel 单元格的列索引(比如,A
,B
)和地址(比如,A1
,B2
)。
cell|readonlycell.column_letter
cell|readonlycell.coordinate
# 打开 Data.xlsx 中的工作表 Values
from openpyxl import load_workbook
workbook = load_workbook('Data.xlsx')
worksheet = workbook['Values']
# 显示 C2 列索引和地址
c2 = worksheet['C2']
print(f'列索引:{c2.column_letter} 地址:{c2.coordinate}')
列索引:C 地址:C2
使用相对位置获取 Excel 单元格
Cell
对象的offset
方法,可以通过相对位置获取一个 Excel 单元格,该相对位置相对于Cell
对象对应的单元格。如果计算出的目标单元格的位置无效,比如行索引为0
,那么将导致异常。
cell.offset(row=0, column=0)
- row 参数
row
参数是需要获取的目标单元格与Cell
对象对应的单元格之间的行偏移值。- column 参数
column
参数是需要获取的目标单元格与Cell
对象对应的单元格之间的列偏移值。
# 打开 Data.xlsx 中的工作表 Values
from openpyxl import load_workbook
workbook = load_workbook('Data.xlsx')
worksheet = workbook['Values']
b1 = worksheet['B1']
# 获取 B1 左边的单元格 A1
print(b1.offset(column=-1))
# 获取 B1 右下角的单元格 C2
print(b1.offset(1, 1))
<Cell 'Values'.A1>
<Cell 'Values'.C2>
获取 Excel 单元格所隶属的工作表
Cell
,ReadOnlyCell
对象的parent
变量,表示了 Excel 单元格所隶属的工作表对象。
cell|readonlycell.parent
openpyxl Excel 单元格保护对象 Protection
openpyxl
包中的Protection
类,属于模块openpyxl.styles.protection
,用于表示 Excel 单元格的保护信息,其构造器如下。
Protection(locked=True, hidden=False)
- locked 参数
locked
参数是一个布尔值,如果为True
则表示当工作表被保护时,单元格将被锁定(无法被编辑)。- hidden 参数
hidden
参数是一个布尔值,如果为True
则表示当工作表被保护时,单元格中的公式将被隐藏。
Protection 对象的变量
Protection
对象拥有变量locked
,hidden
,在未作出修改时,他们的值与传递给Protection
构造器的实参的值相同。
获取和设置 Excel 单元格的保护信息
Cell
对象拥有名称为protection
的变量,可将其类型视为Protection
类,他被用于获取和设置 Excel 单元格的保护信息。
ReadOnlyCell
对象拥有名称为protection
的只读属性,其类型为Protection
类,可用于设置 Excel 单元格的保护信息。
cell|readonlycell.protection
cell.protection = protection
- protection 值
protection
为表示单元格保护信息的Protection
对象。
工作表
关于 Excel 工作表的保护信息,你可以查看openpyxl Excel 工作表保护对象 SheetProtection,获取和设置 Excel 工作表的保护信息两段。
# 打开 Data.xlsx 中的工作表 Types
import openpyxl
workbook = openpyxl.load_workbook('Data.xlsx')
worksheet = workbook['Types']
from openpyxl.styles.protection import Protection
g1 = worksheet['G1']
# 显示单元格 G1 的保护信息
print(g1.protection)
# 当工作表被保护时,将隐藏 G1 单元格的公式
g1.protection = Protection(False, True)
workbook.save('P.xlsx')
<openpyxl.styles.protection.Protection object>
Parameters:
locked=True, hidden=False
Cell 对象的其他特性
以下是Cell
对象的其他相关特性。
- encoding 属性
Cell
对象的encoding
属性,用于表示单元格所属工作表的编码,他被指定为'utf-8'
。- base_date 属性
Cell
对象的base_date
属性,用于表示单元格所属工作簿的日期系统的开始日期,其返回值等同于对应Workbook
对象的epoch
属性。
工作簿
关于Workbook
对象的epoch
属性,你可以查看获取 Excel 工作簿的日期系统一段。