[]
SpreadJS는 스프레드시트에서 동적 배열 수식(Dynamic Array Formula)을 사용하는 것을 광범위하게 지원합니다.
동적 배열 수식은 자동 확장(spilling) 및 셀 범위로의 자동 확장을 통해 여러 결과를 반환합니다. 이를 통해 스프레드시트에서 배열 수식을 훨씬 더 쉽고 빠르게 사용할 수 있습니다.
동적 배열 수식은 특히 다음과 같은 경우에 유용합니다:
사용자가 스프레드시트에서 데이터 캐시를 효과적으로 활용하고자 할 때
사용자가 랜덤 액세스를 지원하면서도 메모리 사용량이 적은(컴팩트한) 캐시 친화적 데이터 구조를 만들고자 할 때
(일반적으로, 동적 배열은 크기 및 용량에 대한 정보를 저장하기 위한 고정된 오버헤드만을 추가로 가지므로 가능합니다)
UNIQUE
함수는 셀 범위 내의 모든 고유 값을 반환합니다.
예: 셀 C4에 수식 "=UNIQUE(A4:A15)"
가 포함되어 있을 경우, A4에서 A15까지의 값 중 고유한 고객 이름만 반환됩니다. 고유 값의 개수에 따라 동적 배열 수식은 C5부터 C8까지의 셀 범위로 자동 확장(spill)됩니다. 아래 이미지를 참조하시기 바랍니다:
FILTER
함수는 정의된 조건에 따라 셀 범위를 필터링합니다. 필터 작업은 단일 조건 또는 여러 조건을 기반으로 수행될 수 있습니다. 두 개 이상의 필터 조건을 결합하려면 " * "
연산자를 사용할 수 있습니다.
예: 셀 F5에 수식 "=FILTER(A5:D17, C5:C17=F1)"
이 포함된 경우, C5에서 C17까지의 셀 범위가 F1 셀(예: Apple)의 값과 일치하는 경우에 한해 A5부터 D17까지의 셀 값이 필터링되어 표시됩니다.
셀 F14에는 수식 "=FILTER(A5:D17, (C5:C17=F1)(A5:A17=F2))"
이 포함되어 있으며, 이는 두 개의 조건을 곱셈 연산자 ()
로 결합하여 A5:D17 셀 범위를 필터링합니다. 첫 번째 조건은 C5:C17 셀 범위가 F1 셀의 제품 값(예: Apple)과 일치해야 하며, 두 번째 조건은 A5:A17 셀 범위가 지역 "East"와 일치해야 합니다. 결과적으로 제품이 "Apple"이고 지역이 "East"인 데이터만 표시됩니다.
RANDARRAY
함수는 무작위 숫자 값의 배열을 반환합니다. 사용자는 행 및 열 수, 최소/최대 값, 정수 또는 소수 여부를 지정할 수 있습니다.
예: 셀 A8에 수식 "=RANDARRAY(5,3)"
이 포함된 경우, 0과 1 사이의 무작위 값이 5행 3열로 반환됩니다.
SORT
함수는 셀 범위 또는 배열의 데이터를 정렬합니다. 이 함수의 결과는 동적 배열로 인접 범위에 spill되어 오름차순(증가) 또는 내림차순(감소)으로 정렬된 값을 표시합니다. 정렬 순서가 지정되지 않은 경우, 기본적으로 알파벳 오름차순으로 정렬됩니다.
예: 셀 D4에 수식 "=SORT(A4:A15)"
가 포함된 경우, 고객 이름이 오름차순으로 정렬되어 반환됩니다.
A4에서 A15까지의 고유 값을 정렬하려면, C4 열에 표시된 고유 리스트에 SORT
함수를 적용하거나, SORT
와 UNIQUE
함수를 하나의 수식으로 결합할 수 있습니다.
예: 셀 E4에 수식 "=SORT(C4#)"
가 포함되어 있는 경우, #
는 스필 범위를 참조하며, C4 셀의 UNIQUE 수식 "=UNIQUE(A4:A15)"
를 기반으로 한 값을 정렬합니다.
또는 두 함수를 결합하여 사용할 수도 있습니다. 예: 셀 F4에 수식 "=SORT(UNIQUE(A4:A15))"
가 포함되어 있으면, A4:A15 범위의 모든 고유 값이 알파벳순으로 정렬되어 반환됩니다.
SORTBY
함수는 대응되는 범위 또는 배열의 값을 기준으로 셀 범위 또는 배열의 내용을 정렬합니다.
예: 셀 G4에 수식 "=SORTBY(A4:B15,B4:B15)"
가 포함된 경우, B4에서 B15까지의 셀 범위를 기준으로 A4:B15 범위를 정렬하며, 나이 기준으로 고객 이름이 함께 표시됩니다.
SEQUENCE
함수는 오름차순의 연속된 숫자 리스트를 배열로 반환합니다.
예: 셀 A2에 수식 "=SEQUENCE(4,5)"
가 포함된 경우, 4행 5열로 구성된 셀 범위에 1부터 20까지의 숫자가 순차적으로 채워집니다.
SINGLE
함수는 암시적 교차(implicit intersection) 논리를 사용하여 단일 값, 단일 셀 범위 또는 오류를 반환합니다.
예: 셀 A15에 수식 "=SINGLE(A15:E15)"
가 포함된 경우, A15:E15 범위의 행과 열의 교차점에 있는 "C" 값을 C16 셀에 반환합니다.
스프레드시트에서 일반 수식을 사용하는 것은 번거로운 작업입니다. 사용자가 결과를 계산하려는 각 셀에 수식을 수동으로 복사해야 하기 때문입니다. 그러나 셀에 동적 배열 수식이 포함된 경우, 배열 요소가 인접한 빈 셀로 스필되며 다중 값이 반환됩니다. 일반 배열과 달리 동적 배열은 원본 범위에서 데이터가 삽입되거나 제거될 때 자동으로 크기가 조정됩니다.
스필링: 모든 수식이 여러 값을 반환할 경우(배열 형태로), 인접 셀에 결과가 채워지는 동작을 스필링이라 합니다. 여러 결과를 반환할 가능성이 있는 수식은 동적 배열 수식으로 간주될 수 있습니다.
스필된 배열 수식: 워크시트 내에서 다중 결과를 반환하고 성공적으로 스필되는 수식은 스필된 배열 수식이라 불립니다.
스필 범위 연산자: #
연산자는 전체 스필 범위를 참조하는 데 사용됩니다. 수식이 다중 결과를 반환하면서 스필 할 수 없는 경우 spill 오류가 반환됩니다.
스프레드시트에서 동적 배열 함수를 사용하려면 다음 코드 스니펫을 사용하여 동적 배열을 먼저 활성화해야 합니다.
// 동적 배열 활성화
spread.options.allowDynamicArray = true;
The following code sample demonstrates how the dynamic array functions are used in the spreadsheet.
// Spread 초기화
var spread = new GC.Spread.Sheets.Workbook(document.getElementById('ss'), { sheetCount: 4 });
// 활성화시트 가져오기
var activeSheet = spread.getActiveSheet();
// 동적 배열 활성화
spread.options.allowDynamicArray = true;
activeSheet.FrozenRowCount = 1;
activeSheet.setText(0, 0, "Dynamic Array Functions");
activeSheet.getCell(0, 0).backColor("LightGray");
activeSheet.addSpan(0, 0, 1, 3, GC.Spread.Sheets.SheetArea.viewport);
// Sheet[0]의 셀에 데이터 설정
activeSheet.setText(2, 0, "Customer's Name");
activeSheet.getCell(2, 0).backColor("LightGray");
activeSheet.setText(3, 0, "Larry");
activeSheet.setText(4, 0, "Safeway");
activeSheet.setText(5, 0, "Safeway");
activeSheet.setText(6, 0, "Raley");
activeSheet.setText(7, 0, "Vallarta");
activeSheet.setText(8, 0, "Safeway");
activeSheet.setText(9, 0, "Raley");
activeSheet.setText(10, 0, "Larry");
activeSheet.setText(11, 0, "Gilbert");
activeSheet.setText(12, 0, "Larry");
activeSheet.setText(13, 0, "Larry");
activeSheet.setText(14, 0, "Raley");
activeSheet.setColumnWidth(0, 120.0, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.setText(2, 1, "Age");
activeSheet.getCell(2, 1).backColor("LightGray");
activeSheet.setText(3, 1, "32");
activeSheet.setText(4, 1, "23");
activeSheet.setText(5, 1, "23");
activeSheet.setText(6, 1, "39");
activeSheet.setText(7, 1, "18");
activeSheet.setText(8, 1, "23");
activeSheet.setText(9, 1, "39");
activeSheet.setText(10, 1, "32");
activeSheet.setText(11, 1, "19");
activeSheet.setText(12, 1, "32");
activeSheet.setText(13, 1, "32");
activeSheet.setText(14, 1, "39");
activeSheet.setColumnWidth(1, 50.0, GC.Spread.Sheets.SheetArea.viewport);
// "Unique" 수식 설정
activeSheet.setText(2, 2, "Unique List");
activeSheet.getCell(2, 2).backColor("LightBlue");
activeSheet.setFormula(3, 2, "UNIQUE(A4:A15)");
activeSheet.setColumnWidth(2, 90.0, GC.Spread.Sheets.SheetArea.viewport);
// "Sort" 수식 설정
activeSheet.setText(2, 3, "Sort");
activeSheet.getCell(2, 3).backColor("LightBlue");
activeSheet.setFormula(3, 3, "SORT(A4:A15)");
activeSheet.setColumnWidth(3, 90.0, GC.Spread.Sheets.SheetArea.viewport);
// 고유 목록에 대한 "Sort" 수식 설정
activeSheet.setText(2, 4, "Sort Unique");
activeSheet.getCell(2, 4).backColor("LightBlue");
activeSheet.setFormula(3, 4, "SORT(C4#)");
activeSheet.setColumnWidth(4, 90.0, GC.Spread.Sheets.SheetArea.viewport);
// "Sort+Unique" 수식을 함께 설정
activeSheet.setText(2, 5, "Sort Unique");
activeSheet.getCell(2, 5).backColor("LightBlue");
activeSheet.setFormula(3, 5, "SORT(UNIQUE(A4:A15)");
activeSheet.setColumnWidth(5, 90.0, GC.Spread.Sheets.SheetArea.viewport);
// A4:B15 범위를 B4:B15 범위를 기준으로 정렬하는 "SortBy" 수식 설정
activeSheet.setText(2, 6, "SortBy");
activeSheet.getCell(2, 6).backColor("LightBlue");
activeSheet.setFormula(3, 6, "SORTBY(A4:B15, B4:B15)");
activeSheet.setColumnWidth(6, 90.0, GC.Spread.Sheets.SheetArea.viewport);
// 두 번째 시트를 가져오기
var activeSheet = spread.getSheet(1);
// Sheet[1]의 셀에 데이터 설정
for (var i = 0; i < 9; i++)
activeSheet.setColumnWidth(i, 70.0, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.setText(3, 0, "Region");
activeSheet.getCell(3, 0).backColor("LightGray");
activeSheet.setText(4, 0, "East");
activeSheet.setText(5, 0, "North");
activeSheet.setText(6, 0, "Wast");
activeSheet.setText(7, 0, "Sast");
activeSheet.setText(8, 0, "East");
activeSheet.setText(9, 0, "East");
activeSheet.setText(10, 0, "West");
activeSheet.setText(11, 0, "South");
activeSheet.setText(12, 0, "North");
activeSheet.setText(13, 0, "North");
activeSheet.setText(14, 0, "East");
activeSheet.setText(15, 0, "South");
activeSheet.setText(16, 0, "West");
activeSheet.setText(3, 1, "Sales Rep");
activeSheet.getCell(3, 1).backColor("LightGray");
activeSheet.setText(4, 1, "Tom");
activeSheet.setText(5, 1, "Fred");
activeSheet.setText(6, 1, "Amy");
activeSheet.setText(7, 1, "Sal");
activeSheet.setText(8, 1, "Hector");
activeSheet.setText(9, 1, "Xi");
activeSheet.setText(10, 1, "Amy");
activeSheet.setText(11, 1, "Sal");
activeSheet.setText(12, 1, "Fred");
activeSheet.setText(13, 1, "Tom");
activeSheet.setText(14, 1, "Hector");
activeSheet.setText(15, 1, "Sravan");
activeSheet.setText(16, 1, "Xi");
activeSheet.setText(3, 2, "Product");
activeSheet.getCell(3, 2).backColor("LightGray");
activeSheet.setText(4, 2, "Apple");
activeSheet.setText(5, 2, "Grape");
activeSheet.setText(6, 2, "Pear");
activeSheet.setText(7, 2, "Banana");
activeSheet.setText(8, 2, "Apple");
activeSheet.setText(9, 2, "Banana");
activeSheet.setText(10, 2, "Banana");
activeSheet.setText(11, 2, "Pear");
activeSheet.setText(12, 2, "Apple");
activeSheet.setText(13, 2, "Grape");
activeSheet.setText(14, 2, "Grape");
activeSheet.setText(15, 2, "Apple");
activeSheet.setText(16, 2, "Grape");
activeSheet.setText(3, 3, "Units");
activeSheet.getCell(3, 3).backColor("LightGray");
activeSheet.setText(4, 3, "6380");
activeSheet.setText(5, 3, "2344");
activeSheet.setText(6, 3, "3434");
activeSheet.setText(7, 3, "5461");
activeSheet.setText(8, 3, "2341");
activeSheet.setText(9, 3, "3234");
activeSheet.setText(10, 3, "6532");
activeSheet.setText(11, 3, "7323");
activeSheet.setText(12, 3, "2334");
activeSheet.setText(13, 3, "8734");
activeSheet.setText(14, 3, "1932");
activeSheet.setText(15, 3, "7682");
activeSheet.setText(16, 3, "3293");
activeSheet.setText(0, 4, "Product:");
activeSheet.getCell(0, 4).backColor("LightGray");
activeSheet.setText(0, 5, "Apple");
activeSheet.setText(1, 4, "Region:");
activeSheet.getCell(1, 4).backColor("LightGray");
activeSheet.setText(1, 5, "East");
activeSheet.setText(2, 5, "Filtering performed on one Criteria");
activeSheet.getCell(2, 5).backColor("LightBlue");
activeSheet.addSpan(2, 5, 1, 4, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.setText(3, 5, "Region");
activeSheet.getCell(3, 5).backColor("LightGray");
activeSheet.setText(3, 6, "Sales Rep");
activeSheet.getCell(3, 6).backColor("LightGray");
activeSheet.setText(3, 7, "Product");
activeSheet.getCell(3, 7).backColor("LightGray");
activeSheet.setText(3, 8, "Units");
activeSheet.getCell(3, 8).backColor("LightGray");
// 하나의 조건을 사용한 "Filter" 수식 설정: C5:C21 범위가 F1 셀의 값과 같은 경우 A5:D21 범위를 필터링
activeSheet.setFormula(4, 5, "FILTER(A5:D21, C5:C21=F1)", GC.Spread.Sheets.SheetArea.viewport);
activeSheet.setText(12, 5, "Region");
activeSheet.getCell(12, 5).backColor("LightGray");
activeSheet.setText(12, 6, "Sales Rep");
activeSheet.getCell(12, 6).backColor("LightGray");
activeSheet.setText(12, 7, "Product");
activeSheet.getCell(12, 7).backColor("LightGray");
activeSheet.setText(12, 8, "Units");
activeSheet.getCell(12, 8).backColor("LightGray");
activeSheet.setText(11, 5, "Filtering performed on two Criteria");
activeSheet.getCell(11, 5).backColor("LightBlue");
activeSheet.addSpan(11, 5, 1, 4, GC.Spread.Sheets.SheetArea.viewport);
// 두 개의 조건을 사용한 "Filter" 수식 설정: C5:C21 범위가 F1 셀의 값과 같고 A5:A21 범위가 F2 셀의 값과 같은 경우 A5:D21 범위를 필터링
activeSheet.setFormula(13, 5, "FILTER(A5:D21, (C5:C21=F1)*(A5:A21=F2))", GC.Spread.Sheets.SheetArea.viewport);
// 두 번째 시트 가져오기
var activeSheet = spread.getSheet(2);
// Sheet[2]의 열 너비 설정
for (var i = 0; i < 7; i++)
activeSheet.setColumnWidth(i, 130.0, GC.Spread.Sheets.SheetArea.viewport);
// "Sequence" 수식 설정
// 열 너비 설정: activeSheet.Columns[0, 7].Width = 130;
activeSheet.setText(0, 0, "SEQUENCE(4,5) Function");
activeSheet.addSpan(0, 0, 1, 2, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.getCell(0, 0).backColor("SkyBlue");
activeSheet.setFormula(1, 0, "SEQUENCE(4,5)", GC.Spread.Sheets.SheetArea.viewport);
// "RandArray" 수식 설정
activeSheet.setText(6, 0, "RANDARRAY(5,3) Function");
activeSheet.addSpan(6, 0, 1, 2, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.getCell(6, 0).backColor("SkyBlue");
activeSheet.setFormula(7, 0, "RANDARRAY(5,3)", GC.Spread.Sheets.SheetArea.viewport);
// "Single" 수식 설정
activeSheet.setText(13, 0, "SINGLE Function is represented by @ i.e. =@(A15:E15)");
activeSheet.addSpan(13, 0, 1, 4, GC.Spread.Sheets.SheetArea.viewport);
activeSheet.getCell(13, 0).backColor("SkyBlue");
activeSheet.setValue(14, 0, "A");
activeSheet.setValue(14, 1, "B");
activeSheet.setValue(14, 2, "C");
activeSheet.setValue(14, 3, "D");
activeSheet.setValue(14, 4, "E");
activeSheet.setFormula(15, 2, "@(A15:E15)", GC.Spread.Sheets.SheetArea.viewport);