Este tutorial ira demonstrar a integração do openRPT, um excelente gerador de relatórios, a um aplicativo Qt.
O openRPT é escrito em Qt, roda no Linux, Windows e Mac-Os, dos geradores de relatórios que eu experimentei e dentre aqueles mostrados no site, para mim é o melhor, mais flexível, mais fácil de usar e mais fácil de integrar ao aplicativo, e esta em constante desenvolvimento e atualização.
Ele se conecta ao PostgreSql, Oracle e ODBC, tem suporte a codigo de barras e graficos, e orientado por faixas ou seções, a semelhança do Kugar ou do Quickreport.  Exporta para PDF.

O site oficial é:

http://www.xtuple.com/openrpt/

Download:

http://sourceforge.net/projects/openrpt/files/

Documentação:

http://www.xtuple.org/docs/openrpt

http://mirrors.isc.org/pub/postgresql/projects/pgFoundry/openrpt/OpenRPT_UserGuide_011106.pdf

Guia do usuario

Vamos começar a partir do ultimo tutorial sobre relatórios, o do Agata Report, com base neste tutorial iremos acrescentar uma nova classe para gerar os relatórios do openRPT.
Abra aqui os fontes do aplicativo.
Abra no Designer o arquivo fClientes_Parent.ui, que é a janela principal do nosso aplicativo, nela iremos acrescentar mais um QpushButton, vamos chama-lo de botao_openRPT:

Abaixo:Janela principal com botão openRPT.(Clique na imagem para ampliar).

>Janela principal com botão openRPT

Feito isso vamos criar uma nova janela que sera responsável por chamar o openRPT e passar os parâmetros ao relatório.
No Designer, crie um novo Qwidget e chame-o de fAntRelOpenRPT_Parent, nele você ira colocar:
Dois QgroupBox.
Quatro QradioButton.
Um CheckBox.
Dois QpushButton.
Um QComboBox. Salve-o com o nome de fAntRelOpenRPT_Parent.ui

Abaixo, a janela no Designer:(Clique na imagem para ampliar).

>a janela no Designer

Veja na figura abaixo o Object Inspector com os nomes.(Clique na imagem para ampliar).

>Object Inspector com os nomes.

Abaixo, as propriedades do QWidget fAntRelOpenRPT_Parent

>propriedades do QWidget fAntRelOpenRPT_Parent

Agora, abra o Kdevelop e no src.pro adicione em FORMS o nome do arquivo fAntRelOpenRPT_Parent.ui:

FORMS += fClientes_Parent.ui \
         fAnt_rel_Agata_Parent.ui \
         fAntRelOpenRPT_Parent.ui


Compile e sera gerado o arquivo ui_fAntRelOpenRPT_Parent.h.
Agora, no Kdevelop vamos criar o header(.h) e o source(.cpp) da classe que iremos criar para o openRPT.
No menu do Kdevelop, vá em Arquivo->Novo e escolha a opção C/C++ header, de o nome de fAntRelOpenRPT.h, desmarque o checkbox “Adicionar ao projeto”, prefira faze-lo manualmente editando o src.pro.
Repita a operação para criar o source(fonte), escolha no dialogo a opção C++ source(.cpp) e de o nome de fAntRelOpenRPT.cpp, novamente mantendo o checkbox desmarcado.

Abaixo, o fAntRelOpenRPT.h:

