【问题标题】:Please help me run a Python script from Excel 365 VBA on a Mac Mini running Big Sur请帮助我在运行 Big Sur 的 Mac Mini 上从 Excel 365 VBA 运行 Python 脚本
【发布时间】:2021-06-13 20:20:55
【问题描述】:

我关于这个主题的第一个问题由于不够具体而被关闭,所以我会试着告诉你到目前为止我已经尝试过哪些没有奏效的问题。我正在尝试使用 Office 365 将 Excel 2010 工作簿移动到我的新 Mac mini Big Sur 机器。这是我的第一台 Mac,所以我对操作系统以及与 Microsoft 世界的差异非常陌生。这也是我第一次使用 Office 365。我希望你能帮助我。在我的 VBA 宏中,我运行 Python 脚本来抓取网页中的数据。通常我让 Python 脚本创建一个 .csv 文件,然后我在 VBA 宏中打开该文件以读取和填充工作簿中必要的单元格。这是我在PC版中调用Python脚本的代码:

Kill strFileOfData
Set objWsh = VBA.CreateObject("WScript.shell")
strPython = """C:\Users\Phil\AppData\Local\Programs\Python\Python37-32\python.exe"""
strPyScript = """C:\Users\Phil\Documents\PyScripts\GetMarketsStks1-0.py"""
objWsh.Run strPython & strPyScript
Err = 0
Do Until Dir(StrFileOfData) <> 0
  Application.Wait (Now() + TimeValue("0:00:01"))
Loop

它可能不是最好的,但它可以在 PC 上可靠地运行。我先删除数据文件,运行Python脚本,等待数据文件创建完成,然后继续。 我在 Mac 上安装了最新版本的 Python 并重写了 Python 脚本以获取更多数据,并在终端上运行 Python 脚本以确保它正确执行。它运行良好并正确创建了 .csv 文件。 然后,我更改了 VBA 宏中的代码以考虑不同的文件结构。这是新代码:

Kill strFileOfData
Set objWsh = VBA.CreateObject("WScript.shell")
strPython = """/Library/Frameworks/Python.framework/Python"""
strPyScript = """/Users/minime/MyDocuments/Finance/GetHistory1-0.py"""
objWsh.Run strPython & strPyScript

Err = 0
Do Until Dir(StrFileOfData) <> 0
  Application.Wait (Now() + TimeValue("0:00:01"))
Loop

当我在 Mac 上运行它时,我得到:

运行时错误“429”:ActiveX 组件无法创建对象

怀疑这是创建和使用 shell 的方式不同,我开始研究如何在 Mac 上从 Excel 调用 Python。经过相当多的死胡同,我发现了 4 年前的这个帖子: How can I launch an external python process from Excel 365 VBA on OSX?

我试图简单地向前推进并按照说明进行操作。我对 AppleScript 有所了解,添加了文件夹:“~/Library/Application Scripts/com.microsoft.Excel/”,创建了名为 PythonCommand.scpt 的 AppleScript 并将其放在该文件夹中。由于我在示例中找不到路径,因此我替换了我认为正确的路径,假设这是由于 MacOS 与 4 年前的差异造成的。我的 AppleScript 如下所示:

on PythonCommand(pythonScript)
   do shell script "/Library/Frameworks/Python.framework/Python" & pythonScript
end PythonCommand

然后我将此代码添加到 VBA 宏中:

strPyScript = """/Users/minime/MyDocuments/Finance/GetHistory1-0.py"""
Dim result As String
result = AppleScriptTask("PythonCommand.scpt", "PythonCommand", strPyScript)

当我运行 VBA 宏时。我收到了这条消息:

运行时错误“13”:类型不匹配

我再次尝试使用单引号而不是三引号并得到相同的结果。 我试图向后工作以确保这些作品有效。我再次从终端窗口运行 Python 脚本没有问题,所以我尝试的下一步是从 IDLE 运行 AppleScript。我输入了这个:

AppleScriptTask("PythonCommand.scpt", "PythonCommand","/Users/minime/MyDocuments/Finance/GetHistory1-0.py")

得到了这个结果:

Traceback(最近一次调用最后一次):文件“”,第 1 行,在 AppleScriptTask("PythonCommand.scpt", "PythonCommand","/Users/minime/My Documents/Finance/GetHistory1-0.py") NameError: name 'AppleScriptTask' 没有定义

经过更多研究,我在编辑器中尝试了这个 AppleScript:

do shell script "/Library/Frameworks/Python.framework/Versions/3.9/Python /Users/minime/MyDocuments/Finance/GetHistory1-0.py"

我得到了这个结果:

错误“sh:/Library/Frameworks/Python.framework/Versions/3.9/Python: 无法执行二进制文件”编号 126

接下来我尝试了这个:

do shell script "Python /Users/minime/MyDocuments/Finance/GetHistory1-0.py"

得到了这个:

