Documentação do HotXLS

Retorno de chamada OnUserFunction / OnUserFunctionEx

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

FunctionNameNome da função a partir do texto da fórmula
ArgsUma matriz Variant baseada em zero contendo os valores dos argumentos avaliados. Para funções sem argumentos, este valor é Null Null
ContextFor 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
ValuePara 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
HandledDefina 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