Overview

TableSheet provides the ability to add, update and remove a column with the meaningful column types(Number, Text, Formula, Lookup, Date, Checkbox, Select, Currency, Percent, Phone, Email, URL, CreatedTime, ModifiedTime, Attachment, Barcode) to a table which will help the customer to design the table easily.

Description
app.js
index.html
styles.css
Copy to CodeMine

The TableSheet lets users enable defining column by the options which will toggle the visibility of the add column button, modify column, remove column and set primary key context menu on the column header:

interface GC.Spread.Sheets.TableSheet.ITableSheetOptions {
  // other properties...
  enableDefineColumn?: boolean;
}

 
 
Column Types

interface GC.Data.IColumn {
    type: string, // the built-in column types: Number, Text, Formula, Checkbox, Date, Currency, Percent, Phone, Email, URL, Lookup, CreatedTime, ModifiedTime, Attachment, Select, Barcode
}

The descriptions of the supported column types:

Column Type Data Type Description
Number number For most numerical values with specified formatting
Text string For the common text
Formula depends on the result To compute a value based on other fields in the record.
Lookup depends on the related To look up a specific field in a related record.
Date date To easily enter a date value
Checkbox boolean Useful to check/uncheck with a TRUE/FALSE data type
Select depends on the option Useful to select an option from a preset list
Currency number Indicates the currency with culture formatting
Percent number Indicates the number formatted as the percent
Phone string Indicates the digit string of numbers with mask validation
Email string Indicates the email address with mask validation
URL string Indicates the URL text
CreatedTime date To set a date when the record create
ModifiedTime date To set a date when the fields updated in the record
Attachment object Allows to attach a file directly on the record
Barcode depends on the input Generates a specified barcode from the field

 
 
Configuration

To communicate with the table, it should configure the remote APIs:

Column API Description
getColumns Retrieve the columns from the table
addColumn Add a column to the table
updateColumn Update the properties of a column to the table
removeColumn Remove a column from the table
batch The changes will post together in the batch mode
var apiForDataUrl = './orders', apiForColumnUrl = './tables/order/columns';
var orderTable = dataManager.addTable("orderTable", {
        remote: {
            read: {
                url: apiForDataUrl,
            },
            update: {
                url: apiForDataUrl,
                method: 'PUT'
            },
            create: {
                url: apiForDataUrl,
            },
            delete: {
                url: apiForDataUrl,
            },
            getColumns: {
                url: apiForColumnUrl
            },
            addColumn: {
                url: apiForColumnUrl,
                method: 'POST'
            },
            updateColumn: {
                url: apiForColumnUrl,
                method: 'PUT'
            },
            removeColumn: {
                url: apiForColumnUrl,
                method: 'DELETE'
            },
            // batch: {
            //     url: './batch',
            // }
        },
        autoSync: true,
        // batch: true
    });

And the column remote APIs could be handled by the self-defined functions which are similar as the Handle Requests.

 
Request and Response

type Column = {
    field: string, // the name of the field
    dataType: 'number' | 'string' | 'boolean', // the data type could be converted to another data type on the remote storage source
    defaultValue?: 'number' | 'string' | 'boolean' | 'undefined', // the static default value for remote storage source
    isPrimaryKey?: boolean, // indicates the field could be the primary
}
type ColumnData = {
    column: Column,
}
type ColumnWithDefaultData = {
    column: Column,
    data?: any[], // in some cases, the data provided by the client should sync to the remote storage source, for example, the column with a formula default value is added to the table has some records
}
type ModifiedColumnData = {
    column: Column,
    originalColumn: Column,
}
type BatchItemData = {
    type: "updateColumn" | "addColumn" | "removeColumn", // it only shows the options about the column changes, the whole changes include the column and data if exited
    column: Column,
    data?: any[],
    originalColumn?: Column,
}
type BatchResultData = {
    succeed: boolean,
    reason?: string,
}
Operation Request Data Response Data
getColumns None Column[]
addColumn ColumnWithDefaultData ColumnData
updateColumn ModifiedColumnData ModifiedColumnData
removeColumn ColumnData ColumnData
batch BatchItemData[] BatchResultData[]

 
 
The Commands

Besides defining through UI, there are also the commands to define the columns:

DefineColumn

The DefineColumn command could add a column:

/**
 * GC.Spread.Sheets.Commands.DefineColumn: { canUndo: boolean, execute(context: GC.Spread.Sheets.Workbook, options: {sheetName: string, col?: number, column: GC.Data.IColumn}): any}
 * Represents the command used to define the column.
 * @property {boolean} canUndo - indicates whether the command supports undo and redo operations.
 * @property {function} execute - performs an execute or undo operation.
 * The arguments of the execute method are as follows.
 * @param {GC.Spread.Sheets.Workbook} context The context of the operation.
 * @param {Object} options The options of the operation.
 * @param {string} options.sheetName The sheet name.
 * @param {number} [options.col] The specified col for inserting, optional.
 * @param {GC.Data.IColumn} options.column The defined column.
 * @param {boolean} isUndo `true` if this is an undo operation; otherwise, `false`.
 */
