quinta-feira, 14 de abril de 2016

Integração Advpl x Excel #2


Integração Advpl x Excel #2

Fala galera!

No post anterior nós falamos sobre o início do programa que faz integração Advpl x Excel. Hoje continuaremos com o post a partir da função reportDef().

Vejamos o código antes de prosseguir:

static function reportDef

local oReport
local oSection
local oBreak

//configura o relatório
oReport := TReport():new("RELCLI","Lista de Clientes",,{|oReport| printReport(oReport)},"Lista de Clientes")
oReport:SetLandscape()  //orientação da página como paisagem
oReport:nFontBody := 10 //tamanho da fonte padrão
oReport:showHeader() //define que será exibido o cabeçalho do relatório
//cria uma seção   
oSection := TRSection():new(oReport,"Lista de clientes",{"SA1"})//importante descrever as tabelas utilizadas
oReport:setTotalInLine(.F.)

TRCell():new(oSection, "CLIENTE",,"")
oSection:cell("CLIENTE"):disable()

//define as colunas com o campo da tabela, tabela e cabeçalho que estará na planilha
TRCell():new(oSection, "A1_COD" , "SA1", "Cód. cliente")
TRCell():new(oSection, "A1_NOME", "SA1", "Nome cliente")
TRCell():new(oSection, "A1_END" , "SA1", "Endereço")
TRCell():new(oSection, "A1_MUN" , "SA1", "Cidade")
TRCell():new(oSection, "A1_EST" , "SA1", "Estado")
TRCell():new(oSection, "A1_PAIS", "SA1", "Pais")
      
return oReport

Bom, o que essa função faz basicamente? É responsável por toda a configuração inicial do seu relatório, ou seja, caso o usuário não deseje modificar alguma coisa, como impressão paisagem ou foto, o relatório assumirá a configuração definida nesta função.

Primeiro precisamos instanciar um objeto de TReport e, para isso, definimos o objeto oReport, onde este receberá as configurações iniciais do relatório.

TReport():new("RELCLI","Lista de Clientes",,{|oReport| printReport(oReport)},"Lista de Clientes")

Este método construtor, tem os seguinte parâmetros:

cReport: Nome do relatório. Exemplo: "RELCLI";
cTitle: Título do relatório;
uParam: Parâmetros do relatório cadastrado no Dicionário de Perguntas (SX1). Também pode ser utilizado bloco de código para parâmetros customizados;
bAction: Bloco de código que será executado quando o usuário confirmar a impressão do relatório;
cDescription: Descrição do relatório;
lLandscape: Aponta a orientação de página do relatório como paisagem;
uTotalText: Texto do totalizador do relatório, podendo ser caracter ou bloco de código;
lTotalInLine: Imprime as células em linha;
cPageTText: Texto do totalizador da página;
lPageTInLine: Imprime totalizador da página em linha;
lTPageBreak: Quebra página após a impressão do totalizador;
nColSpace: Espaçamento entre as colunas;


O construtor TRCell() é célula de impressão de uma seção (TRSection) de um relatório que utiliza a classe TReport. 

Para cada célula adicionada ao relatório é necessário chamar este método com a configurações necessárias com o objeto da seção, nome do campo, nome da tabela e título que será apresentado no arquivo excel.

Agora vamos implementar a função que irá efetuar a consulta no banco de dados, salvar em uma tabela temporária e adicionar ao objeto oSection do relatório.
Esta função definimos com o nome de printReport, que executará a impressão do relatório.

static function printReport()
    
local oSection := oReport:section(1)
local cSql := ""

oSection:init()    

//efetua a pesquisa no banco de dados. Neste caso, seleciona todos os clientes existentes
cSql := " SELECT A1_COD, A1_NOME, A1_END, A1_MUN, A1_EST, A1_PAIS "
cSql += " FROM "+RetSqlName("SA1")+"  SA1 "
cSql += " WHERE SA1.D_E_L_E_T_ = '' "   
cSql += " ORDER BY A1_COD "
    
//salva o código sql na pasta TEMP para consultas no seu SGBD
memoWrite("\TEMP\RELSA1.sql",cSql)                           
//Executa a query e cria uma tabela temporária (TRB)
dbUseArea(.T.,"TOPCONN",TCGenQry(,,cSql),"TRB",.F.,.T.)

oReport:setMeter(TRB->(recCount()))

TRB->(dbGoTop())

//percorre a tabela temporária e 'seta' os valores nas respectivas colunas
while !TRB->(eof())
 oSection:cell("A1_COD"):setValue(TRB->A1_COD)
 oSection:cell("A1_NOME"):setValue(TRB->A1_NOME)
 oSection:cell("A1_END"):setValue(TRB->A1_END) 
 oSection:cell("A1_MUN"):setValue(TRB->A1_MUN)
 oSection:cell("A1_EST"):setValue(TRB->A1_EST)
 oSection:cell("A1_PAIS"):setValue(TRB->A1_PAIS)
 oSection:printLine()
 oReport:incMeter()
 TRB->(dbSkip())
endDo
                  
oSection:finish()
TRB->(dbCloseArea())

return


O objeto oSection é iniciado através de seu método init(), onde é responsável por inicializar as configurações e define a primeira página de impressão.
Utilizamos a variável cSql para definirmos a query de consulta ao banco de dados que será posteriormente utilizada.

O método memowrite() é responsável por salvar o código sql que geramos em um diretório, no nosso caso será na pasta Temp do sistema. Este método é muito simples, basta informar a string contendo o diretório onde será salvo o arquivo, com nome e extensão; e a variável que possui o conteúdo a ser salvo.

Já o método dbUseArea() define um arquivo de dados como uma área de trabalho disponível na aplicação. Aqui nós definimos que trabalharemos com uma tabela temporária nomeada TRB, esta tabela terá todos os campos configurados no método reportDef(). Então para acessá-los basta usar a mesma sintaxe que usaríamos com uma tabela real do banco de dados.

Para mostrar ao usuário o andamento da impressão, utilizamos o método oReport:setMeter(TRB->(recCount())) que mostra uma régua de progressão.


//percorre a tabela temporária e 'seta' os valores nas respectivas colunas
while !TRB->(eof())
 oSection:cell("A1_COD"):setValue(TRB->A1_COD)
 oSection:cell("A1_NOME"):setValue(TRB->A1_NOME)
 oSection:cell("A1_END"):setValue(TRB->A1_END) 
 oSection:cell("A1_MUN"):setValue(TRB->A1_MUN)
 oSection:cell("A1_EST"):setValue(TRB->A1_EST)
 oSection:cell("A1_PAIS"):setValue(TRB->A1_PAIS)
 oSection:printLine()
 oReport:incMeter()
 TRB->(dbSkip())
endDo

O laço de repetição while percorre toda a tabela e adiciona o conteúdo dos campos da tabela TRB nas células respectivas. Após o final desse laço de repetição, a seção é encerrada, a tabela temporária é encerrada e a tela de impressão é exibida ao usuário.

Como vocês puderam acompanhar, não é um monstro de sete cabeças realizar essa integração. A linguagem Advpl é muito fácil de trabalhar, pois tem muitos recursos que permitem a alta abstração que nos permite evitar de se preocupar com configurações básicas ou mais complexas.

Então é isso aí! Até mais galera! Qualquer dúvida é só deixar um comentário que responderei assim que puder.

Código fonte completo em GitHub.
Renan Rodrigues Ramos Desenvolvedor

Sou desenvolvedor, amo desenvolvimento de software, músico e apaixonado por filmes e seriados.