获取最后打开的MS Word文档对象

时间:2015-11-24 18:54:05

标签: ms-word pywin32

我有一个从MS Word 2003模板(.dot)中的VBA AutoNew()子调用的python脚本 - 所以每次从这个Word模板创建文档时它都会运行。

第三方应用程序从此模板创建文档。第三方应用程序如何设置文档存在许多格式问题,因此我的脚本会在第三方脚本运行完毕后进行调整。 (我最初在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文档的方法,我想我可以检查所有名称并选择最后编号最大的名称(在脚本运行文档时不会保存,所以它的名字将是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对象?

1 个答案:

答案 0 :(得分:1)

通过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)
相关问题