Hoje vou mostrar uma forma diferente de integrar com Word, através da extensão XML.
Quem já precisou fazer integração com Word, sabe que o meio mais fácil de se fazer é através de modelos com extensão .dot e .dotx. Inclusive eu já fiz artigos abordando isso.
Porém, teve uma situação em um cliente, onde o documento do Word possuía umas 30 páginas, e centenas de variáveis, o que fazia o usuário ficar esperando um tempinho para a população dos dados.
Para otimizar essa questão, o que foi desenvolvido foi uma integração via XML, dessa forma ficou muito mais rápido, pois basicamente é realizado a leitura de um arquivo XML base e trocado as variáveis em um For de um array.
Abaixo irei detalhar como fazer esse procedimento. Mas ressalto, trabalhar com XML no Word pode ser bem chato a longo prazo (se precisar dar manutenções no arquivo, por causa das quebras de tags).
Obs.: Pré requisito para esse tutorial é ter instalado o Notepad++ e o plugin XML Tools, veja como instalar no artigo Como Indentar um arquivo XML utilizando o Notepad++
- Abra o Word e onde for as variáveis, escreva VAR e o restante do nome (evite escrever underline ou outros caracteres especiais, pois pode impactar na tags XML)
- Clique em Salvar Como, e escolha o tipo Documento XML do Word
- Clique com o botão direito no arquivo, depois em Edit with Notepad++ e acione o Pretty Print no XML Tools
- Copie o arquivo para a Protheus_Data, por exemplo para a subpasta x_dots
- Agora desenvolva um código fonte que leia o conteúdo do arquivo, substitua as variáveis com StrTran e depois abra o arquivo modificado (o fonte esta depois do passo 6)
- Por último, basta ver o resultado gerado quando o Word abrir o arquivo
Abaixo o código fonte desenvolvido:
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function zTstXML
Função de integração com o Word, através de um XML
@type Function
@author Atilio
@since 08/06/2021
/*/
User Function zTstXML()
Processa({|| fGera()})
Return
Static Function fGera()
Local cConteudo := ""
Local aVariaveis
Local nAtual := 0
Local nTotal := 0
Local cDocVar
Local xDocSubst
Local cPasta := GetTempPath()
Local cArquivo := "arquivo_" + dToS(Date()) + "_" + StrTran(Time(), ':', '-') + ".doc"
Local cXMLArquivo := "\x_dots\exemplo.xml"
//Se o arquivo existir
If File(cXMLArquivo)
//Lê todo o conteúdo do arquivo, joga para a memória
cConteudo := fMemoRead(cXMLArquivo)
//Adiciona as variaveis e conteudos
aVariaveis := {}
aAdd(aVariaveis, {"VARNOME", "Daniel"})
aAdd(aVariaveis, {"VARDIA", Date()})
aAdd(aVariaveis, {"VARHORA", Time()})
//Substitui todas as variáveis
nTotal := Len(aVariaveis)
ProcRegua(nTotal)
For nAtual := 1 To nTotal
IncProc("Analisando variável " + cValToChar(nAtual) + " de " + cValToChar(nTotal) + "...")
//Busca a variavel e o conteúdo, conforme eVal do fonte GPEWORD2
cDocVar := aVariaveis[nAtual][1]
xDocSubst := aVariaveis[nAtual][2]
If ValType(xDocSubst) == "D"
xDocSubst := dToC(xDocSubst)
EndIf
If ValType(xDocSubst) == "N"
xDocSubst := cValToChar(xDocSubst)
EndIf
//Retira caracteres especiais para não impactar no XML
xDocSubst := StrTran(xDocSubst, '>', '')
xDocSubst := StrTran(xDocSubst, '<', '')
xDocSubst := StrTran(xDocSubst, '&', '')
xDocSubst := StrTran(xDocSubst, '¡', '')
xDocSubst := Alltrim(xDocSubst)
//Faz a substituição
cConteudo := StrTran(cConteudo, cDocVar, xDocSubst)
Next
//Grava o conteúdo do arquivo, na temporária do sistema, com a extensão .doc
MemoWrite(cPasta + cArquivo, cConteudo)
//Abre o arquivo gerado
ShellExecute("OPEN", cArquivo, "", cPasta, 1)
Else
MsgStop("Arquivo XML não foi encontrado na origem!", "Atenção")
EndIf
Return
//Mais que 65535 bytes
Static Function fMemoRead(cArquivo)
Local cConteudo := ""
Local oFile := FWFileReader():New(cArquivo)
Local aLinhas
Local cLinAtu
//Se o arquivo pode ser aberto
If (oFile:Open())
//Se não for fim do arquivo
If ! (oFile:EoF())
//Definindo o tamanho da régua
aLinhas := oFile:GetAllLines()
ProcRegua(Len(aLinhas))
//Método GoTop não funciona, deve fechar e abrir novamente o arquivo
oFile:Close()
oFile := FWFileReader():New(cArquivo)
oFile:Open()
//Enquanto houver linhas a serem lidas
While (oFile:HasLine())
//Buscando o texto da linha atual
cLinAtu := oFile:GetLine()
cConteudo += cLinAtu
EndDo
EndIf
//Fecha o arquivo e finaliza o processamento
oFile:Close()
EndIf
Return cConteudo
Bom pessoal, por hoje é só.
Abraços e até a próxima.



