从 Python 获取活动 Excel 工作簿的名称

2022-01-14 00:00:00 python com

问题描述

我正在尝试编写一个 Python 脚本,该脚本将使用 Excel COM 接口访问和修改活动的 Excel 工作簿.但是,当有多个 Excel 实例正在运行时,我很难让它工作.比如代码

I am trying to write a Python script that will access and modify the active Excel workbook using the Excel COM interface. However, I am having difficulty getting this to work when there are multiple Excel instances running. For example, the code

import win32com.client

xl = win32com.client.Dispatch("Excel.Application")
print(xl.ActiveWorkbook.FullName)

仅从第一个运行的 Excel 实例中打印出活动工作簿的名称.我真正想要的是我上次单击的工作簿,无论它位于哪个 Excel 实例中.

prints out the name of the active workbook from the first running instance of Excel only. What I really want is the workbook that I last clicked on, regardless of what Excel instance it was in.

谢谢.


解决方案

编辑评论

可能有更好的方法来做到这一点.

There might be a better way to do this.

安装优秀的psutil

import psutil
excelPids = []
for proc in psutil.process_iter():
  if proc.name == "EXCEL.EXE": excelPids.append(proc.pid)

现在枚举窗口,但获取窗口标题和 pid.

Now enumerate the windows, but get the window title and pid.

windowPidsAndTitle = []
win32gui.EnumWindows(lambda hwnd, resultList: resultList.append((win32gui.GetWindowThreadProcessId(hwnd),win32gui.GetWindowText(hwnd))), windowPidsAndTitle)

现在只需找到我们 excelPids 中的第一个 pid

Now just find the first pid that is in our excelPids

  for pid,title in windowPidsAndTitle:
    if pid in excelPids:
      return title 

结束编辑

这里有很多事情需要考虑:

There is a number of things to take into consideration here:

一个实例是否打开了多个工作簿?在这种情况下

Does one instance have multiple workbooks open? In this case

xl = win32com.client.Dispatch("Excel.Application")
xl.ActiveWorkbook.FullName

确实会给你最后一个活动的工作簿.

Will indeed give you the last active workbook.

或者是否有单独的 EXCEL.EXE 实例正在运行?您可以通过获取每个实例:

Or are there separate instances of EXCEL.EXE running? You can get each instance with:

xl = win32com.client.GetObjec(None, "Excel.Application") #instance one
xl = win32com.client.GetObject("Name_Of_Workbook") #instance two

但这违背了目的,因为您需要知道名称,并且这不会告诉您最后一个焦点.

But this defeats the purpose because you need to know the name AND this will not tell you which one last had focus.

对于上面的@tgrays 评论,如果您的 excel 实例保证是前台窗口,那么:

To @tgrays comment above, if your excel instance is guaranteed to be the foreground window then:

import win32gui
win32gui.GetWindowText(win32gui.GetForegroundWindow()) 
#parse this and use GetObject to get your excel instance

但最坏的情况,多个实例,你必须找到最后一个焦点,你必须枚举所有窗口并找到你关心的那个:

But worst case scenerio, multiple instances and you have to find which had focus last, you'll have to enumerate all the windows and find the one you care about:

windows = []
win32gui.EnumWindows(lambda hwnd, resultList: resultList.append(win32gui.GetWindowText(hwnd)),windows)
#enumerates all the windows open from the top down
[i for i in windows if "Microsoft Excel" in i].pop(0)
#this one is closest to the top

祝你好运!

相关文章