HotXLS-dokumentation

OnUserFunction / OnUserFunctionEx-återanrop

Återanropet OnUserFunction gör att programkoden kan beräkna anpassade eller på annat sätt ej stödda kalkylbladsfunktioner under Calculate. Tilldela det på TXLSWorkbook eller TXLSXWorkbook innan du anropar Calculate
Använd OnUserFunctionEx när återanropet behöver den aktuella formelkontexten. Kontexten rapporterar det 1-baserade kalkylbladsindexet samt den 1-baserade raden och kolumnen för formelcellen; Calculate-anrop på arbetsboksnivå som inte beräknar en cell rapporterar rad och kolumn som 0

Syntax

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;

Argument

FunctionName Funktionsnamnet från formeltexten
Args En nollbaserad Variant-array som innehåller beräknade argumentvärden. För funktioner utan argument är detta värde Null
Context För OnUserFunctionEx rapporteras SheetIndex, Row och Col, plus argumentbeskrivningen: ArgCount matchar längden på arrayen Args (0 för anrop utan argument) och ArgKinds klassificerar varje argument som akuValue (literalvärde), akuRangeRef (cell- eller områdesreferens) eller akuArray (arraykonstant). Kalkylblads-, rad- och kolumnvärden är 1-baserade för cellformler; rad och kolumn är 0 när ingen cell beräknas. Typerna fångas innan argumenten utvärderas, så en hanterare i SUM- eller MAP-stil kan se att anroparen skrev en referens även om det utvärderade Args-värdet bara bär värdet
Value Ange detta till funktionsresultatet
Handled Ange True när återanropet tillhandahåller ett resultat. Lämna False för att behålla det normala beteendet för ej stödda funktioner

Säkerhetspolicy för callbacks

AllowUnsafeFormulaCallbacks är som standard False i Classic XLS- och XLSX-arbetsböcker, så att bevarande av en formel aldrig ger programkoden i värdapplikationen tillstånd att hantera ett farligt externt eller makroliknande funktionsnamn
Standardspärren täcker 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 och FILE.DELETE efter att ett känt prefix för framtida funktioner normaliserats
Nekandet sker innan argumenten utvärderas och innan callbacks för arbetsbok, process, resolver eller händelser körs; vanliga anpassade och ej stödda funktionsnamn behåller sitt befintliga callback-beteende
Sätt arbetsboksegenskapen till True bara när varje formel och varje registrerad hanterare är betrott; kontextuell utvärdering kan i stället välja in det för ett enskilt anrop via TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, medan en uttryckligt angiven False åsidosätter en arbetsboksomfattande opt-in

Exempel

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)');

Exempel med kontext

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');

Ta emot områdeargument

När ett argument utvärderas till ett kalkylbladsområde är Args-posten en varUnknown-Variant som bär en ICalcRangeList; det utvärderade värdet för varje täckt cell kopieras inte in i Varianten. Testa och extrahera den med VarIsRange-överlagringen som returnerar listan, och läs sedan de upplösta rektanglarna 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;
    
Koordinaterna följer TXLSGetValue-konventionen: nollbaserade och inkluderande. En hanterare som själv vill returnera ett område bygger en TXLSCalcRangeList och lindar in den med RangeToVariant innan Value tilldelas; motorn behåller då områdesreferensen för beroende formler i stället för en skalär ögonblicksbild

Se även