Python代码实现在Excel工作表中写入公式
在日常工作中,Excel 的公式和函数是数据处理的核心能力。求和、平均值、条件判断、线性回归……手工在 Excel 中输入公式虽然不复杂,但当数据来自数据库、需要定期生成报表、或要批量处理成百上千个工作表时,手动操作就不再现实了。通过 Python 程序化写入公式,你可以让 Excel 像活的数据看板一样自动计算,而无需人工干预。
Python 操作 Excel 的方案有很多,本文演示使用 Free Spire.XLS for Python。它支持通过代码直接写入 Excel 公式,涵盖 SUM、AVERAGE、COUNT、MAX、MIN、IF、SUBTOTAL 等常用函数,以及命名区域引用和数组公式等高级功能。安装方式很简单:
pip install spire.xls.free
1. 准备数据
为了让公式示例更直观,先写一段简短代码,把一份销售数据写入工作表 Sales Report 的 B4:D7 区域:
from spire.xls import *
from spire.xls.common import *
workbook = Workbook()
workbook.Version = ExcelVersion.Version2010
ws = workbook.Worksheets[0]
ws.Name = "Sales Report"
data = [
["North America", 120000, 135000, 148000],
["Europe", 98000, 112000, 125000],
["Asia Pacific", 87000, 95000, 108000],
["Latin America", 56000, 62000, 71000],
]
for row_idx, row_data in enumerate(data, start=4):
for col_idx, value in enumerate(row_data, start=1):
if col_idx == 1:
ws.Range[row_idx, col_idx].Text = str(value)
else:
ws.Range[row_idx, col_idx].NumberValue = float(value)
ws.Range[row_idx, col_idx].Style.NumberFormat = "$#,##0"运行后 B4:D7 存放四地区三个季度的销售数据:B4 是 North America 的 Q1 销售额 120,000,D7 是 Latin America 的 Q3 销售额 71,000。后续所有公式示例都基于这份数据。
2. 基础聚合公式
聚合公式是最常用的 Excel 公式类型,用于对数值区域进行统计计算。Free Spire.XLS for Python 支持 SUM、AVERAGE、MAX、MIN、COUNT 等常见聚合函数,用法与在 Excel 界面中完全一致。下面把聚合公式写入第 1 节数据的下方(第 8~12 行):
写入聚合公式的核心是 Range.Formula 属性。它接受一个以 = 开头的字符串,格式与 Excel 中手动输入完全相同:
# SUM:求和 ws.Range["B8"].Formula = "=SUM(B4:B7)" # AVERAGE:平均值 ws.Range["B9"].Formula = "=AVERAGE(B4:B7)" # MAX:最大值 ws.Range["B10"].Formula = "=MAX(B4:B7)" # MIN:最小值 ws.Range["B11"].Formula = "=MIN(B4:B7)" # COUNT:数值个数 ws.Range["B12"].Formula = "=COUNT(B4:B7)"
注意事项:
- 公式字符串必须以
=开头,这是 Excel 的约定 - 单元格引用使用 A1 样式(如
B4:B7) - 数值格式需要单独设置(如
.Style.NumberFormat = "$#,##0"),公式本身不包含格式信息 - 公式写入后不会立即显示计算结果——需要调用
workbook.CalculateAllValue()或在 Excel 中打开才会计算
3. 命名区域与公式引用
命名区域是 Excel 的重要功能:为某个单元格或区域指定一个有意义的名称,之后在公式中可以直接使用该名称。这比硬编码单元格引用更易于维护,尤其在大型工作簿中。下面把第 1 节的 B4 单元格(North America Q1)命名为 NorthAmerica_Q1,并在第 14 行用命名区域写一个预测公式。
Free Spire.XLS 提供了 Workbook.NameRanges 集合来管理命名区域:
# 创建命名区域:将 NorthAmerica_Q1 指向 B4 单元格
nr = workbook.NameRanges.Add("NorthAmerica_Q1")
nr.RefersToRange = ws.Range["B4"]
# 在公式中直接使用命名区域
ws.Range["B14"].Formula = "=NorthAmerica_Q1*1.1"这段代码做了两件事:
- 创建一个名为
NorthAmerica_Q1的命名区域,指向B4(North America Q1 的销售数据 120,000) - 在
B14单元格写入公式=NorthAmerica_Q1*1.1,即 North America Q1 数据增长 10% 后的预测值
为什么使用命名区域:
- 可读性:
=NorthAmerica_Q1*1.1比=B4*1.1更容易理解公式意图 - 可维护性:如果数据位置变了,只需修改命名区域的
RefersToRange,所有引用该名称的公式自动更新 - 跨工作表引用:命名区域可以引用其他工作表的单元格,在公式中无需写
Sheet2!A1这样冗长的引用
4. 条件公式:IF 函数
IF 是 Excel 中最常用的条件函数,用于根据条件返回不同的值。其语法为:
=IF(条件, 条件成立时的值, 条件不成立时的值)
在 Python 代码中写入 IF 公式时,由于公式本身包含引号和动态行号,推荐使用 f-string 拼接。下面为第 1 节的每个地区判断各季度销售额是否达标,结果写入第 17~20 行:
for i, row_data in enumerate(data, start=4):
target_row = i + 13 # 数据在第 4~7 行,IF 结果显示在第 17~20 行
ws.Range[target_row, 2].Formula = f'=IF(B{i}>110000,"Above Target","Below Target")'
ws.Range[target_row, 3].Formula = f'=IF(C{i}>120000,"Above Target","Below Target")'
ws.Range[target_row, 4].Formula = f'=IF(D{i}>130000,"Above Target","Below Target")'这里为每个地区的每个季度设置了不同的目标阈值(Q1 > 110000、Q2 > 120000、Q3 > 130000),自动标记 "Above Target" 或 "Below Target"。
注意引号处理:Excel 公式中用于字符串的引号在 Python f-string 中需要用不同的引号包裹,上述示例中公式外层用单引号,内部字符串用双引号,避免了转义问题。
5. SUBTOTAL 函数与分组计算
SUBTOTAL 函数可以忽略隐藏行或筛选后的行,在数据分组和筛选场景中非常有用。它的第一个参数决定了要执行哪种计算,其中 1-11 会忽略筛选器隐藏的行,而 101-111 在此基础上还会忽略手动隐藏的行以及被其他 SUBTOTAL 公式嵌套引用的行:
| 函数代码 | 功能 |
|---|---|
| 9 | SUM(求和) |
| 109 | SUM(忽略嵌套的 SUBTOTAL 结果) |
| 101 | AVERAGE(平均值) |
| 102 | COUNT(统计数字个数) |
| 103 | COUNTA(统计非空单元格个数) |
| 104 | MAX(最大值) |
| 105 | MIN(最小值) |
| 107 | STDEV(样本标准差) |
下面在第 22 行对第 1 节的数据使用 SUBTOTAL 做分组汇总:
ws.Range["B22"].Formula = "=SUBTOTAL(9,B4:B7)" # 求和 ws.Range["C22"].Formula = "=SUBTOTAL(109,C4:C7)" # 求和(忽略嵌套的 SUBTOTAL 结果) ws.Range["D22"].Formula = "=SUBTOTAL(102,D4:D7)" # 统计数字个数
6. 数组公式:FormulaArray
普通公式每次只处理一个单元格的值,而数组公式可以同时对一个数组(区域)执行运算,一次完成多项计算。它是 Excel 高级计算的重要工具,适用于条件求和、复杂统计等场景。
Free Spire.XLS for Python 通过 FormulaArray 属性写入数组公式,使用方式与 Formula 类似,但公式内容可以包含针对整个区域的运算。以下示例把数组公式放在 B24:B26 区域(位于 SUBTOTAL 示例下方),对第 1 节的数据做数组运算:
# 求 B4:B7 每个值 ×2 后的总和(等价于手工写 SUM 四个单元格) ws.Range["B24"].FormulaArray = "=SUM(B4:B7*2)" # 数组条件统计:统计 B4:B7 中大于 90000 的单元格个数 ws.Range["B25"].FormulaArray = "=SUM(IF(B4:B7>90000,1,0))" # 另一种写法:利用布尔值参与算术运算 ws.Range["B26"].FormulaArray = "=SUM((B4:B7>90000)*1)"
计算后的结果(CalculateAllValue() 后验证):
=SUM(B4:B7*2)→722000(120000×2 + 98000×2 + 87000×2 + 56000×2)=SUM(IF(B4:B7>90000,1,0))→2(120000、98000 两个值超过 90000)=SUM((B4:B7>90000)*1)→2(与上一条等价)
注意事项:
- 数组公式同样需要
CalculateAllValue()计算后才会有结果 FormulaArray也支持LINEST(线性回归)等返回数组结果的函数,适合做趋势预测- 读取数组公式时使用
.FormulaArray属性,而.Formula返回的也是公式字符串
7. 读取公式及其计算结果
写入公式后,可能还需要在代码中读取公式或它的计算结果。Free Spire.XLS 提供了以下 API:
# 判断单元格是否包含公式
if cell.HasFormula:
print("This cell has a formula")
# 获取公式字符串(如 "=SUM(B4:B7)")
formula_str = cell.Formula
# 获取公式的计算结果(文本形式)
computed_value = cell.FormulaValue
# 获取公式的计算结果(数值形式)
computed_number = cell.FormulaNumberValue示例:遍历所有含公式的单元格
下面的代码加载一份已写入公式的工作簿(例如用第 9 节完整示例生成的 FormulaDemo.xlsx),计算全部公式后遍历查找并打印:
from spire.xls import *
workbook = Workbook()
workbook.LoadFromFile("FormulaDemo.xlsx")
workbook.CalculateAllValue()
ws = workbook.Worksheets[0]
# 遍历指定范围,查找并打印公式
for row in range(1, 25):
for col in range(1, 5):
cell = ws.Range[row, col]
if cell.HasFormula:
print(f"Cell ({row},{col}): Formula={cell.Formula}, Value={cell.FormulaValue}")
workbook.Dispose()输出结果:
Cell (8,2): Formula==SUM(B4:B7), Value=361000
Cell (8,3): Formula==SUM(C4:C7), Value=404000
Cell (8,4): Formula==SUM(D4:D7), Value=452000
Cell (9,2): Formula==AVERAGE(B4:B7), Value=90250
..
注意:如果刚写入公式尚未计算,FormulaValue 可能返回空值。此时需要先调用 workbook.CalculateAllValue() 进行计算。
8. 关键类与方法解析
Range 类
Range 代表工作表中的一个单元格或单元格区域,是公式操作的主要入口。
关键属性:
| 属性 | 说明 |
|---|---|
Formula | 获取或设置单元格的公式(字符串,以 = 开头) |
FormulaArray | 获取或设置单元格的数组公式 |
FormulaValue | 获取公式的计算结果(文本形式) |
FormulaNumberValue | 获取公式的计算结果(数值形式) |
HasFormula | 判断单元格是否包含公式(布尔值) |
Text | 获取或设置单元格的文本值 |
NumberValue | 获取或设置单元格的数值 |
Workbook 类
Workbook 是整个工作簿的操作入口,也负责命名区域管理和公式计算。
关键属性和方法:
| 属性/方法 | 说明 |
|---|---|
NameRanges | 获取命名区域集合,用于添加/删除命名区域 |
CalculateAllValue() | 计算工作簿中所有公式的值 |
LoadFromFile(filePath) | 从指定路径加载 Excel 文件 |
SaveToFile(filePath, version) | 将工作簿保存为 Excel 文件 |
Dispose() | 释放资源 |
NameRange 类
NameRange 代表一个命名区域,用于在公式中引用特定的单元格或区域。
关键属性:
| 属性 | 说明 |
|---|---|
Name | 命名区域的名称(如 NorthAmerica_Q1) |
RefersToRange | 命名区域所引用的单元格范围 |
9. 完整示例:一键生成带公式的销售报表
把第 2~6 节的技巧组合起来,就是一个完整可运行的脚本:创建标题与表头、写入销售数据、逐个写入聚合公式、命名区域、IF、SUBTOTAL 和数组公式,最后计算并保存。运行后即可得到一份含公式的 Excel 报表:
from spire.xls import *
from spire.xls.common import *
outputFile = "FormulaDemo.xlsx"
workbook = Workbook()
workbook.Version = ExcelVersion.Version2010
ws = workbook.Worksheets[0]
ws.Name = "Sales Report"
# 标题与表头
ws.Range["A1"].Text = "Sales Report with Formulas"
ws.Range["A1"].Style.Font.Size = 14
ws.Range["A1"].Style.Font.IsBold = True
ws.Range["A1"].Style.Color = Color.FromRgb(0, 70, 127)
ws.Range["A1"].Style.Font.Color = Color.get_White()
ws.Range["A1:D1"].Merge()
for col, header in enumerate(["Region", "Q1", "Q2", "Q3"], start=1):
ws.Range[3, col].Text = header
ws.Range[3, col].Style.Font.IsBold = True
ws.Range[3, col].Style.Font.Color = Color.get_White()
ws.Range[3, col].Style.Color = Color.FromRgb(0, 112, 192)
ws.Range[3, col].Style.HorizontalAlignment = HorizontalAlignType.Center
# 数据(同第 1 节)
data = [
["North America", 120000, 135000, 148000],
["Europe", 98000, 112000, 125000],
["Asia Pacific", 87000, 95000, 108000],
["Latin America", 56000, 62000, 71000],
]
for row_idx, row_data in enumerate(data, start=4):
for col_idx, value in enumerate(row_data, start=1):
if col_idx == 1:
ws.Range[row_idx, col_idx].Text = str(value)
else:
ws.Range[row_idx, col_idx].NumberValue = float(value)
ws.Range[row_idx, col_idx].Style.NumberFormat = "$#,##0"
ws.Range[row_idx, col_idx].Style.HorizontalAlignment = HorizontalAlignType.Right
# 聚合公式(第 2 节)
funcs = [("Total", "SUM"), ("Average", "AVERAGE"), ("Max", "MAX"),
("Min", "MIN"), ("Count", "COUNT")]
for r, (label, fn) in enumerate(funcs, start=8):
ws.Range[r, 1].Text = label
ws.Range[r, 1].Style.Font.IsBold = True
for col in range(2, 5):
col_letter = chr(64 + col)
ws.Range[r, col].Formula = f"={fn}({col_letter}4:{col_letter}7)"
ws.Range[r, col].Style.NumberFormat = "0" if fn == "COUNT" else "$#,##0"
if fn == "SUM":
ws.Range[r, col].Style.Font.IsBold = True
# 命名区域(第 3 节)
nr = workbook.NameRanges.Add("NorthAmerica_Q1")
nr.RefersToRange = ws.Range["B4"]
ws.Range["B14"].Formula = "=NorthAmerica_Q1*1.1"
ws.Range["B14"].Style.NumberFormat = "$#,##0"
ws.Range["A14"].Text = "Projected (10% growth)"
ws.Range["A14"].Style.Font.IsBold = True
ws.Range["A14:B14"].Merge()
# IF 条件公式(第 4 节)
ws.Range["A16"].Text = "Performance"
ws.Range["A16"].Style.Font.IsBold = True
for col, h in zip(range(2, 5), ["Q1", "Q2", "Q3"]):
ws.Range[16, col].Text = h
ws.Range[16, col].Style.Font.IsBold = True
ws.Range[16, col].Style.Color = Color.FromRgb(0, 112, 192)
ws.Range[16, col].Style.Font.Color = Color.get_White()
for i, row_data in enumerate(data, start=4):
target_row = i + 13 # 数据在第 4~7 行,IF 结果显示在第 17~20 行
ws.Range[target_row, 2].Formula = f'=IF(B{i}>110000,"Above Target","Below Target")'
ws.Range[target_row, 3].Formula = f'=IF(C{i}>120000,"Above Target","Below Target")'
ws.Range[target_row, 4].Formula = f'=IF(D{i}>130000,"Above Target","Below Target")'
# SUBTOTAL 分组公式(第 5 节)
ws.Range["A22"].Text = "SUBTOTAL Test"
ws.Range["A22"].Style.Font.IsBold = True
ws.Range["B22"].Formula = "=SUBTOTAL(9,B4:B7)"
ws.Range["B22"].Style.NumberFormat = "$#,##0"
ws.Range["C22"].Formula = "=SUBTOTAL(109,C4:C7)"
ws.Range["C22"].Style.NumberFormat = "$#,##0"
ws.Range["D22"].Formula = "=SUBTOTAL(102,D4:D7)"
ws.Range["D22"].Style.NumberFormat = "$#,##0"
# 数组公式(第 6 节)
ws.Range["A24"].Text = "Array Formula Test"
ws.Range["A24"].Style.Font.IsBold = True
ws.Range["B24"].FormulaArray = "=SUM(B4:B7*2)"
ws.Range["B24"].Style.NumberFormat = "$#,##0"
ws.Range["B25"].FormulaArray = "=SUM(IF(B4:B7>90000,1,0))"
ws.Range["B26"].FormulaArray = "=SUM((B4:B7>90000)*1)"
# 列宽
ws.Columns[0].ColumnWidth = 20
ws.Columns[1].ColumnWidth = 12
ws.Columns[2].ColumnWidth = 14
ws.Columns[3].ColumnWidth = 14
# 计算所有公式并保存
workbook.CalculateAllValue()
workbook.SaveToFile(outputFile, ExcelVersion.Version2010)
workbook.Dispose()
print(f"Report generated: {outputFile}")运行后在 Excel 中打开,效果如下(与第 2~6 节各公式的说明一一对应):

