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

6 投票
2 回答
14476 浏览
提问于 2025-04-15 22:57

我正在尝试写一个Python脚本,想要通过Excel的COM接口来访问和修改当前打开的Excel工作簿。不过,当有多个Excel实例同时运行时,我遇到了困难。例如,下面的代码

import win32com.client

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

只会打印出第一个运行的Excel实例中的活动工作簿的名称。我真正想要的是我最后点击的那个工作簿,不管它是在什么Excel实例中。

谢谢。

2 个回答

4

使用xlwings,你可以很简单地这样做:

import xlwings as xw
print(xw.books.active.name)

即使你同时打开了多个Excel窗口,这个方法也能正常工作。

8

编辑以回应评论

可能有更好的方法来实现这个。

安装这个很棒的 psutil

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

现在列出所有窗口,同时获取窗口的标题和进程ID(pid)。

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

接下来,只需找到第一个在我们的 excelPids 列表中的进程ID。

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

编辑结束

这里有几个需要考虑的事情:

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

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

确实会给你最后一个活跃的工作簿。

或者是否有多个 EXCEL.EXE 实例在运行? 你可以用以下方法获取每个实例:

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

但这样就失去了目的,因为你需要知道名称,而且这不会告诉你哪个窗口最后获得了焦点。

针对 @tgrays 上面的评论,如果你的 Excel 实例保证是最前面的窗口,那么:

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

但在最糟糕的情况下,如果有多个实例,你需要找出哪个窗口最后获得了焦点,你就得列出所有窗口,找到你关心的那个:

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

祝你好运!

撰写回答