ClientDataSet - dececando aggregates |
Top Previous Next |
|
// power ClientDataSet <--- despido, desvendado, aniquilado
// para todos os exemplo crie este programa:
1 ClientDataSet (Tb) 1 DataSource (Ds) 1 DBGrid (Grid)
object Form1: TForm1 object Grid: TDBGrid DataSource = Ds end object Tb: TClientDataSet Active = True FieldDefs = < item Name = 'Cidade' DataType = ftString Size = 20 end item Name = 'Nome' DataType = ftString Size = 20 end item Name = 'Vendas' DataType = ftFloat end> IndexDefs = < item Name = 'ICidade' Fields = 'Cidade; Nome' end> IndexName = 'ICidade' object TbCidade: TStringField FieldName = 'Cidade' end object TbNome: TStringField FieldName = 'Nome' end object TbVendas: TFloatField FieldName = 'Vendas' end end object Ds: TDataSource DataSet = Tb end end
//// Codigo fonte:
procedure TForm1.FormCreate(Sender: TObject); begin if FileExists('c:\arq.xml') then Tb.LoadFromFile('c:\arq.xml'); end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Tb.SaveToFile('c:\arq.xml'); end;
************************************************************************* Outra obs do junior: praticamente voce precisa de 1 item dentro de Tb.Aggregates para cada quebra.
e 1 campo dentro do Field do tipo TAggregateField para calculos.
*************************************************************************
// "popule" o cliente com dados de algumas cidades, nomes e valores // repita o nome da cidade e o nome algumas vezes...
************************************************************************* ************ Como fazer uma quebra sem somas ******************* *************************************************************************
CRICIUMA JOAO ANTONIO ICARA MARIA PEDRO ANTONIO
1. Basta criar um indice pelo campo que será a quebra e coloque o grouplevel do indice para 1
2. Se quiser ver o resultado numa grid basta colocar este código no onGetText do campo cidade:
if gbFirst in Tb.GetGroupState(1) then Text := TStringField(Sender).asString else Text := '';
3. Tb.AggregatesActive = True
************************************************************************* ************ Como fazer um somatório geral que ficará ******************* ************ abaixo da grid ******************* *************************************************************************
JOAO ................... 10,00 ANTONIO ..................4,40 MARIA ....................2,20 TOTAL -----------------> 16,60
1. Crie um novo campo no FieldsEditor de nome TOTAL do tipo AGGREGATE (selecione Aggregate no radiogroup)
2. Nas propriedades do field coloque: Expression = 'sum(vendas)' Active = True
3. No ClientDataSet coloque AggregatesActive = True
4. Coloque um DBText na tela e associe com este campo.
PS. Se quiser que o campo apareca na grid basta colocá-lo como Visible = True
************************************************************************* ************ Fazer um relatorio com quebra por um campo ***************** *************************************************************************
CRICIUMA OBI WAN ................. 1,01 QUIM GON ................ 2,40
FLORIPA FRODO ................... 4,00 LANCELOT ................ 3,00 SHREK ................... 1,99
ICARA ANAKIN ................. 10,00
Voce pode determinar a posicao relatorio de um registro dentro de um agregado chamando o metodo GetGroupState do dataset. GetGroupState retorna um valor de gbFirst, gbLast, gbMiddle.
Para tal, voce precisar criar um indice pelo campo que quer fazer a quebra
1. coloque um TMemo no exemplo com font COURIER NEW
2. No Aggrate Total coloque na propriedade
IndexName = 'ICidade' GroupLevel = 1
3. coloque um botao e no click adicione:
Tb.First; while not Tb.EOF do begin if gbFirst in Tb.GetGroupState(1) then Memo1.Lines.Add(TbCidade.asString); Memo1.Lines.Add(' ' + AlinhaEsq(TbNome.asString, 20) + AlinhaDir(TbVendas.asFloat, 10)); Tb.Next; end;
o grouplevel diz para o dataset que deve utilizar apenas a primeira parte do indice (no nosso exemplo nosso indice é por cidade e nome.) assim a cada "mudanca" no campo cidade o cliente ativa a flag gbFirst para o Group(1)
************************************************************************* ***************** Fazer somatorios pela quebra ************************** *************************************************************************
CRICIUMA OBI WAN ................. 1,01 QUIM GON ................ 2,40 subtotal.................... 3,41
FLORIPA FRODO ................... 4,00 LANCELOT ................ 3,00 SHREK ................... 1,99 sutotal .................... 8,99
ICARA ANAKIN ................. 10,00 subtotal .................. 10,00
TOTALGERAL ................ 22,40
Basta usar o agregado que já criamos e adicionar esta linha ANTES do NEXT:
if gbLast in Tb.GetGroupState(1) then Memo1.Lines.Add(' ' + AlinhaDir(TbTotal.Value, 30));
Agora para colocar o valor total de todos os registros é necessário criar um novo agregate:
TbTotalGeral: TAggregateField; FieldName = 'TotalGeral' Active = True Expression = 'sum(Vendas)'
Após o End do While coloque:
Memo1.Lines.Add(' ' + AlinhaDir(TbTotalGeral.Value, 30));
************************************************************************* *************** Fazer sub-grupo 2 niveis de quebra e soma ************** *************************************************************************
CRICIUMA OBI WAN .... 1,01 .... 2,00 subtotal: 3,01
QUIM GON .... 2,40 subtotal: 2,40
TOTAL Cidade: 5,41 ---------------------------- FLORIPA FRODO .... 4,00 .... 2,99 .... 0,50 subtotal: 7,49
LANCELOT .... 3,00 .... 2,20 subtotal: 5,20
SHREK .... 1,99 subtotal: 1,99
TOTAL Cidade: 14,68 ---------------------------- TOTAL GERAL: 30,09
Basta criar apenas mais 1 aggregate,
TbTotalNome: TAggregateField FieldName = 'TotalNome' Active = True Expression = 'sum(Vendas)' IndexName = 'ICidade' GroupingLevel = 2 // usa a 2 parte do índice (o indice é composto)
modifique o código fonte do botão imprimir para isto:
Tb.First; while not Tb.EOF do begin // cabeçalho de quebra por cidade if gbFirst in Tb.GetGroupState(1) then Memo1.Lines.Add(TbCidade.asString);
// cabeçalho de quebra por nome (note o grouplevel [2]) if gbFirst in Tb.GetGroupState(2) then Memo1.Lines.Add(' ' + TbNome.asString);
// cada registro é impresso aqui (detalhe) Memo1.Lines.Add(' ....' + AlinhaDir(TbVendas.asFloat, 15));
// subtotal por nome if gbLast in Tb.GetGroupState(2) then begin Memo1.Lines.Add(' subtotal:' + AlinhaDir(TbTotalNome.Value, 10)); Memo1.Lines.Add(''); end;
// subtotal por cidade if gbLast in Tb.GetGroupState(1) then begin Memo1.Lines.Add('TOTAL Cidade:' + AlinhaDir(TbTotal.Value, 8)); Memo1.Lines.Add('----------------------------'); end;
Tb.Next; end; // total geral Memo1.Lines.Add(''); Memo1.Lines.Add('TOTAL GERAL:' + AlinhaDir(TbTotalGeral.Value, 10));
// assim sucessivamente, tecnicamente nao existe limite do numero // de quebras que se pode fazer.
******************* Well done *********************
|