vamos aprender a criar relatórios agrupados com o QuickReport,  utilizando apenas uma tabela. Este artigo é destinado a iniciantes em  relatórios com QuickReport, e para quem utiliza componentes da palheta  IBX (Interbase) para o acesso a dados.
Há muito tempo atrás, em alguma galáxia bem distante.....
 
O tal relacionamento de tabelas diz que para uma base de dados inteligente   e eficiente, deve-se ter o mínimo de campos dentro das tabelas, ou seja,   apenas os essenciais, para não pesar o sistema, isso é importantíssimo,   tanto que todos nós quando criamos um programa de pedidos por exemplo, temos 4 tabelas essenciais contendo no mínimo esses campos:
 Tabela Clientes:
  Cod_Cli
  Nm_Cliente
  Endereco
Tabela Produtos:
  Cod_Prod
  Descricao
  Vl_Unit
  Q_Estoque
Tabela Pedidos:
  Cod_Ped
  Cod_Cli
  Data
  Vl_Total
Tabela Itens_Pedido:
  Cod_Ped
  Cod_Cli
  Cod_Prod
  Nm_Produto
  Quant
  Vl_Itens
 Veja, que a ligação entre elas são os campos de códigos   (ID), a tabela clientes se relaciona com a tabela de pedidos que por sua vez   se relaciona com a tabela itens de pedidos, a qual tem um campo que guarda   o código do cliente e o código do produto. Isso é relacionamento de tabelas! Pergunta: pra que isso?
 
Para mostrar que, para se criar um relatório eficiente, é preciso   primeiro saber quais campos se tem nas tabelas e quais você vai querer   impressos em seus relatórios. Isso chama-se planejamento. Pode poupar   grande tempo na hora de criar softwares. Antes de ir para linha de código,   planeje  o máximo possível. Também podemos criar   uma tabela para guardar serviços faturados, clientes pré-cadastrados   que executam serviços pagos no decorrer do mês, contendo apenas   campos essenciais para consulta como:
 COD_PEDIDO / CLIENTE / DATA / SERVICO / QUANT / VALOR
 Ou seja, em uma mesma tabela, temos o nome completo do cliente, a data da   compra, o tipo do produto, a quantidade e o subtotal do item. Claro que em   uma tabela comum, temos até mais campos, como por exemplo um campo booleano   que irá controlar se o acúmulo de serviços do cliente   já foi pago ou não, e, o nome do cliente muitas vezes não   se tem, o que se tem é apenas o código do cliente. Para   facilitar esse exemplo, vamos considerar que na mesma tabela tenhamos estes   campos. Em   outro artigo estarei mostrando como montar um formulário Mestre/Detalhe com o relacionamento de 3 tabelas.
 
  Agrupamento em apenas 1 tabela 
 
Inicie um novo projeto no delphi, deixe o nome do form principal como Form1   mesmo, salve a Unit como Ureport e o projeto como Preport. Adicione um botão   e um componente DateTimePicker da palheta Win32. Adicione também  os   seguintes componentes da palheta Interbase: 1 IBDatabase, 1 IBTransaction e   IBQuery. Configure-os de acordo com a sua base de dados.
 
 
Vamos partir para a criação do relatório propriamente dito – ATENÇÃO PARA OS DETALHES.
 
Vá em File/New/Other e escolha Report.
 
O delphi irá criar um novo formulário já com um componente   QuickReport todo configurado. Configure o relatório com o nome de Qr1   (propriedade Name) e salve a Unit como UrelAG. Pronto, vamos começar   a configurar nosso relatório.
 
Para testarmos o exemplo durante o desenvolvimento, antes de mais nada, adicione   uma IBQuery da palheta Interbase no form do relatório (QR1) e configure as seguintes propriedades:
   DataBaseName: IBDatabase1
  SQL: Select * from ItensPedidos
  Active: true;
 Lembre-se: se estiver usando algum DataModule, não esqueça de   colocar no DatabaseName da Ibquery o endereço completo (exemplo: dm1.IBDataBase1).   Caso não esteja aparecendo na propriedade DatabaseName da Ibquery o   caminho do DataModule, basta ir à unit do relatório, e após   a palavra implemention escreva a seguinte linha:
