English | 中文
npm i --save excel-collab- Create a React app
npm create vite@latest my-app -- --template react-ts
cd my-app
npm i- Install the Required Libraries
npm i --save excel-collab- Modify the Main File
// src/main.tsx
import { createRoot } from 'react-dom/client';
import { StrictMode } from 'react';
import { Excel } from 'excel-collab';
import 'excel-collab/style.css';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<Excel style={{ height: '100vh' }} />
</StrictMode>,
);- Start the app
npm run devgit clone https://github.com/nusr/excel.git
cd excel
yarn install
npm run startThe root start script starts the demo frontend and backend together.
Excel-collab is a web-based spreadsheet application that supports real-time collaboration, formulas, formatting, and data processing.
- Real-time Collaboration: Multiple users can edit the same spreadsheet simultaneously with conflict resolution
- Formula Calculation: Excel-style formulas with cross-sheet references and FormulaJS-backed functions
- Rich Formatting: Fonts, colors, borders, alignment, number formats, and more
- High Performance: OffScreenCanvas rendering and Web Worker formula computation
- File Compatibility: Import/export XLSX, XLSM, XLAM, XLTM, XLTX, and CSV
The application follows a modular architecture with clear separation of concerns:
excel/
├── packages/excel-collab/
│ ├── src/
│ │ ├── canvas/ # Canvas rendering engine
│ │ │ ├── MainCanvas.ts # Main canvas controller
│ │ │ ├── offScreenWorker.ts # Offscreen canvas worker
│ │ │ └── worker.ts # Web Worker for heavy computations
│ │ ├── components/ # Reusable UI components
│ │ ├── containers/ # Application containers and business logic
│ │ │ ├── Excel/ # Main editor container
│ │ │ ├── FormulaBar/ # Formula input and editing
│ │ │ ├── CanvasContainer/ # Canvas wrapper
│ │ │ └── store/ # State management
│ │ ├── controller/ # Business logic controller
│ │ │ ├── Controller.ts # Main controller
│ │ │ └── decorator.ts # Transaction decorators
│ │ ├── formula/ # Formula parser and evaluator
│ │ │ ├── parser.ts # Expression parser
│ │ │ ├── scanner.ts # Token scanner
│ │ │ ├── interpreter.ts # Expression interpreter
│ │ │ └── eval.ts # Formula evaluation
│ │ ├── model/ # Data models
│ │ ├── types/ # TypeScript type definitions
│ │ ├── util/ # Utility functions
│ │ └── i18n/ # Internationalization
The canvas rendering system uses OffScreenCanvas for high-performance rendering:
- MainCanvas: Bridges React components with the canvas rendering
- OffScreenWorker: Handles rendering operations in a separate thread
- Worker: Manages communication between main thread and worker thread
This architecture ensures smooth UI interactions even with large spreadsheets.
The formula system implements a classic compiler architecture:
Formula String → Scanner → Parser → Interpreter → Result
↓ ↓ ↓
Tokens AST Values
Scanner (scanner.ts): Tokenizes formula strings into lexical tokens
- Recognizes numbers, strings, cell references, functions, operators
- Handles Excel error values (#REF!, #NAME?, etc.)
- Supports defined names and R1C1 references
Parser (parser.ts): Builds Abstract Syntax Tree (AST)
- Implements recursive descent parsing
- Supports operator precedence (exponent → unary → multiplication/division → addition/subtraction)
- Handles function calls with parameters
- Supports cell ranges and array expressions
Interpreter (interpreter.ts): Evaluates the AST
- Visitor pattern for traversing expression trees
- Resolves cell references and ranges
- Calls Excel functions with proper parameter handling
- Manages circular dependency detection
Formula support includes named ranges, cross-sheet references, rectangular array constants, and error propagation. Dynamic array spilling and several advanced Excel reference types are not supported. See the formula compatibility notes for the supported syntax and limitations.
- Controller Pattern: Centralized business logic through
Controllerclass - Transaction Support: Batch operations with undo/redo capability
- Event System: Event emitter for component communication
- Immutable Updates: Ensures predictable state changes
Built on Yjs for CRDT-based real-time collaboration:
- Conflict-free concurrent editing
- Awareness protocol for user presence
- Offline support and synchronization
- Online Collaboration
- Create File
- Change File Name
- Undo/Redo
- Copy/Cut/Paste
- Find and Replace
- FormulaJS-backed functions
- Rectangular array constants
- Cross-sheet References
- Defined Names
- Circular Reference Detection
- Web Worker Formula Parsing
- Font Family
- Font Size
- Font Color
- Fill Color
- Bold/Italic/Strikethrough/Underline
- Borders
- Text Alignment
- Text Wrapping
- Number Formats
- Date/Time Formats
- Custom Formats
- AutoFilter
- Sort
- Merge Cells
- Insert Row/Column
- Delete Row/Column
- Hide Row/Column
- Row Height
- Column Width
- Freeze Panes
- Charts
- Floating Pictures
- Sparklines
- Insert Sheet
- Delete Sheet
- Rename Sheet
- Hide/Unhide Sheet
- Sheet Color
- Import XLSX
- Export XLSX, XLSM, XLAM, XLTM, XLTX
- Import CSV
- Export CSV
- Export PDF
- Dark Mode
- Internationalization (i18n)
- Keyboard Shortcuts
- Context Menu
- Data Validation
- Conditional Formatting
Formula parsing and evaluation run in Web Workers to prevent blocking the main thread:
- Complex formulas with nested functions
- Bulk formula updates across many cells
- Circular dependency detection
Rendering operations are offloaded to OffScreenCanvas:
- Large spreadsheet rendering
- Frequent repaints during scrolling/zooming
- Background rendering operations
- Smart diffing for cell changes
- Debounced renders
- Selective re-rendering of affected areas
import { Excel } from 'excel-collab';
import 'excel-collab/style.css';
// Simple usage
<Excel style={{ height: '100vh' }} />
// With custom configuration
<Excel
style={{ height: '100vh' }}
menubarLeftChildren={<CustomMenu />}
toolbarChildren={<CustomToolbar />}
sheetBarChildren={<CustomSheetBar />}
/>Access the controller for programmatic operations:
import { useExcel } from 'excel-collab';
// Get controller instance
const { controller } = useExcel();
// Cell operations
controller.setCellValue(range, value);
controller.getCellValue(range);
// Range operations
controller.selectRange(range);
controller.copyRange(range);
controller.pasteRange(range);
// Worksheet operations
controller.addSheet(name);
controller.deleteSheet(sheetId);
controller.renameSheet(sheetId, name);
// Formula operations
controller.setCellFormula(range, formula);
controller.computeFormulas();controller.on('change', (changeSet) => {
// Handle changes
});
controller.on('save', (json) => {
// Handle save
});