[]
        
(Showing Draft Content)

계층 데이터

SpreadJS는 데이터 소스가 계층적임을 정의하기 위해 데이터 스키마에 hierarchy 옵션을 제공합니다.

hierarchy 옵션은 GC.Data.IDataSourceOption 인터페이스로부터 상속되며, 다음과 같은 매개변수를 제공합니다:

  • type: 계층 유형을 정의합니다. 사용 가능한 값은 Parent, ChildrenPath, Level 또는 Custom입니다.

  • column: 계층 데이터를 구성하는 데 사용할 키 열을 지정합니다.

  • levelOffset: 계층 수준을 증가 또는 감소시킬 수 있는 오프셋을 나타냅니다. 일반적으로 계층 수준은 0에서 시작합니다.

  • outlineColumn: GC.Data.IHierarchyOutlineColumnOptions로부터 상속되며, 계층으로 표시할 수 있는 열을 지정합니다.

  • summaryFields: GC.Data.IHierarchySummaryFieldCollection로부터 상속되며, 필드에 대한 수식(공식)을 정의합니다.

  • parse: GC.Data.IHierarchyCustomParseOptions로부터 상속되며, 커스텀 계층 유형의 기본 키를 부모 키로 파싱합니다.

  • unparse: GC.Data.IHierarchyCustomUnparseOptions로부터 상속되며, 커스텀 계층 유형의 기본 키를 생성합니다.

계층 유형

계층에는 Parent, Level, ChildrenPath, Custom의 네 가지 유형이 있습니다. 각 유형은 데이터 매니저에 테이블을 추가할 때 구성할 수 있습니다:

Parent 계층

Parent 계층에서는 hierarchy type을 ‘Parent’로 설정하며, 기본 키는 계층 ID를 나타냅니다.

parent-hierarchy.0a0565


다음 코드는 테이블 시트에서 Parent 계층을 설정하는 방법을 보여줍니다:

<script>
        var spread = new GC.Spread.Sheets.Workbook(document.querySelector('#ss'), { sheetCount: 0 });
        initSpread(spread)
        function initSpread(spread) {
            var dataManager = spread.dataManager();

            initHierarchyParentType(spread, dataManager);

        }
        function initHierarchyParentType(spread, dataManager) {
            var table = dataManager.addTable("hierarchyParentTable", {
                data: initHierarchyParentData(),
                schema: {
                    hierarchy: {
                        type: 'Parent', // 부모 계층 유형 구성
                        column: 'parentId', // 계층적 보기를 구성하는 데 사용할 수 있는 열을 지정
                    },
                    columns: {
                        'id': { dataName: 'id', isPrimaryKey: true }, // 기본 키는 필수
                        'parentId': { dataName: 'parentId', dataType: "reorder" },
                    }
                }
            });
            var sheet = spread.addSheetTab(0, "HierarchyParent", GC.Spread.Sheets.SheetType.tableSheet);
            sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
            sheet.options.allowAddNew = true;

            table.fetch().then(function () {
                var myView = table.addView("myView", [
                    {
                        value: "parentId", width: 200,
                        outlineColumn: {
                            showImage: true,
                            images: ['https://en.onboarding.grapecitydev.com/spreadjs/demos/spread/source/images/task-1.png', 'https://en.onboarding.grapecitydev.com/spreadjs/demos/spread/source/images/task-2.png', 'https://en.onboarding.grapecitydev.com/spreadjs/demos/spread/source/images/task-3.png'],
                            expandIndicator: 'https://en.onboarding.grapecitydev.com/spreadjs/demos/spread/source/images/increaseIndicator.png',
                            collapseIndicator: 'https://en.onboarding.grapecitydev.com/spreadjs/demos/spread/source/images/decreaseIndicator.png',
                        },

                    },
                    { value: "id", width: 200 },
                ]);

                sheet.setDataView(myView);
            });
        }
        function initHierarchyParentData() {
            var data = [
                { id: 1, parentId: -1 },
                { id: 2, parentId: -1 },
                { id: 3, parentId: 1 },
                { id: 4, parentId: 1 },
                { id: 5, parentId: 2 },
                { id: 6, parentId: 2 },
                { id: 6, parentId: 2 },
            ];
            return data;
        }
</script>

ChildrenPath 계층

