Olá pessoal, vamos nesse artigo aprimorar um pouco mais a construção de relatórios utilizando o Rave Code Based, desenvolveremos um relatório de Vendas, quebrando por Clientes. Vamos ao trabalho!!!

Montando a Aplicação

Crie uma nova aplicação e insira os seguintes componentes:

Componente

Database

AliasName

Alias apontando para DBDemos

Componente

SQLQuery

Name

qryOrders

SQL

Select * from ORDERS Order by CustNo, OrderNo

Componente

SQLQuery

Name

qryItems

SQL

Select I.*, P.Description, P.ListPrice, ((I.Qty * P.ListPrice) - I.Discount) as TotalItem

From Items I

Inner Join Parts P

on P.PartNo = I.PartNo

Where I.OrderNo = :OrderNo

Order by ItemNo

Componente

SQLQuery

Name

qryCustomer

SQL

Select * from Customer C Where C.CustNo = :CustNo

Insira um DataSource para cada SQLQuery, logo teremos três DataSource (dtsOrders, dtsItems e dtsCustomer); associe o DataSource dtsOrders na propriedade “DataSource” das Querys qryItems e qryCustomer.

Importante: Não esqueça de verificar se foi gerado um parâmetro (CustNo para Query Customer e OrderNo para a Query Items) propriedade Params e se esses parâmetros estão configurados como DataType = ftFloat e ParamType = ptInput.

Agora, insira uma grid para demonstrar o conteúdo da query Orders e ligue essa grid ao DataSource correspondente a Query, insira também um DBNavigator associado a esse mesmo DataSource, faça esses mesmos passos para demonstrar o conteúdo da Query Items e Customer.

Por fim, insira dois botões, um chamado “Result” e o outro “Report”, sua tela ficará parecida com a imagem abaixo:

ver imagem

Tudo bem, tudo bem a sua deve ter ficado mais bonita, ahahaha, mas como o intuito desse artigo não é montar uma tela bonita e sim um relatório, não vamos nos prender a esse pequeno detalhe (ufa...).

Insira o código abaixo no clique do botão “Result”:

qryOrders.Close;

qryOrders.Open;

E no evento After Open da Query qryOrders insira o seguinte código:

qryCustomer.Close;

qryCustomer.Open;

qryCustomer.Close;

qryCustomer.Open;

Rode a aplicação, clique sobre o botão e verifique se o mestre-detalhe está funcionando.

Montando o Relatório

Bom, agora vamos para a parte que realmente nos interessa nesse artigo, o relatório.

Insira um componente RVSystem e configure as seguintes propriedades:

SystemPrinter

Units à unCM

MarginLeft à 1

MarginRight à 1

MarginTop à 1

MarginBottom à 1

SystemPreview

FormState à wsMaximized

No Evento OnBeforePrint do RVSystem, vamos configurar a página e criar os tabs que serão a estrutura do nosso relatório. Com o seguinte código:

with Sender as TBaseReport do

begin

SetPaperSize(DMPAPER_A4, 0, 0);

//Customer / Employee

ClearTabs;

SetTab(1.2, pjLeft, 3, 0, BOXLINEHORIZ, 0); //CustNo

SetTab(NA , pjLeft, (PageWidth – 5.2), 0, BOXLINEHORIZ, 0); //Company

SaveTabs(1);

//Orders

ClearTabs;

SetTab(1.5, pjLeft, 2.0, 0, BOXLINENONE, 0); //OrderNo

SetTab(NA , pjLeft, 2.5, 0, BOXLINENONE, 0); //SaleDate (data venda)

SetTab(NA , pjLeft, 2.5, 0, BOXLINENONE, 0); //ShipDate (data entrega)

SetTab(NA , pjLeft, 2.0, 0, BOXLINENONE, 0); //ShipVia (Forma de Entrega)

SetTab(NA , pjLeft, 3.0, 0, BOXLINENONE, 0); //PaymentMethod (Forma de Pagamento)

