获取最后打开的 MS Word 文档对象
Getting last opened MS Word document object
我有一个从 MS Word 2003 模板 (.dot) 中的 VBA AutoNew() 子程序调用的 python 脚本 - 所以每次文档是 运行s从此 Word 模板创建。
第三方应用程序从该模板创建文档。第三方应用程序如何设置文档存在许多格式问题,因此我的脚本会在第三方脚本完成 运行ning 后对其进行调整。 (我最初是在 VBA 中编写脚本的,但是 VBA 计时器的问题导致它在很长一段时间内崩溃。python 版本完美无缺。)
我希望脚本只与调用它的文档一起工作,该文档始终是最近打开的 Word 文件。 (该文件是 .doc 而不是 .docx,如果这有什么区别的话。)我找到了三种方法来获取 Word 的打开实例(因为这个脚本是由 AutoNew 调用的,所以总会有一个可用的打开实例):
win32com.client.GetActiveObject (Class = 'Word.Application')
win32com.client.gencache.EnsureDispatch('Word.Application')
win32com.client.Dispatch('Word.Application')
如果新创建的文档是唯一打开的 Word 文件,这三个中的任何一个都非常有用。但是如果一个 Word 文档已经打开,并且我 运行 第三方软件从这个模板创建一个新文档,python 脚本每次都会使用所有三种方法获取旧实例。
我已经尝试寻找遍历 Word 文档的方法,我的想法是我可以检查所有名称和 select 最后编号最大的那个(当时脚本 运行s 文档不会被保存,所以它的名字将是 Document1、Document2 等)不幸的是我只找到了循环关闭文档的方法(打开一个,做某事,关闭它,继续下一个) ,不是(如我的情况)已经打开的。
有没有办法直接python到最近打开的Word文档?
编辑 相关问题:Word VBA and Multiple Word Instances
我找到了如何获取我要控制的文档的 Windows 句柄整数:
import win32gui
import re
#Create a list of all open Microsoft Word document titles and their
#handle integers
titles = []
def foreach_window(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
title = win32gui.GetWindowText(hwnd)
if 'Microsoft Word' in title:
titles.append([title, hwnd])
return True
win32gui.EnumWindows(foreach_window, None)
#Find the handle of the newest open, unsaved Word document
winOrder = []
for s in titles:
item = re.search(r'Document\d', s[0])
if item:
winOrder.append(int(re.search(r'\d+', s[0]).group()))
else:
winOrder.append(0)
hwnd = titles[winOrder.index(max(winOrder))][1]
#Get the edit window from inside the Word instance
def callback(hwnd, hwnds):
if win32gui.GetClassName(hwnd) == '_WwG':
hwnds.append(hwnd)
#I think there should be a 'return False' here to let EnumChildWindows
#know it doesn't have to keep looping once it finds the edit window,
#but it crashes with 'pywintypes.error: (0, 'EnumChildWindows',
#'No error message is available') if I try that
return True
hwnds = []
win32gui.EnumChildWindows(whndl, callback, hwnds)
#Something like this...
#window = win32gui.AccessibleObjectFromWindow(hwnds[0])
现在 - 如何从 Windows 句柄创建 COM 对象?
通过 NVDA(非可视化桌面访问)的 GitHub 代码搜索终于找到了我要找的对象:
#Part of the pywin32 package that must be installed with the pywin32
#installer:
import win32com.client as win32
import win32gui
from ctypes import oledll
from ctypes import byref
#installed by easy_install comtypes
from comtypes import POINTER
from comtypes.automation import IDispatch
import comtypes.client.dynamic as comDy
#Handle integer hwnds[0] per my edit in the question
OBJID_NATIVEOM = -16
p = POINTER(IDispatch)()
oledll.oleacc.AccessibleObjectFromWindow(hwnds[0], OBJID_NATIVEOM,
byref(IDispatch._iid_), byref(p))
window = comDy.Dispatch(p)
word = window.application
cert = word.Documents(1)
我有一个从 MS Word 2003 模板 (.dot) 中的 VBA AutoNew() 子程序调用的 python 脚本 - 所以每次文档是 运行s从此 Word 模板创建。
第三方应用程序从该模板创建文档。第三方应用程序如何设置文档存在许多格式问题,因此我的脚本会在第三方脚本完成 运行ning 后对其进行调整。 (我最初是在 VBA 中编写脚本的,但是 VBA 计时器的问题导致它在很长一段时间内崩溃。python 版本完美无缺。)
我希望脚本只与调用它的文档一起工作,该文档始终是最近打开的 Word 文件。 (该文件是 .doc 而不是 .docx,如果这有什么区别的话。)我找到了三种方法来获取 Word 的打开实例(因为这个脚本是由 AutoNew 调用的,所以总会有一个可用的打开实例):
win32com.client.GetActiveObject (Class = 'Word.Application')
win32com.client.gencache.EnsureDispatch('Word.Application')
win32com.client.Dispatch('Word.Application')
如果新创建的文档是唯一打开的 Word 文件,这三个中的任何一个都非常有用。但是如果一个 Word 文档已经打开,并且我 运行 第三方软件从这个模板创建一个新文档,python 脚本每次都会使用所有三种方法获取旧实例。
我已经尝试寻找遍历 Word 文档的方法,我的想法是我可以检查所有名称和 select 最后编号最大的那个(当时脚本 运行s 文档不会被保存,所以它的名字将是 Document1、Document2 等)不幸的是我只找到了循环关闭文档的方法(打开一个,做某事,关闭它,继续下一个) ,不是(如我的情况)已经打开的。
有没有办法直接python到最近打开的Word文档?
编辑 相关问题:Word VBA and Multiple Word Instances
我找到了如何获取我要控制的文档的 Windows 句柄整数:
import win32gui
import re
#Create a list of all open Microsoft Word document titles and their
#handle integers
titles = []
def foreach_window(hwnd, lParam):
if win32gui.IsWindowVisible(hwnd):
title = win32gui.GetWindowText(hwnd)
if 'Microsoft Word' in title:
titles.append([title, hwnd])
return True
win32gui.EnumWindows(foreach_window, None)
#Find the handle of the newest open, unsaved Word document
winOrder = []
for s in titles:
item = re.search(r'Document\d', s[0])
if item:
winOrder.append(int(re.search(r'\d+', s[0]).group()))
else:
winOrder.append(0)
hwnd = titles[winOrder.index(max(winOrder))][1]
#Get the edit window from inside the Word instance
def callback(hwnd, hwnds):
if win32gui.GetClassName(hwnd) == '_WwG':
hwnds.append(hwnd)
#I think there should be a 'return False' here to let EnumChildWindows
#know it doesn't have to keep looping once it finds the edit window,
#but it crashes with 'pywintypes.error: (0, 'EnumChildWindows',
#'No error message is available') if I try that
return True
hwnds = []
win32gui.EnumChildWindows(whndl, callback, hwnds)
#Something like this...
#window = win32gui.AccessibleObjectFromWindow(hwnds[0])
现在 - 如何从 Windows 句柄创建 COM 对象?
通过 NVDA(非可视化桌面访问)的 GitHub 代码搜索终于找到了我要找的对象:
#Part of the pywin32 package that must be installed with the pywin32
#installer:
import win32com.client as win32
import win32gui
from ctypes import oledll
from ctypes import byref
#installed by easy_install comtypes
from comtypes import POINTER
from comtypes.automation import IDispatch
import comtypes.client.dynamic as comDy
#Handle integer hwnds[0] per my edit in the question
OBJID_NATIVEOM = -16
p = POINTER(IDispatch)()
oledll.oleacc.AccessibleObjectFromWindow(hwnds[0], OBJID_NATIVEOM,
byref(IDispatch._iid_), byref(p))
window = comDy.Dispatch(p)
word = window.application
cert = word.Documents(1)