基本应用

集算表支持交叉列,即来自相关表或指定列表的记录的列。

此外,每个交叉列可以具有与基本列相同的属性。

可以使用带有以下选项的 addView 方法设置交叉列: 要显示交叉列,有一条重要规则,即只能使用在架构中定义为查找字段的字段。 有4个步骤: 1.在数据源架构中添加多个带有列选项的表 2.指定表的主键 3.添加表之间的关系 4.添加带有跨栏选项的自定义视图 这是使用相关表添加交叉列的示例代码。 要过滤指定的交叉列,请启用 allowDynamicArray 属性。 FILTER 的第一个参数必须指定添加关系时使用的主键,第二个参数是条件。 可以使用选项格式化程序来格式化跨列标题。 这些值可以通过如下公式计算: =SUM(FILTER([@grades.Grade],[@grades.workItem.Type]="Homework")) 这是使用带有列表的交叉列的示例代码。 可以使用标题选项来定义交叉列的标题。 这是组合交叉列的示例代码。 当组合具有相同交叉选项的交叉列时,最好使用 showCrossValueHeader 显示不同的值。
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ var baseApiUrl = getBaseApiUrl(); var baseTableName = "Cross_Column_"; window.onload = function() { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 }); initSpread(spread); }; function initSpread(spread) { spread.suspendPaint(); spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; spread.clearSheets(); //init a data manager var dataManager = spread.dataManager(); initStudentGradeTableSheet(spread, dataManager); initPaymentTableSheet(spread, dataManager); initInspectionReportTableSheet(spread, dataManager); initStudentsGradesTableSheet(spread, dataManager); spread.resumePaint(); } function initStudentGradeTableSheet(spread, dataManager) { // enable allowDynamicArray to using FILTER formula for cross column spread.options.allowDynamicArray = true; var dataSource = prepareData(); var studentTable = dataManager.addTable("Students", { autoSync: true, remote: { read: fakeRead(dataSource.students), update: fakeUpdate(dataSource.students), create: fakeCreate(dataSource.students), delete: fakeDelete(dataSource.students), }, schema: { columns: { ID: { dataType: "number" }, Name: { dataType: "string" }, } } }); studentTable.primaryKey("ID"); var workItemTable = dataManager.addTable("WorkItems", { autoSync: true, remote: { read: fakeRead(dataSource.workItems), update: fakeUpdate(dataSource.workItems), create: fakeCreate(dataSource.workItems), delete: fakeDelete(dataSource.workItems), }, schema: { columns: { ID: { dataType: "number" }, Date: { dataType: "date" }, Description: { dataType: "string" }, TotalPoints: { dataType: "number" }, Type: { dataType: "string" }, } } }); workItemTable.primaryKey("ID"); var gradeTable = dataManager.addTable("Grades", { autoSync: true, remote: { read: fakeRead(dataSource.grades), update: fakeUpdate(dataSource.grades, ['StudentID', 'WorkItemID']), create: fakeCreate(dataSource.grades), delete: fakeDelete(dataSource.grades, ['StudentID', 'WorkItemID']), }, schema: { columns: { StudentID: { dataType: "number" }, WorkItemID: { dataType: "number", lookup: "workItem" }, Grade: { dataType: "number" } } } }); gradeTable.primaryKey("StudentID,WorkItemID"); dataManager.addRelationship(gradeTable, "StudentID", "student", studentTable, "ID", "grades"); dataManager.addRelationship(gradeTable, "WorkItemID", "workItem", workItemTable, "ID", "grades"); var gradeSheet = spread.addSheetTab(0, "Grade Book", GC.Spread.Sheets.SheetType.tableSheet); gradeSheet.options.allowAddNew = true; var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions; var options = gradeSheet.rowActionOptions(); options.push( rowActions.removeRow, rowActions.saveRow, rowActions.resetRow, ); gradeSheet.rowActionOptions(options); var gradeView = studentTable.addView("gradeView", [ { value: 'Name', width: 150 }, { value: "grades.Grade", cross: { over: 'grades.WorkItemID', attributes: ['grades.workItem.Type', 'grades.workItem.TotalPoints', { value: 'grades.workItem.Date', formatter: 'dd-MMM' }], // format the value filter: '=FILTER([grades.workItem.ID],[grades.workItem.Description]<>"HW 20")', // Filter the WorkItems table } }, { value: '=SUM(FILTER([@grades.Grade],[@grades.workItem.Type]="Homework"))', caption: 'Total Grade of Homework', width: 190 }, { value: '=SUM(FILTER([@grades.Grade],[@grades.workItem.Type]="Quiz"))', caption: 'Total Grade of Quiz', width: 150 }, { value: '=SUM(FILTER([@grades.Grade],[@grades.workItem.Type]="Exam"))', caption: 'Total Grade of Exam', width: 150 }, ], undefined, { defaultColumnWidth: 80 } ); gradeView.fetch().then(function () { gradeSheet.setDataView(gradeView); }); } function initPaymentTableSheet(spread, dataManager) { var paymentTable = dataManager.addTable("Payments", { data: [ { "CustomerID": "1", "CustomerName": "Overbees Stocks", "PmtDate": "2/10/2019", "PmtMethod": "ACH", "Amount": 2000 }, { "CustomerID": "2", "CustomerName": "Lincoln Construction", "PmtDate": "3/15/2029", "PmtMethod": "Cash", "Amount": 3900 }, { "CustomerID": "3", "CustomerName": "Excelton Foods", "PmtDate": "3/18/2019", "PmtMethod": "CC", "Amount": 3500 }, { "CustomerID": "4", "CustomerName": "Cheasepeak inc", "PmtDate": "4/10/2019", "PmtMethod": "Cash", "Amount": 2300 } ], schema: { columns: { CustomerID: { dataType: "string" }, CustomerName: { dataType: "string" }, PmtDate: { dataType: "date" }, PmtMethod: { dataType: "string", lookup: ["Cash", "Check", "ACH", "CC"] // specify the values can lookup, and could be used for cross columns }, Amount: { dataType: "number" } } }, }); paymentTable.primaryKey('CustomerID'); var paymentSheet = spread.addSheetTab(1, "Payments Ledger", GC.Spread.Sheets.SheetType.tableSheet); paymentSheet.options.allowAddNew = true; var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions; var options = paymentSheet.rowActionOptions(); options.push( rowActions.removeRow, rowActions.saveRow, rowActions.resetRow, ); paymentSheet.rowActionOptions(options); var paymentView = paymentTable.addView("paymentView", [ { value: 'CustomerName', width: 150 }, { value: 'PmtDate', width: 120, style: { formatter: 'MM/dd/yyyy' } }, { value: "Amount", cross: { over: 'PmtMethod', caption: 'Payment Method', // setting the pre-defined header for cross columns }, style: { formatter: '$#,##0' } }, ], undefined, { defaultColumnWidth: 100 }); paymentView.fetch().then(function () { paymentSheet.setDataView(paymentView); }) } function initInspectionReportTableSheet(spread, dataManager) { var itemTableName = "Items"; var itemTableApiUrl = baseApiUrl + "/" + baseTableName + itemTableName; var itemTable = dataManager.addTable(itemTableName, { remote: { read: { url: itemTableApiUrl }, update: { url: itemTableApiUrl, method: 'PUT' }, create: { url: itemTableApiUrl }, delete: { url: itemTableApiUrl }, batch: { url: itemTableApiUrl + "Collection" } }, autoSync: true, schema: { columns: { Id: { dataType: "number" }, Name: { dataType: "string" }, } } }); itemTable.primaryKey('Id'); var subItemTableName = "SubItems"; var subItemTableApiUrl = baseApiUrl + "/" + baseTableName + subItemTableName; var subItemTable = dataManager.addTable(subItemTableName, { remote: { read: { url: subItemTableApiUrl }, update: { url: subItemTableApiUrl, method: 'PUT' }, create: { url: subItemTableApiUrl }, delete: { url: subItemTableApiUrl }, batch: { url: subItemTableApiUrl + "Collection" } }, autoSync: true, schema: { columns: { Id: { dataType: "number" }, ItemId: { dataType: "number" }, SubItemId: { dataType: "string" }, Description: { dataType: "string" }, } } }); subItemTable.primaryKey('Id'); var detailTableName = "Details"; var detailTableApiUrl = baseApiUrl + "/" + baseTableName + detailTableName; var detailTable = dataManager.addTable(detailTableName, { remote: { read: { url: detailTableApiUrl }, update: { url: detailTableApiUrl, method: 'PUT' }, create: { url: detailTableApiUrl }, delete: { url: detailTableApiUrl }, batch: { url: detailTableApiUrl + "Collection" } }, autoSync: true, schema: { columns: { Id: { dataType: "number" }, ItemId: { dataType: "number" }, SubItemId: { dataType: "string" }, Workshop: { dataType: "string", lookup: ['Workshop1', 'Workshop2', 'Workshop3'] }, Result: { dataType: "boolean", dataPattern: "1|0" }, Problem: { dataType: "string" }, } } }); detailTable.primaryKey('Id'); dataManager.addRelationship(detailTable, "SubItemId", "subItem", subItemTable, "SubItemId", "details"); dataManager.addRelationship(subItemTable, "ItemId", "item", itemTable, "Id", "subItems"); var inspectionReportSheet = spread.addSheetTab(2, "Inspection Report", GC.Spread.Sheets.SheetType.tableSheet); inspectionReportSheet.options.allowAddNew = false; var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions; var options = inspectionReportSheet.rowActionOptions(); options.push( rowActions.saveRow, rowActions.resetRow, ); inspectionReportSheet.rowActionOptions(options); var inspectReportView = subItemTable.addView("inspectReportView", [ { value: '=RIGHT([@SubItemId])&" "&[@Description]', caption: 'Description', width: 300 }, { value: "details.Result", caption: "Pass?", cross: "workshopResult", width: 120, style: { cellType: new GC.Spread.Sheets.CellTypes.CheckBox(), hAlign: 'center', vAlign: 'center' } }, { value: "details.Problem", caption: "Note", cross: "workshopResult", width: 120 }, ], undefined, { cross: { // combined the cross column together workshopResult: { over: 'details.Workshop', }, }, showCrossValueHeader: true // show the headers specify by the property value } ); inspectReportView.fetch().then(function () { inspectionReportSheet.setDataView(inspectReportView); inspectionReportSheet.groupBy([ { field: 'item.Id', caption: 'No.', width: 70 }, { field: 'item.Name', caption: 'Category', width: 250 }, ]); }) } function initStudentsGradesTableSheet (spread, dataManager) { // enable allowDynamicArray to using FILTER formula for cross column spread.options.allowDynamicArray = true; let templateSheet = initTemplateSheet(spread); var dataSource = prepareStudentsGradesData(); var studentTable = dataManager.addTable("Students2", { autoSync: true, remote: { read: fakeRead(dataSource.students), update: fakeUpdate(dataSource.students), create: fakeCreate(dataSource.students), delete: fakeDelete(dataSource.students), }, schema: { columns: { ID: { dataType: "number" }, Name: { dataType: "string" }, } } }); studentTable.primaryKey("ID"); var classesTable = dataManager.addTable("Classes", { autoSync: true, remote: { read: fakeRead(dataSource.classes), update: fakeUpdate(dataSource.classes), create: fakeCreate(dataSource.classes), delete: fakeDelete(dataSource.classes), }, schema: { columns: { ID: { dataType: "number" }, ClassName: { dataType: "string" }, Type: { dataType: "string" }, } } }); classesTable.primaryKey("ID"); var gradeTable = dataManager.addTable("Grades2", { autoSync: true, remote: { read: fakeRead(dataSource.grades), update: fakeUpdate(dataSource.grades, ['StudentID', 'ClassID']), create: fakeCreate(dataSource.grades), delete: fakeDelete(dataSource.grades, ['StudentID', 'ClassID']), }, schema: { columns: { StudentID: { dataType: "number" }, ClassID: { dataType: "number", lookup: "class" }, Grade: {}, } } }); gradeTable.primaryKey("StudentID,ClassID"); dataManager.addRelationship(gradeTable, "StudentID", "student", studentTable, "ID", "grades"); dataManager.addRelationship(gradeTable, "ClassID", "class", classesTable, "ID", "grades"); var studentsGradesSheet = spread.addSheetTab(0, "Students Grades", GC.Spread.Sheets.SheetType.tableSheet); studentsGradesSheet.options.allowAddNew = false; studentsGradesSheet.options.defaultStackRowHeight = 30; studentsGradesSheet.setDefaultRowHeight(120, 1); studentsGradesSheet.setDefaultRowHeight(50); var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions; var options = studentsGradesSheet.rowActionOptions(); options.push( rowActions.saveRow, rowActions.resetRow, ); studentsGradesSheet.rowActionOptions(options); var cellType = new GC.Spread.Sheets.CellTypes.RangeTemplate(templateSheet, 0, 0, 1, 2); var rangeTemplateStyle = new GC.Spread.Sheets.Style(); //StyleOptions doesn't support RangeTemplateCellType, so keep use Style here rangeTemplateStyle.cellType = cellType; var formulaRule = { ruleType: "formulaRule", formula: "AND(@<60,@>0)", style: { backColor: "rgb(254,89,88)" } }; var gradeView = studentTable.addView("gradeView", [ { value: '=[@]', caption: "Name", width: 200, headerStyle: {backColor: "#3CC200", foreColor: "white"}, style: {foreColor: "#66474E", backColor: "white", cellType: cellType}}, { value: '=IFS(AVERAGE(FILTER([@grades.Grade],[@grades.class.Type]="Tests"))>80,"A",AVERAGE(FILTER([@grades.Grade],[@grades.class.Type]="Tests"))>70,"B",AVERAGE(FILTER([@grades.Grade],[@grades.class.Type]="Tests"))>60,"C", AVERAGE(FILTER([@grades.Grade],[@grades.class.Type]="Tests"))>0, "E")', caption: 'Tests', width: 50, headerFit: "stack", headerStyle: {backColor: "#FBD0DA", foreColor: "#66474E", hAlign: "center", font: "bold 12pt Arial"}, style: {backColor: "#FBD0DA", foreColor: "#66474E", hAlign: "center", vAlign: "center", font: "bold 11pt Arial"} }, { value: "grades.Grade", cross: { over: 'grades.ClassID', attributes: ['grades.class.ClassName'], // format the value filter: '=FILTER([grades.class.ID],[grades.class.Type]="Tests")', // Filter the Tests table }, headerFit: "vertical", width: 45, headerStyle: {backColor: "#FDEDF4", foreColor: "#66474E", vAlign: "bottom"}, style: {backColor: "#FDEDF4", foreColor: "#66474E", vAlign: "center", hAlign: "center"}, conditionalFormats: [formulaRule] }, { value: "grades.Grade", cross: { over: 'grades.ClassID', attributes: ['grades.class.ClassName'], // format the value filter: '=FILTER([grades.class.ID],[grades.class.Type]="Projects")', // Filter the Projects table }, headerStyle: {textOrientation: -90, backColor: "#FFFCEA", foreColor: "#66474E", vAlign: "bottom"}, width: 45, style: {backColor: "#FFFCEA", foreColor: "#66474E", vAlign: "center", hAlign: "center"} }, { value: '=AVERAGE(FILTER([@grades.Grade],[@grades.class.Type]="Homeworks"))', caption: 'Homeworks', width: 50, headerFit: "stack", headerStyle: {backColor: "#FEF8C4", foreColor: "#66474E", hAlign: "center", font: "bold 12pt Arial"}, style: {backColor: "#FEF8C4", foreColor: "#66474E", vAlign: "center", hAlign: "center", font: "bold 11pt Arial"} }, { value: "grades.Grade", cross: { over: 'grades.ClassID', attributes: ['grades.class.ClassName'], // format the value filter: '=FILTER([grades.class.ID],[grades.class.Type]="Homeworks")', // Filter the Homeworks table }, headerFit: "vertical", width: 45, headerStyle: {backColor: "#FDECB3", foreColor: "#66474E", vAlign: "bottom"}, style: {backColor: "#FDECB3", foreColor: "#66474E", vAlign: "center", hAlign: "center"} }, ], undefined, { defaultColumnWidth: 45 } ); var style = new GC.Spread.Sheets.Style(); let lineBorder = new GC.Spread.Sheets.LineBorder(); lineBorder.style = 1; lineBorder.color = "lightgrey"; style.borderBottom = lineBorder; style.borderRight = lineBorder; style.borderLeft = lineBorder; style.borderTop = lineBorder; studentsGradesSheet.options.alternatingRowOptions = { style: style, step: [1,0] }; var hoverStyle = { backColor: "#E8F7FF", } gradeView.addStyleRule("hover-row", hoverStyle, { state: GC.Data.RowColumnStates.hover, direction: GC.Data.StateRuleDirection.row }); gradeView.fetch().then(function () { studentsGradesSheet.setDataView(gradeView); }); } function initTemplateSheet (spread) { var templateSheet = new GC.Spread.Sheets.Worksheet("TemplateSheet"); spread.addSheet(0, templateSheet); var style = new GC.Spread.Sheets.Style(); style.vAlign = GC.Spread.Sheets.VerticalAlign.center; templateSheet.setStyle(-1, 1, style); templateSheet.suspendPaint(); templateSheet.setRowHeight(0, 50); templateSheet.setColumnWidth(0, 60); templateSheet.setColumnWidth(1, 100); templateSheet.getCell(0,0).bindingPath("Image").formatter("=IMAGE(@)"); templateSheet.getCell(0,1).bindingPath("Name").font("bold 14px Arial"); templateSheet.options.gridline.showHorizontalGridline = false templateSheet.options.gridline.showVerticalGridline = false templateSheet.visible(false); spread.setActiveSheetTab(0); templateSheet.resumePaint(); return templateSheet; } function prepareData() { var dataSource = {}; var students = [ { "ID": 1, "Name": "Ellen Robinson" }, { "ID": 2, "Name": "Jerry Williams" }, { "ID": 3, "Name": "Steven Kunes" }, { "ID": 4, "Name": "Lisa Williamsburg" }, { "ID": 5, "Name": "Donald Draglin" } ]; var workItems = [ { "ID": 1, "Date": "9/12/2020", "Description": "Know your numbers", "TotalPoints": 10, "Type": "Homework" }, { "ID": 2, "Date": "10/10/2020", "Description": "Add numbers", "TotalPoints": 10, "Type": "Homework" }, { "ID": 3, "Date": "10/15/2020", "Description": "Addition", "TotalPoints": 25, "Type": "Quiz" }, { "ID": 4, "Date": "11/5/2020", "Description": "Subtract Numbers", "TotalPoints": 10, "Type": "Homework" }, { "ID": 5, "Date": "11/30/2020", "Description": "Subtraction", "TotalPoints": 25, "Type": "Quiz" }, { "ID": 6, "Date": "12/10/2020", "Description": "Mid-term", "TotalPoints": 100, "Type": "Exam" }, { "ID": 7, "Date": "2/2/2020", "Description": "HW 20", "TotalPoints": 10, "Type": "Homework" }, { "ID": 8, "Date": "2/22/2022", "Description": "HW 20", "TotalPoints": 20, "Type": "Homework" } ]; var grades = [ { "StudentID": 1, "WorkItemID": 1, "Grade": 4 }, { "StudentID": 2, "WorkItemID": 1, "Grade": 9 }, { "StudentID": 3, "WorkItemID": 1, "Grade": 8 }, { "StudentID": 4, "WorkItemID": 1, "Grade": 9 }, { "StudentID": 5, "WorkItemID": 1, "Grade": 6 }, { "StudentID": 1, "WorkItemID": 2, "Grade": 7 }, { "StudentID": 2, "WorkItemID": 2, "Grade": 5 }, { "StudentID": 3, "WorkItemID": 2, "Grade": 7 }, { "StudentID": 4, "WorkItemID": 2, "Grade": 8 }, { "StudentID": 5, "WorkItemID": 2, "Grade": 9 }, { "StudentID": 1, "WorkItemID": 3, "Grade": 18 }, { "StudentID": 2, "WorkItemID": 3, "Grade": 23 }, { "StudentID": 3, "WorkItemID": 3, "Grade": 15 }, { "StudentID": 4, "WorkItemID": 3, "Grade": 19 }, { "StudentID": 5, "WorkItemID": 3, "Grade": 6 }, { "StudentID": 1, "WorkItemID": 4, "Grade": 5 }, { "StudentID": 2, "WorkItemID": 4, "Grade": 8 }, { "StudentID": 3, "WorkItemID": 4, "Grade": 9 }, { "StudentID": 4, "WorkItemID": 4, "Grade": 8 }, { "StudentID": 5, "WorkItemID": 4, "Grade": 6 }, { "StudentID": 1, "WorkItemID": 5, "Grade": 22 }, { "StudentID": 2, "WorkItemID": 5, "Grade": 7 }, { "StudentID": 3, "WorkItemID": 5, "Grade": 12 }, { "StudentID": 4, "WorkItemID": 5, "Grade": 10 }, { "StudentID": 5, "WorkItemID": 5, "Grade": 8 }, { "StudentID": 1, "WorkItemID": 6, "Grade": 45 }, { "StudentID": 2, "WorkItemID": 6, "Grade": 45 }, { "StudentID": 3, "WorkItemID": 6, "Grade": 21 }, { "StudentID": 4, "WorkItemID": 6, "Grade": 86 }, { "StudentID": 5, "WorkItemID": 6, "Grade": 6 }, ]; dataSource.students = students; dataSource.workItems = workItems; dataSource.grades = grades; return dataSource; } function prepareStudentsGradesData() { var dataSource = {}; var students = [ { "ID": 1, "Name": "Ellen Robinson", "Image": "$DEMOROOT$/spread/source/images/avatar/63.png", }, { "ID": 2, "Name": "Jerry Williams", "Image": "$DEMOROOT$/spread/source/images/avatar/91.png", }, { "ID": 3, "Name": "Steven Kunes", "Image": "$DEMOROOT$/spread/source/images/avatar/20.png", }, { "ID": 4, "Name": "Lisa Williamsburg", "Image": "$DEMOROOT$/spread/source/images/avatar/95.png", }, { "ID": 5, "Name": "Donald Draglin", "Image": "$DEMOROOT$/spread/source/images/avatar/58.png", }, { "ID": 6, "Name": "Cathy Mahon", "Image": "$DEMOROOT$/spread/source/images/avatar/12.png", }, { "ID": 7, "Name": "Jerry Frizzell", "Image": "$DEMOROOT$/spread/source/images/avatar/77.png", }, { "ID": 8, "Name": "John Fair", "Image": "$DEMOROOT$/spread/source/images/avatar/10.png", }, { "ID": 9, "Name": "Jonathan Weiss", "Image": "$DEMOROOT$/spread/source/images/avatar/60.png", }, { "ID": 10, "Name": "Michael Peterson", "Image": "$DEMOROOT$/spread/source/images/avatar/20.png", }, { "ID": 11, "Name": "Rebecca Kemp", "Image": "$DEMOROOT$/spread/source/images/avatar/95.png", }, { "ID": 12, "Name": "Johnson Smith", "Image": "$DEMOROOT$/spread/source/images/avatar/23.png", } ]; var classes = [ { "ID": 1, "ClassName": "Test1", "Type": "Tests" }, { "ID": 2, "ClassName": "Test2", "Type": "Tests" }, { "ID": 3, "ClassName": "Test3", "Type": "Tests" }, { "ID": 4, "ClassName": "Project1", "Type": "Projects" }, { "ID": 5, "ClassName": "Project2", "Type": "Projects" }, { "ID": 6, "ClassName": "Homework1", "Type": "Homeworks" }, { "ID": 7, "ClassName": "Homework2", "Type": "Homeworks" }, { "ID": 8, "ClassName": "Homework3", "Type": "Homeworks" }, { "ID": 9, "ClassName": "Homework4", "Type": "Homeworks" } ]; var grades = [ { "StudentID": 1, "ClassID": 1, "Grade": 95 }, { "StudentID": 1, "ClassID": 2, "Grade": 68 }, { "StudentID": 1, "ClassID": 4, "Grade": "C" }, { "StudentID": 1, "ClassID": 6, "Grade": 84 }, { "StudentID": 1, "ClassID": 7, "Grade": 57 }, { "StudentID": 1, "ClassID": 8, "Grade": 78 }, { "StudentID": 1, "ClassID": 9, "Grade": 57 }, { "StudentID": 2, "ClassID": 1, "Grade": 66 }, { "StudentID": 2, "ClassID": 2, "Grade": 78 }, { "StudentID": 2, "ClassID": 4, "Grade": "B" }, { "StudentID": 2, "ClassID": 6, "Grade": 90 }, { "StudentID": 2, "ClassID": 7, "Grade": 69 }, { "StudentID": 2, "ClassID": 8, "Grade": 63 }, { "StudentID": 2, "ClassID": 9, "Grade": 69 }, { "StudentID": 3, "ClassID": 1, "Grade": 78 }, { "StudentID": 3, "ClassID": 2, "Grade": 78 }, { "StudentID": 3, "ClassID": 4, "Grade": "A" }, { "StudentID": 3, "ClassID": 6, "Grade": 80 }, { "StudentID": 3, "ClassID": 7, "Grade": 88 }, { "StudentID": 3, "ClassID": 8, "Grade": 65 }, { "StudentID": 3, "ClassID": 9, "Grade": 88 }, { "StudentID": 4, "ClassID": 1, "Grade": 76 }, { "StudentID": 4, "ClassID": 2, "Grade": 55 }, { "StudentID": 4, "ClassID": 4, "Grade": "B" }, { "StudentID": 4, "ClassID": 6, "Grade": 80 }, { "StudentID": 4, "ClassID": 7, "Grade": 78 }, { "StudentID": 4, "ClassID": 8, "Grade": 66 }, { "StudentID": 4, "ClassID": 9, "Grade": 78 }, { "StudentID": 5, "ClassID": 1, "Grade": 86 }, { "StudentID": 5, "ClassID": 2, "Grade": 63 }, { "StudentID": 5, "ClassID": 4, "Grade": "C" }, { "StudentID": 5, "ClassID": 6, "Grade": 84 }, { "StudentID": 5, "ClassID": 7, "Grade": 45 }, { "StudentID": 5, "ClassID": 8, "Grade": 66 }, { "StudentID": 5, "ClassID": 9, "Grade": 45 }, { "StudentID": 6, "ClassID": 1, "Grade": 45 }, { "StudentID": 6, "ClassID": 2, "Grade": 43 }, { "StudentID": 6, "ClassID": 4, "Grade": "C" }, { "StudentID": 6, "ClassID": 6, "Grade": 70 }, { "StudentID": 6, "ClassID": 7, "Grade": 55 }, { "StudentID": 6, "ClassID": 8, "Grade": 67 }, { "StudentID": 6, "ClassID": 9, "Grade": 55 }, { "StudentID": 7, "ClassID": 1, "Grade": 29 }, { "StudentID": 7, "ClassID": 2, "Grade": 45 }, { "StudentID": 7, "ClassID": 4, "Grade": "B" }, { "StudentID": 7, "ClassID": 6, "Grade": 59 }, { "StudentID": 7, "ClassID": 7, "Grade": 53 }, { "StudentID": 7, "ClassID": 8, "Grade": 64 }, { "StudentID": 7, "ClassID": 9, "Grade": 53 }, { "StudentID": 8, "ClassID": 1, "Grade": 55 }, { "StudentID": 8, "ClassID": 2, "Grade": 78 }, { "StudentID": 8, "ClassID": 4, "Grade": "C" }, { "StudentID": 8, "ClassID": 6, "Grade": 70 }, { "StudentID": 8, "ClassID": 7, "Grade": 72 }, { "StudentID": 8, "ClassID": 8, "Grade": 63 }, { "StudentID": 8, "ClassID": 9, "Grade": 72 }, { "StudentID": 9, "ClassID": 1, "Grade": 94 }, { "StudentID": 9, "ClassID": 2, "Grade": 45 }, { "StudentID": 9, "ClassID": 4, "Grade": "A" }, { "StudentID": 9, "ClassID": 6, "Grade": 58 }, { "StudentID": 9, "ClassID": 7, "Grade": 59 }, { "StudentID": 9, "ClassID": 8, "Grade": 64 }, { "StudentID": 9, "ClassID": 9, "Grade": 59 }, { "StudentID": 10, "ClassID": 1, "Grade": 15 }, { "StudentID": 10, "ClassID": 2, "Grade": 19 }, { "StudentID": 10, "ClassID": 4, "Grade": "B" }, { "StudentID": 10, "ClassID": 6, "Grade": 70 }, { "StudentID": 10, "ClassID": 7, "Grade": 73 }, { "StudentID": 10, "ClassID": 8, "Grade": 55 }, { "StudentID": 10, "ClassID": 9, "Grade": 73 }, { "StudentID": 11, "ClassID": 1, "Grade": 36 }, { "StudentID": 11, "ClassID": 2, "Grade": 45 }, { "StudentID": 11, "ClassID": 4, "Grade": "E" }, { "StudentID": 11, "ClassID": 6, "Grade": 76 }, { "StudentID": 11, "ClassID": 7, "Grade": 74 }, { "StudentID": 11, "ClassID": 8, "Grade": 58 }, { "StudentID": 11, "ClassID": 9, "Grade": 74 }, { "StudentID": 12, "ClassID": 1, "Grade": 88 }, { "StudentID": 12, "ClassID": 2, "Grade": 79 }, { "StudentID": 12, "ClassID": 4, "Grade": "B" }, { "StudentID": 12, "ClassID": 6, "Grade": 68 }, { "StudentID": 12, "ClassID": 7, "Grade": 78 }, { "StudentID": 12, "ClassID": 8, "Grade": 80 }, { "StudentID": 12, "ClassID": 9, "Grade": 79 }, ]; dataSource.students = students; dataSource.classes = classes; dataSource.grades = grades; return dataSource; } function fakeRead(data) { return function () { return Promise.resolve(data); } } function isPropertiesEqual(idNames, item, data) { for (let j = 0; j < idNames.length; j++) { const p = idNames[j]; if (item[p] != data[p]) { return false; } } return true; } function fakeUpdate(data, idNames = ['ID']) { return function (item) { for (var i = 0; i < data.length; i++) { if (isPropertiesEqual(idNames, item, data[i])) { data[i] = item; return Promise.resolve(item); } } return Promise.reject("Not found"); } } function fakeDelete(data, idNames = ['ID']) { return function (item) { for (var i = 0; i < data.length; i++) { if (isPropertiesEqual(idNames, item[0], data[i])) { data.splice(i, 1); return Promise.resolve(item); } } return Promise.reject("Not found"); } } function getFakeId(data, idName) { let max = 0; for (let i = 0, length = data.length; i < length; i++) { let id = parseInt(data[i][idName]); if (id > max) { max = id; } } return max + 1; } function fakeCreate(data, idName = 'ID') { return function (item) { item[idName] = getFakeId(data, idName); data.push(item); return Promise.resolve(item); } } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/SpreadJSTutorial\//)[0] + 'server/api'; }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture" content="zh-cn" /> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill --> <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> </div> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; }