Artigo Clube Delphi Edição 12 - Relatório com Múltiplas Quebras
Artigo da Revista Clube Delphi Edição 12.
Atenção: por essa edição ser muito antiga não há arquivo PDF para download. Os artigos dessa edição estão disponíveis somente através do formato HTML.
Relatório com Múltiplas Quebras
Na minha opinião, o QuickReport é uma ferramenta excelente para a criação de relatórios com o Delphi. Considero-o bastante poderoso devido a sua flexibilidade na manipulação de eventos e componentes. Porém, muitos usuários, por desconhecerem o funcionamento da ferramenta, se contentam com relatórios sem muita complexidade ou se rendem as famosas "marretas" para forçar um determinado resultado. Este tipo de técnica (?), na maioria dos casos, pode ser evitada simplesmente alterando algumas propriedades.
Para exemplificar isso, vamos criar um relatório que, apesar de pequeno, possui uma estrutura que servirá perfeitamente como referência para vários outros relatórios maiores e mais complexos. Nosso relatório abrange conceitos como agrupamentos, múltiplos níveis, subtotais, totais, e possui a seguinte hierarquia:
figura1
Antes de iniciar a construção do relatório, crie as tabelas necessárias para este exemplo, conforme a listagem abaixo:
EMPRESA.DB
CodEmpresa +*
NomeA50
FUNCIONARIO.DB
CodFuncionario+*
CodEmpresa I
NomeA50
Salário$
FILHO.DB
CodFilho+*
CodFuncionario I
NomeA
As tabelas se relacionam da seguinte forma:
[gráfico]
Crie um alias para o diretório no qual as tabelas foram salvas, nomeando-o qrExemplo. Vamos agora iniciar a construção do relatório:
Em um novo formulário do QR insira dois objetos TQuery (palheta data access), quatro objetos TQRBand (palheta QReport), um objeto TQRGroup (palheta QReport) e um objeto TQRSubDetail. Configure suas propriedades conforme a listagem a seguir:
Query1
DatabaseNameQRExemplo
SQLselect
empresa.codempresa, empresa.nome as nomeempresa,
funcionario.codfuncionario, funcionario.nome as nomefuncionario,
funcionario.salario
from empresa, funcionario
where funcionario.codempresa = empresa.codempresa
order by nomeempresa, nomefuncionario
Query2
DatabaseNameQRExemplo
SQLselect nome
from filho
where codfuncionario = :MCodFunc
order by nome
Nota: É importante definir o tipo do parâmetro (MCodFunc) declarado na query acima, que será Integer (ftInteger). Para isto, clique na propriedade Params, selecione o item McodFunc e altere a propriedade
DataType.
QuickReport
DataSet Query1
ReportTitleRelação de Empresa/Funcionário/Dependente
QRBand1
BandTyperbPageHeader
Height32
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom TRUE
QRBand2
BandTyperbDetail
HasChildTrue
Height17
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom FALSE
ChildBand1
Frame.DrawTopFALSE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom FALSE
QRBand3
BandTyperbGroupFooter
Color$00DFDFDF
HasChildTrue
Height17
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom TRUE
ChildBand2
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom TRUE
QRBand4
BandTyperbSummary
Height32
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom FALSE
QRGroup1
Color$00DFDFDF
ExpressionQuery1.CodEmpresa
FooterBandQRBand3
Height22
Frame.DrawTopTRUE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom TRUE
Nota: O QRGroup é a band responsável pela quebra do relatório. Portanto, o valor definido na propriedade Expression é considerado a chave dos agrupamentos.
QRSubDetail1
DataSetQuery2
Height14
Frame.DrawTopFALSE
Frame.DrawLeftTRUE
Frame.DrawRightTRUE
Frame.DrawBottom FALSE
Ao final desta etapa nosso relatório ficará basicamente com o seguinte visual (em tempo de edição):
figura2
Em seguida, vamos inserir os objetos (todos da palheta QReport) para a exibição dos títulos das colunas e dos valores gravados no banco, conforme a listagem abaixo:
QrBand1-1 TqrSysData
QrGroup1-1 TqrDbText
QrBand2-2 TqrLabel e 2 TqrDbText
ChildBand1-1 TqrLabel
QrSubDetail1 -1 TqrLabel
QrBand3-1 TqrLabel e 1 TqrExpr
ChildBand2-não tem objeto
QrBand4-1 TqrLabel e 1 TQrExpr
QRSysData1 (QRBand1)
AlignmenttaCenter
AlignToBand True
DataqrsReportTitle
font.StyleBold
Font.Size12
QRDBText1 (QRGroup1)
AlignmenttaCenter
AlignToBand True
Color$00DFDFDF
DataFieldnomeempresa
DataSetQuery1
QRLabel1 (QRBand2)
CaptionFuncionario:
Left16
QRDBText2 (QRBand2)
DataFieldnomefuncionario
DataSetQuery1
Left96
QRLabel2 (QRBand2)
CaptionSalario:
Left264
QRDBText3 (QRBand2)
DataFieldsalario
DataSetQuery1
Left 320
QRLabel3 (ChildBand1)
CaptionFilho(s):
Left40
Font.StyleBold
QRLabel4 (QRSubDetail1)
Captionnome do filho
Left56
QRLabel5 (QRBand3)
CaptionSubTotal de Salários:
Left424
Font.StyleBold
QRExpr1 (QRBand3)
Expressionsum(Query1.Salario)
ResetAfterPrintTRUE
Left576
Font.StyleBold
QRLabel7 (QRBand4)
CaptionTotal Geral de Salários:
Left424
Font.StyleBold
QRExpr2 (QRBand4)
Expressionsum(Query1.Salario)
Left576
Font.StyleBold
Agora nosso relatório já está com uma boa forma:
figura3
Abaixo o código do relatório:
unit ReEmpFun;
interface
uses Windows, SysUtils, Messages, Classes, Graphics, Controls,
StdCtrls, ExtCtrls, Forms, Quickrpt, QRCtrls, Db, DBTables;
type
TqrEmpFun = class(TQuickRep)
Query1: TQuery;
QRBand1: TQRBand;
QRGroup1: TQRGroup;
QRDBText1: TQRDBText;
QRBand2: TQRBand;
QRDBText2: TQRDBText;
QRSubDetail1: TQRSubDetail;
QRLabel4: TQRLabel;
ChildBand1: TQRChildBand;
QRLabel3: TQRLabel;
Query2: TQuery;
QRBand3: TQRBand;
QRExpr1: TQRExpr;
QRDBText3: TQRDBText;
QRLabel1: TQRLabel;
QRLabel2: TQRLabel;
QRLabel5: TQRLabel;
QRShape1: TQRShape;
ChildBand2: TQRChildBand;
QRBand4: TQRBand;
QRLabel7: TQRLabel;
QRExpr2: TQRExpr;
QRSysData1: TQRSysData;
procedure QRBand2BeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
procedure QRSubDetail1BeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
private
public
end;
var
qrEmpFun: TqrEmpFun;
implementation
{$R *.DFM}
procedure TqrEmpFun.QRBand2BeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
begin
//atribui valor ao parâmetro da query filho para filtar o(s) filho(s) do funcionário corrente
with Query2 do
begin
Close;
ParamByName('MCodFunc').Value := Query1.FieldByName('codfuncionario').AsInteger;
Open;
end;
end;
procedure TqrEmpFun.QRSubDetail1BeforePrint(Sender: TQRCustomBand;
var PrintBand: Boolean);
begin
//testa se query de filho esta vazia para o funcionário corrente
if Query2.IsEmpty then
QRLabel4.Caption := 'Não Possui Filho(s)'
else
QRLabel4.Caption := Query2.FieldByName('nome').AsString;
end;
end.
Conforme comentado, esta é uma estrutura que dá uma base para criar relatórios mais completos/complexos no Delphi. Não existe um segredo para a criação de relatórios que possuam agrupamentos, múltiplos níveis, subtotais, totais, etc. E nem muito menos a necessidade de escrever várias linhas de código para obter tal resultado, o importante é explorar ao máximo as propriedades dos componentes do QR.
Após esses passos, nosso relatório está basicamente pronto. Ao executá-lo, teremos como resultado todos os funcionários agrupados por empresa que por sua vez terão todos os seus dependentes listados (se houverem). O total de salários pagos por empresa e o total geral de salários pagos também serão exibidos. Desta forma, teremos o relatório abaixo:
figura4
Como você pode observar, foram criados dois grupos separados (Business Tech e Wam Corporation), na mesma página. Caso você queira colocar um grupo em cada página, basta mudar a propriedade ForceNewPage do QRGroup1 para True. Através deste artigo, meu objetivo foi mostrar como é fácil construir relatórios no QuickReport, sem a necessidade de páginas de digitação de código. Este exemplo pode ser baixado no endereço http://www.clubedelphi.com.br/edicao12/qr.zip
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo