DB Grid: Deleting Multiple Records...

Is it possible to display a progress bar to show the progress of the records being deleted?  For example, in my application if I select 150 records to delete I would like to see a progress meter show the percentage done as it deletes each record.  Please show code.
dokkenAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rwilson032697Commented:
You could use something like a BDE call back detailed in this TI:

Although the code below is for a TBatchMove, it should be able to work for this operation too.

Cheers,

Raymond.


------- Borland TI # 3103

This TI demonstrates using a BDE DbiCallBack function
to drive a progress bar during a lengthy batch move
operation under Delphi 2.01.

Additional documentation on BDE function calls can be found
in the file BDE32.HLP (located in the directory where the
32 bit IDAPI is installed).

When you install a callback function to the BDE, the BDE
will "call back" to a function in your application, letting
your application know when certain events take place, and in
some cases, allow your application to return information  
back to the BDE.

The BDE defines several callback types that may be installed:

           during large batch operations.
           requests a response from the caller.
           

This TI details installing a cbGENPROGRESS callback to drive
a progress bar in your application.


To do this, first call the DbiGetCallBack() function to retrieve
the handle to any callback that might already be installed
(and it's parameters), and save this information to a data
structure.  Then install your callback, replacing any previous
callback installed.

You will need to pass a pointer the data structure containing
the information to the previously installed callback to the BDE
when you install your callback, so when your callback function
is executed, you can call the original callback
(if one is installed).

The BDE will call back to your application every so often,
reporting either a text message containing the number of records
it has processed or how far the batch move has progressed,
expressed as an integer percentage. Your callback should be able
to deal with either of these situations. If the percentage field
of the callback structure is greater than -1, then the percentage
is correct and you are free to update your progress bar. If the
percentage reported is less than zero, the callback has received
a text message in the szTMsg field containing a message that
includes the number of records processed. In this case, you will
need to parse the text message and convert the remaining string
to an integer, then calculate the percentage done and update
the progress bar.

Finally, when your batch move is complete, you will need to
un-register your callback, and reinstall the previous callback
function (if it exists).


The following code example is based on a form containing two tables,
a batch move component, a progress bar, and a button.

----- Code Follows ---------

unit Testbc1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DBGrids, DB, DBTables, ComCtrls;

type
  TForm1 = class(TForm)
    Table1: TTable;
    BatchMove1: TBatchMove;
    Table2: TTable;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses Bde; {Dbi Types and Procs are located here}

{$R *.DFM}

{data structure  type to save previous callback info}
type TDbiCbInfo = record
  ecbType     : CBType;
  iClientData : longint;
  DataBuffLn  : word;
  DataBuff    : pCBPROGRESSDesc;
  DbiCbFn     : pointer;
end;
type PDbiCbInfo = ^TDbiCbInfo;


{Our callback  function}
function DbiCbFn(ecbType     : CBType;
                 iClientData : Longint;
                 CbInfo      : pointer): CBRType stdcall;
var
  s : string;
begin
 {Check to see if the callback type is what we expect}
  if ecbType = cbGENPROGRESS then begin
   {if iPercentDone is less that zero then extract the number}
   {of records processed from szMsg parameter}
    if pCBPROGRESSDesc(cbInfo).iPercentDone < 0 then begin
      s := pCBPROGRESSDesc(cbInfo).szMsg;
      Delete(s, 1, Pos(': ', s) + 1);
     {Calculate percentage done and set the progress bar}
      Form1.ProgressBar1.Position :=
        Round((StrToInt(s) / Form1.Table1.RecordCount) * 100);
    end else
    begin
     {Set the progress bar}
      Form1.ProgressBar1.Position :=
        pCBPROGRESSDesc(cbInfo).iPercentDone;
    end;
  end;
 {was there a previous callback registered}
 {if so - call it and return}
  if PDbiCbInfo(iClientData)^.DbiCbFn <> nil then
    DbiCbFn :=
      pfDBICallBack(PDbiCbInfo(iClientData)^.DbiCbFn)
        (ecbType,
         PDbiCbInfo(iClientData)^.iClientData,
         cbInfo) else
    DbiCbFn := cbrCONTINUE;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  CbDataBuff: CBPROGRESSDesc; {DBi Structure}
  OldDbiCbInfo : TDbiCbInfo;  {data structure to save previous
                               callback info}
begin
 {Make sure the table we are moving from is open}
  Table1.Open;
 {make sure the table we are batch moving to is closed}
  Table2.Close;
 {get info about any installed callback}
  DbiGetCallBack(Table2.Handle,
                 cbGENPROGRESS,
                 @OldDbiCbInfo.iClientData,
                 @OldDbiCbInfo.DataBuffLn,
                 @OldDbiCbInfo.DataBuff,
                 pfDBICallBack(OldDbiCbInfo.DbiCbFn));
 {register our callback}
  DbiRegisterCallBack(Table2.Handle,
                      cbGENPROGRESS,
                      longint(@OldDbiCbInfo),
                      SizeOf(cbDataBuff),
                      @cbDataBuff,
                      @DbiCbFn);

  Form1.ProgressBar1.Position := 0;
  BatchMove1.Execute;

 {if a previous callback exists - reinstall it else}
 {unregister our callback}
  if OldDbiCbInfo.DbiCbFn <> nil then
    DbiRegisterCallBack(Table2.Handle,
                        cbGENPROGRESS,
                        OldDbiCbInfo.iClientData,
                        OldDbiCbInfo.DataBuffLn,
                        OldDbiCbInfo.DataBuff,
                        OldDbiCbInfo.DbiCbFn) else
    DbiRegisterCallBack(Table2.Handle,
                        cbGENPROGRESS,
                        longint(@OldDbiCbInfo),
                        SizeOf(cbDataBuff),
                        @cbDataBuff,
                        nil);

 {lets show our success!}
  Table2.Open;

end;

end.

0
kretzschmarCommented:
hi dokken,

raymond, you are terrible overdressed

so it goes:

unit db_batchdelete_u;

interface

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

type
  TForm1 = class(TForm)
    ProgressBar1: TProgressBar;
    Table1: TTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Table1AfterDelete(DataSet: TDataSet);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  BatchDeleting : Boolean = False;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
begin
  If dbgrid1.SelectedRows.Count > 0 then
  begin
    progressbar1.Max := dbgrid1.SelectedRows.Count;
    progressbar1.Min := 0;
    progressbar1.Position := 0;
    progressbar1.Step := 1;
    BatchDeleting := True;
    dbgrid1.SelectedRows.Delete;
    BatchDeleting := False;
  end;
end;

procedure TForm1.Table1AfterDelete(DataSet: TDataSet);
begin
  if BatchDeleting then
    progressbar1.StepIt;
end;

end.

meikl ;-)
0
dokkenAuthor Commented:
meikl,

Your comment worked perfectly... post something as an answer so I can give you the points.


Thanks.
0
kretzschmarCommented:
hi dokken,

glad that you like it :-)
good luck again

meikl ;-)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rwilson032697Commented:
Nice example Meikl!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.