Alterando documentos do Word automaticamente
11 de Maio de 2006 às 09:35 Thiago | Enviar por e-mail Hits para esta publicação: 3521
Surgiu um problema interessante aqui no trabalho. Muitos de nossos documentos de requisitos fazem referência a seções de outros documentos, e de forma especial, os documentos contendo os casos de uso fazem constantes referências aos documentos de regras de negócio. O problema é que a leitura de um caso de uso fica dificultada, pois nem toda a informação necessária para o completo entendimento está em um único documento. Como a idéia de incorporar (inline) as regras dentro dos casos de uso não nos é conveniente por diversas razões, sugeri a utilização de links, isto é, o leitor poderia clicar na referência e o outro documento seria aberto na seção desejada.
Essa parecia ser a solução ideal, mas outras questões surgiram. Primeiramente, eu nunca usei a função de ligar um documento com outro no Word. Eu tinha uma intuição de que era possível, mas nunca fiz isso antes. Após consultar a ajuda do Word (e acreditem, as ajudas do Word e do Excel são bem completas, descobri muita coisa bacana nelas e portanto valem a pena serem lidas) descobri como inserir um link entre documentos (usando a excelente função de bookmarks também). Ainda bem que é fácil.
A outra questão deriva do fato de usarmos o Requisite Pro para gerenciar os requisitos e ele altera as extensões dos arquivos de .DOC para outras, decididas pelo padrão da empresa. Acontece que volta e meia precisamos enviar artefatos para os clientes, então os documentos são “exportados” para documentos .DOC do Word normais, mas como o nome dos arquivos muda, os links são quebrados. Dá para corrigir manualmente, link a link, mas todos podem imaginar o quanto isso é trabalhoso e quão fácil é cometer um erro.
Assim, vislumbrei a criação de um script que alterasse os documentos para mim automaticamente.
Minha primeira tentativa foi abrir o documento, procurar pela extensão trocada e substitui-la pela string “.DOC”. Fiz isso, mas há dois problemas:
1º) Se o tamanho do arquivo muda (as extensões são de tamanhos diferentes) então o arquivo é considerado inválido pelo Word.
2º) Se as extensões são do mesmo tamanho, ainda assim é necessário abrir arquivo por arquivo e atualizar os links (update field).
Como no meu caso as extensões são de tamanhos diferentes, precisava encontrar outra forma. E achei.
A Microsoft tem um time de programadores extremamente competentes. O Windows é razoavelmente ruim pela mesma razão que o conjunto de instruções dos processadores da Intel é um desastre (experimente programar em assembler num deles): backward compatibility. Uma das coisas que dizem que a Microsoft fez certo foi COM (Component Object Model). No meu caso, usando COM eu poderia comandar o Word para realizar as alterações de que necessitava automaticamente. Então segui nessa direção.
Encontrei uma biblioteca chamada win32com para Python. Ela permite que scripts Python realizem operações COM. Depois de procurar pela documentação no site da Microsoft e experimentar um pouco, consegui criar um script que faz o que preciso. Ele está listado a seguir:
# coding=iso-8859-1
# Script que altera os hyperlinks de documentos do Word de forma
# que eles apontem para arquivos .DOC ao invés de arquivos .BLABLA.
# ------------------------------------------------------------------------------
# Criado por Thiago F Chaves
# Este script depende da biblioteca win32com.
# A biblioteca pode ser baixada em:
# http://sourceforge.net/project/showfiles.php?group_id=78018
# Padrões de codificação:
# -----------------------
# st > ScrolledText
# doc > Documento Word
# noarq > Nome de arquivo
# ls > Lista
# hl > Hyperlink
# c > Contador
# tx > Texto (string)
import win32com.client
import tkFileDialog
import os
import ScrolledText
st = ScrolledText.ScrolledText()
def exibir(*args):
global st
for arg in args:
st.insert(ScrolledText.END, arg)
st.insert(ScrolledText.END, " ")
st.insert(ScrolledText.END, "n")
st.pack()
def alterar_documento(noarq):
global wordapp
doc = wordapp.Documents.Open(noarq) # Use o caminho completo
exibir("Documento", noarq)
lshl = doc.Hyperlinks
chl = 0
for i in range(1, lshl.Count + 1):
hl = doc.Hyperlinks(i)
txold = hl.Address
if not "BLABLA" in txold:
if "BLABLA" in txold.upper(): # Apenas uma garantia
exibir(hl.TextToDisplay)
exibir("Link não foi alterado!!!")
continue
chl += 1
exibir(hl.TextToDisplay)
txnew = txold.replace("BLABLA", "DOC")
hl.Address = txnew
exibir("De", txold, "para", txnew, ".")
if chl == 0:
exibir("Nenhum hyperlink encontrado.")
doc.Close()
exibir("--- // ---")
return
exibir("--- // ---")
doc.Save()
doc.Close()
pasta = tkFileDialog.askdirectory()
lsnoarq = [noarq for noarq in os.listdir(pasta) if noarq.upper().endswith(".DOC") and not noarq.startswith("~")]
if len(lsnoarq) == 0:
exibir("Nenhum documento encontrado.")
else:
wordapp = win32com.client.Dispatch("Word.Application")
for noarq in lsnoarq:
alterar_documento(os.path.realpath(os.path.join(pasta, noarq)))
wordapp.Quit()
st.mainloop()
Publicação arquivada em: Tecnologia
Enviar por e-mail | Hits para esta publicação: 3522
2 Comentários Faça seu próprio
1. Matheus | 11 de Maio de 2006 às 11:36
Bacana esse negócio! Tenho que aprender Python logo, heheh. Uma linguagem de script sempre quebra um bom galho.
Uma observação sobre seu script. Acho que seria melhor usar nomes mnemônicos para as variáveis do que criar um comentário com padrões de nomenclatura de pedaços de nomes. Não é porque é um script que os nomes das variáveis tem que ser pouco mnemônico. Garanto que você não faz esse tipo de coisa num programa Java, certo?
2. Thiago | 11 de Maio de 2006 às 13:05
Claro que faço!
Rebelei-me contra nomes de variáveis com 66 caracteres!!!
Na verdade, Matheus, já há algum tempo li um artigo com uma compilação da notação húngara original e resolvi colocar em prática, pois a idéia parece ser realmente útil.
Aviso: Há dois tipos de notação húngara. Estou usando a original, que é a menos difundida (não é a que a Microsoft usa e abusa).
Comecei a fazer isso depois de ler um texto do Joel on Software e estou gostando. Evito usar no trabalho porque não há um padrão definido, mas sempre que posso defino um padrão e uso.
Mais uma coisa: em uma linguagem dinamicamente tipada como Python ter noção do tipo da variável ajuda muito (não há IDE que ajude).
Deixe um Comentário
Linkar esta publicação | Assine os comentários via o RSS