El callback OnUserFunction permite al código de la aplicación evaluar funciones de hoja de cálculo personalizadas o no compatibles 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 el índice de hoja de base 1 más la fila y columna de base 1 de la celda de 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 arreglo Variant de base 0 con los valores de los argumentos ya evaluados. Para funciones sin argumentos este valor es Null |
| Context |
Para OnUserFunctionEx, informa SheetIndex, Row y Col, más el descriptor de argumentos: ArgCount coincide con la longitud del arreglo 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 de base 1 en las fórmulas de celda; la fila y la columna son 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 lleve solo el valor |
| Value |
Asígnelo con el resultado de la función |
| Handled |
Asígnelo a True cuando el callback entrega un resultado. Déjelo en False para conservar el comportamiento normal con funciones no compatibles |
Política de seguridad de callbacks
AllowUnsafeFormulaCallbacks es False de forma predeterminada en los libros de trabajo XLS clásicos y XLSX, de modo que preservar una fórmula nunca autoriza al código de la aplicación host a manejar nombres de funciones peligrosos de tipo externo o macro
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, después de normalizar cualquier prefijo de función futura reconocido
El rechazo ocurre antes de evaluar los argumentos y antes de que se ejecuten los callbacks del libro de trabajo, del proceso, del resolutor o de eventos; los nombres de funciones personalizadas y no compatibles ordinarias conservan su comportamiento de callback existente
Establezca la propiedad del libro de trabajo en True solo cuando confíe en todas las fórmulas y manejadores registrados; la evaluación contextual puede habilitarlo solo para una llamada mediante TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, mientras que un False explícito anula una habilitación de todo el 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 hoja de cálculo, la entrada Args es un Variant varUnknown que contiene un 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 luego lea los rectángulos resueltos a través de 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: de base 0 e inclusivas. Un manejador que quiera devolver un rango por sí mismo construye un TXLSCalcRangeList y lo envuelve con RangeToVariant antes de asignar Value; el motor conserva entonces la referencia del rango para las fórmulas dependientes en lugar de una instantánea escalar
Ver también