Python 数据分析基础入门:《Excel Python:飞速搞定数据分析与处理》学习笔记系列(第十章 Python 驱动的 Excel 工具 上篇)

Excel Python:飞速搞定数据分析与处理

第四部分 使用 xlwings 对 Excel 应用程序进行编程

第十章 Python 驱动的 Excel 工具

第 9 章介绍了如何编写脚本来自动化 Microsoft Excel。虽然这些脚本很强大,但它们需要用户能够熟练使用 Anaconda Prompt 或者像 VS Code 这样的编辑器来运行脚本。如果你的工具是给商业用户使用的,那么这样的要求可能就不太现实。对于这样的用户,你会想要将 Python 隐藏起来,从而让这些 Excel 工具感觉像是普通的带有宏的工作簿那样,而如何使用 xlwings 达到这样的效果便是本章的主题。本章首先会向你展示如何用最简单的方法 在 Excel 中执行 Python 代码。然后会挑战一下部署 xlwings 工具,在这个过程中我们会对 xlwings 提供的各种选项有一个更细致的了解。和第 9 章一样,本章也需要你在 Windows 或者 macOS 中安装好 Microsoft Excel。

10.1 利用 xlwings 将 Excel 用作前端

前端 (frontend)指的是应用程序中用户 可以看见 且可以与之互动 的那一部分,也被称为图形用户界面 (graphical user interface,GUI )或者用户界面 (user interface,UI )。工作表可以让用户更快、更直观地输入数据,与不完善的 Web 界面相比,Excel 的界面生产力反而更高 。本节首先会介绍 xlwings 的 Excel 插件以及 xlwings 的 CLI(command line interface,命令行接口)。然后会通过 quickstart 命令创建我们的第一个项目。最后会展示从 Excel 中调用 Python 代码的两种方法:点击插件中的运行按钮以及使用 VBA 中的 RunPython 函数。下面先来安装 xlwings 的 Excel 插件。

10.1.1 Excel 插件

想在 Excel 中调用 Python 脚本,需要安装 Excel 插件或者在独立模式中配置工作簿。10.2 节会介绍独立模式,而本节展示如何使用这个插件。要安装这个插件,需要在 Anaconda Prompt 中执行下列命令:

复制代码
(base)> xlwings addin install

每次更新 xlwings 时,都需要保持 Python 包的版本和 Excel 插件的版本一致。因此在更新 xlwings 时需要执行两条命令:一条用于 Python 包,另一条用于 Excel 插件。使用不同的包管理器时,更新 xlwings 的方式也不一样,下面分别是使用 Conda 和 pip 时所需执行的命令。

复制代码
Conda(搭配 Anaconda Python 发行版使用)
	(base)> conda update xlwings  
	(base)> xlwings addin install

pip(搭配其他 Python 发行版使用)
	(base)> pip install --upgrade xlwings  
	(base)> xlwings addin instal

注意 :xlwings 有时候会被杀毒软件 标记成恶意插件,特别是当你使用的是最新版本的 xlwings 时。如果你在自己的计算机上碰到了这种情况,那么可以进入杀毒软件的设置,在这里应该能够将 xlwings 标记为可以安全运行的软件。一般来说,你也可以通过杀毒软件的主页来报告这样的误报。

在 Anaconda Prompt 中输入 xlwings 时,你使用的是 xlwings CLI。除了可以让 xlwings 插件的安装更方便,它还提供了一些其他的命令:我会在需要使用这些命令的时候对其进行介绍,但你随时可以在 Anaconda Prompt 中输入 xlwings 然后按回车键来打印可用选项。 现在来仔细看看 xlwings addin install 都干了些什么。

插件的实际安装 是将 xlwings.xlam 从 Python 包的目录复制到 Excel 的 XLSTART 文件夹中。这是一个特殊文件夹,Excel 会在每次启动时打开其中的所有文件。当你在 Anaconda Prompt 中执行 xlwings addin status 命令时,它会打印 XLSTART 目录在系统中的位置以及是否已安装了插件。

在第一次安装插件时,插件会将环境配置为执行 install 指令时所用的 Python 解释器或者 Conda 环境。下图所示,Conda Path 和 Conda Env 的值是由 xlwings CLI1自动填写的。这些值被保存在 home 目录的 .xlwings 文件夹的 xlwings.conf 文件中。在 Windows 中,一般保存在 C:\Users\.xlwings\xlwings.conf 中;在 macOS 中, 一般保存在 /Users//.xlwings/xlwings.conf 中。在 macOS 中,在默认情况 下,名称前面有一个点的文件夹和文件会被隐藏。在访达中按下键盘快捷键 Command Shift-. 可以切换隐藏文件的可见性。

执行完安装命令后,必须重启 Excel 才能在功能区中看到上图所示的 xlwings 标签页。

macOS 中的功能区插件:在 macOS 中,功能区看起来会有点儿不一样,因为它并没有关于用户定义函数和 Conda 的部分:这是由于 macOS 不支持用户定义函数,而 Conda 环境也不需要特殊对待,也就是说它是在 Python 分组下在解释器选项中配置的。

