HotXLS 문서

OnUserFunction / OnUserFunctionEx 콜백

OnUserFunction 콜백을 사용하면 응용 프로그램 코드가 Calculate 중 사용자 지정 또는 지원되지 않는 워크시트 함수를 평가할 수 있습니다. Calculate를 호출하기 전에 TXLSWorkbook 또는 TXLSXWorkbook에 할당합니다
콜백이 현재 수식 컨텍스트를 필요로 할 때 OnUserFunctionEx를 사용합니다. 컨텍스트는 1 기반 시트 인덱스와 수식 셀의 1 기반 행 및 열을 보고합니다. 셀을 평가하지 않는 통합 문서 수준 Calculate 호출은 행과 열을 0으로 보고합니다

구문

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;

인수

FunctionName 수식 텍스트에 있는 함수 이름입니다
Args 평가된 인자 값을 담는 0 기반 Variant 배열입니다. 인자가 없는 함수의 경우 이 값은 Null입니다
Context OnUserFunctionEx에서 SheetIndex, Row, Col과 인자 디스크립터를 보고합니다. ArgCount는 Args 배열 길이와 일치하고(인자 없는 호출은 0), ArgKinds는 각 인자를 akuValue(리터럴 값), akuRangeRef(셀 또는 범위 참조), akuArray(배열 상수)로 분류합니다. 셀 수식에서는 시트·행·열 값이 1 기반이고, 평가 중인 셀이 없으면 행과 열은 0입니다. 종류는 인자가 평가되기 전에 기록되므로, SUM이나 MAP 스타일 핸들러는 평가된 Args 항목에 값만 담겨 있더라도 호출자가 참조를 썼다는 사실을 알 수 있습니다
Value 함수 결과로 설정합니다
Handled 콜백이 결과를 제공하면 True로 설정합니다. False로 두면 기존의 지원되지 않는 함수 동작이 유지됩니다

콜백 보안 정책

AllowUnsafeFormulaCallbacks는 클래식 XLS와 XLSX 통합 문서에서 기본값이 False입니다. 따라서 수식을 보존한다고 해서 위험한 외부·매크로 스타일 함수 이름을 호스트 애플리케이션 코드가 처리하도록 승인되지는 않습니다
기본 게이트는 알려진 future-function 접두사가 정규화된 뒤 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, FILE.DELETE를 차단합니다
거부는 인자 평가 이전, 그리고 통합 문서 로컬·프로세스 전역·resolver·이벤트 콜백이 실행되기 이전에 일어납니다. 일반적인 사용자 지정 및 지원되지 않는 함수 이름은 기존 콜백 동작을 그대로 유지합니다
모든 수식과 등록된 핸들러를 신뢰할 수 있을 때만 통합 문서 속성을 True로 설정하십시오. 컨텍스트 평가는 TXLSFormulaEvaluationOptions.AllowUnsafeFormulaCallbacks를 통해 호출 한 번에만 선택적으로 허용할 수 있고, 명시적으로 지정한 False는 통합 문서 전체 허용보다 우선합니다

예제

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)');

컨텍스트 인식 예제

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');

범위 인수 받기

인자가 워크시트 범위로 평가되면 Args 항목은 ICalcRangeList를 담는 varUnknown Variant입니다. 덮인 각 셀의 평가된 값이 Variant로 복사되지는 않습니다. 목록을 반환하는 VarIsRange 오버로드로 검사·추출한 다음 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;
    
좌표는 TXLSGetValue 규약과 같은 0 기반 포함(inclusive) 범위입니다. 자신이 범위를 반환해야 하는 핸들러는 TXLSCalcRangeList를 만들어 RangeToVariant로 감싼 뒤 Value에 할당합니다. 그러면 엔진은 스칼라 스냅샷 대신 종속 수식을 위한 범위 참조를 유지합니다

참조