ChildrenPath 계층에서는 hierarchy type을 ‘ChildrenPath’로 설정합니다. 이 경우 기본 키는 필수가 아니지만, 자식 항목에 대해 지정하는 것이 좋습니다.

childrenpath-hierarchy.8ff026


다음 코드는 테이블 시트에서 ChildrenPath 계층을 설정하는 방법을 보여줍니다:

<script>
        var spread = new GC.Spread.Sheets.Workbook(document.querySelector('#ss'), { sheetCount: 0 });
        initSpread(spread)
        function initSpread(spread) {
            var dataManager = spread.dataManager();
            initHierarchyParentType(spread, dataManager);
        }
        function initHierarchyParentType(spread, dataManager) {
            var taskTable = dataManager.addTable("Tasks", {
                data: initHierarchyChildData(),
                schema: {
                    hierarchy: {
                        type: 'ChildrenPath',
                        column: 'TaskChildren',
                    },
                    columns: {
                        TaskName: { dataName: 'name' },
                        TaskChildren: { dataName: 'children' },
                        // other columns in the child
                    }
                }
            });
            var sheet = spread.addSheetTab(0, "HierarchyParent", GC.Spread.Sheets.SheetType.tableSheet);
            sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
            sheet.options.allowAddNew = true;
            taskTable.fetch().then(r => {
                var taskView = taskTable.addView('TaskView', [
                    {
                        value: 'TaskName', outlineColumn: true, width: "*" // 이 옵션은 윤곽 열로 표시되는 열을 나타냄
                    }
                ]);
                sheet.setDataView(taskView);
            })
        }
        function initHierarchyChildData() {
            var data = [
                {
                    name: 'USA',
                    children: [
                        {
                            name: 'Texas',
                            children: [
                                {
                                    name: 'Houston',
                                },
                                {
                                    name: 'Dallas',
                                },
                                {
                                    name: 'San Antonio',
                                }
                            ]
                        }
                    ]
                },
                {
                    name: 'India',
                    children: [
                        {
                            name: 'UP',
                            children: [
                                { name: 'Noida' },
                                { name: 'Ghaziabad' },
                                { name: 'Agra' },
                            ]
                        }
                    ]
                }
            ]
            return data;
        }
</script>

Level 계층

Level 계층에서는 hierarchy type을 ‘Level’로 설정합니다. 이 경우도 기본 키는 필수가 아니지만, 지정해주는 것이 좋습니다.

level-hierarchy.001cb2


다음 코드는 테이블 시트에서 Level 계층을 설정하는 방법을 보여줍니다:

<script>
        var spread = new GC.Spread.Sheets.Workbook(document.querySelector('#ss'), { sheetCount: 0 });
        initSpread(spread)
        function initSpread(spread) {
            var dataManager = spread.dataManager();

            initHierarchyParentType(spread, dataManager);
        }
        function initHierarchyParentType(spread, dataManager) {
            var taskTable = dataManager.addTable("Tasks", {
                data: initHierarchyLevelData(),
                schema: {
                    hierarchy: {
                        type: 'Level',
                        column: 'TaskLevel',
                    },
                    columns: {
                        TaskName: { dataName: 'name' },
                        TaskId: { dataName: 'id', isPrimaryKey: true }, // 기본 키를 사용하여 계층 ID를 표시 (존재하는 경우 선택적으로 사용)
                        TaskLevel: { dataName: 'level' },
                    }
                }
            });
            var sheet = spread.addSheetTab(0, "HierarchyParent", GC.Spread.Sheets.SheetType.tableSheet);
            sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
            sheet.options.allowAddNew = true;
            taskTable.fetch().then(r => {
                var taskView = taskTable.addView('TaskView', [
                    {
                        value: 'TaskName', outlineColumn: true // 이 옵션은 윤곽 열로 표시되는 열을 나타냄
                    }
                ]);

                sheet.setDataView(taskView);
            })
        }
        function initHierarchyLevelData() {
            var data = [
                { name: 'USA', level: -1, id: 1 },
                { name: 'Texas', level: 0, id: 2 },
                { name: 'Houston', level: 1, id: 3 },
                { name: 'California', level: 0, id: 4 },
                { name: 'San Francisco', level: 1, id: 5 },
                { name: 'Los Angeles', level: 1, id: 6 },
            ];
            return data;
        }
 </script>

Custom 계층

