获取上次打开的 MS Word 文档对象 [英] Getting last opened MS Word document object

查看:49
本文介绍了获取上次打开的 MS Word 文档对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a python script called from a VBA AutoNew() sub in a MS Word 2003 template (.dot) - so it runs every time a document is created from this Word template.

第三方应用程序从此模板创建文档.第三方应用程序如何设置文档存在许多格式问题,因此我的脚本会在第三方脚本完成运行后对其进行调整.(我最初是用 VBA 编写脚本的,但是 VBA 计时器的问题导致它在很大一部分时间内崩溃.python 版本完美无缺.)​​

A third-party application creates documents from this template. There are a number of formatting issues with how the third-party application sets up the document, thus my script to tweak it once the third-party script has finished running. (I originally wrote the script in VBA, but problems with the VBA timer cause it to crash a significant fraction of the time. The python version works flawlessly.)

我希望脚本只处理调用它的文档,该文档将始终是最近打开的 Word 文件.(该文件是 .doc 而不是 .docx,如果这有区别的话.)我找到了三种方法来获取 Word 的打开实例(因为这个脚本是由 AutoNew 调用的,所以总会有一个可用的打开实例):

I want the script to work with just the document that called it, which will always be the most recently opened Word file. (The file is a .doc and not a .docx, if that makes any difference.) I have found three ways to get an open instance of Word (since this script is called by AutoNew there will always be an available open instance):

win32com.client.GetActiveObject (Class = 'Word.Application')
win32com.client.gencache.EnsureDispatch('Word.Application')
win32com.client.Dispatch('Word.Application')

如果新创建的文档是唯一打开的 Word 文件,则这三个中的任何一个都可以很好地工作.但是如果一个 Word 文档已经打开,并且我运行第三方软件从这个模板创建一个新文档,python 脚本每次都会使用所有三种方法抓取旧实例.

Any of these three work great if the newly created document is the only open Word file. But if a Word document is already open, and I run the third-party software to create a new document from this template, the python script grabs the older instance every time with all three methods.

我尝试寻找循环遍历 Word 文档的方法,想法是我可以检查所有名称并选择最后编号最大的那个(脚本运行时文档将不会被保存),因此它的名称将是 Document1、Document2 等.)不幸的是,我只找到了循环遍历已关闭文档的方法(打开一个,做某事,关闭它,继续下一个),而不是(在我的情况下)已经打开的.

I've tried searching for ways to loop through Word documents, with the idea that I could check all the names and select the one with the highest number at the end (at the time the script runs the document will not be saved, so its name will be Document1, Document2, etc.) Unfortunately I only found methods to loop through closed documents (opening one, doing something, closing it, moving on to the next), not (as in my case) already open ones.

有没有办法将python定向到最近打开的Word文档?

Is there a way to direct python to the most recently opened Word document?

EDIT 相关问题:Word VBA 和多词实例

我已经找到了如何获取我想要控制的文档的 Windows 句柄整数:

I have found how to get the Windows handle integer of the document I want to control:

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'Documentd', 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 对象?

So now - how to create a COM object from the Windows handle?

推荐答案

通过 NVDA (Non-Visual Desktop Access) 的 GitHub 代码的一些搜索终于找到了我正在寻找的对象:

Some searching through the GitHub code of NVDA (Non-Visual Desktop Access) finally got me the object I was looking for:

#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 文档对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