【问题标题】:What defines which Excel instance an Excel.Application COM object connects to?什么定义了 Excel.Application COM 对象连接到哪个 Excel 实例?
【发布时间】:2019-03-05 10:26:12
【问题描述】:
import win32com.client as win32

excel = win32.gencache.EnsureDispatch('Excel.Application')
for wb in excel.Workbooks:
    print(wb.Name)

当我使用 Sublime Text 运行这个脚本时: 打印打开的工作簿的名称列表。

当我使用 PyCharm 运行此脚本时: 我得到一个空白列表。

两者都在同一台 PC 上,并且使用相同版本的 Python(3.5 32 位)。

不确定这条信息是否有所作为,但我在第一次下载 PyCharm 时从未运行过 PyCharm 安装程序。我下载了 zip 文件,每次都从解压缩的文件夹中运行 PyCharm.exe。会不会是这个原因?

【问题讨论】:

  • 您的两个 IDE 是否以同一用户身份运行且没有提升权限?
  • 现在我想起来了,我正在以管理员身份运行 PyCharm。你认为这可以解释它吗?
  • 是的,Excel COM 不会重用其他用户的主机进程(使用提升运行实际上与其他用户一样)。我将此添加到答案中。
  • 确实,在禁用 PyCharm.exe 的“以管理员身份运行”选项后,脚本按预期工作,显示打开的工作簿列表。谢谢!

标签: python excel pywin32 win32com


【解决方案1】:

原因一定是,在一种情况下,您连接到正在运行的 Excel 实例,而在另一种情况下,打开一个新实例(或连接到其他某个实例)。

为确保连接到现有实例,您可以按照Attaching to an already running Office application from your application using GetActiveObject or BindToMoniker – .NET4Office 使用win32com.client.GetActiveObject(<ProgID>)


这些是我注意到的模式,它们控制Excel.Application 对象连接到哪个 Excel 实例:

  • 如果您有一个在运行程序之前手动启动的 Excel 实例,则程序会连接到该实例
  • 如果没有,excel.exe 实例由托管 DCOM 进程启动器服务的 svchost.exe 进程生成
    • 此实例最初没有打开任何个工作簿
  • 但是,如果在此之后手动启动 Excel,则会创建第二个实例。 DCOM 实例具有优先权。
  • An instance is not closed even after .Quit as long as there are references to it,因此任何来自同一个进程的进一步分派,当它具有对它的引用时,都将获得相同的实例。
  • 您无法连接到以不同用户身份运行的 Excel 进程(这包括使用 vs 不使用提升)。

所以如果你例如从交互式控制台运行您的代码,或者 IDE 不会每次都重新启动 Python 进程(不太可能但可能),您可能有旧的现有引用。

【讨论】:

    猜你喜欢
    • 2014-01-28
    • 2011-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    • 2020-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多