ReoGrid ReoGrid Web

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

OptionTypeDefaultDescription
showSheetTabsbooleantrueShow the sheet tab bar at the bottom of the grid.
initialSheetNamestring'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', ...]
MethodDescription
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 per-worksheet worksheet.loadXlsx() loads only into the active sheet.)

// 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)

Workbook view state round-trips through xlsx: the active sheet, per-sheet hidden state, and tab colors are written on export and restored on load (ReoGrid-JSON also preserves each sheet’s showGridlines).

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. 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.

Stay Updated

Be first to know — get updates as they ship

Get notified of new releases, features, and announcements.
No spam — just updates that matter.