Розробка онлайн-редактора таблиць
Онлайн-редактор таблиць — найскладніший клас веб-додатків. Завдання включає: віртуалізацію великих таблиць, формульний рушій, спільне редагування з розвязанням конфліктів, імпорт/експорт XLSX. Повноцінний аналог Google Sheets потребує багаторічної розробки; реалістичні цілі — вбудований редактор для конкретного бізнес-кейса або спеціалізована таблиця з обмеженим набором функцій.
Віртуалізація UI
Таблиця з 100,000 рядків не може рендерити всі DOM-елементи одночасно. Віртуалізація — рендер тільки видимих рядків + невеликий буфер:
- TanStack Virtual (раніше react-virtual) — headless хук для віртуалізації
- AG Grid — feature-rich комерційна сітка з віртуалізацією, формулами, експортом
- Handsontable — близько до Excel за функціями, MIT або комерційна ліцензія
Реалізація віртуалізації рядків з TanStack Virtual:
const rowVirtualizer = useVirtualizer({
count: rows.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 24, // висота рядка в px
overscan: 10,
});
return (
<div style={{ height: rowVirtualizer.getTotalSize() }}>
{rowVirtualizer.getVirtualItems().map(virtualRow => (
<Row key={virtualRow.index} row={rows[virtualRow.index]}
style={{ transform: `translateY(${virtualRow.start}px)` }} />
))}
</div>
);
Формульний рушій
Формульний рушій — парсинг виразів вида =SUM(A1:B10) * C5 + IF(D1>0, E1, 0).
HyperFormula (Handsontable team) — open-source рушій з підтримкою 400+ формул, XLSX-сумісний. Написаний на TypeScript, працює в браузері та Node.js:
import HyperFormula from 'hyperformula';
const hf = HyperFormula.buildFromArray([
['=SUM(B1:B3)', 10, 20, 30],
[1, 2, 3],
]);
console.log(hf.getCellValue({ row: 0, col: 0, sheet: 0 })); // 6
Dependency tracking: при зміні ячейки рушій перераховує тільки залежні ячейки (lazy evaluation за графом залежностей).
Спільне редагування
OT (Operational Transformation) або CRDT для розвязання конфліктів при одночасному редагуванні:
Yjs — CRDT-бібліотека з підтримкою shared types. Для таблиць: Y.Map для ячеєк.
const ydoc = new Y.Doc();
const cells = ydoc.getMap('cells'); // key: "A1", value: ячейка
// Провайдер для синхронізації
const provider = new WebsocketProvider('ws://server', 'spreadsheet-123', ydoc);
// Оновлення ячейки
cells.set('A1', { value: 100, formula: null });
Конфлікт при одночасній зміні однієї ячейки двома користувачами в CRDT: останнє оновлення (LWW — Last Write Wins) за timestamp lamport clock.
Історія змін та undo/redo
Undo/redo — через стек операцій. Кожна зміна (включаючи формули) записується як reversible operation. Collaborative undo складніше: відміна своїх змін, не чужих.
Типи даних та форматування
Ячейка може містити: рядок, число, дату, boolean, формулу. Форматування: шрифт, колір фону/тексту, числовий формат (%, дата, валюта), вирівнювання, межі.
Числові формати зберігаються як рядки формату: #,##0.00, DD.MM.YYYY, 0%.
Імпорт/Експорт XLSX
- SheetJS (xlsx) — повна підтримка XLSX, XLS, CSV. Читає та пише файли. Працює в браузері (FileReader) та Node.js.
- ExcelJS — створення XLSX з форматуванням, зображеннями, формулами.
При імпорті XLSX: витяг ячеєк → нормалізація у внутрішній формат. Формули зберігаються як рядки, обчислюються через HyperFormula.
Часові рамки
Спеціалізована таблиця (конкретний шаблон, 100-1000 рядків, базові формули, без спільного редагування): 2–3 місяці. Повноцінний редактор з віртуалізацією, спільним редагуванням, імпортом XLSX та 200+ формулами: 6–10 місяців.







