O callback OnUserFunction permite que o código da aplicação avalie
funções de planilha personalizadas ou não suportadas durante
Calculate. Atribua-o em TXLSWorkbook ou
TXLSXWorkbook antes de chamar Calculate
Use OnUserFunctionEx quando o callback precisar do contexto da fórmula atual. O contexto reporta o índice da planilha (base 1) mais a linha e a coluna (base 1) da célula da fórmula; chamadas de Calculate no nível da pasta de trabalho que não estão avaliando uma célula reportam linha e coluna como 0
Sintaxe
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 |
O nome da função extraído do texto da fórmula |
| Args |
Um array de Variant com base 0 contendo os valores avaliados
dos argumentos. Para funções sem argumentos, esse valor é
Null |
| Context |
Para OnUserFunctionEx, reporta SheetIndex, Row e Col, além do descritor de argumentos: ArgCount corresponde ao comprimento do array Args (0 para chamadas sem argumentos) e ArgKinds classifica cada argumento como akuValue (valor literal), akuRangeRef (referência a célula ou intervalo) ou akuArray (constante de matriz). Os valores de planilha, linha e coluna são base 1 para fórmulas de célula; linha e coluna são 0 quando nenhuma célula está sendo avaliada. Os tipos são capturados antes que os argumentos sejam avaliados, então um handler no estilo SUM ou MAP pode saber que o chamador escreveu uma referência mesmo que a entrada Args avaliada carregue apenas o valor |
| Value |
Defina isto como o resultado da função |
| Handled |
Defina como True quando o callback fornecer
um resultado. Deixe False para manter o comportamento
normal de função não suportada |
Política de segurança de Callback
O AllowUnsafeFormulaCallbacks tem padrão False nas pastas de trabalho XLS clássicas e XLSX, então preservar uma fórmula nunca autoriza o código da aplicação host a tratar um nome de função perigosa externa ou no estilo macro
A barreira padrão cobre 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 e FILE.DELETE depois que qualquer prefixo reconhecido de future-function é normalizado
A negação acontece antes da avaliação dos argumentos e antes de callbacks locais da pasta de trabalho, de processo, de resolver ou de evento rodarem; nomes comuns de funções personalizadas e não suportadas mantêm o comportamento de callback existente
Defina a propriedade da pasta de trabalho como True apenas quando toda fórmula e handler registrado for confiável; a avaliação contextual pode, em vez disso, habilitar isso para uma única chamada por meio de TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, enquanto um False fornecido explicitamente sobrepõe uma habilitação no nível da pasta de trabalho
Exemplo
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)');
Exemplo com 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');
Recebendo argumentos de intervalo
Quando um argumento avalia para um intervalo de planilha, a entrada Args é um Variant varUnknown que contém um ICalcRangeList; o valor avaliado de cada célula coberta não é copiado para o Variant. Teste e extraia com o overload de VarIsRange que retorna a lista, depois leia os retângulos resolvidos por meio 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;
As coordenadas seguem a convenção de TXLSGetValue: base 0 e inclusivas. Um handler que quiser retornar um intervalo ele próprio constrói um TXLSCalcRangeList e o embrulha com RangeToVariant antes de atribuir Value; o motor então mantém a referência do intervalo para fórmulas dependentes em vez de um snapshot escalar
Veja também