现在你已经装好了 xlwings 插件,我们需要一个工作簿和一些 Python 代码来测试一下。

10.1.2 quickstart 命令

为了让你的首个 xlwings 工具的开发过程尽可能地方便,xlwings CLI 提供了 quickstart 命令。在 Anaconda Prompt 中,使用 cd 命令切换至你想要创建的第一个项目的目录(如 cd Desktop),然后执行下列命令创建名为 first_project 的项目:

复制代码
(base)> cd Desktop
(base)> xlwings quickstart first_project

项目名称必须是合法的 Python 模块名称:可以包含字母、数字和下划线,但不能包含空白或者横线,也不能以数字开头。10.1.4 节会介绍如何将 Excel 文件的名称修改为无须遵循这种规则的名称。执行 quickstart 命令将会在当前目录中创建一个叫作 first_project 的文件夹。在 Windows 的文件资源管理器或是 macOS 的访达中打开该文件夹时,你会看到两个文件:first_project.xlsm 和 first_project.py 如下图。在 Excel 中打开 Excel 文件,在 VS Code 中打开 Python 文件。从 Excel 执行 Python 代码的最简单的方法是点击插件中的 Run main 按钮。 下面来看看怎么做。

10.1.3 Run main

等一下再更细致地研究 first_project.py。现在首先保持 first_project.xlsm 为活动的文件,然后在 xlwings 插件的最左边点击 Run main 按钮 ," Hello xlwings!" 会被写入第一张工作表的 A1 单元格中。再次点击按钮,单元格内容会变成 "Bye xlwings!"。祝贺你,你刚刚在 Excel 中运行了你的第一个 Python 函数!下面来看看例 10-1 中的 first_project.py。

复制代码
例 10-1 first_project.py
import xlwings as xw 

def main(): 
    wb = xw.Book.caller() ➊ 
    sheet = wb.sheets[0] 
    if sheet["A1"].value == "Hello xlwings!": 
        sheet["A1"].value = "Bye xlwings!" 
    else: 
        sheet["A1"].value = "Hello xlwings!" 
        
@xw.func ➋ 
def hello(name): 
    return f"Hello {name}!" 
if __name__ == "__main__": ➌ 
    xw.Book("first_project.xlsm").set_mock_caller() 
    main()

➊ xw.Book.caller() 是一个 xlwings book 对象,它引用的是在点击 Run main 按钮时活动的 Excel 工作簿 。在本例中,它就对应着 xw.Book("first_project.xlsm")。xw.Book. caller() 可以让你对文件系统中的 Excel 文件进行重命名和移动位置,且不会破坏文件之间的引用关系。当你在多个 Excel 实例中打开同一个 Excel 文件时,它还可以保证你操作的是正确的工作簿。

➋ 本章会忽略 hello 函数,第 12 章会讲到它。如果你在 macOS 中执行 quickstart 命令, 则无论如何都看不见 hello 函数,因为只有 Windows 才支持用户定义函数。

➌ 第 11 章在介绍调试时会解释最后 3 行代码。对于本章来说,你可以直接忽略这几行, 甚至可以直接删掉第一个函数之后的所有内容。

Excel 插件中的 Run main 按钮是一个方便的功能:它可以调用与 Excel 文件同名的 Python 模块中的名为 main 的函数,并且不需要事先在工作簿中添加按钮。即使你将工作簿保存为无宏的 xlsx 格式,这个按钮依然可以正常工作。不过,如果你想调用一个甚至多个不叫 main 的 Python 函数,或者它们并不在与工作簿同名的模块之中,就需要使用 VBA 中的 RunPython 函数。下一节会详细介绍这个函数。

10.1.4 RunPython 函数

如果需要对 Python 代码有更高的控制权,那么可以使用 VBA 函数 RunPython,因此 RunPython 需要将工作簿保存为启用了宏的工作簿 。当你打开一个启用了宏的工作簿(扩展名为 xlsm,比如 quickstart 命令生成的工作簿)时,需要点击启用内容 (Windows 系统)或者启用宏 (macOS 系统)。当你在 Windows 中使用配套代码库的 xlsm 文件时,还需要点击启用编辑,否则 Excel 无法正常打开从互联网上下载的文件。

RunPython 能够接受字符串形式的 Python 代码:最常见的情况是,你导入一个 Python 模块,然后运行其中的一个函数。当你按下快捷键 Alt + F11(Windows 系统)或者 Option - F11(macOS 系统)打开 VBA 编辑器时,会看到 quickstart 命令在名为 "Module1" 的 VBA 模块中添加了一个叫作 SampleCall 的宏(参见下图)。如果没有看到 SampleCall,则可以双击左边 VBA 项目树中的 Module1。

这些代码看起来有一点儿复杂,但这只是为了在项目命名为任何名称时 quickstart 命令都能动态地工作。由于我们的 Python 模块叫作 first_project,因此你可以把里面的代码替换成等效但更易懂的版本:

复制代码
Sub SampleCall() 
    RunPython "import first_project; first_project.main()" 
End Sub

