[]
        
(Showing Draft Content)

워크시트 외부에서 수식 계산

SpreadJS는 워크시트 셀 외부에서도 수식을 평가하고 계산을 수행할 수 있는 강력한 계산 엔진을 제공합니다. GC.Spread.Sheets.CalcEngine 모듈은 워크시트에 직접 설정하지 않고도 수식을 파싱, 평가, 변환할 수 있는 여러 유틸리티 메서드를 포함하고 있습니다.

판매 데이터가 포함된 테이블을 준비합니다.

image.9916ad.png

evaluateFormula: 지정된 수식 문자열을 평가하고 결과를 반환합니다.

사용 사례:

  • 코드에서 동적으로 수식 결과를 계산해야 할 때 (예: 백엔드에서 데이터를 처리하거나 수식 논리를 일괄 검증할 때), 워크시트 렌더링이나 사용자 동작에 의존하지 않고 계산 가능.

  • 배열 수식의 여러 결과를 모두 유지해야 할 때, 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']]

evaluateFormulaAsync: 지정된 수식 문자열을 평가하고 결과를 Promise로 반환합니다.

참고:

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}

expressionToFormula: 표현식을 수식 문자열로 변환

사용 사례:

  • 복잡한 수식을 동적으로 생성할 때 (문자열 연결 위험 회피), 일반적으로 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]])

formulaToExpression: 수식 문자열을 표현식으로 파싱

사용 사례:

  • 기존 수식을 프로그램적으로 파싱하고, 일부 인수나 로직 수정 후 다시 수식 생성.

  • 수식에서 참조되는 셀, 함수, 종속성을 확인하여 데이터 흐름 분석 또는 감사.

  • 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

formulaToRanges: 수식 문자열을 참조된 셀 범위 배열로 변환

사용 사례:

  • 수식이 참조하는 모든 셀 범위를 신속히 가져와 데이터 종속성 그래프 또는 영향 분석 수행.

  • 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: 범위 배열을 수식 문자열로 변환

사용 사례:

  • 런타임 데이터 기반으로 범위 참조 수식을 동적으로 생성할 때.

  • 코드에서 워크시트 참조 처리 시 복잡한 문자열 수동 연결을 피할 때.

  • 상대/절대 참조를 유연하게 전환할 필요가 있을 때.

메서드: 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]'