Imprimir um total de grupo no cabeçalho do grupo
Este método é usado com frequência e requer o uso de um script, já que o valor de um total de grupo somente é conhecido após processar todos os registros no grupo. Para exibir o total no cabeçalho do grupo (ou seja, antes que o grupo seja exibido no relatório) é utilizado o seguinte algoritmo:
ative a opção de relatório dois passos (item de menu "Relatório > Opções...")
no primeiro passo, calcule o total de cada grupo e salve-os em um array
no segundo passo, extraia os valores do array e exiba-os nos cabeçalhos dos grupos
Vamos demonstrar dois métodos de executar esta tarefa. Crie um relatório novo. Coloque o componente "Consulta ADO" na página e configura sua propriedade SQL:
SQL =
select * from customer, orders
where orders.CustNo = customer.CustNo
order by customer.CustNo, orders.OrderNo
UserName = 'Group'
Habilite dois passos nas configurações do relatório (item de menu "Relatório > Opções..."). Adicione duas bandas ao relatório: "Cabeçalho de Grupo" e "Dados Mestre". No editor da banda "Cabeçalho de Grupo", insira o campo de dados Group."CustNo". Conecte a banda de dados à fonte de dados "Group" e arranje alguns objetos da seguinte maneira:
Para exibir o total, usamos o objeto com a seta no design (em nosso exemplo ele é chamado de "Memo8").
O primeiro método.
Usaremos a classe TStringList
como um array para armazenar os totais – vamos armazenar os valores numéricos como cadeias. O primeiro item na StringList corresponderá ao total do primeiro grupo, etc. Uma variável de número inteiro (que iremos incrementar após imprimir cada grupo) é usada para calcular o número de índice do grupo.
Então nosso script terá o seguinte aspecto:
PascalScript:
var
List: TStringList;
i: Integer;
procedure frReport1OnStartReport(Sender: TfrxComponent);
begin
List := TStringList.Create;
end;
procedure frReport1OnStopReport(Sender: TfrxComponent);
begin
List.Free;
end;
procedure Page1OnBeforePrint(Sender: TfrxComponent);
begin
i := 0;
end;
procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
begin
if Engine.FinalPass then
Memo8.Text := 'Sum: ' + List[i];
end;
procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
begin
if not Engine.FinalPass then
List.Add(FloatToStr(SUM(<Group."ItemsTotal">,MasterData1)));
Inc(i);
end;
begin
end.
C++ Script:
TStringList List;
int i;
void frReport1OnStartReport(TfrxComponent Sender)
{
List = TStringList.Create();
}
void frReport1OnStopReport(TfrxComponent Sender)
{
List.Free();
}
void Page1OnBeforePrint(TfrxComponent Sender)
{
i = 0;
}
void GroupHeader1OnBeforePrint(TfrxComponent Sender)
{
if (Engine.FinalPass)
Memo8.Text = "Sum: " + List[i];
}
void GroupFooter1OnBeforePrint(TfrxComponent Sender)
{
List.Add(FloatToStr(SUM(<Group."ItemsTotal">,MasterData1)));
i++;
}
{
}
Os nomes dos procedimentos no script mostram quais eventos utilizamos. Eles são: "Report.OnStartReport", "Report.OnStopReport", "Page1.OnBeforePrint", "GroupHeader1.OnBeforePrint" e "GroupFooter1.OnBeforePrint". Os primeiros dois eventos são chamados no início e no final do relatório, respectivamente. Para criar manipuladores para estes dois eventos, selecione o objeto "Report" na lista suspensa do inspetor de objetos e suas propriedades serão exibidas no inspetor de objetos. Então abra a guia "Eventos" do inspetor de objetos e crie os manipuladores.
Por que não criamos a variável List
no procedimento principal do script? Nos a criamos no evento "OnStartReport" porque variáveis criadas dinamicamente devem ser destruídas após concluir o relatório. É lógico criar variáveis dinâmicas no evento "OnStarReport" e destruí-las no evento "OnStopReport". Em outros casos (quando a memória não precisa ser liberada na conclusão do script) é possível usar o procedimento principal do script para a inicialização de variáveis.
A criação e destruição da variável List
é simples. Agora vamos ver como o script funciona. No início da página, o contador do grupo atual (a variável "i") é redefinida como zero e é incrementada após a impressão de cada grupo (no evento "GroupFooter1.OnBeforePrint"). O total calculado é adicionado a List
neste evento antes de incrementar o contador. O evento "GroupHeader1.OnBeforePrint" não faz nada no primeiro passo (condição if "Engine.FinalPass"), mas durante o segundo passo (quando List
foi preenchida com valores) o total que corresponde ao grupo atual é recuperado de List
e a saída é enviada para o objeto "Memo8" para exibir o total no cabeçalho do grupo. No relatório concluído, o total é exibido desta maneira:
Este algoritmo é bastante simples. No entanto, ele pode ser simplificado ainda mais.
O segundo método.
Vamos usar a coleção de variáveis do relatório como um array para armazenar os totais dos grupos. Lembre-se de que as variáveis do relatório são acessadas através das funções Get
e Set
. Usar estas funções também nos poupa de ter que criar e destruir estas variáveis de maneira explícita. Este será nosso script:
PascalScript:
procedure GroupHeader1OnBeforePrint(Sender: TfrxComponent);
begin
if Engine.FinalPass then
Memo8.Text := 'Sum: ' + Get(<Group."CustNo">);
end;
procedure GroupFooter1OnBeforePrint(Sender: TfrxComponent);
begin
Set(<Group."CustNo">,
FloatToStr(SUM(<Group."ItemsTotal">,MasterData1)));
end;
begin
end.
C++ Script:
void GroupHeader1OnBeforePrint(TfrxComponent Sender)
{
if (Engine.FinalPass)
Memo8.Text = "Sum:" + Get(<Group."CustNo">);
}
void GroupFooter1OnBeforePrint(TfrxComponent Sender)
{
Set(<Group."CustNo">,
FloatToStr(SUM(<Group."ItemsTotal">,MasterData1)));
}
{
}
Como você pode ver, este script é um pouco mais simples. O código no manipulador "GroupFooter1.OnBeforePrint" define o valor de uma variável que possui um nome derivado do número do cliente (também é possível usar qualquer outro identificador que identifique o cliente de maneira não ambígua, por exemplo <Group."Company">). Se não existir nenhuma variável com este nome, o script a cria automaticamente; de outro modo, se ela existir, seu valor é atualizado. O valor da variável apropriada é recuperado no manipulador "GroupHeader1.OnBeforePrint".