Jump to content
Ian Branch

Return an array from a function??

Recommended Posts

Hi Team,

I am playing in an area I have no experience in, again.

I have the following routine found while googling.....

D10.4.2.

function RecordToArray(aDataSet: TDataSet);
var
  Data: array of variant;
  aRecord: array of TVarRec;
  i: integer;
  max: integer;
begin
  max := aDataSet.fields.count - 1;
  // set the lenghth of the arecord array to be the same as the number of
  // elements in the data array
  SetLength(arecord, max + 1);
  SetLength(data, max + 1);

  // set the variant type pointers to the data array
  for i := 0 to max do
  begin
    arecord[i].VType := vtVariant;
    arecord[i].VVariant := @data[i];
  end;

  Result := aRecord;

end;

The objective is to copy the contents of a table row into an array, which is then returned to the calling routine so the table can be closed and the array values accessed throughout the remainder of the program.  I want to keep the routine generic so I can use where ever it is convenient.  The contents of the fields can be any valid data type.  The array can vary in length.

The original routine simply took the array and copied it back into the dataset and didn't return anything.

I figured, obviously incorrectly, that if 'arecord' is declared as a TVarRec, then the function return should be an Array. Delphi didn't like it.

OK.  I declared a type of TVarArray = array of variant;, and set the return as TVarArray.  Nope, Delphi says I must return a dynamic array.

 

How do I do that please?  What should the return type be?

 

Regards & TIA,

Ian

Share this post


Link to post

Couple of ways to accomplish it,

One simple method.

 

type
 TVariantArray = array of variant;

function Foo(data:byte):TVariantArray;
begin
 SetLength(result,2);
 result[0]:=data + 123;
 result[1]:='ABCD';
end;

procedure FooTest;
var
 res:TVariantArray;
begin
 res:=Foo(1);
 ShowMessage(IntToStr(res[0]) + ' ' + res[1]);
end;

 

Share this post


Link to post

You could also do something like this, which gives you the results converted to actual types instead of variants.

 

Share this post


Link to post

There is one fundamental thing missing in your function - copying the field values. The other thing is that you don't need to mess with TVarRec at all. Here's how I would do it:

function RecordToArray(DS: TDataSet): TArray<Variant>;
var
  FieldIndex: Integer;
begin
  SetLength(Result, DS.FieldCount);
  for FieldIndex := 0 to DS.FieldCount - 1 do
    Result[FieldIndex] := DS.Fields[FieldIndex].Value;
end;

procedure ArrayToRecord(DS: TDataSet; const Values: TArray<Variant>);
var
  FieldIndex: Integer;
begin
  Assert(DS.FieldCount = Length(Values));
  for FieldIndex := 0 to DS.FieldCount - 1 do
    DS.Fields[FieldIndex].Value := Values[FieldIndex];
end;

Another option is to use variant array:

function RecordToVarArray(DS: TDataSet): Variant;
var
  FieldIndex: Integer;
  Data: PVariant;
begin
  Result := VarArrayCreate([0, DS.FieldCount - 1], varVariant);
  Data := VarArrayLock(Result);
  try
    for FieldIndex := 0 to DS.FieldCount - 1 do
    begin
      Data^ := DS.Fields[FieldIndex].Value;
      Inc(Data); // move to next elemnt in resulting array
    end;
  finally
    VarArrayUnlock(Result);
  end;
end;

procedure VarArrayToRecord(DS: TDataSet; const Values: Variant);
var
  FieldIndex: Integer;
  Data: PVariant;
begin
  Assert(VarIsType(Values, varArray or varVariant));
  Assert(VarArrayDimCount(Values) = 1);
  Data := VarArrayLock(Values);
  try
    for FieldIndex := 0 to DS.FieldCount - 1 do
    begin
      DS.Fields[FieldIndex].Value := Data^;
      Inc(Data); // move to next elemnt in resulting array
    end;
  finally
    VarArrayUnlock(Values);
  end;
end;


// you could then access those value using index:
var Values := RecordToVarArray(DS);
Writeln(VarToStr(Values[0]));
Writeln(VarToStr(Values[1]));
...

 

  • Like 1

Share this post


Link to post

All,

Thank you for your inputs & suggestions.

I have gone with 0x8000FFFF's first suggestion for its simplicity and flexibility.

 

Again, my thanks to all.

 

Regards,

Ian

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×