HotXLS-dokumentation

OnUserFunction / OnUserFunctionEx-tilbagekald

Tilbagekaldet OnUserFunction lader programkode evaluere brugerdefinerede eller på anden måde ikke-understøttede regnearksfunktioner under Calculate. Tildel det på TXLSWorkbook eller TXLSXWorkbook, før du kalder Calculate
Brug OnUserFunctionEx, når tilbagekaldet har brug for den aktuelle formelkontekst. Konteksten rapporterer det 1-baserede arkindeks samt den 1-baserede række og kolonne for formelcellen; Calculate-kald på projektmappeniveau, der ikke evaluerer en celle, rapporterer række og kolonne som 0

Syntaks

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;

Argumenter

FunctionName Funktionsnavnet fra formelteksten
Args Et 0-baseret Variant-array med evaluerede argumentværdier. For funktioner uden argumenter er værdien Null
Context For OnUserFunctionEx rapporteres SheetIndex, Row og Col plus argumentbeskrivelsen: ArgCount svarer til længden af Args-arrayet (0 ved kald uden argumenter), og ArgKinds klassificerer hvert argument som akuValue (literal værdi), akuRangeRef (celle- eller områdereference) eller akuArray (arraykonstant). Ark-, række- og kolonneværdier er 1-baserede for celformler; række og kolonne er 0, når der ikke evalueres en celle. Typerne fanges, før argumenterne evalueres, så en SUM- eller MAP-agtig handler kan se, at kalderen skrev en reference, selv om det evaluerede Args-element kun bærer værdien
Value Sættes til funktionens resultat
Handled Sættes til True, når callback'en leverer et resultat. Lad den være False for at beholde den normale håndtering af ikke-understøttede funktioner

Sikkerhedspolitik for callbacks

AllowUnsafeFormulaCallbacks er som standard False i klassiske XLS- og XLSX-projektmapper, så det at bevare en formel aldrig giver værtsprogrammets kode tilladelse til at håndtere et farligt eksternt eller makroagtigt funktionsnavn
Standardporten dækker 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 og FILE.DELETE, efter et genkendt future-function-præfiks er normaliseret
Afvisningen sker, før argumenterne evalueres, og før projektmappe-lokale, procesglobale, resolver- og event-callbacks kører; almindelige tilpassede og ikke-understøttede funktionsnavne bevarer deres eksisterende callback-adfærd
Sæt egenskaben på projektmappen til True kun, når alle formler og registrerede handlers er betroede; kontekstuel evaluering kan i stedet tilvælge for ét kald via TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, mens en eksplicit angivet False tilsidesætter et arbejdsbogsomfattende tilvalg

Eksempel

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

Kontekstbevidst eksempel

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

Modtagelse af områdeargumenter

Når et argument evalueres til et regnearksområde, er Args-elementet en varUnknown-Variant, der holder en ICalcRangeList; den evaluerede værdi af hver dækket celle kopieres ikke ind i Varianten. Test og udtræk den med den VarIsRange-overload, der returnerer listen, og læs de opløste rektangler 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;
    
Koordinaterne følger TXLSGetValue-konventionen: 0-baserede og inklusive. En handler, der selv vil returnere et område, bygger en TXLSCalcRangeList og pakker den med RangeToVariant, før Value tildeles; motoren beholder så områdereferencen til afhængige formler i stedet for et skalar-snapshot

Se også