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에 할당합니다. 그러면 엔진은 스칼라 스냅샷 대신 종속 수식을 위한 범위 참조를 유지합니다
참조