/***************************************************************************
 *   Copyright (C) 2009 by Rodolfo Ribeiro Machado   *
 *   rodolfo@Programador   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef FANTRELOPENRPT_H
#define FANTRELOPENRPT_H

#include "ui_fAntRelOpenRPT_Parent.h"

class QProcess;
class QFile;
class QButtonGroup;
class QSqlQuery;
class QComboBox;

class fAntRelOpenRPT:public QWidget,private Ui::fAntRelOpenRPT_Parent
{
  Q_OBJECT
  public:
    fAntRelOpenRPT(QWidget* parent=0);
    ~fAntRelOpenRPT();

  private:
    QButtonGroup* radio_Grupo_Ordem;//Para ordenar a consulta ao banco
    QButtonGroup* radio_grupo_Formato;//Para  escolher entre o formato default e PDF

    QProcess* chama_openRPT;//Para chamar o rptRender
    QFile* arq_Anterior;//Para excluir arquivos antigos.

    QComboBox* combo_codigo_Clientes;//Para filtrar o relatório por cliente.
    QSqlQuery* query_Clientes;

  private slots:
    void gera_rel_openRPT();//Para gerar o relatório, passar os parâmetros.
    void trava_libera_filtro();

};



#endif



Abaixo, o fAntRelOpenRPT.cpp:

/***************************************************************************
 *   Copyright (C) 2009 by Rodolfo Ribeiro Machado                         *
 *   rodolfo@Programador                                                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "fAntRelOpenRPT.h"
#include <QDesktopWidget>
#include <QSettings>
#include <QFile>
#include <QProcess>
#include <QMessageBox>
#include <QSqlQuery>
#include <QComboBox>
#include <QTextStream>

fAntRelOpenRPT::fAntRelOpenRPT(QWidget* parent)
{
  setupUi(this);

  this->setAttribute(Qt::WA_DeleteOnClose,true);//Para a janela se auto-destruir;

  QRect rect = QApplication::desktop()->availableGeometry(this);

  this->move(rect.center() - this->rect().center()); //para centralizar na tela.

  this->setFixedSize (this->size()); //para não minimizar a janela.


  radio_Grupo_Ordem=new QButtonGroup(this);//cria o QbuttonGroup
  radio_Grupo_Ordem->setExclusive(true);//clicou em um, desmarcou o outro
  radio_Grupo_Ordem->addButton(botao_Codigo);//adiciona o RadioButton ao QbuttonGroup
  radio_Grupo_Ordem->setId(botao_Codigo,0);// indice do RadioButton dentro do QbuttonGroup
  radio_Grupo_Ordem->addButton(botao_Nome);
  radio_Grupo_Ordem->setId(botao_Nome,1);

  radio_grupo_Formato=new QButtonGroup(this);//Para escolher o formato, se PDF ou default.
  radio_grupo_Formato->setExclusive(true);
  radio_grupo_Formato->addButton(botao_Default);
  radio_grupo_Formato->setId(botao_Default,0);
  radio_grupo_Formato->addButton(botao_PDF);
  radio_grupo_Formato->setId(botao_PDF,1);
  

  connect(botao_Imprimir,SIGNAL(clicked()),this,SLOT(gera_rel_openRPT()));

  chama_openRPT = new QProcess(this);//para criar o objeto Qprocess
  arq_Anterior=new QFile(this);

  combo_codigo_Clientes=new QComboBox(this);//Cria e preenche o combobox com os valores do campo nome da tabela clientes no banco de dados, cria um segundo combo não visivel com os codigos.
  combo_codigo_Clientes->setVisible(false);
  query_Clientes=new QSqlQuery;
  query_Clientes->exec("select codigo,nome from clientes order by nome");
  while (query_Clientes->next())
  {
    combo_Clientes->addItem(query_Clientes->value(1).toString(),query_Clientes->value(1).toString());
    combo_codigo_Clientes->addItem(query_Clientes->value(0).toString(),query_Clientes->value(0).toString());
  }
  connect(check_Clientes,SIGNAL(stateChanged(int)),this,SLOT(trava_libera_filtro()));
}

fAntRelOpenRPT::~fAntRelOpenRPT()
{
  delete chama_openRPT;
  delete radio_Grupo_Ordem;
  delete radio_grupo_Formato;
  delete arq_Anterior;
}

void fAntRelOpenRPT::gera_rel_openRPT()
{
  QString arq_Modelo,arq_Saida,form_Arq,ext_Arq,nomeScript;
  QString hostname,databasename,user_Name,user_Password,arq_Antigo;
  QString openRPT,caminho_Relatorios,aplicativo_Saida;

  user_Name=QSqlDatabase::database().userName();//Para pegar o nome e a senha do usuario e passa-la ao openRPT para ele se conectar ao banco.
  user_Password=QSqlDatabase::database().password();


  //O codigo ira montar algumas strings para passar como parametro.
  QString caminho=QCoreApplication::applicationDirPath();//Acha o caminho do binario, no mesmo diretório esta o arquivo config.txt
  caminho.append("/config.txt");

  QSettings settings(caminho,QSettings::IniFormat);//abre o arquivo de configuração.
  caminho_Relatorios=settings.value("caminhos/relatorios").toString();//pega o caminho dos relatorios

  hostname=settings.value("banco/hostname").toString();
  databasename=settings.value("banco/databasename").toString();


  arq_Antigo=caminho_Relatorios;//para excluir relatórios antigos

  if (radio_grupo_Formato->checkedId()==1)//testa o formato do relatório
  {
    aplicativo_Saida=settings.value("caminhos/pdf").toString();
    form_Arq="pdf";
    ext_Arq="pdf";
    arq_Antigo.append("/clientes.");
    arq_Antigo.append(ext_Arq);
    if (arq_Anterior->exists(arq_Antigo))
    {
      #ifdef Q_OS_UNIX//Para diferenciar Linux de Windows, shell script de batch do DOS.
        arq_Antigo.prepend("rm ");
      #endif

      #ifdef Q_OS_WIN
        arq_Antigo.prepend("del ");
      #endif

      chama_openRPT->start(arq_Antigo);
      chama_openRPT->waitForFinished();
    }
    arq_Saida=caminho_Relatorios;//monta a string que representa o arquivo gerado
    arq_Saida.append("/clientes.");
    arq_Saida.append(ext_Arq);
  }
 
  arq_Modelo=caminho_Relatorios;
  if (check_Clientes->isChecked())//Testa se foi filtrado por cliente.
  {
    arq_Modelo.append("/clientes_filtrado.xml ");
    nomeScript=settings.value("scripts/openRPTfiltrado").toString();
  }
  else
  {
    if (radio_Grupo_Ordem->checkedId()==0)//testa se é por ordem de codigo ou nome
      arq_Modelo.append("/clientes_codigo.xml ");
    else
      arq_Modelo.append("/clientes_nome.xml ");
    nomeScript=settings.value("scripts/openRPT").toString();
  } 


  //parametros openRPT
  QString host_banco;
  host_banco="-databaseURL=psql://";
  host_banco.append(hostname);
  host_banco.append("/");
  host_banco.append(databasename);
  host_banco.append(":5432 ");

  user_Name.prepend("-username=");
  user_Password.prepend(" -passwd=");

  QString pdf="";
  QString tipo_Print="";
  
  if (radio_grupo_Formato->checkedId()==1)//Se for escolhido pdf,cria o arquivo pdf, senão, chama o preview.
  {
    pdf=" -pdf -outpdf=";
    pdf.append(arq_Saida);
  }
  else
    tipo_Print=" -PrintPreview";
  
  QString close=" -close ";
  
  QString parametro;
  if (check_Clientes->isChecked())//Se for filtrado, passa o codigo do cliente como parâmetro ao openRPT.
  {
    QString cod_Cliente;
    combo_codigo_Clientes->setCurrentIndex(combo_Clientes->currentIndex());
    cod_Cliente=combo_codigo_Clientes->currentText();
    parametro=" -param=cod_cli:int=";
    parametro.append(cod_Cliente);
  }
  else
    parametro="";

  QStringList a;
    a<<host_banco<<user_Name<<user_Password<<parametro<<tipo_Print<<pdf<<close<<arq_Modelo;//esta stringlist é passada como parametro
  QString retorno;
  caminho_Relatorios.append("/");
  caminho_Relatorios.append(nomeScript);


  #ifdef Q_OS_UNIX //Se Linux,chama o shell script com as strings como parametros.
    chama_openRPT->start(caminho_Relatorios, a);
  #endif

  #ifdef Q_OS_WIN //Se Windows,cria e chama o batch do DOS.
    openRPT=settings.value("caminhos/openRPT").toString();
    QFile file(caminho_Relatorios);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
      return;

    QTextStream out(&file);
    out <<openRPT<<" "<<host_banco<< user_Name<<user_Password<<parametro<<tipo_Print<<pdf<<close<<arq_Modelo << "\n";
    file.close();
    QString retorno;
    QStringList argumento;
    argumento<<"";
    chama_openRPT->start(caminho_Relatorios,argumento);//chama o batch, sem parametros, já que em um batch do DOS não se pode passar o caracter "=" como parâmetro,pois o DOS considera o "=" como delimitador.
  #endif


  chama_openRPT->waitForFinished();

  retorno=chama_openRPT->readAllStandardOutput();//retorna a linha do console

  QMessageBox::information(0,"Relatório de clientes",retorno);

  if (radio_grupo_Formato->checkedId()==1)
  {
    QStringList saida;
    saida<<arq_Saida;
  
    chama_openRPT->start(aplicativo_Saida,saida);//para cada formato de arquivo, pdf, html, txt etc, o arquivo config.txt tem de ter o aplicativo correspondente que ira abrir o arquivo.
  }
}

void fAntRelOpenRPT::trava_libera_filtro()
{
  if (check_Clientes->isChecked())
    combo_Clientes->setEnabled(true);
  else
    combo_Clientes->setEnabled(false);
}


Vou comentar o código:
No constructor criamos dois QbuttonGroup para agruparmos e administrarmos os radio botões, conectamos o botão imprimir a função que gera os relatórios, fazemos uma consulta ao banco para preenchermos um combo box com os nomes dos clientes e outro combo, que ficara invisível e guardara os códigos dos clientes, os dois serão sincronizados e caso o usuário resolva filtrar o relatório, o código sera usado.
A função gera_rel_openRPT() tem a função essencial de passar parâmetros ao rptRender, que é o responsável por mostrar o relatório, seja através de preview ou imprimi-lo diretamente ou ainda gerar um arquivo pdf.

A lógica de funcionamento do openRPt é a seguinte, você monta os relatórios no próprio openRPT, que é a ferramenta de designer, salva estes mesmos relatórios num diretório da sua escolha, no formato xml, se precisar passar parâmetros à consulta, você pode testa-los no metaSQL e por fim para chamar o relatório que é o arquivo xml a partir de um aplicativo externo ao openRPT, você chama o rptRender, que precisa de dois tipos de parâmetros, os básicos, que sempre serão utilizados, que são os parâmetros de conexão ao banco, username, password, hostname, databasename etc, o caminho do arquivo xml e os parâmetros da própria consulta SQL ao banco, estes podem ou não estar presentes, depende do tipo da consulta, sé é uma simples listagem da tabela inteira ou se a algum filtro na consulta. Ex:

-databaseURL=psql://localhost/projetoqt:5432 -username=rodolfo -passwd=001122 -PrintPreview -close /home/rodolfo/sistemaqt/relatorios/clientes_codigo.xml

Se você compilar o aplicativo no Linux, eu criei um shell script que recebe estes parâmetros e chama o rptRender, a finalidade disso é usarmos os recursos do sistema operacional, o poder do Bash no Linux para termos mais controle sobre o processo e evitarmos algum problema.

No caso de você compilar no Windows®, usaremos um batch file do DOS, com a diferença de que ele não recebera parâmetros, porque no batch file o caracter “=” e interpretado como um delimitador, por isso nós iremos criar, de dentro do aplicativo Qt, usando Qfile,um arquivo totalmente novo, contendo dentro dele tod a linha com os parâmetros, ao invés de passar os parâmetros, depois é só chamar o batch file usando Qprocess.
Veja que se você quiser não usar shell script ou batch file é perfeitamente possível, eu uso para ter um maior controle.
No inicio da função temos a declaração de varias variáveis Qstring que irão receber os valores dos parâmetros, parte destes parâmetros já esta definida no arquivo config.txt que esta junto ao binário.
Após isto lemos o arquivo config.txt, atribuímos os valores as variaveis e em seguida testamos o formato do relatório, se sera default ou pdf, se for pdf verificamos se já existe algum arquivo com o mesmo nome no diretório, se sim ele é excluído e é atribuído valor as variáveis que representam a extensão do arquivo(pdf) e o utilitário que ira abri-lo(Kpdf, Adobe etc).

Veja que a uma diretiva de compilação para separar o código compilado no Linux do código compilado no Windows®, que são os comando rm do Linux e del do DOS.
É chamado então uma funçaõ para excluir o eventual arquivo antigo.
Depois é feito um teste para saber se o usuário quer uma listagem completa da tabela de clientes ou se ele vai escolher apenas um cliente, para cada caso é preciso criar um arquivo xml diferente no openRPT, se não for filtrado testa-se se a consulta é por ordem de código ou nome, da mesma forma é preciso um arquivo xml para cada um.

Depois, a uma seqüência de atribuição de valores a variáveis, novamente um teste se o formato é pdf ou default, desta vez para sabermos se sera chamado o preview ou não.
Depois, testa se foi filtrada a consulta, se sim passa-se o código do cliente escolhido.
Agora, finalizando, monta-se uma QstringList com todos os parâmetros que sera passada a função Qprocess e também o caminho do shell script ou batch file do DOS.
Então ambos os parâmetros são passados a função da Qt Qprocess, o caminho do script e todos os parâmetros do openRPT concatenados em uma QstringList.

Novamente a as diretivas de compilação para testar o OS e char o shell script ou criar o batch file do DOS. Repare que no caso do DOS o argumento é vazio, “”, os parâmetros já estão dentro do arquivo. Aqui nós não fizemos, mas você pode escolher, na opção default, enviar direto para a impressora.

Se foi escolhido pdf, em ambos os sistemas , Linux e Windows®, o rptRender sabe o que fazer, os parâmetros informam a ele se é para chamar o preview do relatório default ou se é para criar um arquivo pdf. Se foi escolhido o pdf, em seguida tem a chamada do aplicativo padrão do sistema para visualizar pdf que você deve colocar o caminho no arquivo config.txt.
Isto finaliza a parte do aplicativo, propriamente dito, que lida com o openRPT, você deve conectar ,em cadastro.cpp, o botão que chama a janela fAntRelOpenRPT a uma função que instancia a janela:

connect(botao_openRPT,SIGNAL(clicked()),this,SLOT(gera_Relatorio_openRPT()));

void fCad_Clientes::gera_Relatorio_openRPT()
{
  fAnt_openRPT=new fAntRelOpenRPT(this);
  fAnt_openRPT->show();
}


Nos fontes você tem os arquivos completos:

Fontes do aplicativo

O batch do DOS o aplicativo cria, aqui, o shell script:

#!/bin/bash
if [ -e /mnt/disco2/Recursos_Kdevelop_QTDesigner/relatorios/openRPT/openrpt-3.1.0/rptrender ]; then
  if [ -z $1 ] ;then
    echo "Verifique os parâmetros do relatório";
    echo "Especifique o caminho do modelo do     relatório.Ex:/home/sistemaqt/relatorios/clientes...";
    echo "Especifique o formato do relatório.Ex: pdf, txt, xml, html, csv, sxw";
    echo "Especifique o caminho de saida do relatório.Ex: Ex:/home/vendas/relatorios/cidades.pdf";
   else
     echo $1 $2 $3 $4 $5 $6 $7 $8;
     if /mnt/disco2/Recursos_Kdevelop_QTDesigner/relatorios/openRPT/openrpt-3.1.0/./rptrender $1 $2 $3 $4 $5 $6 $7 $8; then
       echo Gerando relatório;
     else
       echo Nâo foi possivel gerar o relatório.;
     fi;
  fi;
else
  echo /mnt/disco2/Recursos_Kdevelop_QTDesigner/relatorios/openRPT/openrpt-3.1.0/rptrender não esta instalado!;
fi; 


Vamos agora a uma breve introdução ao openRPT, na documentação dele você tem mais exemplos de como fazer.
A instalação é muito simples, tanto no Linux como no Windows®, ele vem pré-compilado, é só extrair o arquivo compactado num diretório da sua preferencia e fazer os testes.
A tela principal do openRPT é esta:(Clique na imagem para ampliar).

>openRPT

Esta, portanto, é a ferramenta de designer, onde você fara a conexão com o banco, montara sua consulta e desenhara o relatório.
No menu database->conect to database você faz a conexão com o banco, no botão Options abre-se um dialogo para configurar a conexão:

>openRPT tela de login.

No menu File->New File você começa a criar seu relatório,em Open File você abre arquivos já existentes, lembre-se que o openRPT salva por padrão no formato xml.

Abaixo, o relatório de cidades:(Clique na imagem para ampliar).

>openRPT relatório de clientes.

No menu Document->Query Sources você monta as consultas ao banco:(Clique na imagem para ampliar).

>openRPT lista de queryes.

Nos botões add ou edit você monta as consultas:(Clique na imagem para ampliar).

>openRPT consultas.

Como disse anteriormente, no caso de consultas parametrizadas você deve criar um arquivo separado, abaixo a consulta do relatório parametrizado:(Clique na imagem para ampliar).

>openRPT consulta parametrizada.

Sobre isso consulte a seção meta-sql na documentação do openRPT.
No menu Document->Section Editor você insere as bandas ou faixas:(Clique na imagem para ampliar).

>openRPT section editor.

Os demais componentes, labels, campos, textos, linhas, codigos de barra etc estão todos disponíveis na barra de ferramentas do openRPT.

No link abaixo você pode baixar os dois arquivos xml do tutorial e mais um arquivo de exemplo que cria uma tabela com 65 registros, um cadastro de cidades, e um relatório de cidades agrupadas por estado para você testar:

Arquivos de exemplo openRPT

Para criar as tabelas do tutorial no banco olhe os tutoriais anteriores no qual este foi baseado:

Tutoriais

Quando você tiver montado seu relatório acessando a tabela clientes no banco projetoqt, compile o aplicativo e rode:
Abaixo, a aplicativo com a tela de configuração do openRPT e , se me permitem uma licença poética, uma bela nave Soyuz ao fundo:(Clique na imagem para ampliar).

>openRPT e aplicativo.

Abaixo, o preview do relatório:(Clique na imagem para ampliar).

>openRPT preview.

Abaixo, o relatório em pdf:(Clique na imagem para ampliar).

>openRPT e pdf.


Tutorial anterior:Integrando o Agata Report a um aplicativo Qt
Próximo Tutorial: Compilando a Qt no Windows®

Pagina inicial


Comentários:


Nenum comentário

Deixe seu comentário:


 *
 *

 *
   Campos marcados com * são obrigatórios.