We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

How to edit dbf records in Delphi 1.02 with uniqueness demand?

shrldu
shrldu asked
on
Medium Priority
458 Views
Last Modified: 2010-04-06
How to edit dbf records? I try to work out a proper way of doing it. Let's say I have dbf file with an index and I want inserted records to be unique. On the other hand I do not want to use additional components (TEdit or TMaskEdit) to keep the data before inserting new record.
So, I have DBGrid on my form connected to Table1. It is used to browse the data. And I have a couple of DBEdits connected with current record in DBGrid. They are disabled. I push edit button on my form and I enable DBEdits and disable DBGrid. The user change data in DBEdits. They are accepted and then I have to check out if the key is unique. In dbf standard I have to seek for the new value, but moving the pointer in the table calls post method and the changes are written to the file. Somebody told me I can use two TTable components to connect to the same dbf file. Table1 is connected to DBGrid, Table2 to DBEdits. The user can edit data in DBEdits, and the program can check the data using Table1. It does not call the post for Table2. It works great, but after inserting record into Table2 I cannot get Table1 and Table2 synchronized. DBGrid does not show newly inserted records, although I make Table1.Refresh.
So my question is - how to edit dbf files which require uniqueness without additional components?
Thanks
Comment
Watch Question

Commented:
Use the BeforePost event.  In the handler, use FindKey to see if the key exists.  If it does, don't even add the record (raise an EAbort exception to cancel the post).  In this way you don't have to worry about grids and edit boxes etc...

Ian C.

Author

Commented:
I've just tried the solution. I used BeforePost event to check the key. Before FindKey I called SetKey. And this called BeforePost. And this called SetKey. And this called BeforePost... Until Runtime error happend, you know... The problem is that trying to check the key invokes Post method, I suppose...

Commented:
I'm not sure why you called SetKey, but that doesn't matter.  If you have a recursion problem, then disconnect your handler while you are working.

PROCEDURE Txxxx.BeforePostHandler;
BEGIN
   Table.BeforePost := NIL;
   {do your key stuff here}
   Table.BeforePost := BeforePostHandler;
END;

This will let you work without calling yourself.

Let me know.
Ian C.

Author

Commented:
Yes, it solves the recursion problem. But FindKey now calls a Post (I put a ShowMessage in AfterPost event handler), this time without entering Table1BeforePost. In THIS moment the new value is written to the file. Then, after restoring the BeforePost handler and aborting, the program returns and I have two records with the same key values... just what I wanted to prevent.


procedure TForm1.Table1BeforePost(DataSet: TDataset);
begin
  Table1.BeforePost := NIL;
  if Table1.FindKey(['3']) then
  begin
    Table1.BeforePost := Table1BeforePost;
    Abort;
  end;
  Table1.BeforePost := Table1BeforePost;
end;

Commented:
Sorry, your only chance is to put a simple TEDIT control on the form, use the OnChange method of your TTable component to update the TEDIT control - only for informating the user.

Let the User put in something in the TEDIT control, make your requests with FindKey and the decide, is the Key present, tell the User to select an other, if not, make a new database record.

If this is not clear, I can send some source.

Bye

Hartwig

Author

Commented:
Thank you, Mr Hartwig, that was my first attempt, later I tried to connect two TTables to one dbf file. Any advice on why I cannot synchronize those two tables after the record is inserted in one of them?

Bye

Commented:
If you are willing to use another TTable then there are several solutions.

procedure TForm1.Table1BeforePost(DataSet: TDataset);
Var tt2: TTable;
begin
  tt2 := TTable.Create(self);
  TRY
     tt2.tablename := Dataset.TableName; {and other setup}
     if Tt2.FindKey(['3']) then
     begin
        Abort;
     end;
   FINALLY
     Tt2.Free;
     END;
end;

If you want to keep the table around, thats up to you.  You don't have to re-create it for every use in this manner.   Also if you want to synchronize them then use Table2.GoToCurrent(Table1) for example.

With two ttable objects there are several solutions.  Let me know if you want more help, however this should do the trick.

Cheers,
Ian C.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
That's great, Ian, it works at least, just what I needed. I am going to accept this answer, but you wrote there are SEVERAL solutions with two tables. Could you write a couple of words on this, please?

Commented:
When you grade me, also give me your E-mail.  I'll send you some other thoughts in this area.  I have done extensive work with this.
Ian C.  :)

Author

Commented:
lobster@silesia.top.pl
That's what you should do:

As far as I understand, you have one TTable, one TDataSource and one TDBGrid. You need to have one more TTable which will have exactly the same DatabaseName, TableName and TableType as Table1 does. On Table1.BeforePost you call Table2.FindKey() and check: if the key value is already there, you cancel your post. You do not want to keep the tables synchronized since second TTable is used only for lookup purposes and its current record is not shown anywhere. Table1.Refresh should show the inserted record in DBGrid attached to Table1. Beware - Windows can cache the output so the record could be not physically written yet. In the database engine I use (Apollo) there is a setting to dump all updates to the disk automatically but I am not sure about BDE.
Closing and reopening Table1 always helps but that could be very slow.
Also be sure both TTables have Exclusive set to False. (Someone reported he could have two TTables on one form with Exclusive=True pointing to the same physical table, but I never could reproduce that)
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.