【问题标题】:How to connect Python to an open Excel workbook, using win32?如何使用 win32 将 Python 连接到打开的 Excel 工作簿?
【发布时间】:2021-07-15 16:21:39
【问题描述】:

我有多个 Excel 实例正在运行,并且想要连接到其中一个中打开的特定文件。我尝试按照Tim Golden 的说明按完整文件名获取工作簿。这就是我在 iPython 中所做的:

import win32com.client as win32
xl1 = win32.Dispatch("Excel.Application")
xl1.Visible = False
wb1 = xl1.Workbooks.Add()
wb1.SaveAs(r"C:\Users\[...]\test.xlsx")
xl2 = win32.DispatchEx("Excel.Application")
wb2 = win32.GetObject(r"C:\Users\[...]]\test.xlsm")

结果是:

Traceback (most recent call last)
<ipython-input-22-471d068eb257> in <module>
----> 1 wb2 = win32.GetObject(r"C:\Users\[...]\test.xlsm")

c:\users\[...]\venv\lib\site-packages\win32com\client\__init__.py in GetObject(Pathname, Class, clsctx)
     70     return GetActiveObject(Class, clsctx)
     71   else:
---> 72     return Moniker(Pathname, clsctx)
     73
     74 def GetActiveObject(Class, clsctx = pythoncom.CLSCTX_ALL):

c:\users\[...]\venv\lib\site-packages\win32com\client\__init__.py in Moniker(Pathname, clsctx)
     85     Python friendly version of GetObject's moniker functionality.
     86   """
---> 87   moniker, i, bindCtx = pythoncom.MkParseDisplayName(Pathname)
     88   dispatch = moniker.BindToObject(bindCtx, None, pythoncom.IID_IDispatch)
     89   return __WrapDispatch(dispatch, Pathname, clsctx=clsctx)

com_error: (-2147221014, 'Moniker cannot open file', None, None)

我做错了什么?

【问题讨论】:

  • 嗯,这很有趣。我会尝试查看 ROT(运行对象表)以了解工作簿的名称是什么。 Windows SDK 或 Visual Studio 中有一个工具可以显示 ROT 中的内容。在您的示例中,理论上您不需要调用 GetActiveObject() 因为该对象已作为 wb1 对象加载。如果您确保工作簿已关闭并且 Excel 已关闭并完全关闭,您会得到相同的结果吗? (没有正在运行的实例)
  • @JosephWillcoxson 如果我关闭 wb1 并退出 xl1,我可以使用 GetObject 和完整路径获取 wb2。在这种情况下没有问题,但它不是解决方案。它能告诉你什么吗?
  • 告诉我它不喜欢进程空间中已经存在的活动对象。另一项测试是在 Python 脚本未运行且所有 Excel 进程关闭的情况下恢复基线。然后,在 Excel 中打开工作簿,看看是否可以使用 GetActiveObject()。
  • @JosephWillcoxson 如果我能找到这个绰号 - 我将如何使用它来访问工作簿?
  • @JosephWillcoxson 另外 - 退出 Python 并在 Excel 中打开工作簿后,我可以使用 GetObject() 访问同一个工作簿。

标签: python excel com pywin32 win32com


【解决方案1】:

以下代码在我的机器上运行良好(Windows 10 64 位,Python Anaconda 3.6.4)。在您的示例中,您使用的文件具有不同的名称。 IDK 如果那是问题?

import win32com.client as win32
FileName = r"c:\toolbox\erase\auto.xlsx"
xl1 = win32.Dispatch("Excel.Application")
xl1.Visible = False
wb1 = xl1.Workbooks.Add()
wb1.SaveAs(FileName)
xl2 = win32.DispatchEx("Excel.Application")
wb2 = win32.GetObject(FileName)
print(wb2.Name)
xl1.Quit()

【讨论】:

  • 糟糕!看起来像是错字...将尽快确认!
  • 确认!那应该教会我服从 DRY!无论如何-感谢您发现它。现在我可以使用它来对我的 vba 代码进行单元测试,而不必每次我想通过循环运行它时关闭工作簿。
  • 不知道 DRY 的首字母缩略词……有多少人读过它并没有看到错字?当它不是语法时很容易做到。有时对于这样的事情,在 procmon 实用程序下运行很有启发性。它可能会认识到它找不到文件。
  • 不要重复自己(DRY)——我应该像你一样使用变量!
猜你喜欢
  • 1970-01-01
  • 2014-09-12
  • 2011-09-14
  • 2022-10-08
  • 2017-08-02
  • 2023-04-01
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多