O retorno de chamada OnUserFunction permite que o código da aplicação avalie funções de folha de cálculo personalizadas ou não suportadas durante
Calculate. Atribua-o em TXLSWorkbook ou
TXLSXWorkbook antes de chamar Calculate
Utilize OnUserFunctionEx quando o retorno de chamada precisar do contexto de fórmula actual. O contexto reporta o índice de folha de base 1 mais a linha e coluna de base 1 da célula de fórmula; as chamadas Calculate ao nível do livro que não estão a avaliar 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 | Nome da função a partir do texto da fórmula |
| Args | Uma matriz Variant baseada em zero contendo os valores dos argumentos avaliados. Para funções sem argumentos, este valor é Null
Null |
| Context | For OnUserFunctionEx, reports SheetIndex, Row, and Col, plus the argument descriptor: ArgCount matches the Args — o comprimento da matriz (0 para chamadas sem argumentos) e ArgKinds classifies each argument as akuValue (literal value), akuRangeRef (cell or range reference), or akuArray (constante de matriz). Os valores de folha, linha e coluna são de base 1 nas fórmulas de célula; a linha e a coluna valem 0 quando nenhuma célula está a ser avaliada. Os tipos são capturados antes de os argumentos serem avaliados, por isso um handler ao estilo SUM ou MAP consegue perceber que o chamador escreveu uma referência, mesmo que o argumento avaliado Args entry carries only the value |
| Value | Para OnUserFunctionEx, reporta SheetIndex, Row e Col. Os valores de folha, linha e coluna são baseados em 1 para fórmulas de célula; linha e coluna são 0 quando não está a ser avaliada nenhuma célula |
| Handled | Defina isto para o resultado da função True Handled False Defina para True quando a callback fornecer um resultado. Deixe False para manter o comportamento normal de função não suportada |
Política de segurança das callbacks
AllowUnsafeFormulaCallbacks assume o valor predefinido False nos livros Classic XLS e XLSX, pelo que preservar uma fórmula nunca autoriza o código da aplicação anfitriã a tratar um nome de função perigoso externo ou de estilo macro
O portão predefinido 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, FCLOSEe FILE.DELETE , após a normalização de qualquer prefixo de função futura reconhecido
A recusa acontece antes da avaliação dos argumentos e antes de quaisquer callbacks ao nível do livro, do processo, do resolver ou de eventos correrem; os nomes de funções personalizadas e não suportadas comuns mantêm o comportamento de callback existente
Defina a propriedade do livro como True apenas quando todas as fórmulas e os manipuladores registados são de confiança; a avaliação contextual pode, em alternativa, ativar a opção para uma única chamada através de TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks, enquanto um False fornecido explicitamente sobrepõe-se a uma ativação ao nível do livro
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');
Receção de argumentos de intervalo
Quando um argumento avalia para um intervalo de folha de cálculo, a entrada Args é um Variant varUnknown que contém uma ICalcRangeList; o valor avaliado de cada célula abrangida não é copiado para o Variant. Teste e extraia-o com a sobrecarga VarIsRange que devolve a lista e, depois, leia os retângulos resolvidos atravé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;
As coordenadas seguem a convenção de TXLSGetValue : de base 0 e inclusivas. Um manipulador que queira devolver ele próprio um intervalo constrói uma TXLSCalcRangeList e envolve-a com RangeToVariant antes de atribuir Value; o motor mantém então a referência do intervalo para as fórmulas dependentes em vez de um instantâneo escalar
Ver também