[]
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 계층에서는 hierarchy type을 ‘Parent’로 설정하며, 기본 키는 계층 ID를 나타냅니다.
다음 코드는 테이블 시트에서 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 계층에서는 hierarchy type을 ‘ChildrenPath’로 설정합니다. 이 경우 기본 키는 필수가 아니지만, 자식 항목에 대해 지정하는 것이 좋습니다.
다음 코드는 테이블 시트에서 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 계층에서는 hierarchy type을 ‘Level’로 설정합니다. 이 경우도 기본 키는 필수가 아니지만, 지정해주는 것이 좋습니다.
다음 코드는 테이블 시트에서 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 계층에서는 hierarchy type을 ‘Custom’으로 설정합니다. 이 경우도 기본 키는 선택 사항입니다.
다음 코드는 테이블 시트에서 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, 위/아래로 이동, 전/후/상/하 위치에 추가, 계층 확장/축소 레벨 등의 메뉴 항목은 런타임 시 표시하거나 숨길 수 있습니다.
아래 스냅샷은 행 머리글을 클릭했을 때 표시되는 메뉴 항목을 보여줍니다.
아래 스냅샷은 열 머리글을 마우스 오른쪽 버튼으로 클릭했을 때 표시되는 메뉴 항목을 보여줍니다.
다음 코드 샘플은 메뉴 항목의 가시성을 전환하는 방법을 보여줍니다.
// 계층형 레코드를 위한 메뉴 항목 표시
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 디자이너에서도 지원되며, Data Source 및 테이블 시트 리본의 열(Columns) 탭을 통해 설정할 수 있습니다. 계층 유형, 요약 수식, 아웃라인 열 이미지 등을 구성할 수 있습니다.
계층(Hierarchy) 섹션은 다음 옵션들을 제공합니다:
계층 유형(Hierarchy Type): Parent, ChildrenPath, Level 중 하나의 유형을 설정할 수 있습니다.
요약 수식(Summary Formula): 테이블의 특정 열에 대해 계층 요약 수식을 입력할 수 있습니다. 요약 수식에 대한 자세한 내용은 수식 항목을 참조하시기 바랍니다.
개요 열(Outline Column): Outline Column은 아웃라인 열의 표시를 사용자 지정하는 데 사용됩니다.
또한, 테이블 시트(Table Sheet) 디자인 리본의 메뉴 항목 표시(Menu Item Visibility) 버튼을 통해 계층 작업 메뉴 항목의 표시 여부도 구성할 수 있습니다.
메뉴 항목 표시(Menu Item Visibility) 버튼을 클릭하면 메뉴 항목 표시(Menu Item Visibility) 대화상자가 열립니다.