要点速览
-
使用
pip install openpyxl安装 openpyxl -
用
openpyxl.load_workbook('file.xlsx')加载任意.xlsx文件;通过wb.active或wb['SheetName']访问工作表 -
使用
ws['A1'].value读取单元格值;用ws.iter_rows(values_only=True)迭代行 -
通过
ws['A1'] = 'value'写入单元格,并用wb.save('file.xlsx')保存更改 -
完全在 Python 中创建 Excel 公式、条形图、折线图和条件格式——无需打开 Excel
前置条件
要跟随本教程,您需要:
-
您的设备上安装了 Python 3.8 或更高版本
-
具备基本的 Python 知识(变量、循环、函数)
-
已安装 openpyxl(
pip install openpyxl) -
一个电子表格查看器(Excel、Google 表格或 LibreOffice Calc)用于查看输出文件
从此 GitHub 仓库下载本教程使用的视频游戏销量数据集。
Openpyxl 简介
Openpyxl 是一个 Python 库,允许用户读取并写入 Excel 文件。
借助该框架,您无需打开 Excel 应用,就能直接在 Python 中编写函数、格式化表格、创建报告和生成图表。
Openpyxl 还支持遍历工作表,在一次运行中对多个数据集执行相同分析。
这使得跨任意数量的工作表自动化重复性 Excel 工作变得直截了当。
Openpyxl 与 Pandas:如何选择
一个常见问题是:做 Excel 相关工作时该用 openpyxl 还是 pandas?答案取决于您的需求。
| 任务 | openpyxl | pandas |
|---|---|---|
| 从 Excel 读取数据 | 是 | 是 |
| 写入数据到 Excel | 是 | 是(通过 to_excel()) |
| 格式化单元格(字体、颜色、边框) | 是 | 否 |
| 在 Excel 文件内创建图表 | 是 | 否 |
| 使用 Excel 公式 | 是 | 否 |
| 数据分析与变换 | 有限 | 是 |
| 超大文件(>100k 行) | 使用 read_only=True | 默认更省内存 |
当您需要控制 Excel 文件的外观和结构——格式、图表、公式时,用 openpyxl;当您需要筛选、聚合或重塑数据时,用 pandas。我们的 Python pandas 教程深入讲解数据分析部分。
如何安装 Openpyxl
要安装 openpyxl,打开终端或 PowerShell 并运行:
pip install openpyxl
您应会看到如下消息,表示软件包安装成功:

在 Python 中使用 Openpyxl 读取 Excel 文件
本教程将使用 Kaggle 的电子游戏销量数据集。为便于教程演示,我们的团队已对该数据集做了预处理,您可以通过此链接下载修改后的版本。可按以下流程将 Excel 导入 Python:
加载工作簿
下载数据集后,导入 Openpyxl 库并将工作簿加载到 Python 中:
import openpyxl
wb = openpyxl.load_workbook('videogamesales.xlsx')
现在 Excel 文件已作为 Python 对象加载,您需要告诉库要访问哪个工作表。可以通过两种方式完成:
第一种方法是直接调用活动工作表,即工作簿中的第一个工作表,使用以下代码:
ws = wb.active
或者,如果您知道工作表名称,也可以按名称访问。本节将使用“vgsales”工作表:
ws = wb['vgsales']
现在让我们统计此工作表的行数和列数:
print('Total number of rows: '+str(ws.max_row)+'. And total number of columns: '+str(ws.max_column))
以上代码应输出如下结果:
Total number of rows: 16328. And total number of columns: 10
既然我们知道了工作表的尺寸,接下来学习如何从工作簿读取数据。
高效读取大文件
对于包含大量行的工作簿,请以只读模式打开,以避免将整个文件加载到内存:
import openpyxl
wb = openpyxl.load_workbook('videogamesales.xlsx', read_only=True)
ws = wb.active
for row in ws.iter_rows(values_only=True):
print(row)
只读模式会一次流式读取一行,而不是将完整工作簿驻留在内存中。以这种方式打开的工作簿无法回写,因此将其用于大型数据集的读为主流程。
从单个单元格读取数据
以下是我们将在本节中使用的活动工作表的截图:

