El callback OnUserFunction permite que el código de la aplicación evalúe funciones de hoja de cálculo personalizadas o no admitidas durante Calculate. Asígnelo en TXLSWorkbook o TXLSXWorkbook antes de llamar a Calculate
Use OnUserFunctionEx cuando el callback necesite el contexto de fórmula actual. El contexto informa del índice de hoja base 1 más la fila y la columna base 1 de la celda de la fórmula; las llamadas a Calculate a nivel de libro de trabajo que no evalúan ninguna celda informan fila y columna como 0
Sintaxis
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;
Argumentos
| FunctionName |
El nombre de la función tal como aparece en el texto de la fórmula |
| Args |
Un array Variant de base 0 con los valores de los
argumentos ya evaluados. Para funciones sin argumentos este valor es
Null |
| Context |
Para OnUserFunctionEx, informa de SheetIndex, Row y Col, además del descriptor de argumentos: ArgCount coincide con la longitud del array Args (0 en llamadas sin argumentos) y ArgKinds clasifica cada argumento como akuValue (valor literal), akuRangeRef (referencia a celda o rango) o akuArray (constante de matriz). Los valores de hoja, fila y columna son base 1 en las fórmulas de celda; fila y columna valen 0 cuando no se evalúa ninguna celda. Los tipos se capturan antes de evaluar los argumentos, de modo que un manejador al estilo de SUM o MAP puede saber que quien escribió la fórmula usó una referencia aunque la entrada Args evaluada solo lleve el valor |
| Value |
Asigne aquí el resultado de la función |
| Handled |
Póngalo a True cuando el callback suministra
un resultado. Déjelo a False para conservar el comportamiento
normal con funciones no admitidas |
Política de seguridad de callbacks
AllowUnsafeFormulaCallbacks vale False de forma predeterminada en los libros de trabajo Classic XLS y XLSX, de modo que preservar una fórmula nunca autoriza al código de la aplicación anfitriona a manejar un nombre de función externo o de estilo macro peligroso
La barrera predeterminada cubre 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 y FILE.DELETE una vez normalizado cualquier prefijo de future function reconocido
El rechazo se produce antes de evaluar los argumentos y antes de que se ejecuten los callbacks locales del libro de trabajo, los de todo el proceso, los del resolver o los de eventos; los nombres de funciones personalizadas y no admitidas ordinarias conservan su comportamiento de callback habitual
Ponga la propiedad del libro de trabajo a True solo cuando confíe en todas las fórmulas y en todos los manejadores registrados; la evaluación contextual puede activarlo en su lugar para una sola llamada mediante TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, mientras que un False explícito prevalece sobre una activación a nivel de libro de trabajo
Ejemplo
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)');
Ejemplo con contexto
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');
Recepción de argumentos de rango
Cuando un argumento se evalúa como un rango de la hoja de cálculo, la entrada Args es un Variant varUnknown que contiene una ICalcRangeList; el valor evaluado de cada celda cubierta no se copia en el Variant. Compruébelo y extráigalo con la sobrecarga de VarIsRange que devuelve la lista, y lea después los rectángulos resueltos mediante 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;
Las coordenadas siguen la convención de TXLSGetValue: base 0 e inclusivas. Un manejador que quiera devolver él mismo un rango construye una TXLSCalcRangeList y la envuelve con RangeToVariant antes de asignar Value; el motor conserva entonces la referencia al rango para las fórmulas dependientes en lugar de una instantánea escalar
Vease tambien