[]
SpreadJS는 워크시트 셀 외부에서도 수식을 평가하고 계산을 수행할 수 있는 강력한 계산 엔진을 제공합니다. GC.Spread.Sheets.CalcEngine
모듈은 워크시트에 직접 설정하지 않고도 수식을 파싱, 평가, 변환할 수 있는 여러 유틸리티 메서드를 포함하고 있습니다.
판매 데이터가 포함된 테이블을 준비합니다.
사용 사례:
코드에서 동적으로 수식 결과를 계산해야 할 때 (예: 백엔드에서 데이터를 처리하거나 수식 논리를 일괄 검증할 때), 워크시트 렌더링이나 사용자 동작에 의존하지 않고 계산 가능.
배열 수식의 여러 결과를 모두 유지해야 할 때, preserveArrayResult: true
를 사용하여 전체 배열을 얻을 수 있음.
코드에서 R1C1 형식으로 수식을 생성하거나 파싱할 때.
메서드: evaluateFormula(context, formula, baseRow?, baseColumn?, useR1C1?, preserveArrayResult?)
context
(Object) – 평가 컨텍스트 (일반적으로 활성 시트 객체).
formula
(string) – 평가할 수식 문자열.
baseRow
(number, optional) – 상대 참조의 기준이 되는 행 인덱스.
baseColumn
(number, optional) – 상대 참조의 기준이 되는 열 인덱스.
useR1C1
(boolean, optional) – R1C1 참조 스타일 사용 여부 (기본: false
).
preserveArrayResult
(boolean, optional) – true
이면 배열 결과 반환, 아니면 단일 값 반환.
예제 1: 계산 결과 직접 가져오기
var sheet = spread.getActiveSheet();
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=SUM(Table1[[#Data],[Units]])')
//결과: 84878
예제 2: baseRow, baseColumn으로 상대 참조 사용
var sheet = spread.getActiveSheet();
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=Table1[@[Sales Rep]]', 2, 0);
//결과: Tom
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=Table1[@[Sales Rep]]', 5, 0);
//결과: Sal
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=Table1[@[Sales Rep]]', 12, 0);
//결과: Amy
예제 3: R1C1 스타일 사용
var sheet = spread.getActiveSheet();
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=R[3]C[3]', 0, 0, true);
//결과: Grape
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=R[3]C[3]', 2, 1, true);
//결과: 5323
예제 4: 배열 결과를 preserveArrayResult로 가져오기
var sheet = spread.getActiveSheet();
spread.options.allowDynamicArray = true;
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=UNIQUE(Table1[[#Data],[Product]])')
//결과: Apple
GC.Spread.Sheets.CalcEngine.evaluateFormula(sheet, '=UNIQUE(Table1[[#Data],[Product]])', null, null, null, true)
//결과: [['Apple'],['Grape'],['Pear'],['Banana']]
참고:
AsyncFunctionEvaluateMode.onInterval 또는 REFRESH 함수는 지원하지 않습니다.
사용 사례:
비동기 작업을 수행하는 사용자 정의 함수를 사용할 때.
API 또는 데이터를 비동기로 반환하는 데이터 소스와 통합할 때.
사용자 인터페이스가 멈추지 않도록 장시간 계산을 수행할 때.
메서드: evaluateFormulaAsync(context: Object, formula: string, baseRow?: number, baseColumn?: number)
context
: 평가 컨텍스트 객체. 대부분의 경우 활성 시트 객체(GC.Spread.Sheets.Worksheet
)를 전달합니다.
formula
: 평가할 수식 문자열.
참고:
A1 참조 스타일만 지원합니다.
baseRow
(선택): 수식의 기준이 되는 행 인덱스. 셀 외부에서 상대 참조를 사용할 때 필요합니다.
baseColumn
(선택): 수식의 기준이 되는 열 인덱스. 셀 외부에서 상대 참조를 사용할 때 필요합니다.
반환값:
수식 평가 결과를 가진 Promise를 반환합니다.
참고:
여러 번
context.setAsyncResult
를 호출하더라도 Promise는 최초 한 번만 해결됩니다.
예제: 간단한 비동기 사용자 정의 함수 ASUM
(Asynchronous Sum) 정의
// 비동기 함수 ASUM 정의
var asyncSum = function () {};
asyncSum.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction("ASUM", 1, 255);
// 계산 중 표시될 기본값
asyncSum.prototype.defaultValue = function () {
return "Loading...";
};
// 비동기 평가 로직
asyncSum.prototype.evaluateAsync = function (context) {
var args = arguments;
setTimeout(function () {
var result = 0;
// 인수는 1번 인덱스부터 시작 (0번 인덱스는 context)
for (var i = 1; i < args.length; i++) {
result += args[i];
}
// context를 통해 최종 결과 설정
context.setAsyncResult(result * 2); // 예: 합계를 두 배로
}, 2000); // 2초 지연 시뮬레이션
};
// 사용자 정의 함수 전역 등록
GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("ASUM", new asyncSum());
사용 예제 1: 기본 사용
GC.Spread.Sheets.CalcEngine.evaluateFormulaAsync(sheet, "ASUM(2, 2)", 0, 0)
.then(result => {
console.log("ASUM(2, 2) 결과:", result); // 약 2초 후: ASUM(2, 2) 결과: 8
})
.catch(error => {
console.error("평가 오류:", error);
});
//결과: Promise{8}
사용 예제 2: 병렬 비동기 함수
GC.Spread.Sheets.CalcEngine.evaluateFormulaAsync(sheet, "ASUM(2, 2) + ASUM(2, 2)", 0, 0)
.then(result => {
console.log("ASUM(2, 2) + ASUM(2, 2) 결과:", result); // 약 2초 후: 16
})
.catch(error => {
console.error("평가 오류:", error);
});
//결과: Promise{16}
사용 예제 3: 연속(중첩) 비동기 함수
GC.Spread.Sheets.CalcEngine.evaluateFormulaAsync(sheet, "ASUM(ASUM(2, 2), 2)", 0, 0)
.then(result => {
console.log("ASUM(ASUM(2, 2), 2) 결과:", result); // 약 4초 후: 20
})
.catch(error => {
console.error("평가 오류:", error);
});
//결과: Promise{20}
사용 예제 4: 일반(동기) 수식 평가
GC.Spread.Sheets.CalcEngine.evaluateFormulaAsync(sheet, "VSTACK(ASUM(2, 2), ASUM(2))", 0, 0)
.then(result => {
console.log("VSTACK 결과:", result); // 약 2초 후: [[8],[4]]
})
.catch(error => {
console.error("평가 오류:", error);
});
//결과: Promise{[[8],[4]]}
사용 예제 5: 셀/범위 참조 평가
GC.Spread.Sheets.CalcEngine.evaluateFormulaAsync(sheet, "1 + 23", 0, 0)
.then(result => {
console.log("일반 수식 결과:", result); // 결과: 24
})
.catch(error => {
console.error("평가 오류:", error);
});
//결과: Promise{24}
사용 사례:
복잡한 수식을 동적으로 생성할 때 (문자열 연결 위험 회피), 일반적으로 formulaToExpression과 함께 사용.
사용자 정의 이름의 표현식을 파싱하고 해당 수식 생성.
메서드: expressionToFormula(context, expression, baseRow?, baseColumn?, useR1C1?)
context
(Object) – 컨텍스트 (일반적으로 활성 시트 객체).
expression
(GC.Spread.CalcEngine.Expression) – 변환할 표현식 트리.
baseRow
(number, optional) – 상대 참조 기준 행.
baseColumn
(number, optional) – 상대 참조 기준 열.
useR1C1
(boolean, optional) – R1C1 스타일 사용 여부 (기본: false
).
예제: 사용자 정의 이름 표현식을 수식으로 변환
var sheet = spread.getActiveSheet();
sheet.addCustomName('averageUnits', '=AVERAGE(Table1[[#Data],[Units]])');
var cname = sheet.getCustomName("averageUnits");
var expr = cname.getExpression();
GC.Spread.Sheets.CalcEngine.expressionToFormula(sheet, expr);
//결과: AVERAGE(Table1[[#Data],[Units]])
사용 사례:
기존 수식을 프로그램적으로 파싱하고, 일부 인수나 로직 수정 후 다시 수식 생성.
수식에서 참조되는 셀, 함수, 종속성을 확인하여 데이터 흐름 분석 또는 감사.
R1C1과 A1 스타일 간 변환 시, 먼저 수식을 표현식 트리로 변환 후 재구성.
문자열만으로 수식 검증하지 않고 표현식을 사용하여 보다 정확한 분석 가능.
메서드: formulaToExpression(context, formula, baseRow?, baseColumn?, useR1C1?)
context
(Object) – 평가 컨텍스트 (일반적으로 활성 시트 객체).
formula
(string) – 평가할 수식 문자열.
baseRow
(number, optional) – 상대 참조 기준 행.
baseColumn
(number, optional) – 상대 참조 기준 열.
useR1C1
(boolean, optional) – R1C1 스타일 사용 여부 (기본: false
).
예제: 수식을 표현식 객체로 변환
var sheet = spread.getActiveSheet();
var expr = GC.Spread.Sheets.CalcEngine.formulaToExpression(sheet, '=CONCAT(Table1[@Region],Table1[@[Sales Rep]],Table1[@Product])', 4, 0)
//결과:
//expr.functionName is CONCAT
//expr.arguments.length is 3
사용 사례:
수식이 참조하는 모든 셀 범위를 신속히 가져와 데이터 종속성 그래프 또는 영향 분석 수행.
UI에서 수식이 참조하는 모든 셀을 하이라이트하여 사용자가 직관적으로 이해하도록 도움.
수식의 논리 구조 대신 물리적 위치(row, column) 정보가 필요할 때, formulaToExpression보다 더 직접적이고 효율적.
메서드: formulaToRanges(sheet, formula, baseRow?, baseCol?)
sheet
(GC.Spread.Sheets.Worksheet) – 기준 워크시트.
formula
(string) – 분석할 수식.
baseRow
(number, optional) – 상대 참조 기준 행.
baseColumn
(number, optional) – 상대 참조 기준 열.
예제: 수식 참조 범위 가져오기
var sheet = spread.getActiveSheet();
var result = GC.Spread.Sheets.CalcEngine.formulaToRanges(sheet, '=SUM(A1,A2,A5:C8)');
//결과:
//result.sheetName is Sheet1
//result.ranges:[
// Range {row: 0, rowCount: 1, col: 0, colCount: 1}
// Range {row: 1, rowCount: 1, col: 0, colCount: 1}
// Range {row: 4, rowCount: 4, col: 0, colCount: 3}
// Range {row: 2, rowCount: 16, col: 4, colCount: 1}
//]
사용 사례:
런타임 데이터 기반으로 범위 참조 수식을 동적으로 생성할 때.
코드에서 워크시트 참조 처리 시 복잡한 문자열 수동 연결을 피할 때.
상대/절대 참조를 유연하게 전환할 필요가 있을 때.
메서드: rangesToFormula(ranges, baseRow?, baseCol?, rangeReferenceRelative?, useR1C1?)
ranges
(GC.Spread.Sheets.Range[]) – 변환할 범위 배열.
baseRow
(number, optional) – 상대 참조 기준 행.
baseColumn
(number, optional) – 상대 참조 기준 열.
rangeReferenceRelative
(RangeReferenceRelative, optional) – 참조 형태 지정 (절대/상대).
useR1C1
(boolean, optional) – R1C1 스타일 사용 여부.
예제: 범위 배열을 수식으로 변환
var ranges = [
new GC.Spread.Sheets.Range(0,0,1,1),
new GC.Spread.Sheets.Range(3,3,5,5),
];
GC.Spread.Sheets.CalcEngine.rangesToFormula(ranges,0,0,GC.Spread.Sheets.CalcEngine.RangeReferenceRelative.allRelative);
//결과: 'A1, D4:H8'
GC.Spread.Sheets.CalcEngine.rangesToFormula(ranges,0,0,GC.Spread.Sheets.CalcEngine.RangeReferenceRelative.allAbsolute);
//결과: '$A$1, $D$4:$H$8'
GC.Spread.Sheets.CalcEngine.rangesToFormula(ranges,0,0,GC.Spread.Sheets.CalcEngine.RangeReferenceRelative.colRelative);
//결과: 'A$1, D$4:H$8'
GC.Spread.Sheets.CalcEngine.rangesToFormula(ranges,0,0,GC.Spread.Sheets.CalcEngine.RangeReferenceRelative.allRelative, true);
//결과: 'RC, R[3]C[3]:R[7]C[7]'