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.