SetTab(NA , pjLeft, 3.0, 0, BOXLINENONE, 0); //ItemsTotal (Total Venda)

SaveTabs(2);

//Items

ClearTabs;

SetTab(2.0, pjLeft, 1.5, 0, BOXLINENONE, 0); //ItemNo

SetTab(NA , pjLeft, 2.0, 0, BOXLINENONE, 0); //PartNo (código do produto)

SetTab(NA , pjLeft, 5.0, 0, BOXLINENONE, 0); //description (descrição)

SetTab(NA , pjLeft, 2.0, 0, BOXLINENONE, 0); //ListPrice (Valor Unitário)

SetTab(NA , pjLeft, 1.5, 0, BOXLINENONE, 0); //qty (quantidade)

SetTab(NA , pjLeft, 2.0, 0, BOXLINENONE, 0); //discount (Desconto)

SetTab(NA , pjLeft, 2.0, 0, BOXLINENONE, 0); //TotalItem (total)

SaveTabs(3);

end;

Verifique que utilizamos o SetPaperSize para configurar o tamanho que será a página do relatório e o SetTab para montar a estrutura do relatório.

Importante: Não esqueça de executar um ClearTabs sempre antes de iniciar a montagem de uma nova estrutura.

No evento OnPrintHeader montaremos o cabeçalho do relatório, insira o código abaixo:

with Sender as TBaseReport do

begin

SetFont('Arial',8);

PrintRight('Página ' + Macro(midCurrentPage) + ' de ' + Macro(midTotalPages), PageWidth - MarginRight);

NewLine;

SetFont('Arial',12);

Bold := True;

PrintCenter('Relatório de Vendas', PageWidth / 2);

Bold := False;

NewLine;

MoveTo(1.0, 2.0);

LineTo(20.0, 2.0);

end;

Importante: Para entender melhor a função “Macro” leia o artigo “Rave Reports Code Based”.

E para finalizar a parte de estrutura da página vamos montar o rodapé com o código abaixo:

with Sender as TBaseReport do

begin

MoveTo(1.0, 28.5);

LineTo(20.0, 28.5);

YPos := 29.0;

SetFont('Arial',8);

PrintCenter('Data de Impressão: ' + Macro(midCurrDateShort) + ' ' + Macro(midCurrTimeShort), PageWidth/2);

end;

Execute a aplicação e verifique se o cabeçalho e rodapé ficarão corretos.

Agora vamos montar o corpo do relatório, o objetivo desse relatório como já dito anteriormente é demonstrar as vendas separadas por cliente, então nossa preocupação nesse relatório é a mudança do código do cliente e a mudança no código da venda, pois como fizemos no inicio desse artigo, já estamos trazendo as vendas ordenadas pelo código do cliente e pelo código da venda, logo toda vez que mudar de cliente temos que iniciar uma nova página, e enquanto o código da venda for igual teremos que carregar os itens dessa venda.

No evento OnPrint insira o seguinte código:

var

intOrderNo, intCustNo : Integer;

begin

intOrderNo := 0;

intCustNo := 0;

with Sender as TBaseReport do

begin

qryOrders.DisableControls;

qryOrders.First;

while not qryOrders.Eof do

begin

if (intCustNo <> qryOrdersCustNo.AsInteger) then

begin

if intCustNo > 0 then

NewPage;

with qryCustomer do

begin

Close;

Params.ParamByName('CustNo').AsInteger := qryOrdersCustNo.AsInteger;

Prepare;

Open;

end;

SetFont('Arial', 10);

NewLine;

Bold := True;

PrintLeft('Cliente',MarginLeft);

Bold := False;

NewLine;

RestoreTabs(1);

PrintTab('Código .: ' + qryCustomerCustNo.AsString);

PrintTab('Nome .: ' + qryCustomerCompany.AsString);

end;

if intOrderNo <> qryOrdersOrderNo.AsInteger then

begin

if LinesLeft < 3 then

NewPage;

SetFont('Arial',10);

NewLine;

Bold := True;

