Reputation: 3238
I am using Delphi Rio to control Excel. I am reading and writing whole columns, so I am using VarArrayCreate to create an array of variant to read a column's worth of data. I update specific portions of the data, and then write the update back to the Variant array. When done, I write the whole Variant array back to my column.
While looping through the array, I read a single element of the array.... and potentially write back to that element of the array...
... read from the array
CellText := arrData[i, 1];
... possibly update data
... write the updated data back to the array
arrData[i,1] := CellPadded;
This works without issue. My question has to do with writing the update back to the array. I ran into the function VarArrayPut. Why would I use this as opposed to directly putting the data back into the array like in the code above?
Upvotes: 2
Views: 322
Reputation: 3830
The simple answer is that VarArrayPut
is the same as array accessor (square brackets syntax) and in the end they both invoke internal procedure _VarArrayPut
in unit System.Variants
. Likewise reading value from the array using square brackets or VarArrayGet
will result in a call to internal function _VarArrayGet
. You can easily check that yourself by stepping into (F7) the assignment arrData[i, 1] := CellPadded;
during a debugging session.
That said, the variant array accessor is just a syntactic sugar that Delphi compiler provides to make the code shorter and more readable, but that is a subject of personal taste. Consider the following:
arrData[i, 1] := CellPadded;
{ vs }
VarArrayPut(arrData, CellPadded, [i, 1]);
In case you do a lot of data manipulation and you're not resizing the array during the processing you might as well do it in a VarArrayLock
.. VarArrayUnlock
block to gain some extra performance by direct access to array data bypassing all the sanity checks and API calls that _VarArrayGet
and _VarArrayPut
do internally:
{ untested, use at your own risk }
{$POINTERMATH ON}
var
Data: PVariant; { in case of variant array of varVariant }
LBound1, LBound2, HBound2: Integer;
Data := VarArrayLock(arrData);
try
LBound1 := VarArrayLowBound(V, 1);
LBound2 := VarArrayLowBound(V, 2);
HBound2 := VarArrayHighBound(V, 2);
{ access element value at [i, j] }
(Data + i - LBound1 + (j - LBound2) * (HBound2 - LBound2 + 1))^ := CellPadded;
{ ... }
finally
VarArrayUnlock(arrData);
end;
This won't of course work with jagged arrays.
Upvotes: 7