De OnUserFunction-callback laat applicatiecode aangepaste of
verder niet-ondersteunde werkbladfuncties evalueren tijdens
Calculate. Wijs hem toe op TXLSWorkbook of
TXLSXWorkbook vóór het aanroepen van Calculate
Gebruik OnUserFunctionEx wanneer de callback de huidige formulecontext nodig heeft. De context rapporteert de 1-gebaseerde bladindex plus de 1-gebaseerde rij en kolom van de formulecel; Calculate-aanroepen op werkmapniveau die geen cel evalueren, rapporteren rij en kolom als 0
Syntaxis
type
TXLSUserArgKind = (akuValue, akuRangeRef, akuArray);
TXLSUserFunctionContext = record
SheetIndex: Integer;
Row: Integer;
Col: Integer;
ArgCount: Integer;
ArgKinds: array of TXLSUserArgKind;
end;
TXLSUserFunctionEvent = procedure(
Sender: TObject;
const FunctionName: WideString;
const Args: Variant;
var Value: Variant;
var Handled: Boolean) of object;
TXLSUserFunctionExEvent = procedure(
Sender: TObject;
const FunctionName: WideString;
const Args: Variant;
const Context: TXLSUserFunctionContext;
var Value: Variant;
var Handled: Boolean) of object;
property OnUserFunction: TXLSUserFunctionEvent;
property OnUserFunctionEx: TXLSUserFunctionExEvent;
property AllowUnsafeFormulaCallbacks: Boolean;
Arguments
| FunctionName | De functienaam uit de formuletekst |
| Args | Een 0-gebaseerde Variant-array met geëvalueerde
argumentwaarden. Voor functies zonder argumenten is deze waarde
Null |
| Context | Bij OnUserFunctionEx geeft dit SheetIndex, Row en Col door, plus de argumentdescriptor: ArgCount komt overeen met de lengte van de Args-array (0 bij aanroepen zonder argumenten) en ArgKinds classificeert elk argument als akuValue (letterlijke waarde), akuRangeRef (verwijzing naar cel of bereik) of akuArray (arrayconstante). Sheet-, rij- en kolomwaarden zijn 1-gebaseerd bij celformules; rij en kolom zijn 0 wanneer er geen cel wordt geëvalueerd. De kinds worden vastgelegd vóórdat de argumenten worden geëvalueerd, zodat een SUM- of MAP-achtige handler kan zien dat de aanroeper een verwijzing schreef ook al bevat de geëvalueerde Args-entry alleen de waarde |
| Value | Stel hier het functieresultaat in |
| Handled | Zet op True wanneer de callback een
resultaat aanlevert. Laat False staan om het normale
gedrag voor niet-ondersteunde functies te behouden |
Callback-beveiligingsbeleid
AllowUnsafeFormulaCallbacks staat standaard op False voor klassieke XLS- en XLSX-werkmappen, zodat het bewaren van een formule code van de hosttoepassing nooit toestaat om een gevaarlijke externe functienaam of een functienaam in macro-stijl te behandelen
De standaardafschutting dekt DDE, CALL, REGISTER, REGISTER.ID, WEBSERVICE, RTD, SQL.REQUEST, EXEC, RUN, CREATE.OBJECT, APP.ACTIVATE, SEND.KEYS, OPEN, SAVE, SAVE.AS, FOPEN, FWRITE, FWRITELN, FCLOSE en FILE.DELETE , nadat een herkend future-function-prefix is genormaliseerd
Weigering gebeurt vóór de evaluatie van argumenten en vóór het uitvoeren van callbacks op werkmapniveau, procesbrede resolvers of events; gewone aangepaste en niet-ondersteunde functienamen behouden hun bestaande callback-gedrag
Zet de eigenschap van de werkmap alleen op True wanneer elke formule en elke geregistreerde handler vertrouwd wordt; contextuele evaluatie kan in plaats daarvan voor één aanroep meedoen via TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, terwijl een expliciet opgegeven False een werkmapbrede opt-in overschrijft
Voorbeeld
procedure TForm1.WorkbookUserFunction(Sender: TObject;
const FunctionName: WideString; const Args: Variant;
var Value: Variant; var Handled: Boolean);
begin
if SameText(FunctionName, 'DOUBLEPLUS') then
begin
Value := Double(Args[0]) * 2 + Double(Args[1]);
Handled := True;
end;
end;
Workbook.OnUserFunction := WorkbookUserFunction;
Value := Workbook.Calculate('=DOUBLEPLUS(A1;5)');
Context-aware example
procedure TForm1.WorkbookUserFunctionEx(Sender: TObject;
const FunctionName: WideString; const Args: Variant;
const Context: TXLSUserFunctionContext;
var Value: Variant; var Handled: Boolean);
begin
if SameText(FunctionName, 'ROWBONUS') then
begin
Value := Double(Args[0]) + Context.Row + Context.Col;
Handled := True;
end;
end;
Workbook.OnUserFunctionEx := WorkbookUserFunctionEx;
Value := Worksheet.Calculate('=C2');
Bereikargumenten ontvangen
Wanneer een argument evalueert naar een werkbladbereik, is de Args -entry een Variant van type varUnknown die een ICalcRangeListbevat; de geëvalueerde waarde van elke gedekte cel wordt niet in de Variant gekopieerd. Test en extraheer die met de VarIsRange -overload die de lijst teruggeeft, en lees daarna de herleide rectangles via TXLSCalcRange
type
TXLSCalcRange = class
property row1: Integer; { 0-based, inclusive }
property col1: Integer; { 0-based, inclusive }
property row2: Integer;
property col2: Integer;
property SheetIndex: Integer;
end;
ICalcRangeList = interface
property Count: Integer;
property Item[Index: Integer]: TXLSCalcRange;
end;
function VarIsRange(Value: Variant): Boolean; overload;
function VarIsRange(Value: Variant; var Int: ICalcRangeList): Boolean; overload;
function RangeToVariant(Value: TXLSCalcRangeList): Variant;
De coördinaten volgen de TXLSGetValue -conventie: op nul gebaseerd en inclusief. Een handler die zelf een bereik wil teruggeven, bouwt een TXLSCalcRangeList op en wikkelt die in RangeToVariant voordat Valuewordt toegewezen; de engine houdt dan de bereikverwijzing vast voor afhankelijke formules in plaats van een scalaire momentopname
Zie ook