Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 16 total
Thread Creating calculated fields at run time.
Mon, Jul 30 2007 10:28 PMPermanent Link

"Jeff Cook"
Hi  (DBISAM 3.30)

I have a program that is like a poor man's DBSYS ... select a table
from the data directory and display it in a grid, select another table
etc.  We distribute it with our app so that we can do stuff with Remote
Assistant without putting a "dangerous" utility like DBSYS out in
public.

What I want to do is have way of displaying the contents of Blobs -
usually memos really - in the grid without having to double click the
[BLOB] as at present.

My idea was to create a calculated field for each blob field and and
populate it with .AsString" in the oncalculate event.

I've run into three problems.

1.  Even though I think I have created fields for the blobs, I don't
know how to set the FieldKind to calculated.
2.  My created fields don't appear in the grid.
3.  When I change my DBISAMTable component to point at a different
table, I get an error message "DBISAMTable1: Field 'xxxx' not found"
where xxxx is a field in the previous table.  This is despite having
the   DBISAMTable1.FieldDefs.Clear;

My code is below.  Am I on the right track?  Despite having a fairly
low customer number, I've not done much with these
DBISAMTable1.FieldDefs and I could be going down a completely wrong
track.

Cheers

Jeff


======================
procedure TfrmDBISAMFileView.DBISAMTable1BeforeOpen(DataSet: TDataSet);
var
 i: integer;
 b: boolean;
begin
 .
 .
 .
 DBISAMTable1.FieldDefs.Clear;
 DBISAMTable1.FieldDefs.Update;
 b := False;
 for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
 begin
   DBISAMTable1.FieldDefs[i].CreateField(DBISAMTable1);
   if DBISAMTable1.FieldDefs[i].DataType = ftBlob then b := True;
 end;
 if b then
 begin
   for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
     if DBISAMTable1.FieldDefs[i].DataType = ftBlob then
     begin
       DBISAMTable1.FieldDefs.Add(DBISAMTable1.FieldDefs[i].Name +
'_AsString',
         ftString, 100);
     end;
 end;
 DBGrid1.Columns.RebuildColumns;  // I've tried this in th AfterOpen
event to with no success
end;

--
Jeff Cook
Aspect Systems Ltd
www.aspect.co.nz
+
Joan and Jeff Cook
The Cooks Oasis
www.cookislandsoasis.com
Tue, Jul 31 2007 3:10 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Jeff


Do it the easy way - switch to one of the grids that support it - DevEx, TMS, or have a hunt on Torry there are a few there.

Roy Lambert
Tue, Jul 31 2007 5:39 AMPermanent Link

Roy Lambert

NLH Associates

Team Elevate Team Elevate

Jeff

Check out Mike's freeware grid - http://www.scalabium.com/. This will do what you want, and more.


Roy Lambert
Tue, Jul 31 2007 6:26 AMPermanent Link

Eryk Bottomley
Jeff,

From memory, untested:

procedure TfrmDBISAMFileView.DBISAMTable1BeforeOpen(DataSet: TDataSet);
var
  i: integer;
  b: boolean;
begin
  .
  .
  .
  DBISAMTable1.FieldDefs.Clear;
  DBISAMTable1.FieldDefs.Update;
  b := False;
  for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
  begin
    DBISAMTable1.FieldDefs[i].CreateField(DBISAMTable1);
    if DBISAMTable1.FieldDefs[i].DataType = ftBlob then b := True;
  end;
  if b then
    for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
      if DBISAMTable1.FieldDefs[i].DataType = ftBlob then
        with TStringField.Create(DBISAMTable1) do begin
          Calculated := True;
          Size := 63; //or whatever
          FieldKind := fkCalculated;
          FieldName := DBISAMTable1.FieldDefs[i].Name + '_AsString';
          Name := FieldName;
          Index := DBISAMTable1.FieldDefs.Count;
          DataSet := DBISAMTable1;
        end;
end;
Tue, Jul 31 2007 3:58 PMPermanent Link

"Jeff Cook"
Thanks Eryk

Eryk Bottomley wrote:
>
> From memory, untested:
>

.... and perfect - the calculated fields appear in the grid now - I just
have to do the OnCalcFields bit.  Meitaki maata.

.... but I still have my item 3 problem ...

3.  When I change my DBISAMTable component to point at a different
table, I get an error message "DBISAMTable1: Field 'xxxx' not found"
where xxxx is a field in the previous table.  This is despite having
the   DBISAMTable1.FieldDefs.Clear;

I can step through the "end;" of the BeforeOpen event code and the
error occurs.

Also, after getting the error, if I try to reopen the orginal table, I
get another error, this time saying that I have a "Duplicate fieldname
'xxxx'" where 'xxxx' is the first field of the table.

Any thoughts anyone?

Cheers

Jeff

--
Jeff Cook
Aspect Systems Ltd
www.aspect.co.nz
+
Joan and Jeff Cook
The Cooks Oasis
www.cookislandsoasis.com
Tue, Jul 31 2007 4:14 PMPermanent Link

"Jeff Cook"
Roy Lambert wrote:

> Jeff
>
> Check out Mike's freeware grid - http://www.scalabium.com/. This will
> do what you want, and more.
>
>
> Roy Lambert

Thanks Roy,