spread.commandManager().execute({
  cmd: "DefineColumn",
  sheetName: spread.getActiveSheetTab().name(),
  // col: 3, // optional
  column: {
    type: 'Number', // specify the column type
    value: 'Number1', // the column identifier of the column instance from the column type
    caption: '# Number1', // the display of the column for the culture
    style: { formatter: '#,##0.00_);[Red](#,##0.00)' } // the formatter could be specified or be converted from the UI operations
  } as GC.Data.IColumn,
});

ModifyColumn

The ModifyColumn command could change the column properties:

/**
 * field GC.Spread.Sheets.Commands.ModifyColumn: { canUndo: boolean, execute(context: GC.Spread.Sheets.Workbook, options: {sheetName: string, col: number, column: GC.Data.IColumn}): any}
 * Represents the command used to modify the column.
 * @property {boolean} canUndo - indicates whether the command supports undo and redo operations.
 * @property {function} execute - performs an execute or undo operation.
 * The arguments of the execute method are as follows.
 * @param {GC.Spread.Sheets.Workbook} context The context of the operation.
 * @param {Object} options The options of the operation.
 * @param {string} options.sheetName The sheet name.
 * @param {number} options.col The specified col.
 * @param {GC.Data.IColumn} options.column The modified column.
 * @param {boolean} isUndo `true` if this is an undo operation; otherwise, `false`.
 */
spread.commandManager().execute({
  cmd: "ModifyColumn",
  sheetName: spread.getActiveSheetTab().name(),
  col: 3,
  column: {
    type: 'Text', // specify the column type
    value: 'Text1', // the column identifier of the column instance from the column type
    caption: 'A Text1', // the display of the column for the culture
  } as GC.Data.IColumn,
});

RemoveColumn

The RemoveColumn command could remove the column:

/**
 * field GC.Spread.Sheets.Commands.RemoveColumn: { canUndo: boolean, execute(context: GC.Spread.Sheets.Workbook, options: {sheetName: string, col: number}): any}
 * Represents the command used to remove the column.
 * @property {boolean} canUndo - indicates whether the command supports undo and redo operations.
 * @property {function} execute - performs an execute or undo operation.
 * The arguments of the execute method are as follows.
 * @param {GC.Spread.Sheets.Workbook} context The context of the operation.
 * @param {Object} options The options of the operation.
 * @param {string} options.sheetName The sheet name.
 * @param {number} options.col The specified col.
 * @param {boolean} isUndo `true` if this is an undo operation; otherwise, `false`.
 */