RestoreTabs(2);

PrintTab('Venda'); //OrderNo

PrintTab('Data Venda');//SaleDate (data venda)

PrintTab('Data Entrega');// ShipDate (data entrega)

PrintTab('Entrega');/// ShipVia (Forma de Entrega)

PrintTab('Pagamento');// PaymentMethod (Forma de Pagamento)

PrintTab('Total');// ItemsTotal (Total Venda)

Bold := False;

NewLine;

RestoreTabs(2);

PrintTab(qryOrdersOrderNo.AsString); //OrderNo

PrintTab(qryOrdersSaleDate.AsString);//SaleDate (data venda)

PrintTab(qryOrdersShipDate.AsString);// ShipDate (data entrega)

PrintTab(qryOrdersShipVIA.AsString);/// ShipVia (Forma de Entrega)

PrintTab(qryOrdersPaymentMethod.AsString);// PaymentMethod (Forma de Pagamento)

PrintTab(FormatFloat('R$ 0.00', qryOrdersItemsTotal.AsFloat));// ItemsTotal (Total Venda)

end;

if LinesLeft < 3 then

NewPage;

NewLine;

RestoreTabs(3);

SetFont('Arial',8);

Bold := True;

PrintTab('Item');//ItemNo

PrintTab('Código');//PartNo (código do produto)

PrintTab('Nome');//description (descrição)

PrintTab('Vl. Unit.');//ListPrice (Valor Unitário)

PrintTab('Qtde.');//qty (quantidade)

PrintTab('Desconto');//discount (Desconto)

PrintTab('Total');//TotalItem (total)

Bold := False;

with qryItems do

begin

Close;

Params.ParamByName('OrderNo').AsInteger := qryOrdersOrderNo.AsInteger;

Prepare;

Open;

end;

while not qryItems.Eof do

begin

if LinesLeft < 3 then

NewPage;

SetFont('Arial',8);

NewLine;

RestoreTabs(3);

PrintTab(qryItemsItemNo.AsString);//ItemNo

PrintTab(qryItemsPartNo.AsString);//PartNo (código do produto)

PrintTab(qryItemsDescription.AsString);//description (descrição)

PrintTab(FormatFloat('R$ 0.00', qryItemsListPrice.AsFloat));//ListPrice (Valor Unitário)

PrintTab(qryItemsQty.AsString);//qty (quantidade)

PrintTab(FormatFloat('R$ 0.00', qryItemsDiscount.AsFloat));//discount (Desconto)

PrintTab(FormatFloat('R$ 0.00', qryItemsTotalItem.AsFloat));//TotalItem (total)

qryItems.Next;

end;

intOrderNo := qryOrdersOrderNo.AsInteger;

intCustNo := qryOrdersCustNo.AsInteger;

NewLine;

qryOrders.Next;

end;

qryOrders.EnableControls;

end;

Entendendo o código:

Declaramos duas variáveis ( intOrderNo, intCustNo ) para controlar o código da Venda e o código do Cliente, dentro do loop da query Orders verificamos se o conteúdo da variável intCustNo é igual ao registro atual da Query, se for diferente significa que ocorreu uma mudança de Cliente, e de acordo com o escopo do nosso relatório, toda vez que isso ocorrer temos que iniciar uma nova página (NewPage) e demonstrar quem é esse novo cliente, então restauramos a tab correspondente para escrevermos no relatório o código e o nome desse cliente.

Após isso verificamos se o conteúdo da variável intOrderNo é diferente do registro atual da query Orders se for diferente precisamos montar o titulo das colunas e inserir as informações dessa nova venda.

Se o cliente for o mesmo e a venda for a mesma o relatório vai montar os itens dessa venda.

Execute a aplicação e clique sobre o botão “Report” para verificar o resultado do relatório, deverá ficar parecido com a imagem abaixo:

ver imagem

Conclusão

È isso pessoal, espero que tenha dado tudo certo e que esse artigo tenha te ajudado!!! Até o próximo.