error "Traceback (most recent call last):
  File \"/Users/philipackermann/MyDocuments/Finance/GetHistory1-0.py\", line 2, in <module>
    from urllib.request import urlopen
ImportError: No module named request" number 1

这实际上可能是一些进步!该导入语句是我的 Python 脚本中的第一行代码,但我不知道为什么这比上次尝试更进一步,以及为什么它的运行方式与终端中 Python 脚本的执行不同。 但我只是注意到在终端中我输入了 Python3,所以我尝试了这个:

do shell script "Python3 /Users/minime/MyDocuments/Finance/GetHistory1-0.py"

然后弹出一个脚本错误: 还有这个:

在阅读了更多关于终端的信息后,我意识到 Mac 上有隐藏文件,所以我尝试了这个 AppleScript:

do shell script "/usr/local/bin/Python3 /Users/minime/MyDocuments/Finance/GetHistory1-0.py"

而且成功了!! .csv 文件已成功创建。所以现在我需要弄清楚如何从 Excel 中调用它。我在这里找到了一篇文章:

https://stackoverflow.com/questions/38723420/how-to-simply-run-an-applescript-task-from-mac-excel-2016

这确实有效。我将 AppleScript 转换为应用程序(只是将扩展名从 scpt 更改为应用程序)并将其移至 Applications 文件夹,然后将此代码放入 VBA 宏中:

ThisWorkbook.FollowHyperlink Address:="/Applications/RunGetHistory.app", NewWindow:=True

这行得通!当然,它没有传递任何参数或接收任何结果。但是有一个问题,就像我以前的 PC 版本一样,代码不会等待应用程序完成,所以我需要一种方法来检查它是否完成,因为我更改了 Python 脚本以在开头打开文件并编写行在抓取网页时立即创建文件,因此我在 PC 版本中使用的这段代码是不够的:

Do Until Dir(strFileNmHistory) <> ""
    Application.Wait (Now() + TimeValue("0:00:01"))
Loop

我想我可以在 Python 脚本的末尾添加一个单独的文件,只是说它已经完成,但这是一个非常蹩脚的 hack。所以从技术上讲,我想我可以说我解决了这个问题,并且可以从 Excel 运行 Python 脚本,但我必须相信有更好的方法,我相信这个社区有比我聪明得多的人,他们可以做得更好。有没有人能够从 4 年前获得解决方案来工作?这可能会解决参数、结果和等待 Python 脚本结束的问题。您可以提出的任何建议都将是最有帮助的。我已经广泛研究了这个问题,一些答案说沙盒正在阻止 Excel 运行 Python,但如果我们可以运行一个运行 Python 脚本的应用程序,我猜想就可以解决它。如果您可以评论我在上面遇到的具体错误,我会尝试不同的方法并报告回来。 请帮忙。 菲尔

【问题讨论】:

  • 在 VaughanR 的帮助下,我了解了在 VBA 中使用 AppleScriptTask 命令编辑和放置 AppleScript 并使其运行的正确方法。这是该帖子的链接:stackoverflow.com/questions/67994030/… 我用于该练习的 AppleScript 只是简单地返回并成功返回了我传递的参数。但是,当我尝试调用 Python 脚本时,我得到了相同的错误 5:消息。
  • 在我看来,同样的 Erroe5:消息可能由多个问题触发:如果第一个参数(AppleScript 名称)未解析,AppleScript 是否正确但命令名称不正确如果对 Python 脚本的命令调用不正确或有其他问题,请解决(我想我现在在哪里)。

标签: python excel macos-big-sur


【解决方案1】:

已解决! ...一路上我学到了很多东西!我将尝试仅列出完成这项工作所需的步骤,但我确实倾向于漫无目的,抱歉。使这变得比它需要的更难的一个问题是一个简单的问题:AppleScript 的“do shell script”语句中缺少一个空格。这是适用于我的 VBA 代码:

Result = AppleScriptTask("PythonCommand.scpt", "PythonCommandHandler", "/Users/minime/MyDocuments/Finance/PythonScripts/GetHistory1-0.py")

这是 AppleScript 代码:

on PythonCommandHandler(pythonScript)
    do shell script "/usr/local/bin/Python3 " & pythonScript
    return "Handler succeeded!  " & pythonScript
end PythonCommandHandler

注意“Python3”后面的空格。在方便的文件夹中创建 AppleScript 并将其复制到 "/Users/minime/Library/Application Scripts/com.microsoft.Excel"

尝试在该文件夹中编辑它是有问题的,相信我。把它移到那里。 只要您在 VBA 代码中的 AppleScriptTask 命令中给出路径,Python 脚本就可以在任何地方。

确保所有对 .csv 文件的引用都指向 Excel 沙盒文件夹。我用过这个,但我怀疑其他人也会工作: "/Users/minime/Library/Containers/com.microsoft.Excel/Data/Documents"