要用 Openpyxl 从特定单元格取值,您可以这样写:
print(f"The value in cell A1 is: {ws['A1'].value}")
您应得到如下输出:
The value in cell A1 is: Rank
从多个单元格读取数据
既然我们知道如何从特定单元格读取数据,那么如果要打印某一行的所有单元格值该怎么办?
为此,您可以编写一个简单的 for 循环,遍历特定行中的所有值:
values = [ws.cell(row=1,column=i).value for i in range(1,ws.max_column+1)]
print(values)
上述代码将打印第一行的所有值:
['Rank', 'Name', 'Platform', 'Year', 'Genre', 'Publisher', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']
接下来,让我们尝试打印特定列中的多行。
我们将创建一个 for 循环,将“Name”列的前十行渲染为列表。应得到下图红框中所示的名称:

data=[ws.cell(row=i,column=2).value for i in range(2,12)]
print(data)
上述代码将生成如下输出:
['Wii Sports', 'Super Mario Bros.', 'Mario Kart Wii', 'Wii Sports Resort', 'Pokemon Red/Pokemon Blue', 'Tetris', 'New Super Mario Bros.', 'Wii Play', 'New Super Mario Bros. Wii', 'Duck Hunt']
最后,让我们打印电子表格中某个列范围的前十行:
# reading data from a range of cells (from column 1 to 6)
my_list = list()
for value in ws.iter_rows(
min_row=1, max_row=11, min_col=1, max_col=6,
values_only=True):
my_list.append(value)
for ele1,ele2,ele3,ele4,ele5,ele6 in my_list:
(print ("{:<8}{:<35}{:<10}
{:<10}{:<15}{:<15}".format(ele1,ele2,ele3,ele4,ele5,ele6)))
运行以上代码后,应显示前六列的前十行数据:

使用 Openpyxl 写入 Excel 文件
现在我们已经知道如何访问和读取 Excel 文件,让我们来学习如何使用 Openpyxl 写入它们。
写入单元格
使用 Openpyxl 写入文件有两种方法。
首先,您可以使用单元格键直接访问:
ws['K1'] = 'Sum of Sales'
另一种方式是指定要写入的单元格的行列位置:
ws.cell(row=1, column=11, value = 'Sum of Sales')
每次使用 Openpyxl 向 Excel 文件写入后,都需要用以下代码保存更改,否则工作表中不会反映:
wb.save('videogamesales.xlsx')
如果保存时工作簿已打开,您会遇到如下权限错误:

请确保在保存更改前关闭 Excel 文件。然后重新打开以确认更改已经反映到工作表中:

请注意,K1 单元格中新建了一列,名为“Sum of Sales”。
创建新列
现在让我们将各地区的销量求和并写入到 K 列。
我们先对第一行的销量数据进行此操作:
row_position = 2
col_position = 7
total_sales = ((ws.cell(row=row_position, column=col_position).value)+
(ws.cell(row=row_position, column=col_position+1).value)+
(ws.cell(row=row_position, column=col_position+2).value)+
(ws.cell(row=row_position, column=col_position+3).value))
ws.cell(row=2,column=11).value=total_sales
wb.save('videogamesales.xlsx')
请注意,工作表中第一个游戏的总销量已在 K2 单元格计算出来:

类似地,我们创建一个 for 循环,对每一行的销量求和:
row_position = 1
for i in range(1, ws.max_row):
row_position += 1
NA_Sales = ws.cell(row=row_position, column=7).value
EU_Sales = ws.cell(row=row_position, column=8).value
JP_Sales = ws.cell(row=row_position, column=9).value
Other_Sales = ws.cell(row=row_position, column=10).value
total_sales = (NA_Sales + EU_Sales + JP_Sales + Other_Sales)
ws.cell(row=row_position, column=11).value = total_sales
wb.save("videogamesales.xlsx")
您的 Excel 文件现在应多出一列,反映各地区视频游戏的总销量:

追加新行
要向工作簿追加新行,只需创建包含要写入值的元组并写入该表:
new_row = (1,'The Legend of Zelda',1986,'Action','Nintendo',3.74,0.93,1.69,0.14,6.51,6.5)
ws.append(new_row)
wb.save('videogamesales.xlsx')
您可以通过打印工作簿的最后一行来确认数据已被追加:
values = [ws.cell(row=ws.max_row,column=i).value for i in range(1,ws.max_column+1)]
print(values)
将会生成如下输出:
[1, 'The Legend of Zelda', 1986, 'Action', 'Nintendo', 3.74, 0.93, 1.69, 0.14, 6.51, 6.5]
删除行
要删除我们刚创建的新行,运行以下代码:
ws.delete_rows(ws.max_row, 1) # row number, number of rows to delete
wb.save('videogamesales.xlsx')
delete_rows() 的第一个参数是要删除的行号,第二个参数是要删除的行数。
使用 Openpyxl 创建 Excel 公式
您可以像在 Excel 中一样,用 Openpyxl 写入公式。以下是用 Openpyxl 创建的一些基础函数示例:
AVERAGE()
让我们创建一个名为“Average Sales”的新列,用于计算所有市场的视频游戏平均总销量:
ws['P1'] = 'Average Sales'
ws['P2'] = '= AVERAGE(K2:K16220)'
wb.save('videogamesales.xlsx')
所有市场的平均销量约为 0.19。该值将显示在工作表的 P2 单元格。
COUNTA()
Excel 中的 “COUNTA” 函数用于统计特定范围内已填充的单元格数量。我们用它来统计 E2 到 E16220 之间的记录数:
ws['Q1'] = "Number of Populated Cells"
ws['Q2'] = '=COUNTA(E2:E16220)'
wb.save('videogamesales.xlsx')
在此范围内,共有 16,219 条有数据的记录。
COUNTIF()
COUNTIF() 是常用的 Excel 函数,用于统计满足特定条件的单元格数量。我们用它来统计本数据集中类别为 “Sports” 的游戏数量:
ws['R1'] = 'Number of Rows with Sports Genre'
ws['R2'] = '=COUNTIF(E2:E16220, "Sports")'
wb.save('videogamesales.xlsx')
数据集中共有 2,296 款体育类游戏。
SUMIF()
现在,用 SUMIF 函数计算体育类游戏产生的“Sum of Sales”总和:
ws['S1'] = 'Total Sports Sales'
ws['S2'] = '=SUMIF(E2:E16220, "Sports",K2:K16220)'
wb.save('videogamesales.xlsx')
体育类游戏带来的总销量为 454。
CEILING()
Excel 中的 CEILING() 函数将数字向上舍入到最接近的指定倍数。我们用它来对体育类游戏的总销量进行向上取整:
ws['T1'] = 'Rounded Sum of Sports Sales'
ws['T2'] = '=CEILING(S2,25)'
wb.save('videogamesales.xlsx')
我们将体育类游戏的总销量四舍五入到最接近的 25 的倍数,结果为 475。
上述代码片段应在您的 Excel(P1 到 T2 单元格)中生成如下输出:

关于 Excel 公式、运算符和数学函数的速查,请参阅我们的 Excel 基础速查表。
在 Openpyxl 中操作工作表
现在我们知道如何访问并写入工作表,让我们学习如何使用 Openpyxl 操作、删除和复制工作表。
更改工作表名称
首先,使用 Openpyxl 的 title 属性打印当前活动工作表的名称:
print(ws.title)
将会输出:
vgsales
现在,使用以下代码重命名此工作表:
ws.title ='Video Game Sales Data'
wb.save('videogamesales.xlsx')
您的活动工作表名称现在应更改为 “Video Game Sales Data”。
创建新工作表
运行以下代码列出工作簿中的所有工作表:
print(wb.sheetnames)
您将看到一个数组,列出了文件中所有工作表的名称:
['Video Game Sales Data', 'Total Sales by Genre', 'Breakdown of Sales by Genre', 'Breakdown of Sales by Year']
现在创建一个新的空工作表:
wb.create_sheet('Empty Sheet') # create an empty sheet
print(wb.sheetnames) # print sheet names again
wb.save('videogamesales.xlsx')
可以看到一个名为 “Empty Sheet” 的新工作表已经创建:
['Video Game Sales Data', 'Total Sales by Genre', 'Breakdown of Sales by Genre', 'Breakdown of Sales by Year', ‘Empty Sheet’]
删除工作表
要用 Openpyxl 删除工作表,只需使用 remove 属性,并再次打印所有工作表名以确认删除:
wb.remove(wb['Empty Sheet'])
print(wb.sheetnames)
wb.save('videogamesales.xlsx')
可以看到,“Empty Sheet” 工作表已不在列表中:
['Video Game Sales Data', 'Total Sales by Genre', 'Breakdown of Sales by Genre', 'Breakdown of Sales by Year']
复制工作表
最后,运行此行代码以创建现有工作表的副本:
wb.copy_worksheet(wb['Video Game Sales Data'])
wb.save('vgsales_2.xlsx')
再次打印所有工作表名,我们得到如下输出:
['Video Game Sales Data', 'Total Sales by Genre', 'Breakdown of Sales by Genre', 'Breakdown of Sales by Year', 'Video Game Sales Data Copy']
使用 Openpyxl 向 Excel 文件添加图表
Excel 常被视为创建可视化和汇总数据集的首选工具。本节我们将学习如何使用 Openpyxl 直接在 Python 中构建 Excel 图表。
条形图
我们先创建一个简单的条形图,显示按类别汇总的视频游戏总销量。我们将使用 “Total Sales by Genre” 工作表:

该工作表包含一个数据透视表,其中销售总和按类别聚合,如上图所示。
在创建条形图前,先访问该工作表:
ws = wb['Total Sales by Genre'] # access the required worksheet
现在我们需要告诉 Openpyxl 要绘制的值和值对应的类别。
数值:
数值包括我们要绘制的 “Sum of Sales” 数据。需要通过指定起止范围,告诉 Openpyxl 在 Excel 文件中哪里可以找到这些数据。
Openpyxl 中有四个参数用于指定值的位置:
-
Min_column:包含数据的最小列 -
Max_column:包含数据的最大列 -
Min_row:包含数据的最小行 -
Max_row:包含数据的最大行
下图展示了如何定义这些参数:

请注意,最小行是第一行而不是第二行。这是因为 Openpyxl 从包含数值的行开始计数。
# Values for plotting
from openpyxl.chart import Reference
values = Reference(ws, # worksheet object
min_col=2, # minimum column where your values begin
max_col=2, # maximum column where your values end
min_row=1, # minimum row you’d like to plot from
max_row=13) # maximum row you’d like to plot from
类别
现在,我们需要为条形图的类别定义相同的参数:

以下代码可用于设置图表类别的参数:
cats = Reference(ws,
min_col=1,
max_col=1,
min_row=2,
max_row=13)
创建条形图
现在,我们可以创建条形图对象,并将数值和类别包含进去:
from openpyxl.chart import BarChart
chart = BarChart()
chart.add_data(values, titles_from_data=True)
chart.set_categories(cats)
设置图表标题
最后,您可以设置图表标题,并告诉 Openpyxl 要在工作表的哪个位置创建图表:
# set the title of the chart
chart.title = "Total Sales"
# set the title of the x-axis
chart.x_axis.title = "Genre"
# set the title of the y-axis
chart.y_axis.title = "Total Sales by Genre"
# the top-left corner of the chart
# is anchored to cell F2 .
ws.add_chart(chart,"D2")
# save the file
wb.save("videogamesales.xlsx")
然后打开 Excel 文件,转到 “Total Sales by Genre” 工作表。您应看到类似这样的图表:

分组条形图
现在,我们创建一个分组条形图,显示按类别和地区的总销量。此图的数据在 “Breakdown of Sales by Genre” 工作表中:

与创建条形图类似,我们需要定义数值和类别的范围:

现在我们可以访问该工作表,并将其写成代码:
### Creating a Grouped Bar Chart with Openpyxl
ws = wb['Breakdown of Sales by Genre'] # access worksheet
# Data for plotting
values = Reference(ws,
min_col=2,
max_col=5,
min_row=1,
max_row=13)
cats = Reference(ws, min_col=1,
max_col=1,
min_row=2,
max_row=13)
接下来,我们可以像之前一样创建条形图对象,传入数值和类别,并设置标题参数:
# Create object of BarChart class
chart = BarChart()
chart.add_data(values, titles_from_data=True)
chart.set_categories(cats)
# set the title of the chart
chart.title = "Sales Breakdown"
# set the title of the x-axis
chart.x_axis.title = "Genre"
# set the title of the y-axis
chart.y_axis.title = "Breakdown of Sales by Genre"
# the top-left corner of the chart is anchored to cell H2.
ws.add_chart(chart,"H2")
# save the file
wb.save("videogamesales.xlsx")
打开工作表后,您应看到一个类似这样的分组条形图:

堆叠折线图
最后,我们将使用 “Breakdown of Sales by Year” 选项卡中的数据创建堆叠折线图。该工作表按年份和地区细分了视频游戏的销量:

让我们定义此图的数值与类别范围:

现在将这些最小值与最大值写成代码:
# Data for plotting
values = Reference(ws,
min_col=2,
max_col=6,
min_row=1,
max_row=40)
cats = Reference(ws, min_col=1, max_col=1, min_row=2, max_row=40)
最后,创建折线图对象并设置图表标题、x 轴和 y 轴:
# Create object of LineChart class
from openpyxl.chart import LineChart
chart = LineChart()
chart.add_data(values, titles_from_data=True)
chart.set_categories(cats)
# set the title of the chart
chart.title = "Total Sales"
# set the title of the x-axis
chart.x_axis.title = "Year"
# set the title of the y-axis
chart.y_axis.title = "Total Sales by Year"
# the top-left corner of the chart is anchored to cell H2
ws.add_chart(chart,"H2")
# save the file
wb.save("videogamesales.xlsx")
您的工作表中应出现一个类似这样的堆叠折线图:

使用 Openpyxl 格式化单元格
Openpyxl 允许用户对 Excel 工作簿中的单元格进行样式设置。您可以直接在 Python 中更改字体大小、背景颜色和单元格边框,让电子表格更美观。
以下是一些使用 Openpyxl 定制 Python Excel 表格的方式:
更改字体大小与样式
让我们提高 A1 单元格的字体大小并将其加粗:
from openpyxl.styles import Font
ws = wb['Video Game Sales Data']
ws['A1'].font = Font(bold=True, size=12)
wb.save('videogamesales.xlsx')
注意 A1 单元格中的文本现在略大并已加粗:

如果我们想更改第一行所有列表头的字体大小和样式呢?
为此,可复用上述代码,并创建一个 for 循环遍历第一行的所有列:
for row in ws.iter_rows(min_row=1, max_row=1):
for cell in row:
cell.font = Font(bold=True, size=12)
wb.save('videogamesales.xlsx')
当我们遍历 [“1:1”] 时,就是在告诉 Openpyxl 需要循环的起止行。如果要遍历前十行,例如,则应指定为 [“1:10”]。
您可以打开 Excel 表确认更改是否已生效:

更改字体颜色
您可以使用十六进制代码在 Openpyxl 中更改字体颜色:
from openpyxl.styles import colors
ws['A1'].font = Font(color = 'FF0000',bold=True, size=12) ## red
ws['A2'].font = Font(color = '0000FF') ## blue
wb.save('videogamesales.xlsx')
保存工作簿并重新打开后,A1 与 A2 单元格的字体颜色应已改变:
更改单元格背景色
要更改单元格背景色,可使用 Openpyxl 的 PatternFill 模块:
## changing background color of a cell
from openpyxl.styles import PatternFill
ws["A1"].fill = PatternFill('solid', start_color="38e3ff") # light blue background color
wb.save('videogamesales.xlsx')
您的工作表中应反映出如下更改:

添加单元格边框
要使用 Openpyxl 添加单元格边框,运行以下代码:
## cell borders
from openpyxl.styles import Border, Side
my_border = Side(border_style="thin", color="000000")
ws["A1"].border = Border(
top=my_border, left=my_border, right=my_border, bottom=my_border
)
wb.save("videogamesales.xlsx")
您应会在 A1 单元格周围看到如下边框:

条件格式
条件格式是指根据一组条件在 Excel 文件中高亮显示特定值。它能帮助用户更容易地可视化和理解工作表中的数据。
让我们使用 Openpyxl 将所有大于或等于 8 的视频游戏销量高亮为绿色:
from openpyxl.formatting.rule import CellIsRule
fill = PatternFill(
start_color='90EE90',
end_color='90EE90',fill_type='solid') # specify background color
ws.conditional_formatting.add(
'G2:K16594', CellIsRule(operator='greaterThan', formula=[8], fill=fill)) # include formatting rule
wb.save('videogamesales.xlsx')
在第一段代码中,我们指定了要格式化单元格的背景颜色。在这里颜色为浅绿色。
随后,我们创建了一个条件格式规则,声明任何大于 8 的值都应以我们指定的填充色高亮显示。同时也指定了要应用该条件的单元格范围。
运行上述代码后,所有大于 8 的销量值应如下图所示被高亮:

结语
本教程涵盖了大量内容,从使用 Openpyxl 库的基础知识,到在 Python 中创建图表与格式化表格等更高级的操作。
单独来看,Python 与 Excel 覆盖的是数据工作流程的不同部分。Excel 处理报告与临时分析;Python 则用于建模、自动化与大规模计算。
Excel 的最大优势在于几乎人人都会用。从非技术干系人到入门级员工,组织中各层级都能理解用 Excel 电子表格呈现的报告。
另一方面,Python 可用于在海量数据上进行分析和建模,帮助团队自动化繁琐任务并提升组织效率。
当 Excel 与 Python 结合使用时,您可以将数小时的重复性工作实现自动化,同时以全团队都熟悉的格式交付成果。要进一步提升这些技能,我建议学习我们的 Python for Spreadsheet Users 课程,或查看我们的 Python in Excel 指南,在 Excel 电子表格中原生运行 Python。
常见问题
Python 处理大型 Excel 数据集为何比 Excel 本身更高效?
Python 能更高效地处理大型数据集,是因为它拥有如 pandas 和 numpy 等为性能而生的库。与 Excel 不同,Python 不依赖图形界面,能够在内存中处理数百万行数据并执行高级操作,而无需担心崩溃或明显变慢。
Python 能否处理非 Excel 文件格式并将其转换为 Excel?
是否可以使用 Python 合并多个 Excel 文件中的数据?
如何使用 openpyxl 高效读取大型 Excel 文件?
以只读模式(read_only=True)打开工作簿以降低内存占用。只读模式按行流式读取数据,而不是将整个工作簿加载到内存中。它可以在不明显变慢的情况下处理包含数十万行的文件,但不支持回写文件。
使用 openpyxl 与 pandas 操作 Excel 有何区别?
openpyxl 直接针对 Excel 的 .xlsx 格式工作,允许您控制单元格格式、图表、公式以及工作表结构。pandas 将 Excel 视为数据源并将其加载为 DataFrame,更适合数据分析和变换。需要格式化单元格、创建图表或从零构建 Excel 文件时,用 openpyxl;需要从 Excel 过滤、聚合或重塑数据时,用 pandas。
Natassha 是一名在数据科学与营销交汇处工作的数据顾问。她相信,明智地使用数据,能够为个人和组织带来巨大的增长。作为一名自学成才的数据从业者,Natassha 热衷于撰写文章,帮助有志于数据科学的人士进入该行业。她在个人博客以及外部平台发表的文章,平均每月获得 20 万次浏览。

Excel 的一个局限在于难以处理海量数据。在 Excel 中对大量数据执行复杂操作时,尤其是在公式和宏未针对性能优化的情况下,您可能会遇到严重的性能问题。
当您需要重复执行某些任务时,Excel 也会非常耗时。比如,每周都要在多个 Excel 文件上重复同样的分析,就得手动打开文件并一次次地复制粘贴相同的公式。
调查显示,93% 的 Excel 用户认为整合电子表格很耗时,员工每月大约要花 12 小时来合并不同的 Excel 文件。
这些问题可以通过使用 Python 自动化 Excel 工作流来解决。诸如表格合并、数据清洗和预测建模等任务,都可以用一个简单的 Python 脚本在几分钟内完成并写入 Excel 文件。
Excel 用户还可以设置一个Python 自动化脚本按计划运行,免去重复手工操作。
在本文中,我将一步步演示如何: