Table

SpreadJS supports binding source data to a table. Table-level binding is part of cell-level binding, and can be used in a similar way.

Description
app.component.ts
index.html
app.component.html
styles.css
Copy to CodeMine

Use the bindingPath method to bind the table to a field with records, and then bind the table columns to the record's fields. For example:

    var data = { name: 'Jones',  region: 'East',
      sales: [
        { orderDate: '1/6/2013', item: 'Pencil', units: 95, cost: 1.99 },
        { orderDate: '4/1/2013', item: 'Binder', units: 60, cost: 4.99 },
        { orderDate: '6/8/2013', item: 'Pen Set', units: 16, cost: 15.99 }
       ]};
    var tableColumns = [], 
        names = ['orderDate', 'item', 'units', 'cost'],
        labels = ['Order Date', 'Item', 'Units', 'Cost'];
    var table = sheet.tables.add('tableRecords', 10, 1, 4, 4);
    table.autoGenerateColumns(false);
    names.forEach(function (name, index) {
       var tableColumn = new GC.Spread.Sheets.Tables.TableColumn();
       tableColumn.name(labels[index]);
       tableColumn.dataField(name);
       tableColumns.push(tableColumn);
    });

    table.bindColumns(tableColumns);
    table.bindingPath('sales');
    source = new GC.Spread.Sheets.Bindings.CellBindingSource(data);
    sheet.setDataSource(source);

When you set a different data source, the table will automatically bind to the corresponding records.

We also provide the bind API to easily solve complicated call issues:

    //Example1
    var spreadNS = GC.Spread.Sheets;
    var data = {
        name: 'Jones', region: 'East',
        sales: [
            {orderDate: '1/6/2013', item: 'Pencil', units: 95, cost: 1.99, isMakeMoney: true},
            {orderDate: '4/1/2013', item: 'Binder', units: 60, cost: 4.99, isMakeMoney: false},
            {orderDate: '6/8/2013', item: 'Pen Set', units: 16, cost: 15.99, isMakeMoney: false}
        ]
    };
    var convert = function (item) {
        return item['cost'] + '$';
    }
    var table = sheet.tables.add('tableSales', 0, 0, 5, 5);
    var tableColumn1 = new spreadNS.Tables.TableColumn();
    tableColumn1.name("Order Date");
    tableColumn1.dataField("orderDate");
    tableColumn1.formatter("d/M/yy");
    var tableColumn2 = new spreadNS.Tables.TableColumn();
    tableColumn2.name("Item");
    tableColumn2.dataField("item");
    var tableColumn3 = new spreadNS.Tables.TableColumn();
    tableColumn3.name("Units");
    tableColumn3.dataField("units");
    var tableColumn4 = new spreadNS.Tables.TableColumn();
    tableColumn4.name("Cost");
    tableColumn4.dataField("cost");
    tableColumn4.value(convert);
    var tableColumn5 = new spreadNS.Tables.TableColumn();
    tableColumn5.name("IsMakeMoney");
    tableColumn5.dataField("isMakeMoney");
    tableColumn5.cellType(new GC.Spread.Sheets.CellTypes.CheckBox());
    table.autoGenerateColumns(false);
    table.bind([tableColumn1, tableColumn2, tableColumn3, tableColumn4, tableColumn5], 'sales', data);
    //Example2
    var spreadNS = GC.Spread.Sheets;
    var data = {
        name: 'Jones', region: 'East',
        sales: [
            {orderDate: '1/6/2013', item: 'Pencil', units: 95, cost: 1.99, isMakeMoney: true},
            {orderDate: '4/1/2013', item: 'Binder', units: 60, cost: 4.99, isMakeMoney: false},
            {orderDate: '6/8/2013', item: 'Pen Set', units: 16, cost: 15.99, isMakeMoney: false}
        ]
    };
    var convert = function (item) {
        return item['cost'] + '$';
    }
    var table = sheet.tables.add('tableSales', 0, 0, 5, 5);
    var tableColumn1 = new spreadNS.Tables.TableColumn(1, "orderDate", "Order Date", "d/M/yy");
    var tableColumn2 = new spreadNS.Tables.TableColumn(2, "item", "Item");
    var tableColumn3 = new spreadNS.Tables.TableColumn(3, "units", "Units");
    var tableColumn4 = new spreadNS.Tables.TableColumn(4, "cost", "Cost", null, null, convert);
    var tableColumn5 = new spreadNS.Tables.TableColumn(5, "isMakeMoney", "IsMakeMoney", null, new GC.Spread.Sheets.CellTypes.CheckBox());
    table.autoGenerateColumns(false);
    table.bind([tableColumn1, tableColumn2, tableColumn3, tableColumn4, tableColumn5], 'sales', data);

When you bind data source, you can get dirty data-item after change the data source:

  table.getDirtyRows();
Use the bindingPath method to bind the table to a field with records, and then bind the table columns to the record's fields. For example: When you set a different data source, the table will automatically bind to the corresponding records. We also provide the bind API to easily solve complicated call issues: When you bind data source, you can get dirty data-item after change the data source:
import { Component, NgModule, enableProdMode } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { SpreadSheetsModule } from '@mescius/spread-sheets-angular'; import GC from '@mescius/spread-sheets'; import './styles.css'; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { spread: GC.Spread.Sheets.Workbook; dataSource1: any; dataSource2: any; hostStyle = { width: 'calc(100% - 280px)', height: '100%', overflow: 'hidden', float: 'left' }; changeDataSource() { let sheet = this.spread.getActiveSheet(); if (sheet.getDataSource() === this.dataSource1) { sheet.setDataSource(this.dataSource2); } else { sheet.setDataSource(this.dataSource1); } } initSpread($event: any) { this.spread = $event.spread; let spread = this.spread; let company1 = new Company("Baidu", null, "We know everything!", "Beijing 1st road", "Beijing", "010-12345678", "baidu@baidu.com"), company2 = new Company("Tecent", null, "We have everything!", "Shenzhen 2st road", "Shenzhen", "0755-12345678", "tecent@qq.com"), company3 = new Company("Alibaba", null, "We sale everything!", "Hangzhou 3rd road", "Hangzhou", "0571-12345678", "alibaba@alibaba.com"), customer1 = new Customer("A1", "employee 1", company2), customer2 = new Customer("A2", "employee 2", company3), records1 = [new Record("Finance charge on overdue balance at 1.5%", 1, 150), new Record("Invoice #100 for $1000 on 2014/1/1", 1, 150)], records2 = [new Record("Purchase server device", 2, 15000), new Record("Company travel", 100, 1500), new Record("Company Dinner", 100, 200)], invoice1 = new Invoice(company1, "00001", new Date(2014, 0, 1), customer1, customer1, records1), invoice2 = new Invoice(company2, "00002", new Date(2014, 6, 6), customer2, customer2, records2), this.dataSource1 = new GC.Spread.Sheets.Bindings.CellBindingSource(invoice1), this.dataSource2 = new GC.Spread.Sheets.Bindings.CellBindingSource(invoice2); //Get sheet instance spread.suspendPaint(); let sheet = spread.sheets[0]; sheet.name("FINANCE CHARGE"); //Set value or bindingPath and style let bindingPathCellType = new BindingPathCellType(); sheet.getCell(1, 2).bindingPath("company.slogan").cellType(bindingPathCellType).vAlign(GC.Spread.Sheets.VerticalAlign.bottom); sheet.getCell(1, 4).value("INVOICE").foreColor("#58B6C0").font("33px Arial"); sheet.getCell(3, 1).bindingPath("company.name").cellType(bindingPathCellType).foreColor("#58B6C0").font("bold 20px Arial"); sheet.getCell(5, 1).bindingPath("company.address").cellType(bindingPathCellType); sheet.getCell(5, 3).value("INVOICE NO.").font("bold 15px Arial"); sheet.getCell(5, 4).bindingPath("number").cellType(bindingPathCellType); sheet.getCell(6, 1).bindingPath("company.city").cellType(bindingPathCellType); sheet.getCell(6, 3).value("DATE").font("bold 15px Arial"); sheet.getCell(6, 4).bindingPath("date").cellType(bindingPathCellType).formatter("MM/dd/yyyy").hAlign(GC.Spread.Sheets.HorizontalAlign.left); sheet.getCell(7, 1).bindingPath("company.phone").cellType(bindingPathCellType); sheet.getCell(7, 3).value("CUSTOMER ID").font("bold 15px Arial"); sheet.getCell(7, 4).bindingPath("customer.id").cellType(bindingPathCellType); sheet.getCell(8, 1).bindingPath("company.email").cellType(bindingPathCellType); sheet.getCell(10, 1).value("TO").font("bold 15px Arial"); sheet.getCell(10, 3).value("SHIP TO").font("bold 15px Arial"); sheet.getCell(11, 1).bindingPath("customer.name").cellType(bindingPathCellType).textIndent(10); sheet.getCell(12, 1).bindingPath("customer.company.name").cellType(bindingPathCellType).textIndent(10); sheet.getCell(13, 1).bindingPath("customer.company.address").cellType(bindingPathCellType).textIndent(10); sheet.getCell(14, 1).bindingPath("customer.company.city").cellType(bindingPathCellType).textIndent(10); sheet.getCell(15, 1).bindingPath("customer.company.phone").cellType(bindingPathCellType).textIndent(10); sheet.getCell(11, 4).bindingPath("receiverCustomer.name").cellType(bindingPathCellType); sheet.getCell(12, 4).bindingPath("receiverCustomer.company.name").cellType(bindingPathCellType); sheet.getCell(13, 4).bindingPath("receiverCustomer.company.address").cellType(bindingPathCellType); sheet.getCell(14, 4).bindingPath("receiverCustomer.company.city").cellType(bindingPathCellType); sheet.getCell(15, 4).bindingPath("receiverCustomer.company.phone").cellType(bindingPathCellType); sheet.addSpan(17, 1, 1, 2); sheet.getCell(17, 1).value("JOB").foreColor("#58B6C0").font("bold 12px Arial"); sheet.addSpan(17, 3, 1, 2); sheet.getCell(17, 3).value("PAYMENT TERMS").foreColor("#58B6C0").font("bold 12px Arial"); sheet.addSpan(18, 1, 1, 2); sheet.getCell(18, 1).backColor("#DDF0F2"); sheet.addSpan(18, 3, 1, 2); sheet.getCell(18, 3).value("Due on receipt").backColor("#DDF0F2").foreColor("#58B6C0").font("12px Arial"); sheet.getRange(17, 1, 2, 4).setBorder(new GC.Spread.Sheets.LineBorder("#58B6C0", GC.Spread.Sheets.LineStyle.thin), { top: true, bottom: true, innerHorizontal: true }); let table = sheet.tables.add("tableRecordds", 20, 1, 4, 4, GC.Spread.Sheets.Tables.TableThemes.light6); table.autoGenerateColumns(false); let tableColumn1 = new GC.Spread.Sheets.Tables.TableColumn(); tableColumn1.name("DESCRIPTION"); tableColumn1.dataField("description"); let tableColumn2 = new GC.Spread.Sheets.Tables.TableColumn(); tableColumn2.name("QUANTITY"); tableColumn2.dataField("quantity"); let tableColumn3 = new GC.Spread.Sheets.Tables.TableColumn(); tableColumn3.name("AMOUNT"); tableColumn3.dataField("amount"); table.bindColumns([tableColumn1, tableColumn2, tableColumn3]); table.bindingPath("records"); table.showFooter(true); table.setColumnName(3, "TOTAL"); table.setColumnValue(2, "TOTAL DUE"); table.setColumnDataFormula(3, "=[@QUANTITY]*[@AMOUNT]"); table.setColumnFormula(3, "=SUBTOTAL(109,[TOTAL])"); sheet.getCell(26, 1).formula('="Make all checks payable to "&B4&". THANK YOU FOR YOUR BUSINESS!"').foreColor("gray").font("italic 14px Arial"); sheet.options.allowCellOverflow = true; //Adjust row height and column width sheet.setColumnWidth(0, 5); sheet.setColumnWidth(1, 300); sheet.setColumnWidth(2, 115); sheet.setColumnWidth(3, 125); sheet.setColumnWidth(4, 155); sheet.setRowHeight(0, 5); sheet.setRowHeight(1, 40); sheet.setRowHeight(2, 10); sheet.setRowHeight(3, 28); sheet.setRowHeight(17, 0); sheet.setRowHeight(18, 0); sheet.setRowHeight(19, 0); sheet.setRowHeight(25, 10); sheet.options.gridline = { showHorizontalGridline: false, showVerticalGridline: false }; spread.resumePaint(); } } class Company { name: string; logo: string; slogan: string; address: string; city: string; phone: string; email: string; constructor(name: string, logo: string, slogan: string, address: string, city: string, phone: string, email: string) { this.name = name; this.logo = logo; this.slogan = slogan; this.address = address; this.city = city; this.phone = phone; this.email = email; } } class Customer { id: string; name: string; company: any; constructor(id: string, name: string, company: any) { this.id = id; this.name = name; this.company = company; } } class Record { description: string; quantity: number; amount: number; constructor(description: string, quantity: number, amount: number) { this.description = description; this.quantity = quantity; this.amount = amount; } } class Invoice { company: any; number: any; date: any; customer: any; receiverCustomer: any; records: any; constructor(company: any, number: any, date: any, customer: any, receiverCustomer: any, records: any) { this.company = company; this.number = number; this.date = date; this.customer = customer; this.receiverCustomer = receiverCustomer; this.records = records; } } class BindingPathCellType extends GC.Spread.Sheets.CellTypes.Text { constructor() { super(); } paint(ctx: any, value: any, x: number, y: number, w: number, h: number, style: number, context: any) { if (value === null || value === undefined) { let sheet = context.sheet, row = context.row, col = context.col; if (sheet && (row === 0 || !!row) && (col === 0 || !!col)) { let bindingPath = sheet.getBindingPath(context.row, context.col); if (bindingPath) { value = "[" + bindingPath + "]"; } } } super.paint(ctx, value, x, y, w, h, style, context); } } @NgModule({ imports: [BrowserModule, SpreadSheetsModule], declarations: [AppComponent], exports: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule);
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/angular/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- Polyfills --> <script src="$DEMOROOT$/en/angular/node_modules/core-js/client/shim.min.js"></script> <script src="$DEMOROOT$/en/angular/node_modules/zone.js/fesm2015/zone.min.js"></script> <!-- SystemJS --> <script src="$DEMOROOT$/en/angular/node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.import('@angular/compiler'); System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('$DEMOROOT$/en/lib/angular/license.ts'); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html>
<div class="sample-tutorial"> <gc-spread-sheets [hostStyle]="hostStyle" (workbookInitialized)="initSpread($event)"> <gc-worksheet> </gc-worksheet> </gc-spread-sheets> <div class="options-container"> <div class="option-row"> <label style="background-color:#F4F8EB;">Click this button to set the data source for the data-bound table.</label> </div> <input type="button" (click)="changeDataSource($event)" id="changeDataSource" value="Set DataSource" title="Toggle table binding's data source" /> </div> </div>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: calc(100% - 280px); height: 100%; overflow: hidden; float: left; } .options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; } .option-row { font-size: 14px; padding: 5px; margin-top: 10px; } label { display: block; margin-bottom: 6px; } input { padding: 4px 6px; } input[type=button] { margin-top: 6px; display: block; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'ts', typescriptOptions: { tsconfig: true }, meta: { 'typescript': { "exports": "ts" }, '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'core-js': 'npm:core-js/client/shim.min.js', 'zone': 'npm:zone.js/fesm2015/zone.min.js', 'rxjs': 'npm:rxjs/dist/bundles/rxjs.umd.min.js', '@angular/core': 'npm:@angular/core/fesm2022', '@angular/common': 'npm:@angular/common/fesm2022/common.mjs', '@angular/compiler': 'npm:@angular/compiler/fesm2022/compiler.mjs', '@angular/platform-browser': 'npm:@angular/platform-browser/fesm2022/platform-browser.mjs', '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/fesm2022/platform-browser-dynamic.mjs', '@angular/common/http': 'npm:@angular/common/fesm2022/http.mjs', '@angular/router': 'npm:@angular/router/fesm2022/router.mjs', '@angular/forms': 'npm:@angular/forms/fesm2022/forms.mjs', 'jszip': 'npm:jszip/dist/jszip.min.js', 'typescript': 'npm:typescript/lib/typescript.js', 'ts': './plugin.js', 'tslib':'npm:tslib/tslib.js', 'css': 'npm:systemjs-plugin-css/css.js', 'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js', 'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js', '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-angular': 'npm:@mescius/spread-sheets-angular/fesm2020/mescius-spread-sheets-angular.mjs', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'ts' }, rxjs: { defaultExtension: 'js' }, "node_modules": { defaultExtension: 'js' }, "node_modules/@angular": { defaultExtension: 'mjs' }, "@mescius/spread-sheets-angular": { defaultExtension: 'mjs' }, '@angular/core': { defaultExtension: 'mjs', main: 'core.mjs' } } }); })(this);