Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 7 of 7 total
Thread Field not found problem
Mon, Jan 23 2006 4:08 PMPermanent Link

Jeff Cook
Hi

I've allowed users to add custom fields into some tables each prefixed with 'cf'.  I have the mechanics to load CustomFieldNames with the field names and CustomFields with the values and a tailorable entry screen.  The code below in the PropertyTableBeforePost event is supposed to get the entered values into the record.
===========
for i := 0 to CustomFieldNames.Count - 1 do
PropertyTable.FieldByName(CustomFieldNames[i]).AsString := CustomFields[i];
===========
In debugging I can see that CustomFieldNames[i] evaluates to 'cfAlarmCode', but this line gives rise to the exception:-

PropertyTable: Field 'cfAlarmCode' not found.

I've checked the PropertyTable with DBSYS and the field definitely exists - indeed I filled the CustomFieldNames stringlist from the table originally.

Is there something wrong with what I'm doing?  

DBISAM v3.30

Cheers

Jeff


P.S.  I'm aware that I'll need some mechanism to trap errors e.g. If someone types 'XXX' into a currency field, but for the moment I'd be happy if it worked for valid data!

--
Jeff Cook
Aspect Systems Ltd
Phone: +64-9-424 5388
Skype: jeffcooknz
www.aspect.co.nz



Mon, Jan 23 2006 4:17 PMPermanent Link

Sean McCall
Jeff,

Are you using persistent fields? If you have the persistent
fields defined in the DFM file, FieldByName won't find them
in the table even if they exist in the physical table
because FieldByName only looks to the field objects that
have been created for the table instance.

If this is the problem, you will either have to let your
tables dynamically define their fields (no fields defined in
the fields editor) or add persistent fields to the table
while at runtime (table must be closed when you add them).

Hope this helps,

Sean

Jeff Cook wrote:
> Hi
>
> I've allowed users to add custom fields into some tables each prefixed with 'cf'.  I have the mechanics to load CustomFieldNames with the field names and CustomFields with the values and a tailorable entry screen.  The code below in the PropertyTableBeforePost event is supposed to get the entered values into the record.
> ===========
> for i := 0 to CustomFieldNames.Count - 1 do
> PropertyTable.FieldByName(CustomFieldNames[i]).AsString := CustomFields[i];
> ===========
> In debugging I can see that CustomFieldNames[i] evaluates to 'cfAlarmCode', but this line gives rise to the exception:-
>
> PropertyTable: Field 'cfAlarmCode' not found.
>
> I've checked the PropertyTable with DBSYS and the field definitely exists - indeed I filled the CustomFieldNames stringlist from the table originally.
>
> Is there something wrong with what I'm doing?  
>
> DBISAM v3.30
>
> Cheers
>
> Jeff
>
>
> P.S.  I'm aware that I'll need some mechanism to trap errors e.g. If someone types 'XXX' into a currency field, but for the moment I'd be happy if it worked for valid data!
>
> --
> Jeff Cook
> Aspect Systems Ltd
> Phone: +64-9-424 5388
> Skype: jeffcooknz
> www.aspect.co.nz
>  
>
>
>
Mon, Jan 23 2006 6:12 PMPermanent Link

Jeff Cook
Sean McCall <NoSpam@nowhere.com> wrote on Mon, 23 Jan 2006 16:17:23 -0500

>
>Jeff,
>
>Are you using persistent fields? If you have the persistent
>fields defined in the DFM file, FieldByName won't find them
>in the table even if they exist in the physical table
>because FieldByName only looks to the field objects that
>have been created for the table instance.
>
>If this is the problem, you will either have to let your
>tables dynamically define their fields (no fields defined in
>the fields editor) or add persistent fields to the table
>while at runtime (table must be closed when you add them).
>

Sean


I wrote a little test project to prove that I could use FieldByName without persistent fields and I could and was just about to reply that you were wrong! Wink

But I then I added all the fields as persistent fields and it still worked.  Then I removed the one field I was looking at and bingo - an error!  What a funky way for Delphi to work!

You say "add persistent fields to the table while at runtime (table must be closed when you add them)."  

How do you do that?

Cheers

