Criando uma consulta de referencia cruzada no clientdataset em runtime

By: francisco souza

Abstract: Criar uma consulta por referĂȘncia cruzada de dados em runtime utilizando clientdataset

Essa rotina tem por objetivo criar uma consulta cruzada em tempo de runtime. Utilizo ela em meus sistemas para mostrar o cruzamento de dados principalmente na relação Mes x Ano, mas pode ser usada para outros tipos de dados, só depende da criatividade e da necessidade de uso no sistema.

Estarei colocando os passos sem me atentar aos passos básicos para criação de um projeto no delphi, espera-se que o leitor saiba como fazer.

Primeiramente vamos criar uma base de dados com uma tabela onde vai guardar o giro mensal de produtos:

CREATE DATABASE '127.0.0.1/gds_db:C:\dados\dados.ib'  USER 'SYSDBA'
   PAGE_SIZE 8192;


CREATE TABLE TABELA_PRODUTOS_GIRO_MES (
  ID_PRODUTO INTEGER NOT NULL,
  ID_LOJA INTEGER NOT NULL,
  COMPRAS NUMERIC(18,2),
  VENDAS NUMERIC(18,2),
  MES INTEGER NOT NULL,
  ANO INTEGER NOT NULL,
  TOTAL_VENDAS NUMERIC(18,2));

ALTER TABLE TABELA_PRODUTOS_GIRO_MES ADD CONSTRAINT PK_TABELA_PRODUTOS_GIRO_MES PRIMARY KEY (ID_PRODUTO,ID_LOJA,MES,ANO);

GRANT SELECT, INSERT, DELETE, REFERENCES, UPDATE ON TABELA_PRODUTOS_GIRO_MES TO SYSDBA WITH GRANT OPTION;

Vamos entrar no Delphi e criar um novo projeto e adicionar os seguintes componentes ao form:

TSqlconnection,Tsqldataset,Tclientdataset,Tdatasource,Tdbgrid,Tbitbtn

Crie uma conexão ao banco no componente tsqlconnection e altere as seguintes propriedades:

Tsqldataset.name :=sgiro
Tsqldataset.Commandtext:= ‘SELECT * FROM GIRO’;   
Tclientdataset.name=gmov

A tela ficará igual a esta:

Hide image
Click to see full-sized image

No evento onclick do componente bitbtn1 escreve o seguinte código:

var
   vano:integer;
   a:integer;
   Campo1:string;
begin
   sgiro.open;     //abrir o sqldataset
   gmov.Close;  // fechei o clientdataset
   gmov.FieldDefs.Clear;   // limpei a estrutura do clientdataset
   gmov.FieldDefs.Add('Mes',ftstring,3,false);  //criei em runtime o campo de Nome mes
   vano:=yearof(date); //aqui pego o ano atual
   for a:=1 to 5 do begin //gero os campos do clientdataset dos ultimos 5 anos
      Campo1:='S-'+strzero(inttostr(vano),4); //criei o campo numa variável tipo string
      gmov.FieldDefs.add(campo1, ftFLOAT,0, false); //atribui o campo ao clientdataset
      vano:=vano-1; //diminui um ano ate zerar o contador dos ultimos 5 anos.
   end;
   gmov.CreateDataSet; //criei o clientdataset na memoria
   vano:=yearof(date); //pego o ano atual
   for a:=1 to 5 do begin 
      Campo1:='S-'+strzero(inttostr(vano),4);
      TFloatField(gmov.FieldByName(campo1)).displayFormat:='0.00'; //aqui atribuo a mascara numerica ao campo
      vano:=vano-1;
   end;
   GMOV.DisableControls;
   for a:=1 to 12 do begin  //aqui verifico os meses do ano e adiciona o coluna Y do client dataset
      gmov.Append;
      gmov.FieldByName('mes').Value:=copy(NomeMes(a),1,3);
      gmov.Post;
   end;
   gmov.Append;   //aqui adiciono uma coluna totalizadora
   gmov.FieldByName('mes').Value:='TOT';
   gmov.Post;
   while not SGIRO.eof do begin   //aqui leio a consulta sql do banco e vou gravando no clientdaset de acordo o mes e o ano.
      gmov.Locate('mes',copy(NomeMes(SGIROMES.AsInteger),1,3),[]);
      gmov.edit;
      gmov.FieldByName('S-'+strzero(SGIROANO.AsString,4)).ASCURRENCY:=gmov.FieldByName('S-'+strzero(SGIROANO.AsString,4)).ASCURRENCY+abs(SGIROVALOR.ASCURRENCY);
      gmov.Post;
      gmov.Locate('mes','TOT',[]); //aqui gravo o total do ano(a soma dos meses)
      gmov.edit;
      gmov.FieldByName('S-'+strzero(SGIROANO.AsString,4)).ASCURRENCY:=gmov.FieldByName('S-'+strzero(SGIROANO.AsString,4)).ASCURRENCY+abs(SGIROVALOR.ASCURRENCY);
      gmov.Post;
      SGIRO.NEXT;
   end;
   gmov.First;   ///aqui so por estetica, percorro o clientdataset e onde encontro 0, limpo o campo.
   WHILE NOT GMOV.Eof DO BEGIN
      FOR A:=0 TO GMOV.FieldCount-1 DO BEGIN
         IF GMOV.Fields[A].AsString='0' THEN BEGIN
            GMOV.EDIT;
            GMOV.Fields[A].Clear;
            GMOV.POST;
         END;
      END;
      GMOV.Next
   END;
   GMOV.First;
   GMOV.EnableControls;

Também criei estas 2 funcoes para me auxiliar na criação dos campos:

function NomeMes(Mes: integer): string;   //esta retorna o nome do mes passado como parametor pelo indice
const
  NMes : array [1..12] of string[12] =
   ('Janeiro', 'Fevereiro', 'Marco', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro');
begin
result:=nmes[mes];

end;

function StrZero(Zeros: string; Quant: integer): String; //Insere Zeros à frente de uma string}
var
I,Tamanho:integer;
aux: string;
begin
  aux := zeros;
  Tamanho := length(ZEROS);
  ZEROS:='';
  for I:=1 to quant-tamanho do
  ZEROS:=ZEROS + '0';
  aux := zeros + aux;
  StrZero := aux;

end;

Alimente a tabela com alguns dados, e ao clicar no botão consulta giro a tela abaixo aparecerá:

Hide image
Click to see full-sized image


Server Response from: ETNASC01