Obtendo o último objeto de documento aberto do MS Word
Eu tenho um script python chamado de um sub VBA AutoNew () em um modelo do MS Word 2003 (.dot) - portanto, ele é executado sempre que um documento é criado a partir desse modelo do Word.
Um aplicativo de terceiros cria documentos a partir deste modelo. Há vários problemas de formatação com a forma como o aplicativo de terceiros configura o documento, portanto, meu script para ajustá-lo quando o script de terceiros terminar a execução. (Eu originalmente escrevi o script no VBA, mas os problemas com o timer do VBA causam um travamento em uma fração significativa do tempo. A versão python funciona perfeitamente).
Quero que o script funcione apenas com o documento que o chamou, que sempre será o arquivo do Word aberto mais recentemente. (O arquivo é .doc e não .docx, se isso fizer alguma diferença.) Encontrei três maneiras de obter uma instância aberta do Word (como esse script é chamado pelo AutoNew, sempre haverá uma instância aberta disponível):
win32com.client.GetActiveObject (Class = 'Word.Application')
win32com.client.gencache.EnsureDispatch('Word.Application')
win32com.client.Dispatch('Word.Application')
Qualquer um desses três funcionará bem se o documento recém-criado for o único arquivo aberto do Word. Mas se um documento do Word já estiver aberto e eu executar o software de terceiros para criar um novo documento a partir desse modelo, o script python agarra sempre a instância mais antiga com todos os três métodos.
Tentei procurar maneiras de percorrer os documentos do Word, com a ideia de poder verificar todos os nomes e selecionar o que tivesse o número mais alto no final (no momento em que o script é executado, o documento não será salvo, por isso O nome será Documento1, Documento2, etc.) Infelizmente, só encontrei métodos para percorrer documentos fechados (abrir um, fazer alguma coisa, fechá-lo, passar para o próximo), e não (como no meu caso) os já abertos.
Existe uma maneira de direcionar python para o documento do Word aberto mais recentemente?
EDITAR Pergunta relacionada:Word VBA e várias instâncias do Word
Eu descobri como obter o número inteiro do documento do Windows que desejo controlar:
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])
Então agora - como criar um objeto COM a partir do identificador do Windows?