Board index » delphi » DBGrid having difficulty displaying 'summary' of TMemoField

DBGrid having difficulty displaying 'summary' of TMemoField

DBGrid having difficulty displaying 'summary' of TMemoField

* Problem *:    DBGrid displaying rows erratically.  With only three
records, Id's of 1 2 and 3 respectively, present in the table, it would
display 1, 2, 3, 2, 2, ?... when ANY of the 4 methods in the test code
below were tried.  Commenting ALL 4 methods out, and the problem just 'goes
away'.  It seems that ANY attempt to 'read' the TMemoField during an
OnCalcFields event generates this anomaly.

* Desired Effect *:    For each record displayed within a TDBGrid, I want
to be able to show a brief summary of the contents of 'Memo' field(s).

* Question *:    Is my desired effect possible?  If so, how?  But, before
you answer though, please look at my code snip-it below to see the four
methods I have already tried.  All four methods generated the 'problem'. I
have searched the Web and News Groups, via AltaVista's advanced search
area, and was unable to find anything helpful.  Additionally, after
reviewing this news group, I found there were a number of others who were
looking for solutions in this general area, but none of the questions were
as specific as this.

* Test *:    I have created a test to narrow down the problem I have been
experiencing with TMemoField.  This test has been done with a table that
has been created both in Paradox (7) and Oracle 7.3.2.2.1.

I have defined a table, 'jimos', and within it are 2 fields, 'Id' and
'Days'.  In Database Desktop, the Paradox 7 fields defs were Id = Number
and Days = Memo.  In Oracle, Id = Integer and Days = VarChar(1000).  I then
inserted 3 rows of data, indicated below in 'Example Data'.

I then added Table1(generic TTable) to my form, defaults for all properties
except for:
  DatabaseName = '?' - This was determined by an alias to either Paradox or
Oracle.
  TableName = 'jimos'
  IndexFieldNames = 'Id'

I then added a Calculated field to Table1 named 'DAYSSHORT' of type String
and length 40.  The procedure 'Table1CalcFields' below shows the code I
tried.

Then, DataSource1(generic TDataSource) was added to the Form, connecting to
Table1.  Then DBGrid1 (generic TDBGrid) was added to the form and pointed
to DataSource1 for its info.

* Answers *: I would appreciate any illumination that is possible.  Thanks
in advance - Please mail the news group and me, if possible.

L8r,

-jimo

+----------------------------------------------------------------+
 \ My motto: 'Being happy through living, learning, and loving.'  \
  \ Quote: 'Being wise is an effective use of intelligence in      \
   \           being happy.' -Brigetta Barone & Jim O'Flaherty, Jr. \
    \                                                                \
     \ Jim O'Flaherty, Jr.        j...@sequel.com        817-577-4114 \
      \                          Hurst, Texas, USA                     \
       +----------------------------------------------------------------+

PS:
NOTE: This is the code/Data with which I have worked.

