Somar campos selecionados DBGrid sem uso do multselect?

Delphi

08/08/2008

Ola pessoal um colega postou em outro forum um jeito de marcar dados no dbgrid sem uso do multselect, gostei e estou querendo usar aqui no meu projeto.
O código é este aqui.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, DBGrids, Db, DBTables, StdCtrls, Mask, JvExMask, JvToolEdit,
  JvBaseEdits;

type
  TForm1 = class(TForm)
    Table1: TTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Table1EmpNo: TIntegerField;
    Table1LastName: TStringField;
    Table1FirstName: TStringField;
    Table1PhoneExt: TStringField;
    Table1HireDate: TDateTimeField;
    Table1Salary: TFloatField;
    Button1: TButton;
    JvCalcEdit1: TJvCalcEdit;
    procedure DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
      Field: TField; State: TGridDrawState);
    procedure DBGrid1CellClick(Column: TColumn);
    procedure Button1Click(Sender: TObject);
  private fMouseOverRow : integer;
    FSelecionados : array of integer;
    function GetIndex(Value : Integer) : Integer;

  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

type
  THakGrid = class(TCustomGrid);

function TForm1.GetIndex(Value: Integer): Integer;
var
  I : Integer;
begin
  for I := 0 to High(FSelecionados) do
  begin
    if FSelecionados[I] = Value then
    //poderia fazer uma busca indexada pra agilizar
    //mas vai ficar pra proxima.
    begin
      Result := I;
      Exit;
    end;
  end;
  Result := -1;
end;

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;
  Field: TField; State: TGridDrawState);
begin
  if GetIndex(Table1.RecNo) > -1 then
    DBGrid1.Canvas.Brush.Color := clSkyBlue;

  DBGrid1.DefaultDrawDataCell(Rect, Field, State);
end;
procedure TForm1.DBGrid1CellClick(Column: TColumn);
var
  I, I2 : Integer;
begin
  I := GetIndex(Table1.RecNo);
  if 0 > I then
  begin
    I := High(FSelecionados) + 1;
    SetLength(FSelecionados, I + 1);
    FSelecionados[I] := Table1.RecNo;
  end else
  begin
    I2 := High(FSelecionados);
    if I2 > I then
      Move(FSelecionados[I+1], FSelecionados[I], I2-I);

    SetLength(FSelecionados, I2);
  end;
  THakGrid(DBGrid1).InvalidateRow(THakGrid(DBGrid1).Row);

end;

end.


Só que eu aqui uso o Mutselect para somar campos que em marcar no dbgrid assim
procedure TForm1.BtnSomaClick(Sender: TObject);
var
  i: Integer;
  Valor : Single;
begin
  if DBGrid1.SelectedRows.Count > 0 then
  begin
    Valor := 0;
    with DBGrid1.DataSource.DataSet do
    begin
      for i := 0 to DBGrid1.SelectedRows.Count-1 do
      begin
        GotoBookmark(Pointer(DBGrid1.SelectedRows.Items[i]));
        Valor := Valor + Table1.FieldByName(´Salary´).AsFloat;
      end;
    end;
    jvCalcEdit1.Text :=  FloatToStr(Valor);
  end
end;


Só que ai funciona apenas se eu selecionar os que eu quero somar no dbgrid, gostaria de saber se tem como fazer esta soma usando o código que o colega fez, sem precisar do uso do multselect do dbgrid.


Adriano_servitec

Adriano_servitec

Curtidas 0

Respostas

Adriano_servitec

Adriano_servitec

08/08/2008

Resolvido

procedure TForm1.BtnTotalClick(Sender: TObject);
var
  i: Integer;
  Valor : Single;
begin
  if High(FSelecionados) > -1 then
  begin
    Valor := 0;
    with DBGrid1.DataSource.DataSet do
    begin
      for i := 0 to High(FSelecionados) do
      begin
        RecNo := FSelecionados[i];
        Valor := Valor + Table1.FieldByName(´Salary´).AsFloat;
      end;
    end;
    jvCalcEdit1.Text :=  FloatToStr(Valor);
  end
end; 



GOSTEI 0
Marco Salles

Marco Salles

08/08/2008

Quem lhe passou este código ???

Este Cogigo tem erro não ???

veja um exemplo

Selecione os Items nesta ordem
table.Recno -->> 10 , 8, 7 , 9 , 13

Agora desmarque o Item Table.RecNo = 8

de modo que fique somente os Items :
table.Recno -->> 10 , 7 , 9 , 13

Ate ai beleza ... Funciona ????

então Minimize o Formulário e veja o que acontece ...

[b:07afb423c2]o Item 13º marcado irá sumir....[/b:07afb423c2]

para corrigir este inconveniente acredito que dá , mas requer um pouco de codificação extra


GOSTEI 0
Adriano_servitec

Adriano_servitec

08/08/2008

Verdade, vou passar pro autor do código o erro.

Valeu amigo.


GOSTEI 0
Adriano_servitec

Adriano_servitec

08/08/2008

para corrigir este inconveniente acredito que dá , mas requer um pouco de codificação extra

De qualquer modo, vc tem alguma ideia de como resolver isso amigo?


GOSTEI 0
Marco Salles

Marco Salles

08/08/2008

Acho que sim...

não estou aqui com o delphi

A principio olhando o codigo pensei que necessita-sse de codificação extra
mas na fila do mercado (rsss) pensei que talves a simples alteração

de

 I2 := High(FSelecionados); 
    if I2 > I then 
      Move(FSelecionados[I+1], FSelecionados[I], I2-I); 


para

  I2 := High(FSelecionados);
     if I2 > I then
       Move(FSelecionados[I2], FSelecionados[I], I2-I);


