Sticky Multiple Header

If you want to include the tablesheet data range row headers in worksheet, you can enable the sticky options when rendering the TableSheet.

Usage The following code shows how to render a TableSheet into worksheet and then show the row headers Sticky Header Features in This Demo multiple header
import * as React from 'react'; import { createRoot } from 'react-dom/client'; import './styles.css'; import { AppFunc } from './app-func'; import { App } from './app-class'; // 1. Functional Component sample createRoot(document.getElementById('app')).render(<AppFunc />); // 2. Class Component sample // createRoot(document.getElementById('app')).render(<App />);
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import { createRoot } from 'react-dom/client'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-shapes'; import '@mescius/spread-sheets-datacharts-addon'; import "@mescius/spread-sheets-tablesheet"; import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; export function AppFunc() { let initSpread = function(spread) { spread.suspendPaint(); var sheet = spread.getActiveSheet(); initTableSheet(spread, function(tableSheet) { spread.setActiveSheet(sheet.name()); var dataRange = registerTableSheetIntoWorksheet(tableSheet, sheet); beautifySheet(sheet, dataRange); spread.undoManager().clear(); }); spread.resumePaint(); } return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}> </SpreadSheets> </div> </div> ); } async function initTableSheet(spread, callback) { spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; //init a data manager var dataManager = spread.dataManager(); var productAPI = getBaseApiUrl() + "/Product"; var productTable = dataManager.addTable("productTable", { remote: { read: { url: productAPI }, update: { url: productAPI, method: "PUT" }, create: { url: productAPI }, delete: { url: productAPI } } }); //init a table sheet var tableSheet = spread.addSheetTab(0, "MyTableSheet", GC.Spread.Sheets.SheetType.tableSheet); await productTable.fetch(); var myView = productTable.addView("myView", [ { value: "ProductName", caption: "Name", width: 250 }, { value: "SupplierId", caption: ["Foreign Keys", "Supplier Id"], width: 140 }, { value: "CategoryId", caption: ["Foreign Keys", "Category Id"], width: 140 }, { value: "QuantityPerUnit", caption: ["Product Infos", "Quantity Per Unit"], width: 140 }, { value: "UnitPrice", caption: ["Product Infos", "Unit Price"], width: 140 }, { value: "UnitsInStock", caption: ["Product Infos", "Units In Stock"], width: 140 }, { value: "=[@UnitPrice]*[@UnitsInStock]", caption: ["Product Infos", "Total Price"] } ]); tableSheet.setDataView(myView); spread.suspendPaint(); callback && callback(tableSheet); spread.resumePaint(); return tableSheet; } function registerTableSheetIntoWorksheet (tableSheet, sheet) { var name = tableSheet.name() + "_DataRange"; var row = 1; var col = 1; var dataRange = sheet.dataRanges.add(name, tableSheet.name(), new GC.Spread.Sheets.Range(row, col, -1, -1), { sticky: { top: 1 } }); return dataRange; } function beautifySheet(sheet, dataRange) { var range = dataRange.range(); for (var i = range.row; i < range.row + range.rowCount; i++) { sheet.autoFitRow(i); } for (var i = range.col; i < range.col + range.colCount; i++) { sheet.autoFitColumn(i); } sheet.setColumnWidth(1, 30); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; }
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import { createRoot } from 'react-dom/client'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-shapes'; import '@mescius/spread-sheets-datacharts-addon'; import "@mescius/spread-sheets-tablesheet"; import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; const Component = React.Component; function _getElementById(id) { return document.getElementById(id); } export class App extends Component { constructor(props) { super(props); } render() { return ( <div class="sample-tutorial"> <div class="sample-spreadsheets"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}> </SpreadSheets> </div> </div> ); } initSpread(spread) { spread.suspendPaint(); var sheet = spread.getActiveSheet(); initTableSheet(spread, function(tableSheet) { spread.setActiveSheet(sheet.name()); var dataRange = registerTableSheetIntoWorksheet(tableSheet, sheet); beautifySheet(sheet, dataRange); spread.undoManager().clear(); }); spread.resumePaint(); } } async function initTableSheet(spread, callback) { spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; //init a data manager var dataManager = spread.dataManager(); var productAPI = getBaseApiUrl() + "/Product"; var productTable = dataManager.addTable("productTable", { remote: { read: { url: productAPI }, update: { url: productAPI, method: "PUT" }, create: { url: productAPI }, delete: { url: productAPI } } }); //init a table sheet var tableSheet = spread.addSheetTab(0, "MyTableSheet", GC.Spread.Sheets.SheetType.tableSheet); await productTable.fetch(); var myView = productTable.addView("myView", [ { value: "ProductName", caption: "Name", width: 250 }, { value: "SupplierId", caption: ["Foreign Keys", "Supplier Id"], width: 140 }, { value: "CategoryId", caption: ["Foreign Keys", "Category Id"], width: 140 }, { value: "QuantityPerUnit", caption: ["Product Infos", "Quantity Per Unit"], width: 140 }, { value: "UnitPrice", caption: ["Product Infos", "Unit Price"], width: 140 }, { value: "UnitsInStock", caption: ["Product Infos", "Units In Stock"], width: 140 }, { value: "=[@UnitPrice]*[@UnitsInStock]", caption: ["Product Infos", "Total Price"] } ]); tableSheet.setDataView(myView); spread.suspendPaint(); callback && callback(tableSheet); spread.resumePaint(); return tableSheet; } function registerTableSheetIntoWorksheet (tableSheet, sheet) { var name = tableSheet.name() + "_DataRange"; var row = 1; var col = 1; var dataRange = sheet.dataRanges.add(name, tableSheet.name(), new GC.Spread.Sheets.Range(row, col, -1, -1), { sticky: { top: 1 } }); return dataRange; } function beautifySheet(sheet, dataRange) { var range = dataRange.range(); for (var i = range.row; i < range.row + range.rowCount; i++) { sheet.autoFitRow(i); } for (var i = range.col; i < range.col + range.colCount; i++) { sheet.autoFitColumn(i); } sheet.setColumnWidth(1, 30); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; }
<!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/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app" style="height: 100%;"></div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js', '@mescius/spread-sheets-datacharts-addon': 'npm:@mescius/spread-sheets-datacharts-addon/index.js', '@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/index.js', '@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js', 'react': 'npm:react/cjs/react.production.js', 'react-dom': 'npm:react-dom/cjs/react-dom.production.js', 'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js', 'scheduler': 'npm:scheduler/cjs/scheduler.production.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' }, // packages tells the System loader how to load when no filename and/or no extension packages: { src: { defaultExtension: 'jsx' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);