
个人主页杨利杰YJlio❄️个人专栏《Sysinternals实战教程》 《Windows PowerShell 实战》 《WINDOWS教程》 《IOS教程》《微信助手》 《锤子助手》 《Python》 《Kali Linux》《那些年未解决的Windows疑难杂症》让复杂的事情更简单让重复的工作自动化《超简单用 Python 让 Excel 飞起来》读书笔记9.1.2 导入并调用 Python 自定义函数1. 9.1.2 导入并调用 Python 自定义函数2. 先讲清楚RunPython 和 UDF 到底有什么区别3. 适用场景什么时候应该用 RunPython4. 用 quickstart 创建项目自动生成 xlsm 和 py5. Python 端写 main()让它负责完整处理流程6. VBA 端用 RunPython 调用 Python 函数7. 常见问题与踩坑记录RunPython 三大坑位7.1 模块名错误ModuleNotFoundError7.2 解释器错误Excel 调用的 Python 不是你装包的那个7.3 宏安全策略按钮点了但没有任何反应8. 效果验证不要只看“没有报错”8.1 VBA 是否成功触发 Python8.2 Python 是否正确读取数据8.3 Report 是否正确生成9. 我的总结提升10. 发布版补充我建议这样使用这篇笔记1. 9.1.2 导入并调用 Python 自定义函数V4修正版进度标记本篇为 07月15日 第2篇承接前面 Excel 自动化基础内容继续更新。读书笔记定位本文是我阅读《超简单用 Python 让 Excel 飞起来》时整理的学习笔记重点不是照搬原书而是把本节内容重新整理成更适合博客阅读、实操复盘和后续查阅的版本。这一节要解决的核心问题很明确能不能在 Excel 里点一下按钮然后让 Python 自动完成整套数据处理流程前面学习 xlwings 时我们更多是在理解 Python 如何读取 Excel、写入 Excel或者把 Python 函数包装成 Excel 公式。但到了这一节重点就变成了另一种更贴近办公自动化交付的方式用 VBA 作为触发入口用 Python 作为处理引擎用 Excel 作为结果展示界面。这张图展示了 Excel 按钮触发后VBA、xlwings、RunPython 和 Python 代码之间的协作关系。从这张图中我们可以看出RunPython 的价值不是“在 Excel 里写一行公式”而是把 Excel 变成一个操作面板用户只负责点击按钮真正的数据清洗、统计处理、报表生成交给 Python 完成。注意如果只把 RunPython 当成普通函数调用来理解就会低估它的实际价值。它真正适合的是“流程型任务”比如批量整理数据、生成报表、写入结果 Sheet、导出文件等。建议阅读方式先理解 RunPython 和 UDF 的区别再看项目如何创建、Python 端如何写 main()最后重点看常见坑模块名、解释器、宏安全关键词Python、Excel自动化、xlwings、VBA、RunPython、自定义函数、办公自动化、xlsmExcel 按钮或宏VBA 调用 RunPythonxlwings 建立 Excel 与 Python 通道Python 执行 main 函数读取 Excel 数据清洗/统计/汇总写回 Report 工作表用户在 Excel 中查看结果2. 先讲清楚RunPython 和 UDF 到底有什么区别很多新手第一次接触 xlwings 时会把 UDF 和 RunPython 混在一起。这个地方必须先讲清楚否则后面的代码会越看越乱。UDF的定位更像 Excel 公式。比如你在单元格里写MYFUNC(A1)它的使用方式和普通 Excel 函数类似输入一个值返回一个结果适合做单元格级别的计算。RunPython的定位更像“自动化任务入口”。它通常由 VBA 宏、按钮、菜单触发执行的是一整套 Python 流程例如读取数据、清洗数据、生成报表、写回结果。这张图展示了 RunPython 与 UDF 的核心区别左侧是公式计算右侧是流程自动化。从这张图中我们可以看出UDF 更适合“单点计算”RunPython 更适合“流程执行”。如果你的需求只是根据 A1 计算 B1用 UDF 就够了但如果你要一键处理一整张表、一整个工作簿RunPython 更合适。对比项UDFRunPython使用方式单元格公式VBA 宏 / 按钮触发适用场景单值计算、公式扩展批量处理、流程自动化典型入口MYFUNC(A1)RunPython import xxx; xxx.main()结果输出返回到单元格可写回多个 Sheet / 文件更适合谁想扩展 Excel 函数的人想做自动化报表的人我的建议新手不要一上来就纠结哪个更高级而是先判断任务类型。只要任务是“按按钮跑流程”优先考虑 RunPython只要任务是“像公式一样算结果”优先考虑 UDF。3. 适用场景什么时候应该用 RunPythonRunPython 最适合的不是“写一段炫技代码”而是把重复性的 Excel 工作变成稳定流程。尤其是那些手工操作步骤多、容易出错、每周每月都要重复做的表非常适合用 RunPython 改造。常见场景包括一键生成报表从原始数据 Sheet 读取数据清洗后写入 Report Sheet批量数据处理多个工作表统一汇总、去重、筛选、统计模板化交付同事只打开 Excel点按钮即可生成结果复杂逻辑计算Excel 公式难维护但 Python 代码更清晰图表与文件输出生成 PNG、PDF、HTML 报告再回写路径或结果。不推荐的场景如果只是两个单元格相加、简单文本拼接、普通 VLOOKUP 能解决的问题没必要强行上 RunPython。工具不是越复杂越好能稳定解决问题才是目标。从办公自动化角度看RunPython 的意义在于把 Excel 从“手工操作工具”升级为“流程触发入口”。4. 用 quickstart 创建项目自动生成 xlsm 和 py要让 RunPython 跑起来最省事的方法不是自己从零配置而是使用 xlwings 提供的 quickstart 命令。在目标文件夹中打开命令行执行下面的命令xlwings quickstart vba_runpython_demo执行后通常会生成一个项目文件夹里面包含一个 Excel 宏工作簿和一个 Python 脚本文件vba_runpython_demo/ ├── vba_runpython_demo.xlsm └── vba_runpython_demo.py这张图展示了 quickstart 命令执行后自动创建 .xlsm 和 .py 文件的效果。这一步的核心要点是让 Excel 宏文件和 Python 脚本文件保持在同一个目录下。这样 VBA 调用 Python 时模块导入路径最简单后续排错成本也最低。这里不要随便改文件名。比如 Python 文件叫 vba_runpython_demo.py那么 VBA 里导入模块时也应该写 import vba_runpython_demo。文件名、模块名、导入名不一致是 RunPython 新手最常见的错误之一。5. Python 端写 main()让它负责完整处理流程在 RunPython 场景里我建议给 Python 脚本写一个明确的入口函数例如 main()。这样 VBA 端只负责调用 main()具体逻辑都放在 Python 里维护。一个标准的 Python 处理流程通常包括三步从 Excel 读取数据使用 Python 进行统计、清洗、汇总把结果写回 Excel 的 Report 表。这张图展示了 Python 端 main() 的处理流程左侧读取原始数据中间执行 Python 统计处理右侧写入 Report 结果表。从这张图中我们可以看出main() 不应该只是随便放几行代码而应该承担“流程入口”的职责。它负责组织整个任务让代码从读取数据到输出结果形成闭环。下面是一份可直接理解的示例importxlwingsasxwdefsummarize_range(book:xw.Book,sheet_name:str,addr:str): 读取指定 Sheet 的指定区域并计算总和、平均值、最大值、最小值。 shtbook.sheets[sheet_name]valuessht.range(addr).value# 把 Excel 区域值统一展开成一维列表flat[]ifisinstance(values,list):forrowinvalues:ifisinstance(row,list):flat.extend(row)else:flat.append(row)else:flat[values]nums[]forvinflat:try:ifvisNoneorv:continuenums.append(float(v))exceptException:passifnotnums:returnNonereturn{count:len(nums),sum:sum(nums),avg:sum(nums)/len(nums),max:max(nums),min:min(nums),}defwrite_report(book:xw.Book,out_sheet:str,result:dict): 将统计结果写回 Excel 的 Report 工作表。 shtbook.sheets[out_sheet]sht.range(A1).value[[指标,值],[数量 count,result[count]],[总和 sum,result[sum]],[平均 avg,result[avg]],[最大 max,result[max]],[最小 min,result[min]],]defmain(): VBA 调用 RunPython 时推荐统一调用 main()。 wbxw.Book.caller()src_sheetSheet1src_rangeA1:A20out_sheetReport# 如果没有 Report 表则自动创建ifout_sheetnotin[s.nameforsinwb.sheets]:wb.sheets.add(out_sheet)resultsummarize_range(wb,src_sheet,src_range)ifresultisNone:wb.sheets[out_sheet].range(A1).value没有可用数值数据returnwrite_report(wb,out_sheet,result)这段代码的关键点在于 xw.Book.caller()它代表当前从 Excel 调用 Python 的工作簿对象。也就是说Python 不需要重新打开 Excel 文件而是直接接管当前正在运行宏的这个工作簿。推荐做法把复杂逻辑拆成多个函数例如 summarize_range()、write_report()最后由 main() 统一调度。这样后续维护和扩展会轻松很多。6. VBA 端用 RunPython 调用 Python 函数Python 端写好以后就需要在 Excel 的 VBA 里调用它。操作入口是Alt F11 → 打开 VBA 编辑器 → 插入模块 → 编写宏最常用的写法如下Option Explicit Sub RunPythonMain() RunPython import vba_runpython_demo; vba_runpython_demo.main() End Sub这行代码里有两个关键点import vba_runpython_demo导入同目录下的 Python 模块vba_runpython_demo.main()调用 Python 文件里的main()函数。注意模块名如果你的 Python 文件叫 demo.py这里就应该写 import demo; demo.main()。如果文件名和模块名对不上很容易出现 ModuleNotFoundError。如果你想调用 Python 里的某个单独函数也可以这样写defhello(nameYJlio):wbxw.Book.caller()wb.sheets[0].range(D1).valuefHello,{name}!VBA 端对应写法Sub RunPythonHello() RunPython import vba_runpython_demo; vba_runpython_demo.hello(YJlio) End Sub实际做项目时我更推荐先固定一个 main() 作为入口。按钮只调用 main()具体业务逻辑全部放到 Python 里。这样 Excel 端会更干净Python 端也更容易版本管理。7. 常见问题与踩坑记录RunPython 三大坑位RunPython 本身不难真正难的是环境、路径、宏安全这些外围配置。很多时候代码没有错但就是跑不起来问题往往出在下面三个位置。这张图展示了 RunPython 最容易翻车的三大坑位模块名、解释器、宏安全。从这张图中我们可以看出RunPython 的排错不能只盯着 Python 代码本身还要同时检查 Excel 宏环境、Python 解释器路径、模块导入路径。7.1 模块名错误ModuleNotFoundError常见报错类似ModuleNotFoundError: No module named vba_runpython_demo常见原因.xlsm和.py不在同一个目录Python 文件名改了但 VBA 里的 import 没改Python 文件名包含特殊字符或空格当前路径没有被加入 Python 搜索路径。推荐处理新手阶段尽量保持.xlsm和.py同目录并且不要随意改名。7.2 解释器错误Excel 调用的 Python 不是你装包的那个常见报错类似No module named xlwings No module named pandas这类错误不是包真的没装而是 Excel 调用的 Python 解释器和你命令行里装包的解释器不是同一个。处理思路在命令行确认当前 Python 路径where python python-cimport sys; print(sys.executable)在 xlwings 配置中确认 Excel 使用的解释器路径把解释器改成你真正安装了xlwings、pandas的那个环境。不要盲目重复 pip install。先确认 Excel 调用的是哪个 Python否则你可能一直把包装到 A 环境而 Excel 却在用 B 环境。7.3 宏安全策略按钮点了但没有任何反应在公司电脑上宏安全经常是 RunPython 跑不起来的原因之一。尤其是从外部下载、拷贝、邮件接收的 .xlsm 文件可能会被 Excel 阻止宏运行。可以检查文件是否被标记为来自 InternetExcel 宏是否启用文件是否位于受信任位置公司是否有组策略禁用了宏是否需要 IT 侧放行。企业环境不要随便降低宏安全级别。正确做法是确认文件来源、放入受信任位置或者按照公司安全规范申请白名单。8. 效果验证不要只看“没有报错”很多人写自动化脚本只要运行没有报错就认为成功了。这个判断太粗糙。RunPython 的验证至少要看三个层面8.1 VBA 是否成功触发 Python可以在main()里先写一个最小测试defmain():wbxw.Book.caller()wb.sheets[0].range(A1).valueRunPython 调用成功如果 A1 能写入内容说明 VBA 到 Python 的调用链路通了。8.2 Python 是否正确读取数据可以临时把读取到的数据写到另一个单元格确认读取范围没有错。sht.range(H1).valuevalues8.3 Report 是否正确生成最后要检查 Report 表是否存在统计结果是否符合原始数据尤其是总和、平均值、最大值、最小值是否准确。成功标准点击按钮后没有报错指定 Sheet 的数据被正确读取Report 表自动生成或更新统计结果和手工计算一致再次运行不会重复制造脏数据。真正可靠的自动化不是跑一次成功而是反复运行仍然稳定。9. 我的总结提升这一节的核心不是简单记住 RunPython 这一句 VBA 代码而是要理解它在 Excel 自动化体系里的位置。我对 RunPython 的定位是Excel 负责交互VBA 负责触发Python 负责处理Report 负责交付。这和普通 Excel 脚本不一样。普通脚本可能只是帮你少点几下鼠标而 RunPython 更适合做成一个稳定的“小型自动化系统”。我建议重点记住这几条UDF 是公式思维RunPython 是流程思维quickstart 能降低项目创建成本Python 端建议统一写 main() 作为入口VBA 端只负责触发不要堆复杂业务逻辑模块名、解释器、宏安全是三大排错重点验证结果不能只看有没有报错还要看数据是否正确写回。如果只会复制 RunPython import xxx; xxx.main()但不知道 Excel、VBA、Python、解释器、宏安全之间的关系真实办公环境里一定会卡住。所以我更建议把这一节当成“Excel 自动化交付方式”的升级点而不是单纯当成一个语法点。10. 发布版补充我建议这样使用这篇笔记这一节在书中的位置可以理解为第 9 章里从“Python 与 Excel 互通”走向“Excel 触发 Python 自动化”的关键节点。它不适合只做概念阅读更适合边看边搭一个最小项目。最稳的学习路径是先用 xlwings quickstart 生成项目再写一个最简单的 main()最后用 VBA 调用它。等这条链路跑通后再逐步加入读取数据、统计处理、写回 Report 的逻辑。最不推荐的做法是直接复制一大段复杂代码然后在报错时不知道是 VBA 错、Python 错、路径错、解释器错还是宏安全拦截。这样排错会非常痛苦。一句话收尾RunPython 的本质是把 Python 变成 Excel 里的自动化引擎。返回顶部