说明:
- 整个流程无需打开 Excel,从创建数据到写入公式再到保存,完全自动化
CalculateAllValue()在保存前计算所有公式,保证打开文件时数值已就绪- 聚合公式用
chr(64 + col)生成列字母,循环自动适配 B/C/D 三列 - 数据源可以替换为数据库、CSV 或 API 读取的结果,脚本结构不变
总结
通过本文示例,你已经了解了如何使用 Python 在 Excel 工作表中写入各类公式。从基础的 SUM、AVERAGE、COUNT 聚合函数,到命名区域引用、IF 条件判断、SUBTOTAL 分组计算,再到读取公式和计算结果,Free Spire.XLS for Python 提供了完整的公式支持。
相比手动在 Excel 中输入公式,Python 方式具有以下优势:
- 批量生成:一次处理成百上千个工作表,公式自动适配
- 数据驱动:公式范围根据数据行数动态计算,无需人工调整
- 流程自动化:从数据库读取数据→生成报表→发送邮件,全链路无需人工干预
- 格式一致:确保所有报表的公式逻辑和样式完全统一
你可以在此基础上进一步扩展:比如结合定时任务定期生成带公式的销售周报、将公式写入客户提供的模板文件保持格式一致、或对接 BI 系统自动生成可下载的分析报表。如果你正在处理需要公式自动化的场景,这种基于 Python 的方案将显著提升你的工作效率。
以上就是Python代码实现在Excel工作表中写入公式的详细内容,更多关于Python Excel工作表写入公式的资料请关注脚本之家其它相关文章!
相关文章
解决python -m pip install --upgrade pip 升级不成功问题
这篇文章主要介绍了python -m pip install --upgrade pip 解决升级不成功问题,需要的朋友可以参考下2020-03-03
Python读取SQLite3数据库中的文件并获取列名/字段名
这篇文章主要为大家详细介绍了如何使用Python读取SQLite3数据库中的文件并获取列名与字段名,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下2025-07-07


最新评论