Jeff
========Test Project============
procedure TForm1.Button1Click(Sender: TObject);
begin
 DBISAMTable1.Edit;
 DBISAMTable1.FieldByName('cfAlarmCode').AsString := Edit1.Text;
 DBISAMTable1.Post;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
 DBISAMTable1.Open;
 Edit1.Text := DBISAMTable1.FieldByName('cfAlarmCode').AsString;
end;

--
Jeff Cook
Aspect Systems Ltd
Phone: +64-9-424 5388
Skype: jeffcooknz
www.aspect.co.nz



Tue, Jan 24 2006 8:53 AMPermanent Link

Sean McCall
Jeff,

There are two ways I can think of. You can either create a
field object and set its properties (you can look at the DFM
file to see which properties you need to set or at
TFieldDef.CreateField), something like:

AField := TMyStringField.Create(ATable);
AField.Dataset := ATable;
AField.FieldName := 'cfSomething';
etc.

or, you can use the field definition to create the field. I
think this is the prefered method and it should look
something like this:

ATable.FieldDefs.Update;
AFieldDef := ATable.FieldDefs.Find('cfSomething');
AField := AFieldDef.CreateField;

Obviously you don't need to maintain the variable with the
field pointer unless you want to.

Good luck,

Sean

Jeff Cook wrote:
> Sean McCall <NoSpam@nowhere.com> wrote on Mon, 23 Jan 2006 16:17:23 -0500
>
>
>>Jeff,
>>
>>Are you using persistent fields? If you have the persistent
>>fields defined in the DFM file, FieldByName won't find them
>>in the table even if they exist in the physical table
>>because FieldByName only looks to the field objects that
>>have been created for the table instance.
>>
>>If this is the problem, you will either have to let your
>>tables dynamically define their fields (no fields defined in
>>the fields editor) or add persistent fields to the table
>>while at runtime (table must be closed when you add them).
>>
>
>
> Sean
>
>
> I wrote a little test project to prove that I could use FieldByName without persistent fields and I could and was just about to reply that you were wrong! Wink
>
> But I then I added all the fields as persistent fields and it still worked.  Then I removed the one field I was looking at and bingo - an error!  What a funky way for Delphi to work!
>
> You say "add persistent fields to the table while at runtime (table must be closed when you add them)."  
>
> How do you do that?
>
> Cheers
>
> Jeff
> ========Test Project============
> procedure TForm1.Button1Click(Sender: TObject);
> begin
>   DBISAMTable1.Edit;
>   DBISAMTable1.FieldByName('cfAlarmCode').AsString := Edit1.Text;
>   DBISAMTable1.Post;
> end;
>
> procedure TForm1.FormActivate(Sender: TObject);
> begin
>   DBISAMTable1.Open;
>   Edit1.Text := DBISAMTable1.FieldByName('cfAlarmCode').AsString;
> end;
>
> --
> Jeff Cook
> Aspect Systems Ltd
> Phone: +64-9-424 5388
> Skype: jeffcooknz
> www.aspect.co.nz
>  
>
>
>
Tue, Jan 24 2006 5:58 PMPermanent Link

Jeff Cook
Sean McCall <NoSpam@nowhere.com> wrote on Tue, 24 Jan 2006 08:53:52 -0500

>
>Jeff,
>
>There are two ways I can think of. You can either create a
>field object and set its properties (you can look at the DFM
>file to see which properties you need to set or at
>TFieldDef.CreateField), something like:
>
>AField := TMyStringField.Create(ATable);
>AField.Dataset := ATable;
>AField.FieldName := 'cfSomething';
>etc.
>
>or, you can use the field definition to create the field. I
>think this is the prefered method and it should look
>something like this:
>
>ATable.FieldDefs.Update;
>AFieldDef := ATable.FieldDefs.Find('cfSomething');
>AField := AFieldDef.CreateField;
>
>Obviously you don't need to maintain the variable with the
>field pointer unless you want to.
>
>Good luck,
>
>Sean
>


Sean


OK, now I've really confused myself  :-\

I added the code below:-
=========
 if CustomFieldNames.Count > 0 then
 begin
   PropertyTable.Close;
   PropertyTable.FieldDefs.Update;
//    for j := 0 to CustomFieldNames.Count - i do
//      PropertyTable.FieldDefs.Add(CustomFieldNames[j], ftString, 30); // sort out size and type later!
   PropertyTable.Open;
 end;
