Le rappel OnUserFunction permet au code d'application d'évaluer
des fonctions de feuille de calcul personnalisées ou non supportées pendant
Calculate. Assignez-le sur TXLSWorkbook ou
TXLSXWorkbook avant d'appeler Calculate
Utilisez OnUserFunctionEx lorsque le rappel a besoin du contexte de formule actuel. Le contexte signale l'index de feuille à base 1 ainsi que la ligne et la colonne à base 1 de la cellule de formule ; les appels Calculate au niveau du classeur qui n'évaluent pas une cellule signalent la ligne et la colonne comme 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;
Arguments
| FunctionName |
Le nom de la fonction provenant du texte de la formule |
| Args |
Une matrice Variant à base zéro contenant les valeurs
des arguments évalués. Pour les fonctions sans argument, cette valeur est
Null |
| Context |
Pour OnUserFunctionEx, signale SheetIndex, Row et Col, plus le descripteur d'arguments : ArgCount correspond à la longueur du tableau Args (0 pour les appels sans argument) et ArgKinds classe chaque argument en akuValue (valeur littérale), akuRangeRef (référence de cellule ou de plage) ou akuArray (constante tableau). Les valeurs de feuille, de ligne et de colonne sont à base 1 pour les formules de cellule ; la ligne et la colonne valent 0 lorsqu'aucune cellule n'est évaluée. Les types sont capturés avant l'évaluation des arguments, si bien qu'un gestionnaire de style SUM ou MAP peut savoir que l'appelant a écrit une référence alors que l'entrée Args évaluée ne transporte que la valeur |
| Value |
Définissez cette valeur sur le résultat de la fonction |
| Handled |
Définissez-le sur True lorsque le rappel fournit
un résultat. Laissez False pour conserver le comportement normal
des fonctions non supportées |
Politique de sécurité des rappels
AllowUnsafeFormulaCallbacks vaut False par défaut sur les classeurs XLS Classic et XLSX, si bien que préserver une formule n'autorise jamais le code de l'application hôte à traiter un nom de fonction externe ou de style macro dangereux
Le verrou par défaut couvre 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 et FILE.DELETE, après normalisation de tout préfixe de future-function reconnu
Le refus intervient avant l'évaluation des arguments et avant l'exécution des rappels locaux au classeur, globaux au processus, de résolveur ou d'événement ; les noms de fonctions personnalisées et non prises en charge ordinaires conservent leur comportement de rappel existant
Ne passez la propriété du classeur à True que lorsque chaque formule et chaque gestionnaire enregistré est de confiance ; l'évaluation contextuelle peut au lieu de cela accepter un appel unique via TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, tandis qu'un False explicitement fourni prime sur une acceptation à l'échelle du classeur
Exemple
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)');
Exemple prenant en compte le contexte
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');
Recevoir des arguments de plage
Quand un argument s'évalue en une plage de feuille de calcul, l'entrée Args est un Variant varUnknown qui contient un ICalcRangeList ; la valeur évaluée de chaque cellule couverte n'est pas copiée dans le Variant. Testez-le et extrayez-le avec la surcharge VarIsRange qui renvoie la liste, puis lisez les rectangles résolus 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;
Les coordonnées suivent la convention TXLSGetValue : en base zéro et inclusives. Un gestionnaire qui souhaite renvoyer une plage construit lui-même une TXLSCalcRangeList et l'enveloppe avec RangeToVariant avant d'affecter Value ; le moteur conserve alors la référence de plage pour les formules dépendantes au lieu d'un instantané scalaire
Voir aussi