Isso irá vincular a sua unit do relatório (UrelAG) ao Datamodule   que contém todos os seus componentes de acesso a dados. Veja se o nome   da unit do seu datamodule está igual a esse, senão, coloque o nome certo.
 
 Na propriedade SQL da IBQuery, colocamos nada mais que uma   simples declaração sql para trazer todos os campos da tabela   ItensPedidos para o mesmo, assim, quando colocar algum Qrdbtext no relatório   e posicionar o Dataset dele apontando para nossa Ibquery, poderá utilizar   a propriedade DataField para indicar qual campo esse Qrdbtext irá representar. Mais à frente isso ficará mais claro.
 
Importante: No relatório, aponte a propriedade DATASET   do RELATÓRIO   para a Ibquery do relatório. Não esqueça disso, senão   não irá funcionar.
 
  Adicione um componente QrBand da palheta Qreport, altere a propriedade BandType     para rbGroupFooter (Atenção, apartir daí o nome da QRBand     vai aparecer como GroupFooter, não se espante, estou apenas alertando para que não haja confusão), e adicione um QRLabel.
 
Adicione um QrGroup e na sua propriedade FooterBand coloque QRBand1, na   propriedade Expression coloque IBQUERY1.CLIENTE. Isso fará a ligação   dos grupos, o sistema saberá que o campo cliente é que vai fazer   o agrupamento, esse é o segredo!
 
Coloque dentro do QrGroup, um QRDBtext; aponte sua propriedade dataset para   a Ibquery e DataField para CLIENTE. Para ficar melhor destacado, altere na propriedade Font do QRDBtext, o tamanho e estilo da fonte (Negrito).
 
Adicione um QrSubdetail, e dentro dele, 4 qrdbtext, apontando o dataset para   a ibquery, e a propriedade dataField de cada uma deles para os campos DATA,   SERVICO, QUANT e VALOR, respectivamente. Arrume-os um ao lado do outro como preferir.
 
Nesse momento, seu relatório já está agrupando   todos os itens através dos clientes. Para testar, apenas dê um   preview no relatório e verá todos os clientes com seus respectivos   itens abaixo. Lembre-se: para funcionar a Ibquery do relatório deve   estar com a propriedade Active igual a True. O resultado será algo mais ou menos assim:
 CLIENTE 1
  12/04/2006 CAMISA 1  25,00
  13/04/2006 BOLSA  1  12,00
  14/04/2006 CALÇA  3 120,00
CLIENTE 2
  13/04/2006 BOLSA  2  24,00
  14/04/2006 CALÇA  2  80,00
 Para testar isso em RunTime (tempo de execução), vc precisará mudar o dataset   de TODOS OS COMPONENTES (QrBand, QrGroup, QuickReport, QRDBText´s) que   estão   aqui para uma query externa, alguma query que esteja em algum form ou   em datamodule.   Em nosso caso será a Ibquery1 do Form1. Para isso, mude todos os datasets de todos os componentes contidos no Qr1 para Form1.Ibquery1.
 
Na propriedade   Expression do componente QrGroup, não precisa colocar Form1.Ibquery1.CLIENTE.   Apenas deixe IBQuery1.CLIENTE. O componente irá procurar no sistema   todo, a primeira query que ele encontrar com esse nome e já irá agrupar.   Por isso recomendo usar uma Ibquery somente para isso, com um nome específico,   tipo IBQueryItensPed. Isso evitará maiores transtornos futuros. No botão que fará a consulta digite o seguinte comando:
 var
  C : string;
begin
  C:='Select * from ItensFiados Order By Cliente';
  IBQuery1.SQL.Clear;
  IBQuery1.SQL.Add(C);
  IBQuery1.Open;
  if IBQuery1.EOF = False Then
  Begin
    qr1.preview;
  end;