Custom 계층에서는 hierarchy type을 ‘Custom’으로 설정합니다. 이 경우도 기본 키는 선택 사항입니다.

custom-hierarchy.7ef0f0


다음 코드는 테이블 시트에서 Custom 계층을 설정하는 방법을 보여줍니다:

<script>
        var spread = new GC.Spread.Sheets.Workbook(document.querySelector('#ss'), { sheetCount: 0 });
        initSpread(spread)
        function initSpread(spread) {
            var dataManager = spread.dataManager();

            initHierarchyParentType(spread, dataManager);

        }
        function initHierarchyParentType(spread, dataManager) {
            var taskTable = dataManager.addTable("Tasks", {
                data: initHierarchyChildData(),
                schema: {
                    hierarchy: {
                        type: 'Custom',
                        column: 'id',
                        parse: function (options) {
                           // 기본 키 "1.1.1"을 "1.1"로 파싱
                           // 반환된 값은 parentId로 처리
                            let seg = options.data.TaskId.split('.');
                            return seg.slice(0, seg.length - 1).join('.')
                        },
                        unparse: function (options) {
                            let parentIds, currentIndex = options.index, parentData = options.parentData, parentKey = parentData && parentData.TaskId;
                            if (parentKey) {
                                let sp = parentKey.split('.');
                                parentIds = sp;
                            } else {
                                parentIds = [];
                            }
                            parentIds.push(currentIndex + 1);
                            return parentIds.join('.');
                        }
                    },
                    columns: {
                        TaskName: { dataName: 'name' },
                        TaskId: { dataName: 'id', isPrimaryKey: true }, // 기본 키를 사용하여 선택적으로 계층 ID를 표시
                    }
                }
            });
            var sheet = spread.addSheetTab(0, "HierarchyParent", GC.Spread.Sheets.SheetType.tableSheet);
            sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
            sheet.options.allowAddNew = true;

            taskTable.fetch().then(r => {
                var taskView = taskTable.addView('TaskView', [
                    {
                        value: 'TaskName', outlineColumn: true, width: "*" // 이 옵션은 윤곽 열로 표시되는 열을 표시
                    }
                ]);
                sheet.setDataView(taskView);
            })
        }
        function initHierarchyChildData() {
            var data = [
                {
                    id: '1', name: "1"
                },
                { id: '2', name: '2' },
                { id: '1.1', name: "1.1" },
                { id: '1.1.1', name: '1.1.1' },
                { id: '2.1', name: '2.1' }
            ]
            return data;
        }
</script>

계층 작업

테이블 시트는 다음과 같은 계층 작업을 지원합니다:

  • 지정한 행의 계층 수준을 승격

테이블 시트는 promoteHierarchyLevel(row: number) 메서드를 사용하여 지정한 인덱스의 계층 데이터를 승격할 수 있습니다.

tableSheet.promoteHierarchyLevel(8);
  • 지정한 행의 계층 수준을 강등

테이블 시트는 demoteHierarchyLevel(row: number, withChildren?: boolean) 메서드를 사용하여 지정한 행의 계층 수준을 강등할 수 있습니다.

tableSheet.demoteHierarchyLevel(8);
  • 지정한 행의 계층 데이터를 위로 이동

테이블 시트는 moveUp(row: number) 메서드를 사용하여 지정한 인덱스의 계층 데이터를 위로 이동할 수 있습니다.

tableSheet.moveUp(8);
  • 지정한 행의 계층 데이터를 아래로 이동

테이블 시트는 moveDown(row: number) 메서드를 사용하여 지정한 인덱스의 계층 데이터를 아래로 이동할 수 있습니다.

tableSheet.moveDown(8);
  • 선택한 행 다음에 레코드 추가

테이블 시트는 addHierarchyItemAfter(row: number, rowData: any) 메서드를 사용하여 지정한 행 다음에 새 행을 추가할 수 있습니다.

tableSheet.addHierarchyItemAfter(8, {id: 8, name: "grapecity"});
  • 선택한 행 위에 레코드 추가

테이블 시트는 addHierarchyItemAbove(row: number, rowData: any) 메서드를 사용하여 선택한 행 위에 레코드를 추가할 수 있습니다. 추가된 레코드는 선택한 레코드의 위치를 대체하고, 선택한 레코드는 추가된 레코드의 자식이 됩니다.

