I had a form which has a DataSource,AdoQuery,AdoConnection,DBgrid
plus couple edit
and a memo
.
User enter his username,street address, etc.. and hit 'save' button. On that time the application is write the details in a comma separated txt file, which is connected to an Access linked table. When user hit 'save' button it write into the memo instantly but not live update the dbgrid database, only when reopen the app.
I search a lot but everybody has different suggestions: do a dbgrid refresh, adorequery, post, append, showmodal, open and close the database
etc.
My question is why the dbgrid liveupdate doesn't work?
Sourcecode is the following:
unit test;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, StrUtils, Grids, Buttons, pngimage, ExtCtrls,
ComCtrls, DBGrids, DB, DBTables, ColorGrd, DirOutln, ADODB,
FMTBcd, SqlExpr, DBCtrls, DBClient, jpeg;
type
TForm1 = class(TForm)
Memo1: TMemo;
exit: TButton;
resetbtn: TButton;
Label3: TLabel;
GroupBox1: TGroupBox;
Label7: TLabel;
Label8: TLabel;
GroupBox2: TGroupBox;
Label1: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
Generate: TButton;
GroupBox3: TGroupBox;
Label5: TLabel;
Label6: TLabel;
CheckBox1: TCheckBox;
Image1: TImage;
Image2: TImage;
Button6: TButton;
DateTimePicker1: TDateTimePicker;
GroupBox4: TGroupBox;
Label10: TLabel;
Label9: TLabel;
dellastentry: TButton;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
Label13: TLabel;
Label14: TLabel;
Label16: TLabel;
Label17: TLabel;
Label18: TLabel;
Label2: TLabel;
Label4: TLabel;
Label11: TLabel;
Label15: TLabel;
ADOQuery1Username: TWideStringField;
ADOQuery1RequestedNumber: TWideStringField;
ADOQuery1AllocatedNumber: TWideStringField;
ADOQuery1DateofRequest: TWideStringField;
procedure exitClick(Sender: TObject);
procedure resetbtnClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure dellastentryClick(Sender: TObject);
procedure GenerateClick(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetCurrentUserName: string;
const
cnMaxUserNameLen = 50;
var
sUserName: string;
dwUserNameLen: DWORD;
begin
dwUserNameLen := cnMaxUserNameLen - 1;
SetLength(sUserName, cnMaxUserNameLen);
GetUserName(PChar(sUserName), dwUserNameLen);
SetLength(sUserName, dwUserNameLen);
Result := sUserName;
end;
procedure TForm1.exitClick(Sender: TObject);
begin
Memo1.Lines.SaveToFile('C:\Numbergen\NumberDB.txt');
form1.Close;
end;
procedure TForm1.resetbtnClick(Sender: TObject);
begin
edit1.Clear;
edit2.Clear;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Lines.LoadFromFile('C:\Numbergen\NumberDB.txt');
Memo1.WordWrap := true;
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
form1.ShowModal;
form1.Free;
end;
procedure TForm1.FormShow(Sender: TObject);
var lStrings: TStringList;
begin
DataSource1.DataSet.Append;
Label6.Caption :=GetCurrentUserName;
lStrings := TStringList.Create;
LStrings.Delimiter := ',';
lStrings.DelimitedText := Memo1.Lines[Memo1.Lines.Count-1];
Label8.Caption:= lStrings.Strings[0];
Label13.Caption:= lStrings.Strings[1];
Label14.Caption:= lStrings.Strings[2];
Label15.Caption:= lStrings.Strings[3];
end;
procedure TForm1.dellastentryClick(Sender: TObject);
begin
Memo1.Lines.Delete(Memo1.Lines.Count-1);
end;
procedure TForm1.Button6Click(Sender: TObject);
var val2, sum: Integer;
begin
val2 := StrToInt(Edit3.Text);
sum := val2;
Edit3.Text := (IntToStr(sum+1));
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if checkbox1.Checked
then
Edit1.Text := Label6.Caption
else Edit1.Text :='';
end;
procedure TForm1.GenerateClick(Sender: TObject);
var val1, val2, sum: Integer;
begin
val1 := StrToInt(Edit2.Text);
val2 := StrToInt(Edit3.Text);
sum := val1 + val2;
Edit3.Text := IntToStr(sum);
Memo1.Lines.SaveToFile('C:\Numbergen\NumberDB.txt');
if edit1.Text =('')
then MessageDlg('Invalid/Blank Username! Please enter one!',mtError, mbOKCancel, 0)
else
memo1.Lines.Add(edit1.Text+',' +edit2.Text+','+IntToStr(sum-val1)+'-'+edit3.text+ ','+formatdatetime('yyyy/mm/dd', datetimepicker1.date) );
end;
end.
Thank you
It's not the responsibility of a TDBGrid to save changes to data, you need to do that yourself. In other words, the reason your data isn't getting saved is that you aren't actually calling the "save" method of AdoQuery1. This method is actually called Post
, so somewhere in your code, e.g. the non-existent "save" button's OnClick
handler you should be doing
if AdoQuery1.State in [dsEdit, dsInsert] then
AdoQuery1.Post;
Btw, the reason your data gets saved at all with your current code is that certain dataset operations (not DBGrid ones) cause any changes to the dataset to be Post
ed. These include causing the dataset's logical cursor to scroll, e.g. by clicking in a different row in the DBGrid or closing the dataset. But it is extremely bad practice to rely on this - your form should always provide the user with an explicit way to save and cancel changes to a dataset.
Also btw, never write code like you have in your FormKeyDown
- it is an accident waiting to happen.