Multi-Sheet Workbook
Since v1.3.0 a ReoGrid instance is a workbook of N worksheets with one active sheet. The core renders a sheet tab bar (add, rename, drag-to-reorder, hide, tab color), each sheet keeps its own data, selection, scroll, frozen panes, and undo history, and formulas can reference cells on other sheets with =Sheet1!A1.
Multi-sheet works in both Lite and Pro. Tier guards and row/column limits apply per sheet.
Upgrading from single-sheet? Existing code is unchanged — a fresh grid still starts with one sheet. The only visible difference is a ~28 px sheet tab bar at the bottom. Pass
createReogrid({ showSheetTabs: false })to hide it.
Creating a workbook
The instance exposes a workbook coordinator. The first sheet is created for you; add more with addSheet.
import { createReogrid } from '@reogrid/lite'
const grid = createReogrid({
workspace: '#app',
initialSheetName: 'Sales', // optional — defaults to 'Sheet1'
})
// Add more sheets
const expenses = grid.workbook.addSheet('Expenses').worksheet
const summary = grid.workbook.addSheet('Summary').worksheet
// The active sheet is always available as grid.worksheet
grid.worksheet.cell('A1').setValue('Q1 report')
addSheet(name?, index?) returns a WorkbookSheet — { worksheet, actionManager }. Use .worksheet to read and write its cells, exactly like a single-sheet grid.
Workbook options
| Option | Type | Default | Description |
|---|---|---|---|
showSheetTabs | boolean | true | Show the sheet tab bar at the bottom of the grid. |
initialSheetName | string | 'Sheet1' | Name of the sheet created on init. |
The workbook coordinator
grid.workbook manages the set of sheets and the active selection.
const wb = grid.workbook
wb.addSheet('Data') // append a sheet (optionally at an index)
wb.renameSheet(1, 'Archive') // names are sanitized and de-duplicated
wb.moveSheet(2, 0) // reorder (active sheet stays stable)
wb.setActiveSheet(0) // switch the active sheet
wb.removeSheet(1) // refuses to remove the last remaining sheet
wb.getSheets() // WorkbookSheet[] in tab order
wb.getWorksheets() // the Worksheet objects
wb.getSheetNames() // ['Sales', 'Archive', ...]
| Method | Description |
|---|---|
addSheet(name?, index?) | Add a sheet; returns the new WorkbookSheet. |
removeSheet(index) | Remove a sheet (never the last one). |
renameSheet(index, name) | Rename; referencing formulas on every sheet are rewritten. |
moveSheet(from, to) | Reorder tabs. |
setActiveSheet(index) | Make a sheet active. |
getSheets() / getWorksheets() / getSheetNames() | Query the workbook. |
setSheetHidden(index, hidden) | Hide / unhide a sheet. |
setSheetTabColor(index, color) | Set or clear a tab color (CSS color string). |
Whole-workbook I/O
I/O methods on the instance operate on all sheets. The worksheet’s own loaders — loadSheetFromFile / loadSheetFromUrl / loadSheetFromBuffer — load a single sheet into that worksheet; use them only when you deliberately want one sheet. Before v1.7.0 those carried the same names as the instance methods, so grid.worksheet.loadFromFile(file) kept only the first tab. The old names still work but are deprecated — see XLSX Import & Export.
// Export the whole workbook to .xlsx (triggers a download)
grid.saveAsXlsx({ filename: 'report.xlsx' })
// Load every sheet from a File / URL / ArrayBuffer
await grid.loadFromFile(file)
await grid.loadFromUrl('/data/book.xlsx')
await grid.loadXlsx(arrayBuffer)
// JSON serialization (round-trips all sheets + view state)
const doc = grid.toJson()
grid.loadJson(doc)
// Every visible sheet into one PDF (Pro, v1.7.0) — needs a font, see PDF Export
grid.saveAsPdf({ locale: 'ja', sheets: 'all', filename: 'report.pdf' })
Workbook view state round-trips through xlsx: the active sheet, per-sheet hidden state, tab colors and — since v1.7.0 — each sheet’s zoom are written on export and restored on load (ReoGrid-JSON also preserves each sheet’s showGridlines). For several sheets in one PDF, see PDF Export.
Reacting to sheet changes
grid.workbook.onActiveSheetChange((index) => {
console.log('active sheet is now', index)
})
grid.workbook.onSheetsChange(() => {
// fires on add / remove / rename / move / metadata change
console.log('tabs:', grid.workbook.getSheetNames())
})
Each subscribe call returns an unsubscribe function.
Instance-level events follow the active sheet
Subscribe once on the instance and the listener automatically re-points to whichever sheet is active — no re-binding when the user switches tabs.
grid.onSelectionChange((range) => { /* active sheet's selection */ })
grid.onCellValueChange(({ row, column, value }) => { /* ... */ })
Available: onSelectionChange, onCellValueChange, onBulkCellsChange, onScrollChange, onViewportSizeChange, onStructureChange, onContextMenu, and since v1.7.0 onZoomChange and onHyperlinkClick. See Selection & Events for payload shapes.
Cross-sheet formulas
Formulas can reference cells on other sheets — =Sheet1!A1, ='My Sheet'!A1:B2, even non-ASCII names like =シート1!A1. Renaming a sheet rewrites referencing formulas; deleting one turns references into #REF!. Full details and lifecycle rules are in the Formula Engine — Cross-sheet references section.
// On the Summary sheet, consolidate three branch sheets:
summary.cell('B2').value = "='Tokyo'!E6"
summary.cell('B3').value = "='Osaka'!E6"
summary.cell('B4').value = "='Nagoya'!E6"
summary.cell('B5').value = '=SUM(B2:B4)'
React & Vue
Both wrappers expose the workbook through the instance and emit sheet events.
// React
<Reogrid
onReady={(grid) => grid.workbook.addSheet('Data')}
onActiveSheetChange={(index) => console.log('active', index)}
onSheetsChange={() => console.log('sheets changed')}
/>
<!-- Vue -->
<Reogrid
@ready="grid => grid.workbook.addSheet('Data')"
@active-sheet-change="index => console.log('active', index)"
@sheets-change="() => console.log('sheets changed')"
/>
Live demo
See the Multi-Sheet Workbook demo — three branch sheets plus a Summary sheet built entirely from cross-sheet formulas. Edit any branch and watch the totals recalculate across sheets.
Sorry to hear that. What could be improved?