zReport – Criação de relatórios em 10 minutos em AdvPL

Rotina que monta um relatório TReport através de uma cláusula SQL.


Tela de dados, especificando as colunas

Tela de dados, especificando as colunas

Tutorial de como usar: Criação de relatórios em 10 minutos em AdvPL

Vídeo Tutorial de como usar:



Logs de Atualização:

GitHub: github.com/dan-atilio/zReport

VersãoDataObservaçãoDownload
1.017/12/2016Criação do projetoClique Aqui
Dan (Daniel Atilio)
Cristão de ramificação protestante. Especialista em Engenharia de Software pela FIB, graduado em Banco de Dados pela FATEC Bauru e técnico em informática pelo CTI da Unesp. Entusiasta de soluções Open Source e blogueiro nas horas vagas. Autor e mantenedor do portal Terminal de Informação.

61 Responses

  1. WAGNER FERREIRA disse:

    Como faço na query para colocar um grupo de pergunta já criado?

    Tenho que filtrar uma data porém não estou conseguindo fazer

    • Dan_Atilio disse:

      Boa noite Wagner, tudo bem?
      Primeiramente, prepare a consulta SQL, por exemplo:

      SELECT * 
      FROM SB1010 
      WHERE B1_COD >= ' ' AND B1_COD <= 'ZZZ'
      

      Ao gerar o código, ele terá as linhas que você pode editar, então edite a linha conforme os parâmetros que você tem, por exemplo.

      cQryAux += " WHERE B1_COD >= ' ' AND B1_COD <= 'ZZZ' "     + STR_PULA
      

      Após isso, altere conforme os parâmetros que você tem.

      cQryAux += " WHERE B1_COD >= '"+MV_PAR01+"' AND B1_COD <= '"+MV_PAR02+"' "     + STR_PULA
      

      Caso queira, no fonte já é criado a variável cPerg, ai você pode colocar uma pergunta que você já tem criada na SX1.

      Private cPerg := "SUA_PERGUNTA"
      

      Espero ter ajudado.
      Abraços.

      • marcello disse:

        Boa tarde, estou com duvida na ferramenta, se puder esclarecer melhor agradeço.
        Fiz uma consulta SQL usando seu exemplo e usei o grupo de parâmetro MTR080 (já existente do protheus)
        SELECT *
        FROM SB1010
        WHERE B1_COD >= ‘ ‘ AND B1_COD <= 'ZZZ'

        Compilei e fui na rotina pra gerar o relatório, ele carregou os parâmetros corretamente. Informei no parâmetro produto De 000008, Produto Até 000008 pois só quero esse produto, mas quando exporto para Excel aparece todos os produtos, ou seja, não obedeceu o parâmetro.

        Estou fazendo alguma coisa errada?

        • Dan_Atilio disse:

          Bom dia Marcello, tudo bem?
          Após gerar o fonte, vc vai ter que alterar o seu filtro, por exemplo, o fonte gerado vai ter esse trecho:

          cQuery += " WHERE B1_COD >= ' ' AND B1_COD <= 'ZZZ' "
          

          Ai você terá que editar e colocar os seus parâmetros (verifique qual MV_PAR é o produto de/até):

          cQuery += " WHERE B1_COD >= '"+MV_PAR01+"' AND B1_COD <= '"+MV_PAR02+"' "
          

          Abraços.

  2. marcello disse:

    Boa tarde, Dan_Atilio
    Obrigado pelo retorno.
    Então mesmo colocando o grupo de perguntas na rotina, depois editar o fonte e colocar os parâmetros pra cada pergunta, por exemplo se tiver pergunta do parâmetro de data emissão, devo fazer a mesma coisa por exemplo no D1_EMISSAO colocando o parâmetro no fonte assim com no B1_COD, correto?

    • Dan_Atilio disse:

      Bom dia Marcello, tudo bem?
      Sim, você deve colocar, lembrando que se o parâmetro não for do tipo Caracter, você tem que usar funções de conversão para concatenar com a string, por exemplo, dToS para parâmetros de data.
      Abraços.

  3. marcello disse:

    Tudo certo, fiz o teste e funcionou. muito obrigado!!

  4. WAGNER FERREIRA disse:

    Bom dia Dan,

    Teria alguma forma de eu criar um relatório com duas sessoes?

    Quando coloco dois selects o programa tá juntando tudo.

    Muito obrigado pela sua atenção.

    • Dan_Atilio disse:

      Boa noite Wagner, tudo bem?
      Existe forma sim, porém nesse aplicativo, ele gera apenas de uma seção. O que você pode fazer, é gerar dois relatórios e ir comparando e adicionar a outra seção a seu relatório.
      Irei anotar, para uma possível atualização, eu adicionar duas seções no aplicativo.
      Abraços.

  5. WAGNER FERREIRA disse:

    Olá Dan,
    Olha eu apurrinhando aqui de novo. rsrsrs

    Estou pesquisando como faço para tirar a d.ref, hora e emissão do relatório.

    Quando gero no excel ele vem no inicio com essas informações, mas nao consigo tirar.

    Me da um help.
    Mais uma vez muiiiiito obrigado e parabens pelo site, está cada dia melhor.

    • Dan_Atilio disse:

      Grande Wagner, tudo bem?
      Rapaz, primeiramente muito obrigado pelo contato e por apreciar o Ti.
      Você já tentou gerar o relatório do Excel em formato Tabela?
      Existe um combo em que você define o tipo de Planilha, faça um teste com o tipo Tabela.
      Abraços.

  6. WAGNER FERREIRA disse:

    Alguem saberia deixar o cabeçalho das células somente na primeira página quando o relatório é gerado em excel? Quando gero ele adiciona uma linha com o cabeçalho das células na quebra de página.

    • Dan_Atilio disse:

      Boa noite Wagner, tudo bem?
      Acho que você pode realizar dois testes.
      1- Gerar o relatório do Excel com o formato tabela, existe um combo na tela do TReport que você define o tipo de planilha Excel que será gerada, tente colocar o tipo Tabela;
      2- Você pode tentar alterar o atributo lXlsHeader do seu objeto do TReport, por exemplo, oReport:lXlsHeader := .F. (essa operação nunca testei);
      Qualquer dúvida, fico à disposição.
      Abraços.

  7. WAGNER FERREIRA disse:

    Bom dia Dan,

    Você teria algum exemplo do programa funcionando junto com o schedule.

    Tenho que enviar de forma automatica mas não estou conseguindo acrescentar o schedule no fonte.

    • Dan_Atilio disse:

      Boa noite Wagner, tudo bem?
      Fiz uma há muito tempo, nem utilizei o SchedDef, utilizei o RPCSetEnv.
      Abaixo o exemplo que fiz (só a user function que está chamando, sem a criação do TReport, que geralmente faço no fReportDef).

      User Function zRAuto()
      	Local aArea := GetArea()
      	Local oReport
      	Local cPara := ""
      	Private cPerg := "X_ZRAUTO"
      	ConOut("> [zRAuto] Início às "+Time()+"!")
      	
      	//Se o dicionário não tiver aberto, faz a conexão para a empresa e filial 01
      	If Select("SX2") == 0
         	 	RPCSetEnv("01", "01", "", "", "", "", {})
      	EndIf 
      	
      	Pergunte(cPerg, .F.)
      	MV_PAR01 := dDataBase	//Data De
      	MV_PAR02 := dDataBase	//Data Até
      	cPara    := "teste@teste.com.br"
      	
      	//Definindo e disparando o TReport
      	oReport := fReportDef()
      	oReport:nRemoteType := NO_REMOTE //Aponta  de  que  forma  o  Server  está  gerando  o  relatório.  Opções:   1-Sem  Remote,  2-Remote Delphi,3-Remote Windows e 4-Remote Linux
      	oReport:cEmail := cPara
      	oReport:nDevice := 3 //1-Arquivo,2-Impressora,3-email,4-Planilha e 5-Html
      	oReport:SetPreview(.F.)
      	oReport:Print(.F., "", .T.)
      	
      	ConOut("> [zRAuto] Término às "+Time()+"!")
      	
      	RestArea(aArea)
      Return
      

      Abraços.

  8. Boa tarde, compilei o fonte porem mesmo chamando a função nao abre, verifiquei no inspetor de objeto e não esta la tambem, sabe oque pode ser ? estou usando o p11.8

  9. marcello disse:

    Dan_Atilio, boa tarde

    Primeiro quero agradecer pela iniciativa, está ótimo o post.
    Eu editei o fonte e após informar os parâmetros de 01/05/2017 até 31/05/2017, o sistema mostra barra de status do andamento… mas está bem longe de finalizar… tanto que eu tenho que derrubar o usuário.. é como se tivesse colocado um período bem maior no parâmetro…
    O que está errado?

  10. marcello disse:

    segue trecho do fonte.

    //Montando consulta de dados
    cQryAux := “”
    cQryAux += “SELECT D2_FILIAL, D2_CLIENTE, D2_ITEM, D2_SERIE, D2_CF, D2_DOC, D2_EMISSAO, D2_COD, B1_COD, D2_QUANT, D2_PRCVEN, D2_TOTAL, D2_TIPO, D2_TP, D2_CONTA, B1_BASE3, A1_GRPTRIB” + STR_PULA
    cQryAux += “FROM SD2010 A” + STR_PULA
    cQryAux += “INNER JOIN SB1010 B” + STR_PULA
    cQryAux += “ON A.D2_COD = B.B1_COD” + STR_PULA
    cQryAux += “AND A.D2_FILIAL = B.B1_FILIAL” + STR_PULA
    cQryAux += “INNER JOIN SA1010 C” + STR_PULA
    cQryAux += “ON A.D2_CLIENTE = C.A1_COD” + STR_PULA
    cQryAux += “AND A.D2_LOJA = C.A1_LOJA” + STR_PULA
    cQryAux += “–AND A.D2_FILIAL = C.A1_FILIAL” + STR_PULA
    cQryAux += “WHERE A.D_E_L_E_T_ = ” AND B.D_E_L_E_T_ = ”” + STR_PULA
    cQryAux += “AND D2_EMISSAO >= ‘”+Dtos(MV_PAR01)+”‘” + STR_PULA
    cQryAux += “AND D2_EMISSAO = ‘”+MV_PAR03+”‘” + STR_PULA
    cQryAux += “AND D2_CF = ‘”+MV_PAR05+”‘” + STR_PULA
    cQryAux += “AND D2_FILIAL <= '"+MV_PAR06+"' " + STR_PULA
    cQryAux := ChangeQuery(cQryAux)

  11. marcello disse:

    Alterado para:
    cQryAux += “SELECT D2_FILIAL, D2_CLIENTE, D2_ITEM, D2_SERIE, D2_CF, D2_DOC, D2_EMISSAO, D2_COD, B1_COD, D2_QUANT, D2_PRCVEN, D2_TOTAL, D2_TIPO, D2_TP, D2_CONTA, B1_BASE3, A1_GRPTRIB” + STR_PULA
    cQryAux += “FROM SD2010 A” + STR_PULA
    cQryAux += “INNER JOIN SB1010 B” + STR_PULA
    cQryAux += “ON A.D2_COD = B.B1_COD” + STR_PULA
    cQryAux += “AND A.D2_FILIAL = B.B1_FILIAL” + STR_PULA
    cQryAux += “INNER JOIN SA1010 C” + STR_PULA
    cQryAux += “ON A.D2_CLIENTE = C.A1_COD” + STR_PULA
    cQryAux += “AND A.D2_LOJA = C.A1_LOJA” + STR_PULA
    cQryAux += “–AND A.D2_FILIAL = C.A1_FILIAL” + STR_PULA
    cQryAux += “WHERE A.D_E_L_E_T_ = ” AND B.D_E_L_E_T_ = ”” + STR_PULA
    cQryAux += “AND D2_EMISSAO >= ‘”+Dtos(MV_PAR01)+”‘” + STR_PULA
    cQryAux += “AND D2_EMISSAO = ‘”+MV_PAR03+”‘” + STR_PULA
    cQryAux += “AND D2_CF = ‘”+MV_PAR05+”‘” + STR_PULA
    cQryAux += “AND D2_FILIAL <= '"+MV_PAR06+"' " + STR_PULA

    • Dan_Atilio disse:

      Então Marcello, foi aquilo que provavelmente você me mandou no e-Mail.
      Estava com um comentário no meio do trecho ( — ). Através disso, quando se usa o ChangeQuery e ele tira os -Enters-, ficou numa linha só, invalidando o resto do seu Where.
      Abraços.

  12. Túlio disse:

    Bom dia Dan, parabéns por compartilhar seu fonte me ajudou bastante,
    sou novato em advpl e estou com uma dúvida, como faço para totalizar um campo por agrupamento ?
    Att, Túlio

    • Dan_Atilio disse:

      Boa noite Túlio, tudo bem?
      Não entendi muito bem a dúvida, mas você pode criar TRFunctions que totalizam, e você pode passar qual é a célula, e inclusive qual é a quebra, caso queira totalizar pela quebra.
      Abaixo os parâmetros do método New, que eu conheço:

      oCell – Objeto da classe TRCell que o totalizador se refere
      cName – Identificação do totalizador
      cFunction – Função que será utilizada pelo totalizador. Exemplo: SUM, COUNT, MAX, MIN
      oBreak – Objeto da classe TRBreak que define em qual quebra o totalizador será impresso
      cTitle – Título do totalizador. Se não informado será utilizado o título da célula que o totalizador se refere
      cPicture – Máscara de impressão do totalizador. Se não informado será utilizado a máscara da célula que o totalizador se refere
      uFormula – Tipo Caracter: Expressão ADVPL para macro execução. Tipo Bloco de código: Bloco de Código com a expressão ADVPL para execução
      lEndSection – Se verdadeiro. Indica se totalizador será impresso na quebra de seção
      lEndReport – Se verdadeiro. Indica se totalizador será impresso no final do relatório
      lEndPage – Se verdadeiro. Indica se totalizador será impresso no final de cada página
      oParent – Objeto da classe TRSection que o totalizador se refere
      bCondition – Bloco de código com a condição de atualização dos valores do totalizador
      lDisable – Se verdadeiro. Define que não irá atualizar os valores do totalizador
      bCanPrint – Bloco de código com a condição de impressão dos valores do totalizador

      Espero ter ajudado.
      Abraços.

  13. Fernando Filho disse:

    Ele faz para duas sessão?

  14. Herique disse:

    Ele funciona na versão 12 ?

  15. Gilson disse:

    Bom dia,

    Dan,

    você tem este fonte para disponibilizar? Zreport ?

    Atenciosamente,

  16. Rafael Godoy disse:

    Fantástica ferramenta. Recomendo. Muito fácil de usar e relatórios prontos em menos de 10 min.

  17. Rodrigo Pedroso disse:

    Show em Atilio.
    Parabéns.

  18. Amigo meus parabéns excelente ajuda para todos, eu particularmente nunca me dei bem com os desenvolvimentos padrões do Protheus, utilizava o Ireports antes mas era muito trabalhoso configurar. você tem algum modelo no qual é possível fazer cabeçalhos roda-pés ?

  19. Ailton Alves Ferreira disse:

    Amigo, boa tarde!

    Consegui compilar o fonte e montar um relatório.
    Porém, percebo que quando executo a consulta diretamente no SQL SERVER, me informa um valor diferente de quando eu gero o relatório criado.

  20. Elisandro disse:

    Boa tarde
    Primeiramente quero parabenizar pela ferramenta, sou novo em advpl e está me ajudando a criar diversos relatórios.
    Não estou conseguindo exibir uma data no relatório no formato dd/mm/aaaa.
    Obrigado

  21. Henrique disse:

    Como dar cor ao totalizador?

  22. Edelmar Frazao disse:

    sensacional !! muito bom

  23. CLAUDIOMIRO disse:

    pessoal, tem alguma forma de colocar uma condicao no relatorio feito no Zreport para ficar conforme imagem no link ?

    https://drive.google.com/open?id=1HdVQ1g9HHHe8ntO-kiJ44fXNL5c2es-e

    • Dan_Atilio disse:

      +-, você teria que tratar no while da impressão. A ideia seria +- assim:
      1. Criar uma variável de controle, que a cada vez que o laço passar, verificar, se mudar os dados, atualizar a variável (por exemplo matrícula)
      2. Ao alterar a variável, dar um setPrint nas células para que possa ser feita a impressão
      3. Se a variável for igual ao conteúdo, dar um setPrint com textos “” para sair a impressão vazia

      Caso tenha dúvidas, pode nos mandar email ou entrar no nosso fórum no Discord que nós ajudamos.
      Grande abraço.

  24. Eduardo H. Rodrigues disse:

    Top Daniel;

    Teria como colocar um campo em formato de códigos de barras?

    Abraço

  25. neudo campos disse:

    Ótimo exemplo! Como faz para a quebra de seção seja antes do primeiro registro? Só vai a partir do seguindo registro da seção!

  26. Giancarlo disse:

    Boa tarde,
    Primeiramente parabéns pela ferramenta, têm-me sido muito útil!
    Uma dúvida, ela está preparada para a 27 do Protheus com dicionário no banco?
    Obrigado.
    Giancarlo

  27. Diego B disse:

    Primeiramente muito obrigado.. baita ferramenta.. ainda mais pra mim que estou começando no ADVPL
    Uma dúvida. Tem como eu colocar o nome de uma coluna variável? Por exemplo… quero fazer um relatório pegando os ultimos 12 meses… e 12 colunas teria que ficar com o nome da coluna teria q ficar o mês e ano…, tentei somente mudando ali no TRCell colocando o função de data atual mas não deu..
    EX: TRCell():New(oSectDad, “A1_QTD”, “QRY_AUX”, MONTH(DATE()), /Picture/, 15…..

    • Dan_Atilio disse:

      Boa tarde Diego, tudo bem?
      Obrigado pelo feedback.
      Até dá, existem duas formas, a mais fácil, seria mostrar uma tela de parâmetros com ParamBox, antes da chamada do ReportDef, e aí você conseguiria setar o nome das colunas com os meses.
      A outra forma, você teria que pegar o objeto da célula e alterar o title dela, mas como você comentou que está iniciando, tente a primeira alternativa.
      Qualquer dúvida, fico à disposição.

  28. LUCAS TEDINFO disse:

    Estamos 2021 e esse fonte não envelheceu, segue ajudando em novos relatórios.
    Muito obrigado

  29. Tiago Fonseca disse:

    Olá, tudo certo com vocês? essa é minha primeira interação por aqui, estou com um pouco de dúvidas no quesito perguntas, sei que foi a primeira coisa a ser respondida porém eu sou novo no Protheus, eu tenho um grupo de perguntas já, eu preciso colocar ele na query que vai no fonte? ou devo alterar o fonte posteriormente e inserir?
    se precisar ser na query eu vou precisar fazer um relatório de tipo de baixa, especifica pra um titulo, segue query:

    select E5_FILIAL,
    E5_DATA,
    e5_tipo,
    e5_prefixo,
    e5_numero,
    e5_parcela,
    (case when E5_TIPO’NCC’ then E5_VALOR else -E5_VALOR end) AS DACAO
    from SE5000 SE5
    WHERE SE5.D_E_L_E_T_=”
    AND E5_DATA between ‘20210801’ and ‘20210831’
    AND E5_RECPAG=’R’
    AND E5_MOTBX= ‘DAC’
    AND E5_SITUACA’C’

    • Bom dia Tiago, tudo sim graças a Deus e você?
      No caso, você aciona a sua pergunta através da função Pergunte() antes do relatório ser gerado.
      Ai dentro da sua query, você concatena os parâmetros, por exemplo, se tiver o parâmetro de data de/até, e eles forem os parâmetros MV_PAR01 e MV_PAR02 respectivamente, sua query nesse trecho ficaria:
      cQuery += “AND E5_DATA between ‘” + dToS(MV_PAR01) + “‘ and ‘” + dToS(MV_PAR02) + “‘ ”

      No caso, se quiser também, utilize o Autumn, nele é possível você usar seus parâmetros, veja um vídeo – https://youtu.be/thfA89QPFos

Deixe uma resposta para Dan_AtilioCancelar resposta

Terminal de Informação