That is probably what I should do and probably should do in my main
application too.

I've got seven years of development in our product and a heavy
investment in plain old TDBGrid with lots of OnDrawColumnCell code.

For my next major version I'd like change to one of the fancy grid
offerings and modernise the look.

Meanwhile I'd like to tease this problem out - might help my
understanding of how this thing works!

Cheers

Jeff

--
Jeff Cook
Aspect Systems Ltd
www.aspect.co.nz
+
Joan and Jeff Cook
The Cooks Oasis
www.cookislandsoasis.com
Tue, Jul 31 2007 5:04 PMPermanent Link

Eryk Bottomley
Jeff

> 3.  When I change my DBISAMTable component to point at a different
> table, I get an error message "DBISAMTable1: Field 'xxxx' not found"
> where xxxx is a field in the previous table.  This is despite having
> the   DBISAMTable1.FieldDefs.Clear;


FieldDefs and Fields are not the same thing. Clearing one will not clear
the other (at least not in all cases). The code I posted earlier
manually creates some TStringField objects and I just noticed that you
are manually creating fields for everything else with FieldDefs.CreateField.

> Also, after getting the error, if I try to reopen the orginal table, I
> get another error, this time saying that I have a "Duplicate fieldname
> 'xxxx'" where 'xxxx' is the first field of the table.


You have effectively faked the existence of persistent TFields with the
code above (i.e. forced TDataset.DefaultFields to false) so closing the
table component doesn't clear up the associated field components.

Try adding something like:

  for i := Dataset.Fields.Count - 1 downto 0 do
    if Dataset.Fields[i].Tag = 1 then
      Dataset.Fields[i].Free;

....in the AfterClose event handler.

Alternatively, I think you should be able to shift the TStringField
creation code to the AfterOpen event handler and lose the
FieldDefs.CreateField stuff entirelt thus allowing the table to clean up
all the field components automatically when it is closed.

Eryk
Tue, Jul 31 2007 5:51 PMPermanent Link

Eryk Bottomley
Eryk

PS: Forget the reference to Tag := 1 above ...I wrote that before I
noticed that everything was manually created anyway.
Tue, Jul 31 2007 6:09 PMPermanent Link

"Jeff Cook"
Thanks Eryk

Eryk Bottomley wrote:

> Eryk
>
> PS: Forget the reference to Tag := 1 above ...I wrote that before I
> noticed that everything was manually created anyway.

procedure TfrmDBISAMFileView.DBISAMTable1AfterClose(DataSet: TDataSet);
var
 i: integer;
begin
 for i := Dataset.Fields.Count - 1 downto 0 do Dataset.Fields[i].Free;
end;

.... This did the trick.

--
Jeff Cook
Aspect Systems Ltd
www.aspect.co.nz
+
Joan and Jeff Cook
The Cooks Oasis
www.cookislandsoasis.com
Tue, Jul 31 2007 8:50 PMPermanent Link

Sean McCall
Jeff Cook wrote:
> Hi  (DBISAM 3.30)
>
> I have a program that is like a poor man's DBSYS ... select a table
> from the data directory and display it in a grid, select another table
> etc.  We distribute it with our app so that we can do stuff with Remote
> Assistant without putting a "dangerous" utility like DBSYS out in
> public.
>
> What I want to do is have way of displaying the contents of Blobs -
> usually memos really - in the grid without having to double click the
> [BLOB] as at present.
>
> My idea was to create a calculated field for each blob field and and
> populate it with .AsString" in the oncalculate event.
>
> I've run into three problems.
>
> 1.  Even though I think I have created fields for the blobs, I don't
> know how to set the FieldKind to calculated.
> 2.  My created fields don't appear in the grid.
> 3.  When I change my DBISAMTable component to point at a different
> table, I get an error message "DBISAMTable1: Field 'xxxx' not found"
> where xxxx is a field in the previous table.  This is despite having
> the   DBISAMTable1.FieldDefs.Clear;
>
> My code is below.  Am I on the right track?  Despite having a fairly
> low customer number, I've not done much with these
> DBISAMTable1.FieldDefs and I could be going down a completely wrong
> track.
>
> Cheers
>
> Jeff
>
>
> ======================
> procedure TfrmDBISAMFileView.DBISAMTable1BeforeOpen(DataSet: TDataSet);
> var
>   i: integer;
>   b: boolean;
> begin
>   .
>   .
>   .
>   DBISAMTable1.FieldDefs.Clear;
>   DBISAMTable1.FieldDefs.Update;
>   b := False;
>   for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
>   begin
>     DBISAMTable1.FieldDefs[i].CreateField(DBISAMTable1);
>     if DBISAMTable1.FieldDefs[i].DataType = ftBlob then b := True;
>   end;
>   if b then
>   begin
>     for i := 0 to DBISAMTable1.FieldDefs.Count - 1 do
>       if DBISAMTable1.FieldDefs[i].DataType = ftBlob then
>       begin
>         DBISAMTable1.FieldDefs.Add(DBISAMTable1.FieldDefs[i].Name +
> '_AsString',
>           ftString, 100);
>       end;
>   end;
>   DBGrid1.Columns.RebuildColumns;  // I've tried this in th AfterOpen
> event to with no success
> end;
>
Page 1 of 2Next Page »
Jump to Page:  1 2
Image