Разработка онлайн-редактора таблиц
Онлайн-редактор таблиц — сложнейший класс веб-приложений. Задача включает: виртуализацию больших таблиц, формульный движок, совместное редактирование с разрешением конфликтов, импорт/экспорт 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 месяцев.







