···7070 { name: 'range2', desc: 'Additional ranges', required: false },
7171 ],
7272 },
7373+ ADD: {
7474+ desc: 'Returns the sum of two values (equivalent to value1 + value2)',
7575+ params: [
7676+ { name: 'value1', desc: 'The first addend', required: true },
7777+ { name: 'value2', desc: 'The second addend', required: true },
7878+ ],
7979+ },
8080+ MINUS: {
8181+ desc: 'Returns the difference of two values (equivalent to value1 - value2)',
8282+ params: [
8383+ { name: 'value1', desc: 'The value to subtract from', required: true },
8484+ { name: 'value2', desc: 'The value to subtract', required: true },
8585+ ],
8686+ },
8787+ MULTIPLY: {
8888+ desc: 'Returns the product of two values (equivalent to factor1 * factor2)',
8989+ params: [
9090+ { name: 'factor1', desc: 'The first factor', required: true },
9191+ { name: 'factor2', desc: 'The second factor', required: true },
9292+ ],
9393+ },
9494+ DIVIDE: {
9595+ desc: 'Returns the result of dividing one value by another (equivalent to dividend / divisor)',
9696+ params: [
9797+ { name: 'dividend', desc: 'The number to be divided', required: true },
9898+ { name: 'divisor', desc: 'The number to divide by', required: true },
9999+ ],
100100+ },
73101 ABS: {
74102 desc: 'Returns the absolute value of a number',
75103 params: [
+4
src/sheets/formulas.ts
···659659 case 'COUNTA': return flat(args).length;
660660 case 'MIN': { const n = nums(args); return n.length ? Math.min(...n) : 0; }
661661 case 'MAX': { const n = nums(args); return n.length ? Math.max(...n) : 0; }
662662+ case 'ADD': return toNum(args[0]) + toNum(args[1]);
663663+ case 'MINUS': return toNum(args[0]) - toNum(args[1]);
664664+ case 'MULTIPLY': return toNum(args[0]) * toNum(args[1]);
665665+ case 'DIVIDE': { const d = toNum(args[1]); return d === 0 ? '#DIV/0!' : toNum(args[0]) / d; }
662666 case 'ABS': return Math.abs(toNum(args[0]));
663667 case 'ROUND': return Math.round(toNum(args[0]) * Math.pow(10, toNum(args[1] ?? 0))) / Math.pow(10, toNum(args[1] ?? 0));
664668 case 'ROUNDUP': { const f = Math.pow(10, toNum(args[1] ?? 0)); return Math.ceil(toNum(args[0]) * f) / f; }
+9-2
src/sheets/xlsx-import.ts
···429429 }
430430 }
431431432432- // Store row heights as JSON (no existing Y.Map pattern for row heights)
432432+ // Store row heights into the Yjs rowHeights Y.Map
433433 if (parsed.rowHeights && Object.keys(parsed.rowHeights).length > 0) {
434434- sheet.set('rowHeights', JSON.stringify(parsed.rowHeights));
434434+ let rowHeightsMap = sheet.get('rowHeights');
435435+ if (!rowHeightsMap || typeof rowHeightsMap.set !== 'function') {
436436+ rowHeightsMap = new (cells.constructor)();
437437+ sheet.set('rowHeights', rowHeightsMap);
438438+ }
439439+ for (const [rowIdx, height] of Object.entries(parsed.rowHeights)) {
440440+ rowHeightsMap.set(String(rowIdx), height);
441441+ }
435442 }
436443437444 // Expand grid dimensions if needed