tableSheet.addHierarchyItemAbove(8, {id: 8, name: "grapecity"});
  • 선택한 행 아래에 레코드 추가

테이블 시트는 addHierarchyItemBelow(row: number, rowData: any) 메서드를 사용하여 지정한 행의 자식으로 새 행 데이터를 추가할 수 있습니다. 추가된 레코드는 선택한 레코드의 마지막 자식이 됩니다.

tableSheet.addHierarchyItemBelow(8, {id: 8, name: "grapecity"});
  • 레코드 삭제

테이블 시트 해당 레코드와 그 하위 레코드를 삭제할 수 있습니다.

  • 레코드 확장

이 메뉴 항목은 열 머리글을 클릭할 때 나타납니다. expandAllHierarchyLevels() 메서드를 사용하여 모든 계층 수준을 확장합니다.

tableSheet.expandAllHierarchyLevels();
  • 레코드 축소

이 메뉴 항목은 열 머리글을 클릭할 때 나타나며, collapseAllHierarchyLevels() 메서드를 사용하여 모든 계층 수준을 축소합니다.

tableSheet.collapseAllHierarchyLevels();

메뉴 항목 가시성 전환

Promote, Demote, 위/아래로 이동, 전/후/상/하 위치에 추가, 계층 확장/축소 레벨 등의 메뉴 항목은 런타임 시 표시하거나 숨길 수 있습니다.

아래 스냅샷은 행 머리글을 클릭했을 때 표시되는 메뉴 항목을 보여줍니다.

row-rightclick.d8db7e


아래 스냅샷은 열 머리글을 마우스 오른쪽 버튼으로 클릭했을 때 표시되는 메뉴 항목을 보여줍니다.


column-rightclick.02b3eb


다음 코드 샘플은 메뉴 항목의 가시성을 전환하는 방법을 보여줍니다.

// 계층형 레코드를 위한 메뉴 항목 표시
sheet.options.menuItemVisibility = {
  // 아래 옵션은 행 머리글에 표시
promoteMenuItemVisible: true,
demoteMenuItemVisible: true,
  // 아래 옵션은 열 머리글에 표시
expandAllLevelMenuItemVisible: true,
collapseAllLevelMenuItemVisible: true,
expandToLevelMenuItemVisible: true,
  // 아래 옵션은 행 머리글에 표시되며,
  // 해당 열의 dataType이 rowOrder일 경우 메뉴 항목이 활성화
moveUpMenuItemVisible: true,
moveDownMenuItemVisible: true,
addBeforeMenuItemVisible: true,
addAfterMenuItemVisible: true,
addAboveMenuItemVisible: true,
addBelowMenuItemVisible: true,
};

참고: groupBy, 행 고정(pinning rows), resetRow 등의 일부 기능은 계층형 데이터와 함께 사용할 경우 정상 동작하지 않을 수 있습니다.

SpreadJS 디자이너 사용하기

계층형 데이터는 SpreadJS 디자이너에서도 지원되며, Data Source 및 테이블 시트 리본의 열(Columns) 탭을 통해 설정할 수 있습니다. 계층 유형, 요약 수식, 아웃라인 열 이미지 등을 구성할 수 있습니다.


datasource-hierarchy-designer.0ea922

계층(Hierarchy) 섹션은 다음 옵션들을 제공합니다:

  • 계층 유형(Hierarchy Type): Parent, ChildrenPath, Level 중 하나의 유형을 설정할 수 있습니다.

hierarchy-type-design.469f63

  • 요약 수식(Summary Formula): 테이블의 특정 열에 대해 계층 요약 수식을 입력할 수 있습니다. 요약 수식에 대한 자세한 내용은 수식 항목을 참조하시기 바랍니다.

  • 개요 열(Outline Column): Outline Column은 아웃라인 열의 표시를 사용자 지정하는 데 사용됩니다.

또한, 테이블 시트(Table Sheet) 디자인 리본의 메뉴 항목 표시(Menu Item Visibility) 버튼을 통해 계층 작업 메뉴 항목의 표시 여부도 구성할 수 있습니다.

menu-item-visibility.90d7e6

메뉴 항목 표시(Menu Item Visibility) 버튼을 클릭하면 메뉴 항목 표시(Menu Item Visibility) 대화상자가 열립니다.

menu-visible-dialog.657796