Board index » delphi » TFields - How to Assign a UserDefined SET to a Calculated Field

TFields - How to Assign a UserDefined SET to a Calculated Field

I have defined an enumerated type, and then a set of that enumerated type
for a list of bitmap indicators I want to display in a column of a DBGrid.
I have defined a calculated field, and in the Calculate event I add the
appropriate indicator to the set based on several computations.  The problem
I am having is I cannot assign the set to the Calculated field.  I get an
incompatible types Variant and TPatIndSet error, or an Invalid case if I
try:

TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

Any ideas would really be appreciated.

 

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Hi Larry,
variants can hold only those types they can - look at varType function.
To store a SET of whatever in a database table, you will have to
transform your set to something the table can accept - maybe string? You
could also
move the set into longint if its base type is small enough
 (<=32 elements), or into a blob (virtually any set).
You will, however run into troubles if you later decide
to change the number and/or ordering in the base element type.
I would suggest to simply use several boolean fields.
--
Roman
(please remove STOPSPAM. in header)
URL:  www.rksolution.cz (Delphi corner)
MAIL: I...@rksolution.cz

Quote
Larry Hengen wrote in message <6s3uvd$ng...@forums.borland.com>...
>I have defined an enumerated type, and then a set of that enumerated type
>for a list of bitmap indicators I want to display in a column of a DBGrid.
>I have defined a calculated field, and in the Calculate event I add the
>appropriate indicator to the set based on several computations.  The
problem
>I am having is I cannot assign the set to the Calculated field.  I get an
>incompatible types Variant and TPatIndSet error, or an Invalid case if I
>try:

>TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

>Any ideas would really be appreciated.

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Larry:

Depends on how many elements are in the enumeration. If it is 32 or
less, I'm pretty sure you can directly cast the set as an Integer.

HTH,
Glynn

Quote
Larry Hengen wrote:

> I have defined an enumerated type, and then a set of that enumerated type
> for a list of bitmap indicators I want to display in a column of a DBGrid.
> I have defined a calculated field, and in the Calculate event I add the
> appropriate indicator to the set based on several computations.  The problem
> I am having is I cannot assign the set to the Calculated field.  I get an
> incompatible types Variant and TPatIndSet error, or an Invalid case if I
> try:

> TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

> Any ideas would really be appreciated.

--
Linus's Law: Given enough eyeballs, all bugs are shallow.

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Reading the online help for enumerated types indicates that each element of
a type is bit encoded, and there can be up to 256 elements in a set,
therefore up to 32 bytes can be used.  I don't think this will work as a
result.

In fact it doesn't.  I get an invalid type cast error.

Thanks for the suggestion though.  Any other ideas?

Quote
Glynn Owen wrote in message <35E5906A.DA995...@pagekeeper.com>...
>Larry:

>Depends on how many elements are in the enumeration. If it is 32 or
>less, I'm pretty sure you can directly cast the set as an Integer.

>HTH,
>Glynn

>Larry Hengen wrote:

>> I have defined an enumerated type, and then a set of that enumerated type
>> for a list of bitmap indicators I want to display in a column of a
DBGrid.
>> I have defined a calculated field, and in the Calculate event I add the
>> appropriate indicator to the set based on several computations.  The
problem
>> I am having is I cannot assign the set to the Calculated field.  I get an
>> incompatible types Variant and TPatIndSet error, or an Invalid case if I
>> try:

>> TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

>> Any ideas would really be appreciated.

>--
>Linus's Law: Given enough eyeballs, all bugs are shallow.

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Thanks for the response Roman.

I have been looking at Variants as the solution to this problem, but don't
know them all that well.  I agree that converting them  to some variant type
would work, but what type?  I also have to be able to convert the variant
data type back into the set so I can reference it in my OnDrawColumnCell
routine.

The set I am currently testing with has two elements.  Typically I am told,
we will not have more than 3 indicators to display in the grid.  I have
tried assigning the set to an Integer field, and I get an invalid type cast
on the set, and I cannot do a direct assignment.

Quote
Roman Krejci wrote in message <6s409j$ng...@forums.borland.com>...
>Hi Larry,
>variants can hold only those types they can - look at varType function.
>To store a SET of whatever in a database table, you will have to
>transform your set to something the table can accept - maybe string? You
>could also
>move the set into longint if its base type is small enough
> (<=32 elements), or into a blob (virtually any set).
>You will, however run into troubles if you later decide
>to change the number and/or ordering in the base element type.
>I would suggest to simply use several boolean fields.
>--
>Roman
>(please remove STOPSPAM. in header)
>URL:  www.rksolution.cz (Delphi corner)
>MAIL: I...@rksolution.cz

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Larry:

Below is the code of a short app I wrote to illustrate my point -

{***************************}
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

Type TEnum=(One,Two,Three);

procedure TForm1.Button1Click(Sender: TObject);
VAR Tmp:set of TEnum;
begin
  Label1.Caption := InttoStr(sizeof(Tmp));
  Tmp := [];
  Label2.Caption := IntToStr(byte(Tmp))
end;

end.
{***************************}

Delphi puts the set into a BYTE because the base enumeration has only
three elements. If it had 9, then the set would be put into a WORD. If
it had 17, the set would be put into a DWORD. If it had more than 32,
then a corresonding number of bytes would be allocated for the set, up
to the limit of 32 bytes. This makes for very fast operations on sets
with 32 elements or less.