end; Note que usei uma variável string típica para guardar a declaração,   e depois enviar tudo para a propriedade SQL da Ibquery, que se encontra no   form principal, e não na Ibquery que está no Report (Qr1). Pode-se   colocar qualquer coisa na variável como uma consulta por dia, mês   ou período, é só deixar a imaginação fluir.   Exemplo:
   C := 'Select * from ItensFiados where (Data = '+
       #39 + DatetoStr(Dt1.Date) + #39 + ') ' +
       ' Order By Cliente'; Digite uma data no DateTimePicker do form que já contenha registros   na tabela e pronto, ele irá buscar através do dia. Claro que   o campo data da tabela ItensFiados é do tipo Date, não se esqueça   disso!
 
Bom, aí já temos nosso agrupamento por cliente. Ele irá mostrar   todos os clientes que fizeram compras e os respectivos produtos que cada um comprou, ordenado pelo cliente, mas falta alguma coisa:
 
Um subtotal de cada cliente e um total ao final da folha
 
Muitos me disseram para usar o componente Qrexpr da palheta Qreport. Lí sobre   ele no forum aqui do próprio site mas vou falar que eu tentei, fiz de   tudo para ele fazer o cálculo e não funcionou. Apenas consegui   fazê-lo   funcionar em modo de criação (preview do QuickReport dentro do   delphi). Então, um amigo, Danilo Tielles (danilotielles@hotmail.com),   me ajudou com uma dica muito legal, e por isso os créditos são   todos para ele:
 
Declare duas variáveis públicas no relatório (Qr1).
   public
    vlsub, vltot: double; Essas variáveis servirão para guardar os valores encontrados,   lembre-se: estamos trabalhando com valores (dinheiro, moeda), então   usamos as variáveis do tipo double. Pode-se usar qualquer tipo de variável,   não se prenda apenas a esse exemplo.
 
No relatório, de um duplo clique e irá aparecer a tela de configurações   do report. Procure pela opção Sumary e marque seu checkbox.   Será adicionado ao relatório uma nova banda chamada Sumary.   Adicione um QrLabel a esta banda que ficará com o nome de Qrlabel2.   Agora vamos aos comandos:
 
Iremos programar as propriedades BeforePrint das bandas conforme abaixo, siga atentamente a ordem:
 procedure TQR1.PageHeaderBand1BeforePrint(Sender: TQRCustomBand;
  var PrintBand: Boolean);
begin
  vltot:=0;
end;
procedure TQR1.QRGroup1BeforePrint(Sender: TQRCustomBand;
  var PrintBand: Boolean);
begin
  vlsub:= 0;
end;
procedure TQR1.QRSubDetail1BeforePrint(Sender: TQRCustomBand;
  var PrintBand: Boolean);
begin
  vlsub:= vlsub+StrtoFloat(Form1.IBQuery1.fieldbyname('Valor').AsString);
  vltot:= vltot+StrtoFloat(Form1.IBQuery1.fieldbyname('Valor').AsString);
end;
procedure TQR1.QRBand1BeforePrint(Sender: TQRCustomBand;
  var PrintBand: Boolean);
begin
  qrlabel1.Caption:= 'Total do Cliente: '+FormatFloat('R$ #,##0.00', vlsub);
  qrlabel2.Caption:= 'Total: '+FormatFloat('R$ #,##0.00', vltot);
end; Explicação rápida:
 
Em primeiro, zeramos a variável VlTotal, porque ela irá mostrar   o total no final da folha, e  precisamos zerar ela somente uma vez,   quando iniciamos o relatório;
Em segundo, zeramos a variável VlSub, pois a cada agrupamento, deve   ser zerado o campo VAOR, para começar a somar de novo, senão   ele irá acumular   os valores de todos os clientes consecutivamente, ou seja, ele irá somar   os ítens do primeiro com os do segundo cliente e assim por diante.
Em terceiro, dizemos para as variáveis quais campos ela deverá somar.   Nesse caso será o campo VALOR da tabela ItensPedidos, e como o QrSubdetail   se repete conforme acha alguma informação na tabela, ele irá somar   até o final dos itens de cada cliente.
O quarto e último não   precisa de muitos esclarecimentos. Ele irá exibir o valor das variáveis   no formato moeda nos QrLabel´s.