(* To test Oracle and see if problem persists beyond Paradox.
-- ============================================================
--   Table: JIMOS
-- ============================================================
CREATE TABLE JIMOS
(
    ID                            INTEGER                NOT NULL,
    DAYS                          VARCHAR(1000)          ,
    CONSTRAINT PK_JIMOS PRIMARY KEY (ID)
)

Example Data:
  insert into jimos (ID, DAYS) values (
    1,
    '123456789012345678901234567890123456789');
  insert into jimos (ID, DAYS) values (
    2,
    '1234567890123456789012345678901234567890);
  insert into jimos (ID, DAYS) values (
    3,
    '12345678901234567890123456789012345678901');
*)

procedure TdmdBaseTree.Table1CalcFields(DataSet: TDataSet);
  var
    sTemp: String;
    slTemp: TStringList;
  begin
  with Table1 do
    if not FieldByName('Id').IsNull then
      begin
      //Note: 'DAYSSHORT' is a Calc field defined as String(40).
//Method 1
      FieldByName('DAYSSHORT').AsString :=
          Copy(FieldByName('DAYS').AsString, 1, 40);

//Method 2
  //  sTemp := FieldByName('DAYS').AsString;
  //  FieldByName('DAYSSHORT').AsString := sTemp;

//Method 3
  //  sTemp := TMemoFieldToString(TMemoField(FieldByName('DAYS')));
  //  FieldByName('DAYSSHORT').AsString := sTemp;

//Method 4
(*    slTemp := TStringList.Create;
      try
        slTemp.Assign(FieldByName('Description'));
        if slTemp.Count > 0 then
            FieldByName('DescriptionShort').AsString := slTemp[0];
      finally
        slTemp.Free;
      end; {try}
*)
      end;
  end;

//Used in Method 3 above.
  function TMemoFieldToString(Memo: TMemoField): String;
    var
      bsTemp: TBlobStream;
      pcTemp: PChar;
      iSize,
      iHowMany: Integer;
    begin
    bsTemp := TBlobStream.Create(TMemoField(Memo), bmRead);
    try
      iSize := bsTemp.Size;
      if iSize > 0 then
        begin
        GetMem(pcTemp, iSize);
        try
          FillChar(pcTemp^, iSize, #0);
          iHowMany := bsTemp.Read(pcTemp^, iSize);
          Result := '' + pcTemp;
        finally
          FreeMem(pcTemp);
        end; {try}
        end;
    finally
      bsTemp.Free;
    end; {try}
    end;

 

Re:DBGrid having difficulty displaying 'summary' of TMemoField


In article <01bc22bf$6648b470$1dae34cc@atlas>, Jim O'Flaherty
<j...@sequel.com> writes

Quote
>DBGrid having difficulty displaying 'summary' of TMemoField

[problem snipped]

Though I'm unable to help in any way with the poster's problem, an
easier way to display Memo field text in a Grid is to use the
TMemofields 'GetText' event (as opposed to the use a a calc field). An
example (D2) follows, but you could do the same with D1 (subject to a
max string length of 255 characters):

procedure TDM.MemofieldGetText(Sender: TField; var Text: string;
  DisplayText: Boolean);
var BS: TBlobstream;
begin
      if DisplayText and not Sender.Isnull then
      try
         BS := TBlobStream.Create(Sender as TMemoField,bmRead);
         BS.Seek(0,0);
         SetLength(Text,BS.Size);
         SetLength(Text,BS.Read(Text[1],Length(Text)));
         BS.Free;
         while Pos(#13, Text) > 0 do              {remove carriage
returns and}
               Text[Pos(#13, Text)] := ' ';              {line feeds}
         While Pos(#10, Text) > 0 do
               Text[Pos(#10, Text)] := ' ';
      except
      end
      else Text := '';
end;

The check on 'DisplayText' is important.

Mark

--
Mark Williams                   M...@polyhdrn.demon.co.uk

Polyhedron Software Ltd.        
Programs for Programmers - QA, Compilers, Graphics

************ Visit our Web site on http://www.polyhedron.co.uk/ ************

Re:DBGrid having difficulty displaying 'summary' of TMemoField


Thanks for the response.  Alas, it mostly solved my problemit seems that
as long as I do not modify the contents of a TMemoField through a TDBMemo,
everything is hunky dory.  But, regardless of Insert or Edit, if I modify
the contents of the TMemoField through a TDBMemo, it updates the current
record fine, all the other records' same field clear themselves visually.
The display is just empty.

Any idea why?  More importantly, how do I cause it to leave them alone, or
display correctly?

I did modify the code you sent me somewhat.  I resource protected BS.  I
commented why the 'except' was needed.  And I used sTemp instead of Text to
assure any problems were corrected before assigning to Text.  Otherwise,
this code should be identical to yours.

L8r,

-jimo

+----------------------------------------------------------------+
 \ My motto: 'Being happy through living, learning, and loving.'  \
  \ Quote: 'Being wise is an effective use of intelligence in      \
   \           being happy.' -Brigetta Barone & Jim O'Flaherty, Jr. \
    \                                                                \
     \ Jim O'Flaherty, Jr.        j...@sequel.com        817-577-4114 \
      \                          Hurst, Texas, USA                     \
       +----------------------------------------------------------------+

PS:
NOTE: This is the NEW code with which I have worked.

procedure TdmdBaseTree.Table1DAYSGetText(Sender: TField; var Text: string;
    DisplayText: Boolean);
  begin
  TableGetText(Sender, Text, DisplayText);
  end;

procedure TableGetText(Sender: TField; var Text: String;
    DisplayText: Boolean);
  var
    BS: TBlobstream;
    sTemp: String;
  begin
  if DisplayText and (not Sender.Isnull) then
    begin
    try
      BS := TBlobStream.Create(Sender as TMemoField, bmRead);
      try
        BS.Seek(0,0);
        SetLength(sTemp, BS.Size);
        SetLength(sTemp, BS.Read(sTemp[1], BS.Size));
      finally
        BS.Free;
      end; {try}
      while Pos(#13, sTemp) > 0 do //remove carriage returns
        sTemp[Pos(#13, sTemp)] := ' ';
      while Pos(#10, sTemp) > 0 do //remove carriage line feeds
        sTemp[Pos(#10, sTemp)] := ' ';
    except
      //Avert BS.Size anomaly upon TMemoField change, dsEdit or
dsInsert...but
      //  all other displayed records' same field erase UNTIL return to
dsBrowse.
      //Length(sTemp) here returns -1!!!!
      sTemp := '';
    end; {try}
    end
  else
    sTemp := '';
  Text := sTemp;
  end;

Mark Williams <M...@polyhdrn.demon.co.uk> wrote in article
<aQDC3AAQErEzI...@polyhdrn.demon.co.uk>...

Quote
> In article <01bc22bf$6648b470$1dae34cc@atlas>, Jim O'Flaherty
> <j...@sequel.com> writes
> >DBGrid having difficulty displaying 'summary' of TMemoField

> [problem snipped]

> Though I'm unable to help in any way with the poster's problem, an
> easier way to display Memo field text in a Grid is to use the
> TMemofields 'GetText' event (as opposed to the use a a calc field). An
> example (D2) follows, but you could do the same with D1 (subject to a
> max string length of 255 characters):

> procedure TDM.MemofieldGetText(Sender: TField; var Text: string;
>   DisplayText: Boolean);
> var BS: TBlobstream;
> begin
>       if DisplayText and not Sender.Isnull then
>       try
>          BS := TBlobStream.Create(Sender as TMemoField,bmRead);
>          BS.Seek(0,0);
>          SetLength(Text,BS.Size);
>          SetLength(Text,BS.Read(Text[1],Length(Text)));
>          BS.Free;
>          while Pos(#13, Text) > 0 do              {remove carriage
> returns and}
>                Text[Pos(#13, Text)] := ' ';              {line feeds}
>          While Pos(#10, Text) > 0 do
>                Text[Pos(#10, Text)] := ' ';
>       except
>       end
>       else Text := '';
> end;

> The check on 'DisplayText' is important.

> Mark

> --
> Mark Williams                   M...@polyhdrn.demon.co.uk

> Polyhedron Software Ltd.        
> Programs for Programmers - QA, Compilers, Graphics

> ************ Visit our Web site on http://www.polyhedron.co.uk/
************

Re:DBGrid having difficulty displaying 'summary' of TMemoField


In article <01bc22bf$6648b470$1dae34cc@atlas>, j...@sequel.com says...

Quote

>DBGrid having difficulty displaying 'summary' of TMemoField

>* Problem *:    DBGrid displaying rows erratically.  With only three
>records, Id's of 1 2 and 3 respectively, present in the table, it would
>display 1, 2, 3, 2, 2, ?... when ANY of the 4 methods in the test code
>below were tried.  Commenting ALL 4 methods out, and the problem just 'goes
>away'.  It seems that ANY attempt to 'read' the TMemoField during an
>OnCalcFields event generates this anomaly.

In Delphi 2, this works for me (I have the fields defined through the
fields editor on the table - underlying table is paradox)

procedure TForm1.Table1CalcFields(DataSet: TDataSet)
begin
     Table1CalcField.value := MemoField.asString;
end;

Klint.

Other Threads