HTH,
Glynn

Quote
Larry Hengen wrote:

> Reading the online help for enumerated types indicates that each element of
> a type is bit encoded, and there can be up to 256 elements in a set,
> therefore up to 32 bytes can be used.  I don't think this will work as a
> result.

> In fact it doesn't.  I get an invalid type cast error.

> Thanks for the suggestion though.  Any other ideas?

> Glynn Owen wrote in message <35E5906A.DA995...@pagekeeper.com>...
> >Larry:

> >Depends on how many elements are in the enumeration. If it is 32 or
> >less, I'm pretty sure you can directly cast the set as an Integer.

> >HTH,
> >Glynn

> >Larry Hengen wrote:

> >> I have defined an enumerated type, and then a set of that enumerated type
> >> for a list of bitmap indicators I want to display in a column of a
> DBGrid.
> >> I have defined a calculated field, and in the Calculate event I add the
> >> appropriate indicator to the set based on several computations.  The
> problem
> >> I am having is I cannot assign the set to the Calculated field.  I get an
> >> incompatible types Variant and TPatIndSet error, or an Invalid case if I
> >> try:

> >> TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

> >> Any ideas would really be appreciated.

> >--
> >Linus's Law: Given enough eyeballs, all bugs are shallow.

--
Linus's Law: Given enough eyeballs, all bugs are shallow.

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Quote
Larry Hengen wrote:

> I have defined an enumerated type, and then a set of that enumerated type
> for a list of bitmap indicators I want to display in a column of a DBGrid.
> I have defined a calculated field, and in the Calculate event I add the
> appropriate indicator to the set based on several computations.  The problem
> I am having is I cannot assign the set to the Calculated field.  I get an
> incompatible types Variant and TPatIndSet error, or an Invalid case if I
> try:

> TQuery(DataSet).FieldByName('Indicator').Value := Variant(Indicators);

> Any ideas would really be appreciated.

Well, first you have to check if your database field is of an
ordinal type and can hold the complete set, e.g. an Integer field
can hold sets based on up to 32 different elements.

Then you have to typecast your set variable to an integer type
(Byte, Word, LongWord) that corresponds to the storage size of
the set. A set with up to 256 values is stored in a Byte, a set
with up to 65536 values is stored in a Word, etc.

Then you just assign to the field value.

First a set declaration:

type
  TWordSetBase = (wsb1, wsb2, wsb3, wsb4, wsb5, wsb6, wsb7, wsb8, wsb9, wsb10);
  TWordSet = set of TWordSetBase; //this set is stored as a Word

Then a piece of code (assuming that the dataset is in edit mode):

  var
    WordSet: TWordSet;
  begin
  Word(WordSet) := MyField.Value;     //check range if field can hold larger values
  WordSet := WordSet + [wsb5, wsb6];
  MyField.Value := Word(WordSet);
  end;

For sets that are stored in more than 4 Bytes you have to find
other (larger) database field types, but the principles are the same.

Hope that helps,

Karl Waclawek

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Thanks Glynn.  I managed to convert the string back to an enumerated type.
Neat technique.  Thanks again.

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


Quote
Doug Chamberlin wrote:

> On Thu, 27 Aug 1998 13:58:20 -0400, Karl Waclawek
> <wacla...@idirect.com> wrote:
> >Then you have to typecast your set variable to an integer type
> >(Byte, Word, LongWord) that corresponds to the storage size of
> >the set. A set with up to 256 values is stored in a Byte, a set
> >with up to 65536 values is stored in a Word, etc.

> Just a correction for any lurkers who might misunderstand this...

> A byte can hold a set of up to 8 elements, a Word up to 16 elements,
> and a Longint up to 32. Its the number of bits, not the number of bit
> combinations which is used in the set.

Well, the set type in Object Pascal is defined as the powerset of the base type,
i.e. the set of all subsets of the base type - viewing the base type
as a set (in the mathematical sense) itself.

Therefore, if the base type has 8 elements (is a set with 8 elements),
then the "set of basetype" has 2^8 (=256) different subsets as it's values.
If you view the 8 elements of the base type as the bits in a Byte, then
it becomes clear that there are 256 possible combinations of including/excluding
these bits (and thus creating different subsets as elements of the powerset).

By now, this discussion has probably confused the last one who
thought he understood... ;-)))

Karl Waclawek

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   Karl Waclawek
   KD Soft Inc.
 * Phone:  (905) 579-3443
 * E-Mail: wacla...@idirect.com

Re:TFields - How to Assign a UserDefined SET to a Calculated Field


On Thu, 27 Aug 1998 13:58:20 -0400, Karl Waclawek

Quote
<wacla...@idirect.com> wrote:
>Then you have to typecast your set variable to an integer type
>(Byte, Word, LongWord) that corresponds to the storage size of
>the set. A set with up to 256 values is stored in a Byte, a set
>with up to 65536 values is stored in a Word, etc.

Just a correction for any lurkers who might misunderstand this...

A byte can hold a set of up to 8 elements, a Word up to 16 elements,
and a Longint up to 32. Its the number of bits, not the number of bit
combinations which is used in the set.

Other Threads