spread.commandManager().execute({
  cmd: "RemoveColumn",
  sheetName: spread.getActiveSheetTab().name(),
  col: 3,
});
The TableSheet lets users enable defining column by the options which will toggle the visibility of the add column button, modify column, remove column and set primary key context menu on the column header:     Column Types The descriptions of the supported column types: Column Type Data Type Description Number number For most numerical values with specified formatting Text string For the common text Formula depends on the result To compute a value based on other fields in the record. Lookup depends on the related To look up a specific field in a related record. Date date To easily enter a date value Checkbox boolean Useful to check/uncheck with a TRUE/FALSE data type Select depends on the option Useful to select an option from a preset list Currency number Indicates the currency with culture formatting Percent number Indicates the number formatted as the percent Phone string Indicates the digit string of numbers with mask validation Email string Indicates the email address with mask validation URL string Indicates the URL text CreatedTime date To set a date when the record create ModifiedTime date To set a date when the fields updated in the record Attachment object Allows to attach a file directly on the record Barcode depends on the input Generates a specified barcode from the field     Configuration To communicate with the table, it should configure the remote APIs: Column API Description getColumns Retrieve the columns from the table addColumn Add a column to the table updateColumn Update the properties of a column to the table removeColumn Remove a column from the table batch The changes will post together in the batch mode And the column remote APIs could be handled by the self-defined functions which are similar as the Handle Requests.   Request and Response Operation Request Data Response Data getColumns None Column[] addColumn ColumnWithDefaultData ColumnData updateColumn ModifiedColumnData ModifiedColumnData removeColumn ColumnData ColumnData batch BatchItemData[] BatchResultData[]     The Commands Besides defining through UI, there are also the commands to define the columns: DefineColumn The DefineColumn command could add a column: ModifyColumn The ModifyColumn command could change the column properties: RemoveColumn The RemoveColumn command could remove the column:
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ 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(); var dataManager = spread.dataManager(); initDefineOrderTable(spread, dataManager); spread.resumePaint(); } function initDefineOrderTable(spread, dataManager) { spread.options.allowDynamicArray = true; var apiUrl = getApiUrl("DefineOrder"), apiColumnUrl = getColumnApiUrl("DefineOrder"); var orderTable = dataManager.addTable("orderTable", { remote: { read: { url: apiUrl, }, update: { url: apiUrl, method: 'PUT' }, create: { url: apiUrl, }, delete: { url: apiUrl, }, getColumns: { url: apiColumnUrl }, addColumn: { url: apiColumnUrl, method: 'POST' }, updateColumn: { url: apiColumnUrl, method: 'PUT' }, removeColumn: { url: apiColumnUrl, method: 'DELETE' }, // batch: { // url: apiUrl + 'Collection' // } }, schema: { // It could define some options for the existed column on the table columns: { Id: { isPrimaryKey: true }, OrderDate: { dataType: 'date' }, RequiredDate: { dataType: 'date' }, ShippedDate: { dataType: 'date' }, ShipVia: { dataType: 'number', type: 'Select', style: { cellType: { type: 'combobox', editorValueType: 'value', items: [ { text: 'Speedy Express', value: 1 }, { text: 'United Package', value: 2 }, { text: 'Federal Shipping', value: 3 } ] } }, }, Freight: { dataType: 'number', type: 'Currency', style: { formatter: '[$$-409]#,##0.00' }, }, CreatedTime: { type: "CreatedTime", dataType: 'date', trigger: { when: "onNew", formula: "=NOW()" }, readonly: true, defaultValue: '=NOW()', style: { formatter: "m/d/yy h:mm;@" }, }, ModifiedTime: { type: "ModifiedTime", dataType: 'date', trigger: { when: "onNewAndUpdate", formula: "=NOW()", fields: "*" }, readonly: true, style: { formatter: "[$-409]m/d/yy h:mm AM/PM;@" }, }, OrderAttachment: { type: 'Attachment', style: { cellType: { type: 'fileUpload' } }, }, OrderCode: { type: 'Barcode', defaultValue: '=FLOOR.MATH(RAND()*100000000)', style: { formatter: '=BC_GS1_128([@OrderCode],"#000000","#FFFFFF",false,,,,,,,,,,,)' }, }, } }, autoSync: true, // batch: true, }); var employeeTable = dataManager.addTable("employeeTable", { remote: { read: { url: getApiUrl("Employee") } }, schema: { columns: { Id: { isPrimaryKey: true }, BirthDate: { dataType: 'date' }, HireDate: { dataType: 'date' }, } }, autoSync: true }); var customerTable = dataManager.addTable("customerTable", { remote: { read: { url: getApiUrl("Customer") } }, schema: { columns: { Id: { isPrimaryKey: true }, } }, autoSync: true }); dataManager.addRelationship(orderTable, "EmployeeId", "employee", employeeTable, "Id", "orders"); dataManager.addRelationship(orderTable, "CustomerId", "customer", customerTable, "Id", "orders"); var tableSheet = spread.addSheetTab(0, "Orders", GC.Spread.Sheets.SheetType.tableSheet); tableSheet.options.allowAddNew = true; tableSheet.options.enableDefineColumn = true; var rowActions = GC.Spread.Sheets.TableSheet.BuiltInRowActions; var options = tableSheet.rowActionOptions(); options.push( rowActions.removeRow, rowActions.saveRow, rowActions.resetRow, ); tableSheet.rowActionOptions(options); var orderView = orderTable.addView("orderView", [ { value: "Id", width: 50 }, { value: "CustomerId", defaultValue: 'ALFKI', visible: false }, // just for demo { value: "EmployeeId", defaultValue: 1, visible: false }, // just for demo { value: "customer.ContactName", caption: 'Contact', width: 100 }, { value: '=CONCAT([@employee.FirstName], " ", [@employee.LastName])', caption: 'Employee', width: 110 }, { value: "OrderDate", width: 100, style: { formatter: "m/d/yyyy" } }, { value: "ShipVia", width: 140 }, { value: "Freight", width: 80, defaultValue: 0 }, { value: "ShipName" }, { value: '=CONCAT([@ShipState], ", ", [@ShipCity], ", ", [@ShipRegion])', caption: 'Ship State', visible: false }, { value: 'OrderAttachment', caption: 'Attachment', visible: false }, { value: 'OrderCode', caption: 'Logistic Code', width: 160, visible: false }, { value: 'CreatedTime', caption: 'Created Time', width: 160, visible: false }, { value: 'ModifiedTime', caption: 'Modified Time', width: 160, visible: false }, ], null, { defaultColumnWidth: 120 }); orderView.fetch().then(function () { tableSheet.setDataView(orderView); }); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; } function getApiUrl(tableName) { return getBaseApiUrl() + "/" + tableName; } function getColumnApiUrl(tableName) { return getBaseApiUrl() + "/tables/" + tableName + "/columns"; }
<!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/purejs/node_modules/@mescius/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$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.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; }