Deve resolver....


GOSTEI 0
Adriano_servitec

Adriano_servitec

08/08/2008

Olá amigo, bom a principio parece que resolveu o problema.

Tomara que seja só isso o bug :D

Obrigado pela ajuda.


GOSTEI 0
Adriano_servitec

Adriano_servitec

08/08/2008

Olá, segundo o autor do código a solução não é esta.
Olhe a sitação dele
o prob ai é q ao pintar a grade, ele move o ponteiro do dataset internamente, porem sem mover os controles, o q causa uma leitura incorreta do RecNo.


Então ele me passou outro código, veja
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, DBGrids, Db, DBTables, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Table1 : TTable;
    DataSource1 : TDataSource;
    DBGrid1 : TDBGrid;
    Panel1 : TPanel;
    Label1 : TLabel;
    Label2: TLabel;
    Button1: TButton;
    Table1OrderNo: TFloatField;
    Table1CustNo: TFloatField;
    Table1SaleDate: TDateTimeField;
    Table1ShipDate: TDateTimeField;
    Table1EmpNo: TIntegerField;
    Table1ShipToContact: TStringField;
    Table1ShipToAddr1: TStringField;
    Table1ShipToAddr2: TStringField;
    Table1ShipToCity: TStringField;
    Table1ShipToState: TStringField;
    Table1ShipToZip: TStringField;
    Table1ShipToCountry: TStringField;
    Table1ShipToPhone: TStringField;
    Table1ShipVIA: TStringField;
    Table1PO: TStringField;
    Table1Terms: TStringField;
    Table1PaymentMethod: TStringField;
    Table1ItemsTotal: TCurrencyField;
    Table1TaxRate: TFloatField;
    Table1Freight: TCurrencyField;
    Table1AmountPaid: TCurrencyField;
    procedure DBGrid1DrawDataCell(Sender : TObject; const Rect : TRect;
      Field : TField; State : TGridDrawState);
    procedure FormCreate(Sender : TObject);
    procedure FormDestroy(Sender : TObject);
    procedure Button1Click(Sender: TObject);
    procedure DBGrid1CellClick(Column: TColumn);
  private
    MyBookMark : TBookmarkList;
    FVlSel : Double;
  public
    { Public declarations }
  end;

var
  Form1 : TForm1;

implementation

{$R *.DFM}

procedure TForm1.DBGrid1DrawDataCell(Sender : TObject; const Rect : TRect;
  Field : TField; State : TGridDrawState);
begin
  if MyBookMark.CurrentRowSelected then
    DBGrid1.Canvas.Brush.Color := clRed;

  DBGrid1.DefaultDrawDataCell(Rect, Field, State);
end;

type
  HackBookMark = class(TBookmarkList);

procedure TForm1.FormCreate(Sender : TObject);
begin
  MyBookMark := TBookmarkList.Create(DBGrid1);
  HackBookMark(MyBookMark).LinkActive(True);
  FVlSel := 0;
end;

procedure TForm1.FormDestroy(Sender : TObject);
begin
  MyBookMark.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyBookMark.Clear;
  FVlSel := 0;
  Label1.Visible := False;
  Label2.Visible := False;
end;

procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
if MyBookMark.CurrentRowSelected then
  begin
    MyBookMark.CurrentRowSelected := False;
    FVlSel := FVlSel - Table1ItemsTotal.Value;
  end else
  begin
    MyBookMark.CurrentRowSelected := True;
    FVlSel := FVlSel + Table1ItemsTotal.Value;
  end;

  if MyBookMark.Count = 0 then
  begin
      Label1.Visible := False;
      Label2.Visible := False;
  end else
  begin
    Label2.Caption := Format(´¬m´, [FVlSel]);
    Label1.Visible := True;
    Label2.Visible := True;
  end;

end;

end.



GOSTEI 0
Marco Salles

Marco Salles

08/08/2008

Olá, segundo o autor do código a solução não é esta. Olhe a sitação dele Citação: [quote:19eb0b04a7]o prob ai é q ao pintar a grade, ele move o ponteiro do dataset internamente, porem sem mover os controles, o q causa uma leitura incorreta do RecNo
. [/quote:19eb0b04a7]


permita me descordar ... O que faz a leitura errada na Hora de pintar a Grid é o Valor Errado contido no Array , porque o Codigo inicial esta Errado , atribuindo um Valor errado para FSelecionados

Ao substituir
Move(FSelecionados[I+1], FSelecionados[I], I2-I);  por
Move(FSelecionados[I2], FSelecionados[I], I2-I);


O conteudo do Array estara de acordo com a sua intenção , que é Ora Marcar Ora Desmarcar a Grid

Ha mas porque so aparece quando se esconde e se abre o Form ??
é pq nesse momento esta se fazendo um ´nova´ Pintura da Grid

Agora se for fazer ´analize´ de Otimização entre os dois codigos é claro que o uso da String TBookmarkList é mais Otimizada . Tb se comparamos
esses métodos com a Propriedade MultiSelect eu previro este Ultimo , ate porque não ganhei nada com os métodos.

Salvo é claro a utilização de classe TcustomGrid :
type
THakGrid = class(TCustomGrid);
....
THakGrid(DBGrid1).InvalidateRow(THakGrid(DBGrid1).Row);

e no Ultimo método a Utlização de TBookmarkList.

é como quem diz : Recordar é Viver

So quero enfatizar que não estou Tentando desmerecer codigo de ninguem , nen tampouco disputa com ninguem .não estou aqui para isso.
Quero parabenizar o autor pela aproveitamento da classe TcustumGrid e da String Opaca


GOSTEI 0
POSTAR