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

查看:112
本文介绍了获取上次打开的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?

编辑相关问题: Word VBA和多个Word实例

我已经找到了如何获取要控制的文档的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'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对象?

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

推荐答案

通过NVDA(非可视桌面访问)的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天全站免登陆