我正在尝试编写一个 Python 脚本,该脚本将使用 Excel COM 接口访问和修改活动的 Excel 工作簿。但是,当有多个 Excel 实例正在运行时,我很难让它工作。例如,代码
import win32com.client
xl = win32com.client.Dispatch("Excel.Application")
print(xl.ActiveWorkbook.FullName)
Run Code Online (Sandbox Code Playgroud)
仅从 Excel 的第一个运行实例中打印出活动工作簿的名称。我真正想要的是我上次单击的工作簿,无论它在哪个 Excel 实例中。
谢谢。
编辑评论
可能有更好的方法来做到这一点。
安装优秀的psutil
import psutil
excelPids = []
for proc in psutil.process_iter():
if proc.name == "EXCEL.EXE": excelPids.append(proc.pid)
Run Code Online (Sandbox Code Playgroud)
现在枚举窗口,但获取窗口标题和 pid。
windowPidsAndTitle = []
win32gui.EnumWindows(lambda hwnd, resultList: resultList.append((win32gui.GetWindowThreadProcessId(hwnd),win32gui.GetWindowText(hwnd))), windowPidsAndTitle)
Run Code Online (Sandbox Code Playgroud)
现在只需找到我们 excelPids 中的第一个 pid
for pid,title in windowPidsAndTitle:
if pid in excelPids:
return title
Run Code Online (Sandbox Code Playgroud)
结束编辑
这里有很多事情需要考虑:
一个实例是否打开了多个工作簿?在这种情况下
xl = win32com.client.Dispatch("Excel.Application")
xl.ActiveWorkbook.FullName
Run Code Online (Sandbox Code Playgroud)
确实会给你最后一个活动的工作簿。
或者是否有单独的 EXCEL.EXE 实例正在运行? 您可以通过以下方式获取每个实例:
xl = win32com.client.GetObjec(None, "Excel.Application") #instance one
xl = win32com.client.GetObject("Name_Of_Workbook") #instance two
Run Code Online (Sandbox Code Playgroud)
但这违背了目的,因为您需要知道名称,而这不会告诉您最后一个焦点是哪个。
对于上面的@tgrays 评论,如果您的 excel 实例保证是前台窗口,则:
import win32gui
win32gui.GetWindowText(win32gui.GetForegroundWindow())
#parse this and use GetObject to get your excel instance
Run Code Online (Sandbox Code Playgroud)
但最坏的情况是场景,多个实例,你必须找到最后一个焦点,你必须枚举所有窗口并找到你关心的一个:
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
Run Code Online (Sandbox Code Playgroud)
祝你好运!
| 归档时间: |
|
| 查看次数: |
9683 次 |
| 最近记录: |