Zpětné volání OnUserFunction umožňuje kódu aplikace vyhodnocovat
vlastní nebo jinak nepodporované funkce listu během
Calculate. Přiřaďte jej na TXLSWorkbook nebo
TXLSXWorkbook před voláním Calculate
Použijte OnUserFunctionEx, když zpětné volání potřebuje aktuální kontext vzorce. Kontext hlásí index listu (1-based) plus řádek a sloupec buňky se vzorcem (1-based); volání Calculate na úrovni sešitu, která nevyhodnocují žádnou buňku, hlásí řádek a sloupec jako 0
Syntaxe
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;
Argumenty
| FunctionName |
Název funkce z textu vzorce |
| Args |
Pole Variant s indexací od nuly obsahující vyhodnocené
hodnoty argumentů. Pro funkce bez argumentů je tato hodnota
Null |
| Context |
Pro OnUserFunctionEx hlásí SheetIndex, Row a Col, plus deskriptory argumentů: ArgCount odpovídá délce pole Args (0 pro volání bez argumentů) a ArgKinds klasifikuje každý argument jako akuValue (literální hodnota), akuRangeRef (reference na buňku či oblast) nebo akuArray (konstanta pole). Hodnoty listu, řádku a sloupce jsou u buněčných vzorců 1-based; řádek a sloupec jsou 0, když se nevyhodnocuje žádná buňka. Druhy (kinds) se zachytí před vyhodnocením argumentů, takže handler ve stylu SUM či MAP pozná, že volající napsal referenci, i když vyhodnocená položka Args nese jen hodnotu |
| Value |
Nastavte toto na výsledek funkce |
| Handled |
Nastavte na True, když callback poskytuje
výsledek. Nechte False, chcete-li zachovat běžné chování pro
nepodporovanou funkci |
Bezpečnostní politika callbacků
AllowUnsafeFormulaCallbacks má u Classic XLS i XLSX sešitů výchozí hodnotu False, takže samotné zachování vzorce nikdy neautorizuje kód hostitelské aplikace k obsluze nebezpečného externího či makro-style názvu funkce
Výchozí brána pokrývá 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 a FILE.DELETE po normalizaci jakékoli rozpoznané future-function předpony
Odmítnutí proběhne dřív, než se vyhodnotí argumenty a dřív, než se spustí workbook-lokální, process-wide, resolver či event callbacky; obyčejné vlastní a nepodporované názvy funkcí si ponechávají stávající chování callbacků
Vlastnost sešitu nastavte na True jen tehdy, když je každý vzorec i registrovaný handler důvěryhodný; kontextové vyhodnocení se místo toho může pro jedno volání přihlásit přes TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, přičemž explicitně dodané False přebíjí opt-in na úrovni celého sešitu
Příklad
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)');
Kontextový příklad
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');
Přijímání argumentů typu range
Když se argument vyhodnotí na range listu, položka Args je Variant typu varUnknown držící ICalcRangeList; vyhodnocená hodnota každé překryté buňky se do Variantu nekopíruje. Otestujte jej a extrahujte pomocí overloadu VarIsRange, který vrací seznam, a poté přečtěte rozřešené obdélníky přes 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;
Souřadnice dodržují konvenci TXLSGetValue: indexované od nuly a inkluzivní. Handler, který chce sám vrátit range, si sestaví TXLSCalcRangeList a před přiřazením do Value jej zabalí pomocí RangeToVariant; engine pak pro závislé vzorce ponechá referenci na range místo skalárního snímku
Viz také