如果找不到此文件夹,请参阅下面的注释。这在 2021 年 7 月 1 日有效!我们将看看当新的 OS X 出现时会发生什么。对 AppleScriptTask 的调用在继续之前等待 Python 脚本的完整执行。我还没有想出处理 Python 脚本错误的好方法。

以下是我在此过程中学到的一些重要知识,可能对像我这样的第一次使用 Mac 的用户有所帮助:

  1. 更改您的 VBA 编辑器字体。好的,不是真的有必要,但我正在使用的 Mac Excel 365 版本上的 VBA 编辑器的默认字体不是比例字体,所以像 Dim 语句的“as”部分这样的东西不会为我排列。一个小问题却很容易解决:在编辑器中,单击菜单栏中的“Excel”一词(最上面一行文字和图标)。单击“首选项”,将弹出一个标题为“选项”的窗口。单击“编辑器格式”选项卡,然后从“字体:”下拉列表中选择“Courier New”。我将“Size:”更改为 16。哦,顺便说一下,“Command, shift, i”将引导您完成 VBA 代码,就像在 PC 上按 F8 一样。
  2. 将一些文件放入沙盒。关于“沙盒”的一句话,我相信其他人可以比我解释得更好。为了提高安全性,沙盒概念应该限制代码执行超出预期区域的内容:例如您不希望代码(或恶意代码)中的错误来更改某些与您的意图无关的系统设置。我明白了。好概念。在古代(大型机),我们为此类问题获得了 SOC 1。沙盒基本上是您可以在其中玩的计算机的一部分。不要试图超越它(有一些我还不完全理解的例外)。在 Mac 上,这意味着如果您甚至尝试对不在沙箱中的 VBA 代码中的 .csv 文件执行任何操作,您将收到一条警报,提示您需要授予权限才能发生这种情况。带有 VBA 代码的 Excel 工作簿不需要在沙箱中,因为重要的是 Excel 可执行文件在沙箱中(我假设)并且可以访问您的工作簿(规则的例外?)和做所有你要求它做的事情,包括运行你的 VBA 代码,但有限制。 AppleScript 也需要在沙箱中,但 Python 脚本不需要(我不知道为什么)。我们只对 Excel 沙箱感兴趣,显然,对于不同的应用程序有不同的沙箱。现在谈谈别名。为简单起见,请考虑将您的 Excel 沙箱放在此处: “/Users/philipackermann/Library/Containers/com.microsoft.Excel” 这里有一个别名: “/Users/philipackermann/Library/Containers/com.microsoft.Excel/Data/Library/Application Scripts/com.microsoft.Excel” 将一个文件移动到一个文件会魔法般地将文件移动到另一个文件。顺便说一句,如果您尝试通过从头开始走路径来查找该别名路径中的第一个“com.microsoft.Excel”,它将在 Finder 中显示为“Microsoft Excel”。哦,顺便说一句,“指挥,轮班,……”将让您在 Finder 中查看隐藏的文件夹和文件。你需要它来开始。如果我理解正确的话,Finder 中带有左下角小箭头的文件夹图标表明该文件夹是一个别名(或者有一个别名指向它?我不确定)。我用于 .csv 文件的文件夹不是别名或没有别名)所以我不得不使用非常长的路径。因此,Excel 工作簿和 Python 脚本不需要在沙箱中,但 AppleScript 和 .csv 文件确实需要在沙箱中。
  3. 不要在沙盒别名文件夹中编辑!查看我在上面的 cmets 中使用 VaughanR 提到的链接。他帮助我更好地理解别名问题。谢谢VaughanR。尝试在这些文件夹中进行编辑是徒劳的疯狂练习。保存自己的创伤并在本地文件夹中编辑 AppleScript 并将其复制到沙盒文件夹。为此,我打开了两个 Finder 窗口(一个带有本地文件夹,一个带有沙盒文件夹)并按住 Command 和 Option 键,同时将 AppleScript 文件从本地文件夹拖到沙盒文件夹。
  4. 在脚本编辑器中测试 APPLESCRIPT。正如我在其他地方提到的那样,讨厌的错误 5:可能出于多种原因弹出。在脚本编辑器中,在 PythonCommandHandler on 语句上方添加这一行: "PythonCommandHandler("GetHistory1-0.py")" 并在编辑器中运行它以确保它正在执行您希望它执行的操作。这就是我发现缺少空间的问题并测试不同路径以使其运行的方式。
  5. 杂项。优秀笔记。如果您尝试将 Excel 工作簿从 Windows 环境带到 Mac,请注意我迄今为止遇到的这些问题:SORTS。我在我的 VBA 代码中对排序进行了硬编码,当我尝试在 Mac 上运行它们时导致 Excel 崩溃。我记录了一个排序,并且在代码中运行良好。 Mac 上没有用户窗体!我还没有找到替代品。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2021-05-09
    • 1970-01-01
    • 2021-03-31
    • 2012-11-15
    • 2021-04-10
    • 1970-01-01
    相关资源
    最近更新 更多