==========

With the commented code,  I get an error message saying that 'cfAlarmCode already exists even though I haven't defined them in the field editor.
Without the commented code,  I get an error message saying that 'cfAlarmCode' is not found when I come to do the following in BeforePost:-
=============
 for i := 0 to CustomFieldNames.Count - 1 do
   PropertyTable.FieldByName(CustomFieldNames[i]).AsString := CustomFields[i];
=============

What's going on here?  I've looked back at your suggestion and think I understand, but can't see how to to implement it when I don't know until runtime how many fields (and what types I have to deal with).

Cheers


Jeff



--
Jeff Cook
Aspect Systems Ltd
Phone: +64-9-424 5388
Skype: jeffcooknz
www.aspect.co.nz



Wed, Jan 25 2006 8:25 AMPermanent Link

Sean McCall
Jeff,

The FieldDefs.Update loads the table structure into
FieldDefs, so you shouldn't be adding to the FieldDefs
unless you are going to use them to create another table.
The Fields structure holds your persistent fields. What you
need to do is find the field definition for your custom
field in the FieldDefs and then create an additional
persistent TField from the field definition. So, something like:
var
  AFieldDef: TFieldDef; {may need to be TDBISAMFieldDef}
begin
  if CustomFieldNames.Count > 0 then begin
    PropertyTable.Close;
    PropertyTable.FieldDefs.Update;
    for j := 0 to CustomFieldNames.Count - i do begin
      AFieldDef :=
          PropertyTable.FieldDefs.Find(CustomFieldNames[j]);
      if AFieldDef <> nil then begin
         AFieldDef.CreateField;
        end {if custom field exists in table structure}
      else begin
         {exception / message / or just ignore}
      end; {if custom field doesn't exist in table}
    end; {for J}
    PropertyTable.Open;
  end; {if custom fields defined}
end; {procedure}

Note that the AFieldDef.CreateField will create a TField
descendant (eg TStringField) with the correct size and other
properties to match the field that exists in the table
structure.

Let me know if you still have problems & I'll send a tested
example,

Sean

> Sean
>
>
> OK, now I've really confused myself  :-\
>
> I added the code below:-
> =========
>   if CustomFieldNames.Count > 0 then
>   begin
>     PropertyTable.Close;
>     PropertyTable.FieldDefs.Update;
> //    for j := 0 to CustomFieldNames.Count - i do
> //      PropertyTable.FieldDefs.Add(CustomFieldNames[j], ftString, 30); // sort out size and type later!
>     PropertyTable.Open;
>   end;
> ==========
>
> With the commented code,  I get an error message saying that 'cfAlarmCode already exists even though I haven't defined them in the field editor.
> Without the commented code,  I get an error message saying that 'cfAlarmCode' is not found when I come to do the following in BeforePost:-
> =============
>   for i := 0 to CustomFieldNames.Count - 1 do
>     PropertyTable.FieldByName(CustomFieldNames[i]).AsString := CustomFields[i];
> =============
>
> What's going on here?  I've looked back at your suggestion and think I understand, but can't see how to to implement it when I don't know until runtime how many fields (and what types I have to deal with).
>
> Cheers
>
>
> Jeff
>
>
>
> --
> Jeff Cook
> Aspect Systems Ltd
> Phone: +64-9-424 5388
> Skype: jeffcooknz
> www.aspect.co.nz
>  
>
>
>
Wed, Jan 25 2006 3:39 PMPermanent Link

Jeff Cook
Sean McCall <NoSpam@nowhere.com> wrote on Wed, 25 Jan 2006 08:25:50 -0500
>
>The FieldDefs.Update loads the table structure into
>FieldDefs, so you shouldn't be adding to the FieldDefs
>unless you are going to use them to create another table.
>The Fields structure holds your persistent fields. What you
>need to do is find the field definition for your custom
>field in the FieldDefs and then create an additional
>persistent TField from the field definition.

Sean


Magic!  That code did exactly what I wanted.  Thank you so much.  Once I got the difference between the FieldDefs and the Fields structure into my thick head it all made perfect sense.

Cheers and thanks again

Jeff
--
Jeff Cook
Aspect Systems Ltd
Phone: +64-9-424 5388
Skype: jeffcooknz
www.aspect.co.nz



Image