由于在 VBA 中编写多行字符串非常麻烦,因此这里使用了 Python 可以接受的分号 而不是换行。有几种方法可以运行这段代码,比如可以在 VBA 编辑器中将光标放到 SampleCall 宏的任意一行上,然后按下 F5 键。不过,一般来说你可以在 Excel 工作表中而不是 VBA 编辑器中执行代码。因此可以关闭 VBA 编辑器,回到工作簿中。按下快捷键 Alt + F8 (Windows 系统)或者 Option - F8(macOS 系统)可以打开宏菜单:选择 SampleCall 然后点击运行按钮。

或者,为了使其对用户更加友好,可以在 Excel 工作簿中添加一个按钮并将其连接至 SampleCall :首先确保开发者标签页已显示在功能区中。如果没有,则可以进入"文件>选项>自定义功能区 "菜单项中勾选开发工具旁边的复选框。(在 macOS 中,该选项位于 "Excel>偏好设置>功能区和工具栏"。)要插入一个按钮,可以进入开发工具标签页,在控件分组中,点击 "插入>按钮"(在窗体控件下)。在 macOS 中,你需要先进入插入菜单才能看见按钮。当点击按钮图标时,你的鼠标指针就变成了一个小十字:按住鼠标左键绘制出一个矩形区域以生成按钮。一旦放开鼠标左键,你就会看到一个附加宏菜单,选择 SampleCall 然后点击 OK。点击你刚刚创建的按钮(对我来说是叫作 "Button1" 的按钮),它会再次运行我们的 main 函数,如下图所示。

说明窗体控件和 ActiveX 控件

在 Windows 中有两种控件类型:窗体控件和 ActiveX 控件。虽然两种类型的按钮都可以连接 SampleCall 宏,但是只有窗体控件可以在 macOS 中工作。 在第 11 章中,我们会使用矩形作为按钮让它看起来更现代化一些。

现在来看看如何修改 quickstart 命令赋予的默认名称:返回 Python 文件并将其名称从 first_project.py 改为 hello.py。同时将 main 函数重命名为 hello_world。一定要保存文件,然后再次打开 VBA 编辑器,按下快捷键 Alt+F11(Windows 系统)或者 Option-F11 (macOS 系统),依照下面的代码编辑 SampleCall 以反映更改:

复制代码
Sub SampleCall() 
    RunPython "import hello; hello.hello_world()" 
End Su

回到工作表中,点击 "Button 1" 以确认一切照常工作。最后,你可能还想将 Python 脚本和 Excel 文件保存在不同的目录中。为了理解其中暗含的一些问题,先来讲一下有关 Python 的模块搜索路径(module search path):如果你在代码中导入了一个模块,那么 Python 就会在多个目录中寻找这个模块。首先,Python 会检查是否存在以此为名的内置模块,如果没有找到,则继续查看当前工作目录,然后在所谓的 PYTHONPATH 中查找。 xlwings 会自动将工作簿目录添加到 PYTHONPATH 中,这样你就可以通过插件添加额外的路径。为了尝试一下这一特性,可以将名为 hello.py 的 Python 脚本移动到 home 目录下新建的 pyscripts 文件夹中:对于我来说,在Windows 中就是C:\Users\felix\pyscripts,在 macOS 中则是 /Users/felix/pyscripts。当你再次点击按钮时,会得到如下错误:

要修复这个错误,只需将 pyscripts 目录添加到 xlwings 功能区的 PYTHONPATH 设置中即可, 如下图所示。当你再次点击按钮时,它又可以正常工作了。

本书还没有讲到 Excel 工作簿的名称:只要你在调用 RunPython 函数时使用的是显式的模块名称(如first_project)而不是由 quickstart 添加的代码,就可以随意重命名 Excel 工作簿的任何内容。

如果你要创建一个新的 xlwings 项目,那么使用 quickstart 命名是最简单的方法。然而如果你有一个既存的工作簿,则可能更喜欢手动配置(感兴趣的小伙伴可自行学习,笔者这里就跳过了)。

相关推荐
EW Frontier1 小时前
【信号分选】深度学习颠覆射频信号分离:UNet/WaveNet 性能碾压传统方法【附python代码】
python·深度学习·unet·wavenet·射频信号源分离·icassp信号处理挑战赛
2301_809244531 小时前
如何解决宝塔面板磁盘空间占满问题_使用磁盘清理工具清理
jvm·数据库·python
huzhongqiang1 小时前
用元类实现类属性:打造更优雅的服务访问机制
后端·python
WL_Aurora1 小时前
Python 算法基础篇之查找算法(一):顺序查找、二分查找与插值查找
开发语言·python·算法
2401_867623982 小时前
如何设置用户默认表空间_ALTER USER DEFAULT TABLESPACE
jvm·数据库·python
ftpeak2 小时前
LangGraph Agent 开发指南(12~函数式 API)
人工智能·python·ai·langchain·langgraph
yivifu2 小时前
跟水印杠上了——顺便巩固Tkinter的GUI编程
python·opencv·tkinter·去水印
2301_803934612 小时前
html标签怎样划分页面区域_section与div的区别【介绍】
jvm·数据库·python
知学致远2 小时前
Python基础语法_01-注释、输入输出、变量
python